Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow client-side preroll ads with SSAI (DAI) stream #571

Open
devno44 opened this issue Aug 9, 2023 · 10 comments
Open

Allow client-side preroll ads with SSAI (DAI) stream #571

devno44 opened this issue Aug 9, 2023 · 10 comments
Assignees

Comments

@devno44
Copy link

devno44 commented Aug 9, 2023

Hello,

I have a live content that need have to play both of Pre-Roll and Mid-Roll.
So I have a question, How can I implement Pre-Roll and Mid-Roll at the same Player ?
If possible, can you provide an example for the implementation ?

For SSAI, I want to use ImaServerSideAdInsertionMediaSource

The version of ExoPlayer that I am using is ExoPlayer 2.18.3.
Streaming protocol is HLS.

Thank you

@devno44
Copy link
Author

devno44 commented Aug 10, 2023

Looks like ImaServerSideAdInsertionMediaSource doesn't support for CSAI right now.

Although I did as below but no success. There is no Pre-Roll is played. Just Mid-Roll.

     ....
     val adsTagUrl = "https://pubads.g.doubleclick.net/..."

      val contentUri = ImaServerSideAdInsertionUriBuilder()
            .setAssetKey(assetKey)
            .setFormat(C.CONTENT_TYPE_HLS) 
            .setAdTagParameters(adTags)
            .build()

       val mediaItem = MediaItem.Builder()
            .setUri(contentUri)
            .setAdsConfiguration(MediaItem.AdsConfiguration.Builder(Uri.parse(adsTagUrl)).build())

      player.setMediaItem(mediaItem.build())
      player.prepare()
      ....

@tonihei
Copy link
Collaborator

tonihei commented Aug 10, 2023

@devno44 For client-side ad insertion, please use AdsMediaSource with ImaAdsLoader as explained here: https://developer.android.com/guide/topics/media/exoplayer/ad-insertion#client-side_ad_insertion

@devno44
Copy link
Author

devno44 commented Aug 17, 2023

@tonihei
Thank you for your reply.
But I mean, my live content have both of Pre-Roll and Mid-Roll. And I want to play them on the same live content.
For example: Pre-Roll from the Ad tag url, and Mid-Roll from Google DAI.
I tried follow the way bellow, but its not working. The player can play Mid-Roll only.

     ....
     val adsTagUrl = "https://pubads.g.doubleclick.net/..."

      val contentUri = ImaServerSideAdInsertionUriBuilder()
            .setAssetKey(assetKey)
            .setFormat(C.CONTENT_TYPE_HLS) 
            .setAdTagParameters(adTags)
            .build()

       val mediaItem = MediaItem.Builder()
            .setUri(contentUri)
            .setAdsConfiguration(MediaItem.AdsConfiguration.Builder(Uri.parse(adsTagUrl)).build())

      player.setMediaItem(mediaItem.build())
      player.prepare()
      ....

Not only for client-side ad insertion or server-side ad insertion.

Is there any way to do it ? Thank you !

@tonihei
Copy link
Collaborator

tonihei commented Aug 22, 2023

Pre-Roll from the Ad tag url, and Mid-Roll from Google DAI.

Do I understand the problem correctly that you'd like to combined client-side ad insertion for the preroll with server-side ad insertion for the main stream?

So that the result looks something like:

