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

How to add Timed Events to Exoplayer2 #2189

Closed
trckashyap opened this issue Dec 13, 2016 · 20 comments
Closed

How to add Timed Events to Exoplayer2 #2189

trckashyap opened this issue Dec 13, 2016 · 20 comments
Assignees

Comments

@trckashyap
Copy link

Hi,
Need API to add timed events to Exoplayer2
I have 3 events in a video of duration (03:00), I need to get timed event when the time stamp crosses(00:45, 01:50 & 02:30). What should be done to add these events.

Thanks And Regards,
Kashyap Tadikonda

@ojw28 ojw28 added the question label Dec 13, 2016
@trckashyap
Copy link
Author

I have captionslist where each caption contains title, startTime & endTime. how to add these to Exoplayer/embed to subtitle view.
Similarly I have slide events to display slides.

Please help in integrating them to Exoplayer and I need to get time event.

@ojw28
Copy link
Contributor

ojw28 commented Jan 30, 2017

What format are the subtitles provided in? If they're in a standard subtitle format that we support, you can just use ExoPlayer's built in subtitle support.

@ojw28 ojw28 added enhancement and removed question labels Apr 6, 2017
@ojw28
Copy link
Contributor

ojw28 commented Apr 6, 2017

Marking this as a general enhancement to support triggers are certain positions in the media. It's unclear whether that's really what the original poster wants, but request was never clarified.

@mapsver
Copy link

mapsver commented Nov 22, 2017

do u know if is this being worked on for an upcoming release ?

@tonihei
Copy link
Collaborator

tonihei commented Nov 23, 2017

It's being worked on. But not for the upcoming 2.6 release. More likely the next one.

@mapsver
Copy link

mapsver commented Nov 27, 2017

Thank you ! Meanwhile, Is there an example that uses a custom renderer for this purpose (or something similar). I couldn't find anything relevant online or in the demo (could only find usage of SimpleExoPlayer)

@tonihei
Copy link
Collaborator

tonihei commented Nov 28, 2017

While working on this feature, we came across some edge cases where it's unclear how the new feature should work:

  • What happens when the player plays the same position twice (e.g. when repeating, or after seeking back). Should the event be fired again or only once?
  • What happens when the player seeks to a position behind the callback position. Should the event still be triggered or only when the playback naturally progresses over the callback position.
  • Should the event be triggered on an app callback thread (slower, but does not block playback) or on the internal playback thread (direct, but blocks playback)?

Please let us know which version would fit your requirements best.

@mapsver
Copy link

mapsver commented Nov 29, 2017

Im not the OP.. but Ill add my 2cents worth.

What happens when the player plays the same position twice (e.g. when repeating, or after seeking back). Should the event be fired again or only once?
The event should be fired every time it hits that position. Having the event fire only the first time would be a special case, for which the observer can always write logic to check and ignore. Depending on how its implemented, the logic can be to unregister the event listener after the first time.

What happens when the player seeks to a position behind the callback position. Should the event still be triggered or only when the playback naturally progresses over the callback position.
The event should only trigger during forward playback (either in original speed or otherwise), but not when seeking forward or backward past the event position.

Should the event be triggered on an app callback thread (slower, but does not block playback) or on the internal playback thread (direct, but blocks playback)?
My preference would be on an separate thread. With this approach, blocking/allowing playback to continue is controlled by the caller.

Sorry to bug.. but like Id asked earlier, is there an example that uses a custom renderer that I can use to workaround this.

@andrewlewis
Copy link
Collaborator

@mapsver One way to do this is to subclass NoSampleRenderer and return it from a custom RenderersFactory which you pass to newSimpleInstance. There are a few things to be aware of:

  • You can access the player's internal position in the render method of your custom renderer, but please note that this value will be offset by the last value passed to the onRendererOffsetChanged, so you'll need to override that method too to keep track of the offset, then subtract it in render.
  • After subtracting the offset you'll get a period position in microseconds, rather than a window position in milliseconds which is what's exposed by player.getCurrentPosition. Read the documentation of Timeline for more information.
  • render is called on the player's internal thread, so you may need to communicate with another thread that actually handles the event. It's important not to block the player's internal thread.

@mapsver
Copy link

mapsver commented Nov 30, 2017

thank you.. will try it out this weekend !

@damienoliver
Copy link

Thanks for addressing this.

I have created a time renderer track to get around this in the past.

