I need to set duration of a video for a thumbnail to 5 seconds and loop it. I got the loop part, but I can't find documentation for setting specific duration
I tried exoPlayer.seek(duration) but that didn't work
You may use ClippingMediaSource:
ClippingMediaSource​(MediaSource mediaSource, long startPositionUs, long endPositionUs)
Creates a new clipping source that wraps the specified source and provides samples between the specified start and end position.
You can convert to have a new media source and set this new media source for your ExoPlayer:
// Create a new media source with your specified period
val newMediaSource = ClippingMediaSource(mediaSource, 0, 5_000_000)
Related
I am designing an android video editor app and one of the feature is to trim video, selected from gallery. I can give an option to select the range using the RangeSlider, displayed at the bottom of the VideoView, to the user and then use FFMPEG library to trim the video.
But i am not able to show the progress of the video being played, within the selected range, on the RangeSlider.
Not sure if i am approaching properly, hence please provide me a solution to achieve this.
When you change the bounds of the RangeSlider, you need to calculate the startTime and endTime of the video. Once you are able to calculate the startTime and endTime, you need to create a ClippingMediaSource instance.
public ClippingMediaSource(MediaSource mediaSource, long startPositionUs, long endPositionUs)
ClippingMediaSource takes three paramters:
MediaSource
startPositionUs
endPositionUs
You can create media source by following the below snippet:
fun getMediaSource(file: String): MediaSource {
return ProgressiveMediaSource.Factory(DefaultDataSourceFactory(context, userAgent))
.createMediaSource(MediaItem.fromUri(Uri.parse(file)))
}
After creating the MediaSource you can pass on the values for start and end time you had calculated.
Note: startPositionUs and endPositionUs are in micro-seconds.
Once done, you can pass this media source to your ExoPlayer and it will play only the selected/trimmed part of your video.
I'm using Exoplayer to play a video in my application, what I want to do is change the speed of playback, for which Exoplayer provides a straightforward solution:
val playbackParameters = PlaybackParameters(whateverSpeedFloat)
exoPlayer.setPlaybackParameters(playbackParameters)
Now this works, but the problem I have is that the effect is not immediate, when you change the speed it takes a few frames for the actual speed to change. I guess it's because some of the frames are preloaded or buffered and the set playback parameters only affect the frames after this.
If I stop the video, and change speed from say 0.5x to 2x, then press play, it's very obvious that there is a delay in playback speed change. But, if I press stop, change the speed from 0.5x to 2x AND seek a different point in the video, and press play, it works great, there is no delay. I guess it reloads/buffers the new frames with the right playback parameters. I tried doing
exoPlayer.clearVideoDecoderOutputBufferRenderer()
after changing speeds to try and rebuffer the frames after setting the playback parameters but it doesn't seem to change anything.
Any ideas on how to fix this? Or other video player libraries that wouldn't have this problem?
UPDATE:
I still haven't found a solution, I took the problem to ExoPlayer and an issue was raised and "fixed"(https://github.com/google/ExoPlayer/issues/7982), however I'm still having the same problem, so atm I'll just get back to them and wait.
However, what was mentioned is that the delay is a know issue, and that right now there is no solution,
Correct. We looked at options to address the delay a while ago but couldn't find a clean/general/easy to implement approach (there is no API we can use to process the audio just before the mixer, so we have to do it upstream of the audio track buffer, which introduces latency).
Instead, they suggested initialising Exoplayer with a DefaultRenderersFactory with AudioTrackPlaybackParams set to true:
val defaultRenderersFactory =
DefaultRenderersFactory(this).setEnableAudioTrackPlaybackParams(true)
exoPlayer = SimpleExoPlayer.Builder(this, defaultRenderersFactory).build()
And this does in fact get rid of the delay (not 100% but I'd say around 80% which is good enough), but then the video speed gets all clunky and starts freezing and changing speeds every time it is paused/played or seeked to a different point.
I also tried modifying the buffering configuration #GensaGames suggested but even though I tested different configurations for a while, I never saw any change in the behaviour so discarded the solution and went to the exoPlayer repo.
I'll update this question when I finally have a working video speed changer.
I think you can decrease time of the buffering within configuration setup during ExpPlayer initializing. Below ex. on configuration, you can go throw documentation and check possible values.
/* Instantiate a DefaultLoadControl.Builder. */
DefaultLoadControl.Builder builder = new
DefaultLoadControl.Builder();
/* Maximum amount of media data to buffer (in milliseconds). */
final long loadControlMaxBufferMs = 60000;
/*Configure the DefaultLoadControl to use our setting for how many
Milliseconds of media data to buffer. */
builder.setBufferDurationsMs(
DefaultLoadcontrol.DEFAULT MIN BUFFER MS,
loadControlMaxBufferMs,
/* To reduce the startup time, also change the line below */
DefaultLoadControl.DEFAULT_BUFFER_FOR_PLAYBACK_MS,
DefaultLoadControl.DEFAULT_BUFFER_FOR_PLAYBACK_AFTER_REBUFFER_MS);
/* Build the actual DefaultLoadControl instance */
DefaultLoadControl loadControl = builder.createDefaultLoadControl();
/* Instantiate ExoPlayer with our configured DefaultLoadControl */
ExoPlayer player = ExoPlayerFactory.newSimpleInstance(
new DefaultRenderersFactory(this),
new DefaultTrackSelector(),
loadControl);
There is also good article about changing buffer time options.
How do you get the current time for a live video(rtmp) when using Exoplayer?
I tried
player.getCurrentPosition()
but the values start from 0 and not the actual time of the live stream. Is it possible to get the actual video time?
In this case, I implement with subtraction between date now with user start date playing like this. dateStartPlaying is initialized when we want to play some content / change the content.
private long getCurrentTimeLiveStreaming(){
return new Date().getTime() - dateStartPlaying.getTime();
}
I am working on video player using video node of Scene Graph Component. My issue is when i set seek field like
m.video.seek = 20 it's start playing from 15 seconds or 18 seconds but not from exact position 20 seconds. My code is...
inner = createObject("RoSGNode", "ContentNode")
inner.url = "http://-------------.m3u8"
inner.streamformat = "hls"
inner.SwitchingStrategy = "full-adaptation"
Video file format is m3u8 and using ui_resolutions=fhd in manifest file of roku app.
Is this issue related to stream format or others? Please help me.
This is correct behavior you have "hls" streamformat, this is format specific, hls video stream is divided into chunks, so when you set seek, video will start from chunk start not from the middle of this chunk.
I solved this issue by setting video component attribute seekMode to "accurate"
<Video id="videoPlayer" visible="true" translation="[0, 0]" width="1920" height="1080" seekMode = "accurate" enableTrickPlay="true" enableUI="false"/>
I am using Audio track to play a different sounds, in stream mode.
I would like to know if there is a way to know when each sound beings/ends playing.
I create the audio track like this:
AudioTrack tmpAudioTrack = new AudioTrack(
STREAM_TYPE,
SAMPLE_RATE,
CHANNEL_CONFIG_TYPE,
AUDIO_FORMAT_TYPE,
getOptimalBufferSize(),
AUDIO_TRACK_MODE);'
And start it in a background thread:
backround_thread = new Thread(new MyRunnable(aTrack));
backround_thread.start();
I write each sound like this inside the runnable:
byte generatedSnd[] = new byte[2 * beepSamples];
<code for filling the buffer with sound here>
int bytesWritten = track.write(generatedSnd, 0, generatedSnd.length);
It is possible to use any of the AudioTrack APIs such setNotificationMarkerPosition, or setLoopPoints, or setPositionNotificationPeriod to accomplish this? and how do they work?
Each sound can be different duration of time. I think this is key.
I don't fully understand the documentation for these APIs. Is each frame the same as a sample? How do I specify a marker for where each sound begin/end?
Thanks,
This is what I have found out:
To me, frames are samples -- the duration of the sound multiplied times the sample rate.
To use AudioTrack.setPositionNotificationPeriod, you pass an amount of samples. Meaning if you pass 200 samples, the callback will be called every 200 samples, recurrent.
tmpAudioTrack.setPositionNotificationPeriod(duration * sampleRate);
To use .setNotificationMarkerPosition, you also pass an amount of samples. However, this is absolute and not relative like for the period API. So if you want to determine when a sound ends, you pass the sample amount (total sound track duration * sampleRate).
tmpAudioTrack.setNotificationMarkerPosition(duration * sampleRate);
But, if you are already playing, in the middle of your sound track, and want to add a marker so you will get called back let's say 3 seconds from now, then you would need to add the current playhead of the audio track, like this: (where your duration is 3 seconds)
tmpAudioTrack.setNotificationMarkerPosition(tmpAudioTrack.getPlaybackHeadPosition() + (duration * sampleRate));
And this is how you get registered for the period and marker notifications:
tmpAudioTrack.setPlaybackPositionUpdateListener(new OnPlaybackPositionUpdateListener(){
#Override
public void onMarkerReached(AudioTrack arg0) {
}
#Override
public void onPeriodicNotification(AudioTrack arg0) {
}
});