SDK IMA giúp bạn dễ dàng tích hợp quảng cáo đa phương tiện vào trang web và ứng dụng của mình. SDK IMA có thể yêu cầu quảng cáo từ bất kỳ máy chủ quảng cáo tuân thủ VAST nào và quản lý việc phát quảng cáo trong ứng dụng của bạn. Với SDK DAI của IMA, các ứng dụng sẽ đưa ra yêu cầu về luồng cho quảng cáo và video nội dung – có thể là nội dung VOD hoặc nội dung trực tiếp. Sau đó, SDK sẽ trả về một luồng video kết hợp, nhờ đó bạn không phải quản lý việc chuyển đổi giữa quảng cáo và video nội dung trong ứng dụng của mình.
Chọn giải pháp DAI mà bạn quan tâm
DAI phân phát nhóm
Hướng dẫn này minh hoạ cách phát luồng Phân phát nhóm DAI cho nội dung phát trực tiếp hoặc VOD, bằng cách sử dụng SDK DAI IMA cho HTML5 với trình phát video dựa vào hls.js để phát. Để xem hoặc làm theo một mẫu tích hợp hoàn chỉnh, có hỗ trợ cả HLS.js và Safari Playback, hãy xem ví dụ về tính năng phân phát nhóm HLS. Để biết thông tin hỗ trợ DASH.js, hãy xem ví dụ về Phân phát nhóm DASH. Bạn có thể tải các ứng dụng mẫu này xuống từ trang phát hành DAI HTML5 trên GitHub.
Tổng quan về cơ chế Phân phát nhóm DAI
Việc triển khai tính năng Phân phát nhóm bằng IMA DAI SDK bao gồm 2 thành phần chính được minh hoạ trong hướng dẫn này:
PodStreamRequest
/PodVodStreamRequest
: Một đối tượng xác định yêu cầu truyền phát đến các máy chủ quảng cáo của Google. Các yêu cầu chỉ định một Mã mạng vàPodStreamRequest
cũng yêu cầu một Khoá tài sản tuỳ chỉnh và một khoá API không bắt buộc. Cả hai đều có các tham số không bắt buộc khác.StreamManager
: Một đối tượng xử lý hoạt động giao tiếp giữa luồng video và SDK DAI của IMA, chẳng hạn như gửi ping theo dõi và chuyển tiếp các sự kiện luồng phát đến nhà xuất bản.
Điều kiện tiên quyết
Trước khi bắt đầu, bạn cần có những thông tin sau:
3 tệp trống:
- dai.html
- dai.css
- dai.js
Python được cài đặt trên máy tính của bạn, hoặc một máy chủ web hoặc môi trường phát triển được lưu trữ khác để sử dụng cho việc kiểm thử
Định cấu hình môi trường phát triển
Vì SDK tải các phần phụ thuộc bằng cùng một giao thức với trang mà SDK được tải, nên bạn cần sử dụng một máy chủ web để kiểm thử ứng dụng của mình. Một cách nhanh chóng để khởi động máy chủ phát triển cục bộ là sử dụng máy chủ tích hợp của Python.
Sử dụng dòng lệnh, từ thư mục chứa tệp
index.html
, hãy chạy:python -m http.server 8000
Trong trình duyệt web, hãy truy cập vào
http://localhost:8000/
Bạn cũng có thể sử dụng bất kỳ môi trường phát triển được lưu trữ hoặc máy chủ web nào khác, chẳng hạn như Máy chủ HTTP Apache.
Tạo trình phát video
Trước tiên, hãy sửa đổi dai.html để tạo một phần tử video HTML5 và một div để dùng cho các phần tử Giao diện người dùng quảng cáo. Ngoài ra, hãy thêm các thẻ cần thiết để tải tệp dai.css và dai.js, cũng như nhập trình phát video hls.js
.
Sau đó, hãy sửa đổi dai.css để chỉ định kích thước và vị trí của các phần tử trên trang.
Cuối cùng, trong dai.js, hãy xác định các biến để lưu giữ thông tin yêu cầu về luồng phát và một hàm initPlayer()
để chạy khi trang tải.
Các hằng số yêu cầu truyền phát trực tiếp như sau:
BACKUP_STREAM
: URL cho một luồng dự phòng để phát trong trường hợp quy trình quảng cáo gặp phải lỗi nghiêm trọng.STREAM_URL
: Chỉ dùng cho sự kiện phát trực tiếp. URL luồng video do trình thao tác tệp kê khai hoặc đối tác bên thứ ba cung cấp bằng cách sử dụng tính năng Phân phát nhóm. Bạn phải chèn mã nhận dạng luồng do IMA DAI SDK cung cấp trước khi đưa ra yêu cầu. Trong trường hợp này, URL luồng phát có chứa một phần giữ chỗ[[STREAMID]]
. Phần giữ chỗ này sẽ được thay thế bằng mã nhận dạng luồng phát trước khi đưa ra yêu cầu.NETWORK_CODE
: Mã mạng cho tài khoản Ad Manager 360 của bạn.CUSTOM_ASSET_KEY
: Chỉ dùng cho sự kiện phát trực tiếp. Khoá tài sản tuỳ chỉnh xác định sự kiện Phân phát nhóm của bạn trong Ad Manager 360. Tham số này có thể được tạo bởi trình thao tác tệp kê khai hoặc đối tác Phân phát nhóm quảng cáo bên thứ ba.API_KEY
: Chỉ dùng cho sự kiện phát trực tiếp. Khoá API không bắt buộc. Khoá này có thể là khoá bắt buộc để truy xuất mã nhận dạng luồng phát từ IMA DAI SDK.
dai.html
<html>
<head>
<script src="https://cdn.jsdelivr.net/npm/hls.js@latest"></script>
<script src="dai.js"></script>
<link rel="stylesheet" href="dai.css" type="text/css">
</head>
<body onLoad="initPlayer()">
<h2>IMA DAI SDK Demo (HLS.JS)</h2>
<video id="video"></video>
<div id="adUi"></div>
</body>
</html>
dai.css
#video,
#adUi {
width: 640px;
height: 360px;
position: absolute;
top: 35px;
left: 0;
}
#adUi {
cursor: pointer;
}
dai.js
var BACKUP_STREAM =
'https://storage.googleapis.com/interactive-media-ads/media/bbb.m3u8'
// Stream Config.
const STREAM_URL = "";
const NETWORK_CODE = "";
const CUSTOM_ASSET_KEY = "";
const API_KEY = "";
var hls = new Hls(); // hls.js video player
var videoElement;
var adUiElement;
function initPlayer() {
videoElement = document.getElementById('video');
adUiElement = document.getElementById('adUi');
}
Tải SDK DAI của IMA
Tiếp theo, hãy thêm khung DAI bằng thẻ tập lệnh trong dai.html, trước thẻ cho dai.js.
dai.html
<html>
<head>
<script src="https://cdn.jsdelivr.net/npm/hls.js@latest"></script>
<script type="text/javascript" src="//imasdk.googleapis.com/js/sdkloader/ima3_dai.js"></script>
<script src="dai.js"></script>
<link rel="stylesheet" href="dai.css" type="text/css">
</head>
...
Khởi chạy StreamManager và đưa ra yêu cầu phát trực tiếp hoặc phát video theo yêu cầu
Phân phát nhóm sự kiện phát trực tiếp
Để yêu cầu một nhóm quảng cáo, hãy tạo một ima.dai.api.StreamManager
. Lớp này chịu trách nhiệm yêu cầu và quản lý các luồng DAI. Hàm khởi tạo lấy một phần tử video và phiên bản kết quả lấy một phần tử giao diện người dùng quảng cáo để xử lý các lượt tương tác với quảng cáo.
Sau đó, hãy xác định một hàm để yêu cầu phát trực tiếp Pod Serving. Trước tiên, hàm này sẽ tạo một PodStreamRequest
, định cấu hình PodStreamRequest
đó bằng các tham số streamRequest được cung cấp ở bước 2, rồi gọi streamManager.requestStream()
bằng đối tượng yêu cầu đó.
dai.js
function initPlayer() {
videoElement = document.getElementById('video');
adUiElement = document.getElementById('adUi');
streamManager = new google.ima.dai.api.StreamManager(videoElement, adUiElement)
requestLivePodStream(NETWORK_CODE, CUSTOM_ASSET_KEY, API_KEY);
}
function requestLivePodStream(networkCode, customAssetKey, apiKey) {
// clear HLS.js instance, if in use
if (hls) {
hls.destroy();
}
// Generate a Pod Serving live Stream Request
const streamRequest = new google.ima.dai.api.PodStreamRequest();
streamRequest.networkCode = networkCode;
streamRequest.customAssetKey = customAssetKey;
streamRequest.apiKey = apiKey;
streamRequest.format = 'hls';
streamManager.requestStream(streamRequest);
}
Phân phát nhóm VOD
Để yêu cầu một nhóm quảng cáo, hãy tạo một ima.dai.api.StreamManager
. Lớp này chịu trách nhiệm yêu cầu và quản lý các luồng DAI. Hàm khởi tạo lấy một phần tử video và phiên bản kết quả lấy một phần tử giao diện người dùng quảng cáo để xử lý các lượt tương tác với quảng cáo.
Sau đó, hãy xác định một hàm để yêu cầu luồng VOD Phân phát nhóm. Trước tiên, hàm này sẽ tạo một PodVodStreamRequest
, định cấu hình PodVodStreamRequest
đó bằng các tham số streamRequest được cung cấp ở bước 2, rồi gọi streamManager.requestStream()
bằng đối tượng yêu cầu đó.
dai.js
function initPlayer() {
videoElement = document.getElementById('video');
adUiElement = document.getElementById('adUi');
streamManager = new google.ima.dai.api.StreamManager(videoElement, adUiElement)
requestVodPodStream(NETWORK_CODE);
}
function requestVodPodStream(networkCode) {
// clear HLS.js instance, if in use
if (hls) {
hls.destroy();
}
// Generate a Pod Serving VOD Stream Request
const streamRequest = new google.ima.dai.api.PodVodStreamRequest();
streamRequest.networkCode = networkCode;
streamRequest.format = 'hls';
streamManager.requestStream(streamRequest);
}
Xử lý sự kiện luồng
Phân phát nhóm sự kiện phát trực tiếp
Tiếp theo, hãy triển khai trình nghe sự kiện cho các sự kiện chính về video. Ví dụ này xử lý các sự kiện STREAM_INITIALIZED
, ERROR
, AD_BREAK_STARTED
và AD_BREAK_ENDED
bằng cách gọi một hàm onStreamEvent()
. Hàm này xử lý quá trình tải luồng phát và các lỗi, cũng như vô hiệu hoá các chế độ điều khiển trình phát trong khi quảng cáo đang phát (điều này là bắt buộc đối với SDK). Khi luồng được tải, trình phát video sẽ tải và phát URL được cung cấp bằng cách sử dụng hàm loadStream()
.
dai.js
var isAdBreak;
function initPlayer() {
videoElement = document.getElementById('video');
adUiElement = document.getElementById('adUi');
streamManager = new google.ima.dai.api.StreamManager(videoElement, adUiElement);
streamManager.addEventListener(
[google.ima.dai.api.StreamEvent.Type.STREAM_INITIALIZED,
google.ima.dai.api.StreamEvent.Type.ERROR,
google.ima.dai.api.StreamEvent.Type.AD_BREAK_STARTED,
google.ima.dai.api.StreamEvent.Type.AD_BREAK_ENDED],
onStreamEvent,
false);
...
function onStreamEvent(e) {
switch (e.type) {
case google.ima.dai.api.StreamEvent.Type.STREAM_INITIALIZED:
console.log('Stream initialized');
loadStream(e.getStreamData().streamId);
break;
case google.ima.dai.api.StreamEvent.Type.ERROR:
console.log('Error loading stream, playing backup stream.' + e);
loadStream('');
break;
case google.ima.dai.api.StreamEvent.Type.AD_BREAK_STARTED:
console.log('Ad Break Started');
isAdBreak = true;
videoElement.controls = false;
adUiElement.style.display = 'block';
break;
case google.ima.dai.api.StreamEvent.Type.AD_BREAK_ENDED:
console.log('Ad Break Ended');
isAdBreak = false;
videoElement.controls = true;
adUiElement.style.display = 'none';
break;
default:
break;
}
}
function loadStream(streamID) {
var url;
if(streamID) {
url = STREAM_URL.replace('[[STREAMID]]', streamID);
} else {
console.log('Stream Initialization Failed');
url = BACKUP_STREAM;
}
console.log('Loading:' + url);
hls.loadSource(url);
hls.attachMedia(videoElement);
}
Phân phát nhóm VOD
Tiếp theo, hãy triển khai trình nghe sự kiện cho các sự kiện chính về video. Ví dụ này xử lý các sự kiện STREAM_INITIALIZED
, LOADED
, ERROR
, AD_BREAK_STARTED
và AD_BREAK_ENDED
bằng cách gọi một hàm onStreamEvent()
. Hàm này xử lý việc tải và lỗi luồng, cũng như vô hiệu hoá các chế độ điều khiển trình phát trong khi quảng cáo đang phát (theo yêu cầu của SDK).
Ngoài ra, các luồng phát VOD Pod Serving yêu cầu gọi StreamManager.loadStreamMetadata()
để phản hồi sự kiện STREAM_INITIALIZED
. Bạn cũng cần yêu cầu URL phát trực tiếp từ đối tác công nghệ video (VTP). Sau khi lệnh gọi loadStreamMetadata()
thành công, lệnh gọi này sẽ kích hoạt sự kiện LOADED
. Tại đây, bạn nên gọi hàm loadStream()
bằng URL của luồng phát để tải và phát luồng phát.
var isAdBreak;
function initPlayer() {
videoElement = document.getElementById('video');
adUiElement = document.getElementById('adUi');
streamManager = new google.ima.dai.api.StreamManager(videoElement, adUiElement);
streamManager.addEventListener(
[google.ima.dai.api.StreamEvent.Type.STREAM_INITIALIZED,
google.ima.dai.api.StreamEvent.Type.ERROR,
google.ima.dai.api.StreamEvent.Type.AD_BREAK_STARTED,
google.ima.dai.api.StreamEvent.Type.AD_BREAK_ENDED],
onStreamEvent,
false);
...
function onStreamEvent(e) {
switch (e.type) {
case google.ima.dai.api.StreamEvent.Type.STREAM_INITIALIZED:
const streamId = e.getStreamData().streamId;
// 'vtpInterface' is a place holder for your own video technology
// partner (VTP) API calls.
vtpInterface.requestStreamURL({
'streamId': streamId,
})
.then( (vtpStreamUrl) => {
streamUrl = vtpStreamUrl;
streamManager.loadStreamMetadata();
}, (error) => {
// Handle the error.
});
break;
case google.ima.dai.api.StreamEvent.Type.LOADED:
loadStream(streamUrl);
break;
case google.ima.dai.api.StreamEvent.Type.ERROR:
console.log('Error loading stream, playing backup stream.' + e);
loadStream();
break;
case google.ima.dai.api.StreamEvent.Type.AD_BREAK_STARTED:
console.log('Ad Break Started');
isAdBreak = true;
videoElement.controls = false;
adUiElement.style.display = 'block';
break;
case google.ima.dai.api.StreamEvent.Type.AD_BREAK_ENDED:
console.log('Ad Break Ended');
isAdBreak = false;
videoElement.controls = true;
adUiElement.style.display = 'none';
break;
default:
break;
}
}
function loadStream(url) {
if(url) {
console.log('Loading:' + url);
hls.loadSource(url);
} else {
console.log('Stream Initialization Failed');
hls.loadSource(BACKUP_STREAM);
}
hls.attachMedia(videoElement);
}
Xử lý siêu dữ liệu của luồng phát
Trong bước này, bạn triển khai trình nghe sự kiện cho siêu dữ liệu để thông báo cho SDK khi các sự kiện quảng cáo xảy ra. Việc theo dõi các sự kiện siêu dữ liệu trong luồng phát có thể khác nhau, tuỳ thuộc vào định dạng luồng phát (HLS hoặc DASH), loại luồng phát (luồng phát trực tiếp hoặc luồng phát VOD), loại trình phát và loại phần phụ trợ DAI đang được sử dụng. Hãy xem hướng dẫn về Siêu dữ liệu có dấu thời gian của chúng tôi để biết thêm thông tin.
Định dạng luồng HLS (Luồng phát trực tiếp và luồng VOD, trình phát HLS.js)
Nếu bạn đang sử dụng trình phát HLS.js, hãy lắng nghe sự kiện FRAG_PARSING_METADATA
HLS.js để nhận siêu dữ liệu ID3 và truyền siêu dữ liệu đó đến SDK bằng StreamManager.processMetadata()
.
Để tự động phát video sau khi mọi thứ đã tải xong và sẵn sàng, hãy theo dõi sự kiện MANIFEST_PARSED
HLS.js để kích hoạt chế độ phát.
function loadStream(streamID) {
hls.loadSource(url);
hls.attachMedia(videoElement);
// Timed metadata is passed HLS stream events to the streamManager.
hls.on(Hls.Events.FRAG_PARSING_METADATA, parseID3Events);
hls.on(Hls.Events.MANIFEST_PARSED, startPlayback);
}
function parseID3Events(event, data) {
if (streamManager && data) {
// For each ID3 tag in the metadata, pass in the type - ID3, the
// tag data (a byte array), and the presentation timestamp (PTS).
data.samples.forEach((sample) => {
streamManager.processMetadata('ID3', sample.data, sample.pts);
});
}
}
function startPlayback() {
console.log('Video Play');
videoElement.play();
}
DASH.js (định dạng luồng DASH, loại luồng phát trực tiếp và VOD)
Nếu đang sử dụng trình phát DASH.js, bạn phải dùng các chuỗi khác nhau để theo dõi siêu dữ liệu ID3 cho luồng trực tiếp hoặc luồng VOD:
- Sự kiện phát trực tiếp:
'https://developer.apple.com/streaming/emsg-id3'
- Luồng VOD:
'urn:google:dai:2018'
Truyền siêu dữ liệu ID3 đến SDK bằng StreamManager.processMetadata()
.
Để tự động hiện các nút điều khiển video sau khi mọi thứ đã tải xong và sẵn sàng, hãy lắng nghe sự kiện MANIFEST_LOADED
DASH.js.
const googleLiveSchema = 'https://developer.apple.com/streaming/emsg-id3';
const googleVodSchema = 'urn:google:dai:2018';
dashPlayer.on(googleLiveSchema, processMetadata);
dashPlayer.on(googleVodSchema, processMetadata);
dashPlayer.on(dashjs.MediaPlayer.events.MANIFEST_LOADED, loadlistener);
function processMetadata(metadataEvent) {
const messageData = metadataEvent.event.messageData;
const timestamp = metadataEvent.event.calculatedPresentationTime;
// Use StreamManager.processMetadata() if your video player provides raw
// ID3 tags, as with dash.js.
streamManager.processMetadata('ID3', messageData, timestamp);
}
function loadlistener() {
showControls();
// This listener must be removed, otherwise it triggers as addional
// manifests are loaded. The manifest is loaded once for the content,
// but additional manifests are loaded for upcoming ad breaks.
dashPlayer.off(dashjs.MediaPlayer.events.MANIFEST_LOADED, loadlistener);
}
Shaka Player có sự kiện phát trực tiếp (định dạng luồng DASH)
Nếu bạn đang sử dụng Trình phát Shaka để phát trực tiếp, hãy dùng chuỗi 'emsg'
để theo dõi các sự kiện siêu dữ liệu.
Sau đó, hãy sử dụng dữ liệu thông báo sự kiện trong lệnh gọi đến StreamManager.onTimedMetadata()
.
shakaPlayer.addEventListener('emsg', (event) => onEmsgEvent(event));
function onEmsgEvent(metadataEvent) {
// Use StreamManager.onTimedMetadata() if your video player provides
// processed metadata, as with Shaka player livestreams.
streamManager.onTimedMetadata({'TXXX': metadataEvent.detail.messageData});
}
Shaka Player có luồng VOD (định dạng luồng DASH)
Nếu bạn đang sử dụng trình phát Shaka để phát luồng VOD, hãy sử dụng chuỗi 'timelineregionenter'
để theo dõi các sự kiện siêu dữ liệu. Sau đó, hãy sử dụng dữ liệu thông báo sự kiện trong lệnh gọi của bạn đến StreamManager.processMetadata()
bằng chuỗi 'urn:google:dai:2018'
.
shakaPlayer.addEventListener('timelineregionenter', (event) => onTimelineEvent(event));
function onTimelineEvent(metadataEvent) {
const detail = metadataEvent.detail;
if ( detail.eventElement.attributes &&
detail.eventElement.attributes['messageData'] &&
detail.eventElement.attributes['messageData'].value ) {
const mediaId = detail.eventElement.attributes['messageData'].value;
const pts = detail.startTime;
// Use StreamManager.processMetadata() if your video player provides raw
// ID3 tags, as with Shaka player VOD streams.
streamManager.processMetadata('urn:google:dai:2018', mediaId, pts);
}
}
Xử lý sự kiện của trình phát
Thêm trình nghe sự kiện vào các sự kiện pause
và start
của phần tử video để cho phép người dùng tiếp tục phát khi SDK tạm dừng trong thời gian chèn quảng cáo.
function loadStream(streamUrl) {
...
videoElement.addEventListener('pause', onStreamPause);
videoElement.addEventListener('play', onStreamPlay);
}
function onStreamPause() {
console.log('paused');
if (isAdBreak) {
videoElement.controls = true;
adUiElement.style.display = 'none';
}
}
function onStreamPlay() {
console.log('played');
if (isAdBreak) {
videoElement.controls = false;
adUiElement.style.display = 'block';
}
}
Dọn dẹp các thành phần DAI của IMA
Khi đã hoàn tất việc yêu cầu và hiển thị quảng cáo trong luồng Phân phát theo nhóm bằng SDK DAI của IMA, bạn nên dọn dẹp mọi tài nguyên sau khi phiên Phân phát theo nhóm hoàn tất. Gọi StreamManager.destroy()
để dừng phát nội dung phát trực tiếp, dừng tất cả hoạt động theo dõi quảng cáo và giải phóng tất cả các thành phần nội dung phát trực tiếp đã tải.
Để tìm hiểu về các tính năng nâng cao khác của SDK, hãy xem các hướng dẫn khác hoặc các mẫu trên GitHub.