[ pre-roll from CSAI adTagUrl ][[ live stream ... [ mid-roll from DAI ] ... live stream ... ]

Is this correct? If so, this is currently unsupported because our client-side AdsMediaSource does not expect the underlying stream to already have ads defined. I can mark as an enhancement to track support for this feature. Please let me know if I misunderstood the question though.

@tonihei tonihei changed the title [Question] How can implement Pre-Roll and Mid-Roll at the same player Allow client-side preroll ads with SSAI (DAI) stream Aug 22, 2023
@devno44
Copy link
Author

devno44 commented Aug 23, 2023

@tonihei
Thank for your reply.
Yes, exactly what you said. I mean I want to do something like bellow (as you said).
[ pre-roll from CSAI adTagUrl ][[ live stream ... [ mid-roll from DAI ] ... live stream ... ]

Please add this feature.

Thank you so much.

@tonihei
Copy link
Collaborator

tonihei commented Aug 23, 2023

There is a workaround where you add the pre-roll with a media item with 0 duration and the DAI source as different items in a playlist. Generating this empty source for the preroll requires you to use AdsMediaSource directly though:

player.addMediaSource(
    new AdsMediaSource(
        new SilenceMediaSource(/* durationUs= */ 0),
        new DataSpec(adTagUri),
        /* adsId= */ "preroll",
        new DefaultMediaSourceFactory(context),
        adsLoader,
        adViewProvider));
player.addMediaItem(daiMediaItem);

This should work for HLS streams already, but we discovered a bug for multi-period DASH that needs to be fixed first. Once the fix is in, this workaround also works for DASH streams.

@devno44
Copy link
Author

devno44 commented Aug 24, 2023

@tonihei
Thank you.
But I tried follow this way, but still there is no Pre-Roll. Just Mid-Roll is showed.
Im using HLS stream.

Can you please check if is there something wrong on my implementation ?

....
     val adsTagUrl = "https://pubads.g.doubleclick.net/..."

      val contentUri = ImaServerSideAdInsertionUriBuilder()
            .setAssetKey(assetKey)
            .setFormat(C.CONTENT_TYPE_HLS) 
            .setAdTagParameters(adTags)
            .build()

       val mediaItem = MediaItem.Builder()
            .setUri(contentUri)
            //.setAdsConfiguration(MediaItem.AdsConfiguration.Builder(Uri.parse(adsTagUrl)).build())

           (adsLoader as? AdsLoader)?.let { adLoader ->
                    (player as? ExoPlayer)?.addMediaSource(
                        AdsMediaSource(
                            SilenceMediaSource(/* durationUs = */ 0),
                            DataSpec(Uri.parse(adsTagUrl)),
                            /* adsId = */ "preroll",
                            DefaultMediaSourceFactory(context),
                            adLoader,
                           /* adViewProvider = */ playerView
                        )
                    )
                }

      player.setMediaItem(mediaItem.build())
      player.prepare()
      ....

@tonihei
Copy link
Collaborator

tonihei commented Aug 24, 2023

I think the second item should use addMediaItem, because setMediaItem overrides the entire playlist.

@devno44
Copy link
Author

devno44 commented Aug 25, 2023

@tonihei I tried to use addMediaItem instead of setMediaItem. But still there is no pre-roll is displayed.
And I checked on VAST side too, and there is no problem on VAST.

@tonihei
Copy link
Collaborator

tonihei commented Aug 25, 2023

This works without issues in the demo app. You should probably check the pre-roll AdsMediaSource on its own to see if it works and try out your streams in the demo app. If you think there is a bug, please provide more details about your actual strreams, so we can reproduce the issue. (You can send links to [email protected] with "Issue #571" in the subject if needed).

copybara-service bot pushed a commit that referenced this issue Aug 25, 2023
The period index was calculated relative to the contentTimeline
of the DAI stream, but then used with the full timeline of the
player. This means it currently only works when the stream is the
only or first item in the playlist.

Issue: #571
PiperOrigin-RevId: 560023412
copybara-service bot pushed a commit to google/ExoPlayer that referenced this issue Aug 25, 2023
The period index was calculated relative to the contentTimeline
of the DAI stream, but then used with the full timeline of the
player. This means it currently only works when the stream is the
only or first item in the playlist.

Issue: androidx/media#571
PiperOrigin-RevId: 560023412
microkatz pushed a commit to hugohlln/media that referenced this issue Sep 29, 2023
The period index was calculated relative to the contentTimeline
of the DAI stream, but then used with the full timeline of the
player. This means it currently only works when the stream is the
only or first item in the playlist.

Issue: androidx#571
PiperOrigin-RevId: 560023412
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants