ExoPlayer ใช้ได้กับการแทรกโฆษณาทั้งฝั่งไคลเอ็นต์และฝั่งเซิร์ฟเวอร์
การแทรกโฆษณาฝั่งไคลเอ็นต์
ในการแทรกโฆษณาฝั่งไคลเอ็นต์ โปรแกรมเล่นจะสลับระหว่างการโหลดสื่อจาก URL ที่ต่างกันขณะที่มีการเปลี่ยนระหว่างการเล่นเนื้อหาและโฆษณา ข้อมูล เกี่ยวกับโฆษณาจะโหลดแยกต่างหากจากสื่อ เช่น จาก VAST แบบ XML หรือ แท็กโฆษณา VMAP ซึ่งอาจรวมถึงตำแหน่งคิวโฆษณาที่สัมพันธ์กับจุดเริ่มต้นของ URL ของสื่อโฆษณาจริง และข้อมูลเมตา เช่น โฆษณาที่ระบุ ข้ามได้
เมื่อใช้ AdsMediaSource
ของ ExoPlayer สำหรับการแทรกโฆษณาฝั่งไคลเอ็นต์ โปรแกรมเล่น
มีข้อมูลเกี่ยวกับโฆษณาที่จะเล่น ซึ่งมีประโยชน์หลายประการดังนี้
- โปรแกรมเล่นจะแสดงข้อมูลเมตาและฟังก์ชันการทำงานที่เกี่ยวข้องกับโฆษณาโดยใช้ API ของโปรแกรมเล่น
- คอมโพเนนต์ UI ของ ExoPlayer สามารถแสดงเครื่องหมายสำหรับอันดับโฆษณาโดยอัตโนมัติ และเปลี่ยนแปลงลักษณะการทำงานโดยขึ้นอยู่กับว่าโฆษณากำลังเล่นหรือไม่
- จากภายใน โปรแกรมเล่นสามารถรักษาบัฟเฟอร์ให้สม่ำเสมอระหว่างการเปลี่ยน โฆษณาและเนื้อหา
ในการตั้งค่านี้ โปรแกรมเล่นจะดูแลการสลับระหว่างโฆษณาและเนื้อหา หมายความว่าแอปไม่ต้องดูแลการควบคุม โปรแกรมเล่นเบื้องหลัง/ที่ทำงานอยู่เบื้องหน้าสำหรับโฆษณาและเนื้อหา
เมื่อเตรียมวิดีโอเนื้อหาและแท็กโฆษณาเพื่อใช้กับการแทรกโฆษณาฝั่งไคลเอ็นต์ โฆษณาควรวางอยู่ในตัวอย่างการซิงค์ (คีย์เฟรม) ใน วิดีโอเนื้อหาเพื่อให้โปรแกรมเล่นสามารถเล่นเนื้อหาต่อได้อย่างราบรื่น
การรองรับโฆษณาแบบประกาศ
สามารถระบุ URI แท็กโฆษณาเมื่อสร้าง MediaItem
ดังนี้
Kotlin
val mediaItem = MediaItem.Builder() .setUri(videoUri) .setAdsConfiguration(MediaItem.AdsConfiguration.Builder(adTagUri).build()) .build()
Java
MediaItem mediaItem = new MediaItem.Builder() .setUri(videoUri) .setAdsConfiguration( new MediaItem.AdsConfiguration.Builder(adTagUri).build()) .build();
หากต้องการเปิดการสนับสนุนโปรแกรมเล่นสำหรับรายการสื่อที่ระบุแท็กโฆษณา คุณต้องดำเนินการต่อไปนี้
สร้างและแทรก DefaultMediaSourceFactory
ที่กำหนดค่าไว้ด้วย
AdsLoader.Provider
และ AdViewProvider
เมื่อสร้างโปรแกรมเล่น
Kotlin
val mediaSourceFactory: MediaSource.Factory = DefaultMediaSourceFactory(context).setLocalAdInsertionComponents(adsLoaderProvider, playerView) val player = ExoPlayer.Builder(context).setMediaSourceFactory(mediaSourceFactory).build()
Java
MediaSource.Factory mediaSourceFactory = new DefaultMediaSourceFactory(context) .setLocalAdInsertionComponents(adsLoaderProvider, /* adViewProvider= */ playerView); ExoPlayer player = new ExoPlayer.Builder(context).setMediaSourceFactory(mediaSourceFactory).build();
จากภายใน DefaultMediaSourceFactory
จะรวมแหล่งที่มาของสื่อเนื้อหาไว้ในไฟล์
AdsMediaSource
AdsMediaSource
จะได้รับ AdsLoader
จาก
AdsLoader.Provider
และใช้เพื่อแทรกโฆษณาตามที่กำหนดโดยโฆษณาของรายการสื่อ
แท็ก
PlayerView
ของ ExoPlayer จะใช้ AdViewProvider
ExoPlayer IMA
ไลบรารีมี AdsLoader
ที่ใช้งานง่าย ตามที่อธิบายไว้ด้านล่าง
เพลย์ลิสต์ที่มีโฆษณา
เมื่อเปิดเพลย์ลิสต์ที่มีรายการสื่อหลายรายการ ลักษณะการทำงานเริ่มต้นคือ เพื่อขอแท็กโฆษณาและจัดเก็บสถานะการเล่นโฆษณา 1 ครั้งต่อรหัสสื่อแต่ละรหัส ชุดค่าผสมของ URI เนื้อหา และ URI แท็กโฆษณา ซึ่งหมายความว่าผู้ใช้จะเห็นโฆษณาสำหรับ รายการสื่อทุกรายการที่มีโฆษณาซึ่งมีรหัสสื่อหรือ URI เนื้อหาที่แตกต่างกัน แม้ว่า URI แท็กโฆษณาตรงกัน หากมีรายการสื่อซ้ำกัน ผู้ใช้จะเห็น โฆษณาที่ตรงกันเพียงครั้งเดียว (สถานะการเล่นโฆษณาจะจัดเก็บว่าได้มีการโฆษณา เล่น ดังนั้นจึงถูกข้ามหลังจากเล่นครั้งแรก)
คุณปรับแต่งลักษณะการทำงานนี้ได้โดยการส่งผ่านตัวระบุโฆษณาที่ทึบแสง สถานะการเล่นโฆษณาสำหรับรายการสื่อหนึ่งๆ ถูกลิงก์ไว้ โดยอิงตามออบเจ็กต์ ความเท่าเทียม นี่คือตัวอย่างที่สถานะการเล่นโฆษณาลิงก์กับแท็กโฆษณา URI เท่านั้น ไม่ใช่ชุดค่าผสมของรหัสสื่อและ URI แท็กโฆษณา โดย ส่ง URI แท็กโฆษณาเป็นตัวระบุโฆษณา ผลที่ได้คือโฆษณาจะโหลดขึ้น เพียงครั้งเดียวเท่านั้น และผู้ใช้จะไม่เห็นโฆษณาในรายการที่ 2 เมื่อเล่น ตั้งแต่ต้นจนจบ
Kotlin
// Build the media items, passing the same ads identifier for both items, // which means they share ad playback state so ads play only once. val firstItem = MediaItem.Builder() .setUri(firstVideoUri) .setAdsConfiguration(MediaItem.AdsConfiguration.Builder(adTagUri).setAdsId(adTagUri).build()) .build() val secondItem = MediaItem.Builder() .setUri(secondVideoUri) .setAdsConfiguration(MediaItem.AdsConfiguration.Builder(adTagUri).setAdsId(adTagUri).build()) .build() player.addMediaItem(firstItem) player.addMediaItem(secondItem)
Java
// Build the media items, passing the same ads identifier for both items, // which means they share ad playback state so ads play only once. MediaItem firstItem = new MediaItem.Builder() .setUri(firstVideoUri) .setAdsConfiguration( new MediaItem.AdsConfiguration.Builder(adTagUri).setAdsId(adTagUri).build()) .build(); MediaItem secondItem = new MediaItem.Builder() .setUri(secondVideoUri) .setAdsConfiguration( new MediaItem.AdsConfiguration.Builder(adTagUri).setAdsId(adTagUri).build()) .build(); player.addMediaItem(firstItem); player.addMediaItem(secondItem);
ไลบรารี ExoPlayer IMA
ไลบรารี ExoPlayer IMA มี ImaAdsLoader
ซึ่งทำให้
ผสานรวมการแทรกโฆษณาฝั่งไคลเอ็นต์ในแอปของคุณ ซึ่งรวมฟังก์ชันการทำงานของ
IMA SDK ฝั่งไคลเอ็นต์เพื่อรองรับการแทรกโฆษณา VAST/VMAP สำหรับ
วิธีการใช้ไลบรารี รวมถึงวิธีจัดการพื้นหลัง
และเล่นต่อ โปรดดู README
แอปพลิเคชันสาธิตใช้ไลบรารี IMA และมีตัวอย่างหลายรายการ แท็กโฆษณา VAST/VMAP ในรายการตัวอย่าง
ข้อควรพิจารณาเกี่ยวกับ UI
PlayerView
ซ่อนตัวควบคุมการขนส่งระหว่างการเล่นโฆษณาโดย
แต่แอปสามารถเปิด/ปิดลักษณะการทำงานนี้ด้วยการเรียกใช้
setControllerHideDuringAds
IMA SDK จะแสดงมุมมองเพิ่มเติมที่ด้านบนของ
โปรแกรมเล่นขณะที่โฆษณากำลังเล่น (เช่น ลิงก์ "ข้อมูลเพิ่มเติม" และปุ่มข้าม
หากมี)
IMA SDK อาจรายงานว่าโฆษณาถูกบดบังโดยการดูที่ระบุโดยแอปพลิเคชันหรือไม่
ที่แสดงที่ด้านบนของโปรแกรมเล่น แอปที่ต้องวางซ้อนมุมมองที่
สิ่งที่จำเป็นสำหรับการควบคุมการเล่นต้องลงทะเบียนภาพเหล่านั้นกับ IMA SDK เพื่อให้
สามารถละเว้นจากการคำนวณการมองเห็นโฆษณาได้ เมื่อใช้ PlayerView
เป็น
AdViewProvider
ก็จะลงทะเบียนการวางซ้อนการควบคุมโดยอัตโนมัติ แอป
ที่ใช้ UI โปรแกรมเล่นแบบกำหนดเองจะต้องลงทะเบียนมุมมองแบบวางซ้อนโดยการแสดงผลจาก
AdViewProvider.getAdOverlayInfos
สำหรับข้อมูลเพิ่มเติมเกี่ยวกับมุมมองซ้อนทับ โปรดดูที่ เปิด Measurement ใน IMA SDK
โฆษณาที่แสดงร่วม
แท็กโฆษณาบางแท็กมีโฆษณาที่แสดงร่วมเพิ่มเติมที่แสดงใน "ช่อง" ได้ ใน
UI ของแอป สล็อตเหล่านี้ส่งผ่านได้
ImaAdsLoader.Builder.setCompanionAdSlots(slots)
สำหรับข้อมูลเพิ่มเติม โปรดดู
การเพิ่มโฆษณาที่แสดงร่วม
โฆษณาแบบสแตนด์อโลน
IMA SDK ออกแบบมาเพื่อแทรกโฆษณาลงในเนื้อหาสื่อ ไม่ใช่เพื่อการเล่น โฆษณาแบบสแตนด์อโลนด้วยตัวเอง จึงไม่รองรับการเล่นโฆษณาแบบสแตนด์อโลน ด้วยไลบรารี IMA เราขอแนะนำให้ใช้ SDK โฆษณาในอุปกรณ์เคลื่อนที่ของ Google แทน สำหรับกรณีการใช้งานนี้
การใช้ SDK โฆษณาของบุคคลที่สาม
หากคุณต้องโหลดโฆษณาผ่าน SDK โฆษณาของบุคคลที่สาม คุณควรตรวจสอบว่า
โมเดลนี้จะมีการผสานรวม ExoPlayer อยู่แล้ว หากไม่เป็นเช่นนั้น การใช้
AdsLoader
ที่รวม SDK โฆษณาของบุคคลที่สามเป็นวิธีที่แนะนำ
เนื่องจากมีประโยชน์ของ AdsMediaSource
ที่อธิบายไว้ข้างต้น
ImaAdsLoader
ทำหน้าที่เป็นตัวอย่างการใช้งาน
หรือจะใช้การรองรับเพลย์ลิสต์ของ ExoPlayer เพื่อสร้างเป็นลำดับก็ได้ ของโฆษณาและคลิปเนื้อหา
Kotlin
// A pre-roll ad. val preRollAd = MediaItem.fromUri(preRollAdUri) // The start of the content. val contentStart = MediaItem.Builder() .setUri(contentUri) .setClippingConfiguration(ClippingConfiguration.Builder().setEndPositionMs(120000).build()) .build() // A mid-roll ad. val midRollAd = MediaItem.fromUri(midRollAdUri) // The rest of the content val contentEnd = MediaItem.Builder() .setUri(contentUri) .setClippingConfiguration(ClippingConfiguration.Builder().setStartPositionMs(120000).build()) .build() // Build the playlist. player.addMediaItem(preRollAd) player.addMediaItem(contentStart) player.addMediaItem(midRollAd) player.addMediaItem(contentEnd)
Java
// A pre-roll ad. MediaItem preRollAd = MediaItem.fromUri(preRollAdUri); // The start of the content. MediaItem contentStart = new MediaItem.Builder() .setUri(contentUri) .setClippingConfiguration( new ClippingConfiguration.Builder().setEndPositionMs(120_000).build()) .build(); // A mid-roll ad. MediaItem midRollAd = MediaItem.fromUri(midRollAdUri); // The rest of the content MediaItem contentEnd = new MediaItem.Builder() .setUri(contentUri) .setClippingConfiguration( new ClippingConfiguration.Builder().setStartPositionMs(120_000).build()) .build(); // Build the playlist. player.addMediaItem(preRollAd); player.addMediaItem(contentStart); player.addMediaItem(midRollAd); player.addMediaItem(contentEnd);
การแทรกโฆษณาฝั่งเซิร์ฟเวอร์
ในการแทรกโฆษณาฝั่งเซิร์ฟเวอร์ (หรือที่เรียกว่าการแทรกโฆษณาแบบไดนามิกหรือ DAI) แอตทริบิวต์ สตรีมสื่อมีทั้งโฆษณาและเนื้อหา ไฟล์ Manifest สำหรับ DASH อาจชี้ไปยัง เนื้อหาและกลุ่มโฆษณา อาจอยู่ในช่วงเวลาที่แตกต่างกัน สำหรับ HLS โปรดดูที่ Apple ซึ่งเป็นเอกสารเกี่ยวกับการรวมโฆษณาไว้ในเพลย์ลิสต์
เมื่อใช้การแทรกโฆษณาฝั่งเซิร์ฟเวอร์ ลูกค้าอาจต้องแก้ไขสื่อ URL แบบไดนามิกเพื่อรับสตรีมที่ต่อกัน อาจต้องแสดงโฆษณาซ้อนทับ ใน UI หรืออาจต้องรายงานเหตุการณ์ไปยัง SDK โฆษณาหรือเซิร์ฟเวอร์โฆษณา
DefaultMediaSourceFactory
ของ ExoPlayer จะมอบสิทธิ์งานทั้งหมดนี้ให้กับ
การแทรกโฆษณาฝั่งเซิร์ฟเวอร์ MediaSource
สำหรับ URI ที่ใช้รูปแบบ ssai://
Kotlin
val player = ExoPlayer.Builder(context) .setMediaSourceFactory( DefaultMediaSourceFactory(context).setServerSideAdInsertionMediaSourceFactory(ssaiFactory) ) .build()
Java
Player player = new ExoPlayer.Builder(context) .setMediaSourceFactory( new DefaultMediaSourceFactory(context) .setServerSideAdInsertionMediaSourceFactory(ssaiFactory)) .build();
ไลบรารี ExoPlayer IMA
ไลบรารี ExoPlayer IMA มีค่า ImaServerSideAdInsertionMediaSource
ซึ่งช่วยให้ง่ายต่อการผสานรวมกับสตรีมโฆษณาที่แทรกฝั่งเซิร์ฟเวอร์ของ IMA ใน
แอป ซึ่งรวมฟังก์ชันการทำงานของ IMA DAI SDK สำหรับ Android และ
ผสานรวมข้อมูลเมตาของโฆษณาที่ให้ไว้ลงในโปรแกรมเล่น ตัวอย่างเช่น วิธีนี้ทำให้
คุณใช้วิธีการอย่างเช่น Player.isPlayingAd()
ฟังการเปลี่ยนภาพแบบโฆษณาเนื้อหา
และให้โปรแกรมเล่นจัดการตรรกะการเล่นโฆษณา เช่น ข้ามโฆษณาที่เล่นไปแล้ว
หากต้องการใช้ชั้นเรียนนี้ คุณต้องตั้งค่า
ImaServerSideAdInsertionMediaSource.AdsLoader
และ
ImaServerSideAdInsertionMediaSource.Factory
และเชื่อมต่อนาฬิกากับโปรแกรมเล่น โดยทำดังนี้
Kotlin
// MediaSource.Factory to load the actual media stream. val defaultMediaSourceFactory = DefaultMediaSourceFactory(context) // AdsLoader that can be reused for multiple playbacks. val adsLoader = ImaServerSideAdInsertionMediaSource.AdsLoader.Builder(context, adViewProvider).build() // MediaSource.Factory to create the ad sources for the current player. val adsMediaSourceFactory = ImaServerSideAdInsertionMediaSource.Factory(adsLoader, defaultMediaSourceFactory) // Configure DefaultMediaSourceFactory to create both IMA DAI sources and // regular media sources. If you just play IMA DAI streams, you can also use // adsMediaSourceFactory directly. defaultMediaSourceFactory.setServerSideAdInsertionMediaSourceFactory(adsMediaSourceFactory) // Set the MediaSource.Factory on the Player. val player = ExoPlayer.Builder(context).setMediaSourceFactory(defaultMediaSourceFactory).build() // Set the player on the AdsLoader adsLoader.setPlayer(player)
Java
// MediaSource.Factory to load the actual media stream. DefaultMediaSourceFactory defaultMediaSourceFactory = new DefaultMediaSourceFactory(context); // AdsLoader that can be reused for multiple playbacks. ImaServerSideAdInsertionMediaSource.AdsLoader adsLoader = new ImaServerSideAdInsertionMediaSource.AdsLoader.Builder(context, adViewProvider).build(); // MediaSource.Factory to create the ad sources for the current player. ImaServerSideAdInsertionMediaSource.Factory adsMediaSourceFactory = new ImaServerSideAdInsertionMediaSource.Factory(adsLoader, defaultMediaSourceFactory); // Configure DefaultMediaSourceFactory to create both IMA DAI sources and // regular media sources. If you just play IMA DAI streams, you can also use // adsMediaSourceFactory directly. defaultMediaSourceFactory.setServerSideAdInsertionMediaSourceFactory(adsMediaSourceFactory); // Set the MediaSource.Factory on the Player. Player player = new ExoPlayer.Builder(context).setMediaSourceFactory(defaultMediaSourceFactory).build(); // Set the player on the AdsLoader adsLoader.setPlayer(player);
โหลดคีย์เนื้อหา IMA หรือรหัสแหล่งที่มาของเนื้อหาและรหัสวิดีโอโดยการสร้าง URL
ด้วย ImaServerSideAdInsertionUriBuilder
:
Kotlin
val ssaiUri = ImaServerSideAdInsertionUriBuilder() .setAssetKey(assetKey) .setFormat(C.CONTENT_TYPE_HLS) .build() player.setMediaItem(MediaItem.fromUri(ssaiUri))
Java
Uri ssaiUri = new ImaServerSideAdInsertionUriBuilder() .setAssetKey(assetKey) .setFormat(C.CONTENT_TYPE_HLS) .build(); player.setMediaItem(MediaItem.fromUri(ssaiUri));
สุดท้าย ปล่อยตัวโหลดโฆษณาเมื่อไม่ได้ใช้งานแล้ว โดยทำดังนี้
Kotlin
adsLoader.release()
Java
adsLoader.release();
ข้อควรพิจารณาเกี่ยวกับ UI
ข้อควรพิจารณาเกี่ยวกับ UI แบบเดียวกับการแทรกโฆษณาฝั่งไคลเอ็นต์ ใช้บังคับกับ การแทรกโฆษณาฝั่งเซิร์ฟเวอร์ด้วย
โฆษณาที่แสดงร่วม
แท็กโฆษณาบางแท็กมีโฆษณาที่แสดงร่วมเพิ่มเติมที่แสดงใน "ช่อง" ได้ ใน
UI ของแอป สล็อตเหล่านี้ส่งผ่านได้
ImaServerSideAdInsertionMediaSource.AdsLoader.Builder.setCompanionAdSlots(slots)
ดูข้อมูลเพิ่มเติมได้ที่การเพิ่มโฆษณาที่แสดงร่วม
การใช้ SDK โฆษณาของบุคคลที่สาม
หากคุณต้องโหลดโฆษณาโดยใช้ SDK โฆษณาของบุคคลที่สาม คุณควรตรวจสอบว่า
โมเดลนี้จะมีการผสานรวม ExoPlayer อยู่แล้ว หากไม่ ขอแนะนำให้
ระบุ MediaSource
ที่กำหนดเองซึ่งยอมรับ URI ที่มีรูปแบบ ssai://
คล้ายกับ ImaServerSideAdInsertionMediaSource
ตรรกะที่แท้จริงของการสร้างโครงสร้างโฆษณาสามารถมอบให้กับ
วัตถุประสงค์ ServerSideAdInsertionMediaSource
ซึ่งรวมสตรีม MediaSource
แล้วให้ผู้ใช้ตั้งค่าและอัปเดต AdPlaybackState
ที่แสดงโฆษณา
ข้อมูลเมตา
สตรีมโฆษณาที่แทรกฝั่งเซิร์ฟเวอร์มักมีกิจกรรมตามกำหนดเวลาเพื่อแจ้งเตือนโปรแกรมเล่น
เกี่ยวกับข้อมูลเมตาของโฆษณา โปรดดูรูปแบบที่รองรับเพื่อดูข้อมูลเกี่ยวกับ
ExoPlayer รองรับรูปแบบข้อมูลเมตาที่มีกำหนดเวลา SDK โฆษณาที่กำหนดเอง MediaSource
การติดตั้งใช้งานจะเฝ้าติดตามเหตุการณ์ข้อมูลเมตาที่มีกำหนดเวลาจากโปรแกรมเล่นได้โดยใช้
Player.Listener.onMetadata