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

Can I play ads in the period of #6527

Closed
cle-bo opened this issue Oct 10, 2019 · 7 comments
Closed

Can I play ads in the period of #6527

cle-bo opened this issue Oct 10, 2019 · 7 comments
Assignees
Labels

Comments

@cle-bo
Copy link

cle-bo commented Oct 10, 2019

Hello and thanks for your time...

The required fields are below, but here's a short introduction:

I started to develop a new app - I have to admit that I am new to android app and exoplayer but have experience as a java developer - for an android TV-Box (beelink GT1) that downloads media to a SD Card (short videos of 2 to 10 minutes in length), plays it 24/7 and the playback is interrupted every 10 minutes to play a sequence of adverts no matter what media source is currently playing or at what position the currently played media source is at. It just keeps spamming adverts in a defined rhythm. Streaming the media is not an option since I have to deal with different bandwidths at the different box locations and sometimes even offline operating boxes (therefore the idea to download the media and saving it to the external storage before/while playing it).

My first idea was to create a ConcatenatingMediaSource and take this "playlist" as "contentMediaSource" parameter for my AdsMediaSource. But this lead to the following error:

 E/AndroidRuntime: FATAL EXCEPTION: ExoPlayerImplInternal:Handler
     Process: com.airtango.lpsplayer, PID: 8711
     java.lang.IllegalArgumentException
         at com.google.android.exoplayer2.util.Assertions.checkArgument(Assertions.java:39)
         at com.google.android.exoplayer2.source.ads.AdsMediaSource.onContentSourceInfoRefreshed(AdsMediaSource.java:329)
         at com.google.android.exoplayer2.source.ads.AdsMediaSource.onChildSourceInfoRefreshed(AdsMediaSource.java:303)
         at com.google.android.exoplayer2.source.ads.AdsMediaSource.onChildSourceInfoRefreshed(AdsMediaSource.java:55)
         at com.google.android.exoplayer2.source.CompositeMediaSource.lambda$prepareChildSource$0$CompositeMediaSource(CompositeMediaSource.java:97)
         at com.google.android.exoplayer2.source.-$$Lambda$CompositeMediaSource$ahAPO18YbnzL6kKRAWdp4FR_Vco.onSourceInfoRefreshed(lambda)
         at com.google.android.exoplayer2.source.BaseMediaSource.refreshSourceInfo(BaseMediaSource.java:74)
         at com.google.android.exoplayer2.source.ConcatenatingMediaSource.updateTimelineAndScheduleOnCompletionActions(ConcatenatingMediaSource.java:705)
         at com.google.android.exoplayer2.source.ConcatenatingMediaSource.handleMessage(ConcatenatingMediaSource.java:675)
         at com.google.android.exoplayer2.source.ConcatenatingMediaSource.lambda$fl0myfoK2raBckmHYwV9YTd0eeo(ConcatenatingMediaSource.java)
         at com.google.android.exoplayer2.source.-$$Lambda$ConcatenatingMediaSource$fl0myfoK2raBckmHYwV9YTd0eeo.handleMessage(lambda)
         at android.os.Handler.dispatchMessage(Handler.java:98)
         at android.os.Looper.loop(Looper.java:154)
         at android.os.HandlerThread.run(HandlerThread.java:61)

Google searches brought me to the issue 3750 saying that I ...

... can't compose it with other media sources as ImaAdsLoader's logic makes assumptions about the player timeline when it handles player events, and these assumptions may be incorrect if the player is actually playing a concatenation.

My case is a bit different though and here I am asking the question...

[REQUIRED] Searched documentation and issues

[REQUIRED] Question

How can I play a series of short video clips of content media in a everlasting loop - I can do that already with ConcatenatingMediaSource and player.setRepeatMode(..) , but now comes the point where I struggle - and interrupt the playback with ads every 5 minutes?

So basically I want my playlist to be interrupted with ads and not the single clips the playlist is built on. I tried my best to explain my situation and I am happy to answer any questions you may have to understand and maybe help me with my problem.

Thanks alreay!
Cheers, Clement

@christosts
Copy link
Contributor

Hi @cle-bo

With regards to the question

How can I play a series of short video clips of content media in a everlasting loop - I can do that already with ConcatenatingMediaSource and player.setRepeatMode(..) , but now comes the point where I struggle - and interrupt the playback with ads every 5 minutes?

my understanding is that you have a predefined list of items and want to play an ad at predefined 5 minute intervals. You may achieve this by concatenating a series of ClippingMediaSources for the main content and regular media sources for your ad content:

  • use a ClippingMediaSource to play a specified range of a media source, e.g. the first 5 minutes
  • concatenate a MediaSource for your ad - treat the ad as regular content, don't use the AdsMediaSource
  • concatenate the next 5 minutes of the main content with a ClippingMediaSource that plays from the 5th minute until the 10th minute
  • and so on

There are two caveats here:

  • by treating ads as regular content, you will not get the ad markers on the progress bar on the UI
  • to be able to clip your content at 5 minute intervals, you need to ensure that each clip begins at a key frame so that transitions are seamless. Otherwise, you will need to adjust your intervals so that the main content is clipped just before a key frame, or you will not have seamless transitions between your ad and main content

@google-oss-bot
Copy link
Collaborator

Hey @cle-bo. We need more information to resolve this issue but there hasn't been an update in 14 days. I'm marking the issue as stale and if there are no new updates in the next 7 days I will close it automatically.

If you have more information that will help us get to the bottom of this, just add a comment!

@cle-bo
Copy link
Author

cle-bo commented Oct 30, 2019

Hey @christosts thanks a lot! I followed the idea of treating the ads as regular content and that was a big step in the right direction I think.
But since I have to schedule 24 hours with clipped media sources and ads as regular media sources in a playlist I came to the conclusion that this is too static. So I tried to have two player and one player view. In one player, the content player, I play the content 24/7 and whenever I want to play an ad I pause the content player, set the ad player as the player of the view and play it. when the ad has ended I do the opposite.
Can you tell me if the two-player-instances-approach is reasonable or maybe even a "NO-GO!!"? Are there things I should specificly be on the watch for with this design?
Thanks again and have a good day,
Clement

@christosts
Copy link
Contributor

There are many possibilities that a two-players approach will not work (more details in this issue). In short, two players will try to acquire two sets of codecs from the system which is not guaranteed to work. I would not recommend it (more reasons explained below).

When you say that the concatenating media source solution is too static, is it because you think you are adding too many items to the concatenating media source upfront before playback starts? If yes, please note you can add items to a ConcatenatingMediaSource in real-time, after playback has begun, please see the ConcatenatingMediaSource.addMediaSource() function.

Coming back to the two-player solution, here are some further considerations you need to take into account. It is possible that two players might work either because the device supports multiple codecs or the main content and ad content are encoded with different codecs.

  1. Transition between main content and ad may not be smooth: When the app is playing main content and is about to switch to the ad, if you call prepare() on the second player at that point, the second player will require some time to download sufficient amount of video before playback begins. There will be some idle time in between switches.

  2. The app might try to warm-up the second player to avoid the idle time between switches. For example, 30 seconds before switching to the ad, the app calls setPlayWhenReady(false) and then prepare() on the second player so that it starts pre-fetching data. If that works, the second player will start pre-fetching data in addition to the first player's data that are already loaded in memory. There will be an increase in memory usage.

  3. To avoid the memory increase, the app will need to stop and release the player that is currently playing content between every switch. In that scenario, there will be idle time between every switch, from main content to ad and from ad to main content.

If you still believe the ConcatenatingMediaSource is not suitable for your needs, and want to switch between contents, you may want to implement your own AdsLoader as described in this issue (see comment no 4), which will have 1 instance of the ExoPlayer handling the pre-fetching of data, minimizing idle time bnetween switches and memory usage.

@tonihei
Copy link
Collaborator

tonihei commented Oct 30, 2019

But since I have to schedule 24 hours with clipped media sources and ads as regular media sources in a playlist I came to the conclusion that this is too static.

This problem will also be simplified when the final version of #3163 is released. This will allow you to update the clipping dynamically:

start playback with:

ClippingMediaSource(
  liveStream,
 /* from default */ C.TIME_UNSET, 
 /* no end specified */ C.TIME_END_OF_SOURCE)

as soon as you know the position of an ad break:

ClippingMediaSource.updateClipping(
   /* from default */ C.TIME_UNSET, /* to */ adBreakPos)
ConcatenatingMediaSource.addMediaSource(adMediaSource)
ConcatenatingMediaSource.addMediaSource(
  new ClippingMediaSource(livestream,
     /* from */ adBreakPos (or default again),
     /* to */ C.TIME_END_OF_SOURCE)

And once the ad is finished, you can remove the previous part of the playlist by calling
ConcatenatingMediaSource.removeMediaSource(...).

The feature tracked by #3163 will add the missing updateClipping method.

@cle-bo
Copy link
Author

cle-bo commented Nov 4, 2019

thanks @tonihei , I will be keeping this in mind!
And @christosts as an update on the 2 player instances approach: To my understanding from the issue you linked there may be problems with certain devices and video formats when working with more than one player instance. Yet I am in total control of the devices the app is installed on (beelink gt1 mini, android sdk 25) and the videos that are being played (mp4, H.264) so I should be fine, right?
So far the tests are positive and the changing of the "active" player works smoothly.

@christosts
Copy link
Contributor

christosts commented Nov 5, 2019

@cle-bo it sounds like you have a very controlled environment. Please make sure to re-test anytime you change a parameter on your setup (video/audio formats, device firmware and/or android version).

Closing this as it seems the issue at hand has been answered.

@ojw28 ojw28 removed the needs triage label Dec 5, 2019
@google google locked and limited conversation to collaborators Jan 5, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

No branches or pull requests

5 participants