In regards to your edge cases, I agree with @mapsver that the event should fire every time in forwards playback at normal speed only (no seek over events). But it would be good to have an option to call this on the direct thread for scenarios in which the latency is critical.

@tonihei
Copy link
Collaborator

tonihei commented Dec 19, 2017

Thanks for your opinions on that matter. We now finished implementing an updated version of player.sendMessages where you can specify additional options like the delivery media time, the delivery handler, and whether the message should be deleted after delivery (or repeated if the position is reached again). It can be used like that:

player.createMessage(target)
  .setPosition(/* playbackPositionInMs= */ 500)
  .setHandler(appHandler)
  .send();

The change will be available on the dev branch soon.

@tonihei tonihei self-assigned this Jan 2, 2018
ojw28 pushed a commit that referenced this issue Jan 3, 2018
This adds options to ExoPlayer.sendMessages which allow to specify a window index
and position at which the message should be sent. Additionally, the options can be
configured to use a custom Handler for the messages and whether the message should
be repeated when playback reaches the same position again.

The internal player converts these window positions to period index and position
at the earliest possibility. The internal player also attempts to update these
when the source info is refreshed. A sorted list of pending posts is kept and the
player triggers these posts when the playback position moves over the specified
position.

Issue:#2189

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=179563355
ojw28 pushed a commit that referenced this issue Jan 3, 2018
This adds options to ExoPlayer.sendMessages which allow to specify a window index
and position at which the message should be sent. Additionally, the options can be
configured to use a custom Handler for the messages and whether the message should
be repeated when playback reaches the same position again.

The internal player converts these window positions to period index and position
at the earliest possibility. The internal player also attempts to update these
when the source info is refreshed. A sorted list of pending posts is kept and the
player triggers these posts when the playback position moves over the specified
position.

Issue:#2189

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=179683841
@ojw28
Copy link
Contributor

ojw28 commented Jan 3, 2018

This functionality is now available to try in the dev-v2 branch.

@tonihei tonihei closed this as completed Jan 3, 2018
@JesusMartinAlonso
Copy link

@tonihei Could you provide an example of this new feature with SimpleExoPlayer? I would like to add a timed event, but I don't know what argument pass to createMessage function (target argument), because I don't have access to video renderers.

This is how I'm creating my ExoPlayer in my Activity:

        player = ExoPlayerFactory.newSimpleInstance(this, DefaultTrackSelector())
        //PlayerView: SimpleExoPlayerView view in XML layout
        playerView.player = player
        playerView.useController = false


        val dataSource = ExtractorMediaSource.Factory{
            AssetDataSource(this)
        }

        
        val video = dataSource.createMediaSource(Uri.parse("assets:///Videos/test.mp4"))
        player.prepare(video)
        

And I want to add a handler when test.mp4 video reach 1500ms. Something like that:

player.createMessage(/*What to put here?*/)
  .setPosition(1500)
  .setHandler(/*?*/)
  .send();

Any suggestion and clarification will be very helpful!

Thank you a lot

@tonihei
Copy link
Collaborator

tonihei commented Feb 26, 2018

@JesusMartinAlonso You can provide your own message target in there to receive the message at the specified time (see interface here).

For example:

player.createMessage(new Target() {
     @Override
     void handleMessage(int messageType, Object payload) throws ExoPlaybackException {
       /* Do something at time 1500. */
     }
   })
  .setPosition(1500)
  .setHandler(new Handler())
  .send();

@JesusMartinAlonso
Copy link

Thank you for your super fast response @tonihei !! It works like a charm! :)

@knowamit
Copy link

@tonihei
player.createMessage(new Target() { @Override void handleMessage(int messageType, Object payload) throws ExoPlaybackException { /* Do something at time 1500. */ } }) .setPosition(1500) .setHandler(new Handler()) .send();

is not available in compile 'com.google.android.exoplayer:exoplayer:2.7.1'

@tonihei
Copy link
Collaborator

tonihei commented Mar 28, 2018

@amitsharma492 It is there, see here and here.

@knowamit
Copy link

@tonihei but I am using SimpleExoPlayer can you tell me how can implement in SimpleExoPlayer

@tonihei
Copy link
Collaborator

tonihei commented Mar 28, 2018

SimpleExoPlayer implements the ExoPlayer interface. That means you should be able to use createMessage.

@google google locked and limited conversation to collaborators May 9, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

8 participants