I want to show video by http data source. but when I set data source, exoplayer immediately start to buffer video, How can start buffering on user play click.
val dataSourceFactory = DefaultDataSourceFactory(context,Util.getUserAgent(context!!,"user_agent"))
player = SimpleExoPlayer.Builder(context!!).build()
playerView!!.player = player
val contentUrl = "my video url.mp4"
videoSource = ProgressiveMediaSource.Factory(dataSourceFactory).createMediaSource(Uri.parse(contentUrl))
player.prepare(videoSource)
P.S:
I try to change DefaultLoadControl to change buffering behavior but I cant find a workaround.
Thanks.
Related
I am building a video player which streams online videos with track selector. If I parse mp4 video, Exoplayer plays the video well but when the video has mpd format, it plays but with black screen.
My code:
val trackSelector = DefaultTrackSelector(context)
val url = "https://storage.googleapis.com/wvmedia/cenc/h264/tears/tears.mpd"
val simpleExoPlayer = SimpleExoPlayer.Builder(context).setTrackSelector(trackSelector).build()
simpleExoPlayer.setMediaItem(MediaItem.fromUri(url))
simpleExoPlayer.seekTo(0)
simpleExoPlayer.prepare()
I have tried the code above and it works with all formats excepts mdp format.
I am using following test stream to render mpd in android exoplayer
https://bitmovin-a.akamaihd.net/content/art-of-motion_drm/mpds/11331.mpd
following is my exoplayer code:
val adaptiveTrackSelection = AdaptiveTrackSelection.Factory()
val trackSelector: TrackSelector = DefaultTrackSelector(mContext!!, adaptiveTrackSelection)
mConcatenatingMediaSource = ConcatenatingMediaSource()
val mediaItem = MediaItem.Builder().setUri(url).setMimeType(MimeTypes.APPLICATION_MPD)
.build()
val dashMediaSource = DashMediaSource.Factory(DefaultDataSourceFactory(mContext!!, mContext!!.packageName))
.createMediaSource(mediaItem)
mConcatenatingMediaSource.addMediaSource(dashMediaSource)
exoPlayer = SimpleExoPlayer.Builder(this).setTrackSelector(trackSelector).build()
.also { exoPlayer ->
exoPlayer.playWhenReady = true
exoPlayer.addMediaSource(mConcatenatingMediaSource as MediaSource)
playerView!!.player = exoPlayer
exoPlayer.prepare()
attachEventListener(exoPlayer)
}
I am getting player state STATE_READY, I am getting position update for each second and finally player state STATE_ENDED as well, but on screen it is always a blank screen. I am testing on samsung device with os android 12.
Can anyone please help me solve this issue.
The link you have shared is to a DRM protected video stream and the behaviour you are seeing is consistent with the player not displaying encrypted content.
If you just want to test ExoPlayer in general then you can simple choose a different stream which is not DRM protected.
If you do want to test this particular stream then you will need to set up the DRM information in ExoPLayer.
The ExoPlayer documentation provides guidance on this including the example below (https://exoplayer.dev/drm.html):
MediaItem mediaItem = new MediaItem.Builder()
.setUri(videoUri)
.setDrmConfiguration(
new MediaItem.DrmConfiguration.Builder(C.WIDEVINE_UUID)
.setLicenseUri(licenseUri)
.setMultiSession(true)
.setLicenseRequestHeaders(httpRequestHeaders)
.build())
.build();
This is for Widevine which is the default DRM on Android and which your stream supports. You can see this by looking in the manifest you linked to and you will see the Widevine UUID listed in a Content protection element.
ContentProtection schemeIdUri="urn:uuid:edef8ba9-79d6-4ace-a3c8-27dcd51d21ed"
As an FYI, the full list of DRM UUID's is here: https://dashif.org/identifiers/content_protection/
I am using the following code to play a stream (which has both a video and an audio). But what if I want a video stream and a separate audio stream for the video stream at the same time synchronously? For example, suppose there are
https://someserver.com/video1/video.mp4
https://someserver.com/video1/audio.mp3
Both video.mp4 and audio.mp3 belong to video1 and have the same length, 1:23:34. Can I play video.mp4 and audio.mp3 synchronously as if they were one stream, with one ExoPlayer? The user must be able to pause/play/seek, and the same action should be applied to both streams.
If not, and I have to use two ExoPlayers, one for video and one for audio, how can I synchronise the audio and the video?
var uri = Uri.parse(url);
var df = DefaultHttpDataSourceFactory(url);
var ms = ExtractorMediaSource(uri, df, DefaultExtractorsFactory(), null, null);
exoPlayer.playWhenReady=true;
exoPlayer.prepare(ms);
You can! This is done in ExoPlayer by creating a MergingMediaSource. The example in the link merges a video source with a subtitle source but it's even easier for audio and video:
MediaSource videoSource = new ProgressiveMediaSource.Factory(...)
.createMediaSource(videoUri);
MediaSource audioSource = new ProgressiveMediaSource.Factory(...)
.createMediaSource(audioUri);
MergingMediaSource mergedSource = new MergingMediaSource(videoSource, audioSource);
I have more than one video to play one by one. After Creating MediaSource of each video, All these are going to ConcatenatingMediaSource(mediaSources[]). Normally it play one by one. But when video is fast forward using seekTo(), 1st video is ok but other videos do not follow seekTo().
Suppose 1st video is 10s, 2nd 12s, 3rd 10s.
If I call seekTo((long)12*1000) it should play 2nd video with 2s forward. But it plays from the beginning of 2nd video.
Setting VideoSources
DefaultDataSourceFactory defaultDataSourceFactory = new DefaultDataSourceFactory(getApplicationContext(),Util.getUserAgent(getApplicationContext(), "ExoPlayer"));
MediaSource mediaSource = new ExtractorMediaSource.Factory(defaultDataSourceFactory).createMediaSource(videoItem.getVideoUri());
videoItemArrayList.get(k).setVideoSource(mediaSource);
Concatenate Sources
MediaSource[] mediaSources = new MediaSource[videoItemArrayList.size()];
int j=0;
for(VideoItem item : videoItemArrayList){
mediaSources[j] = item.getVideoSource();
++j;
}
concatenatedSource = new ConcatenatingMediaSource(mediaSources);
Setup exoplayer
exoPlayer.prepare(concatenatedSource);
exoPlayer.seekTo(0);
exoPlayer.setPlayWhenReady(true);
exoPlayer.getPlaybackState();
Using exoplayer.seekTo(period) internally calls currentWindowIndex() internally of the source. While you are playing the first video in the concatenated mediasource you end up receiving windowIndex as 0. Use seekTo(windowIndex, time) to solve the issue.
I have a list of HLS urls that I need to play consecutively with exoplayer 2. This is not a problem:
val mediaSources = arrayOfNulls<MediaSource>(videoModel.Clips.size)
for (i in videoModel.Clips.indices) {
mediaSources[i] = buildVideoSource(videoModel.Clips.get(i).StreamUrl)
}
val videoSource = if (mediaSources.size == 1) mediaSources[0] else ConcatenatingMediaSource(*mediaSources)
The problem here is that I need to mute these videos, and play a mp3 audio track instead as background tune. How should I go about this? I thought I could just use a MergingMediaSource like this:
val audioSource = buildAudioSource()
val mergedSource = MergingMediaSource(videoSource, audioSource)
player!!.prepare(videoSource)
But that throws the following error: The merge failed because the sources have different period counts.
Source error:
com.google.android.exoplayer2.source.MergingMediaSource$IllegalMergeException
at com.google.android.exoplayer2.source.MergingMediaSource.checkTimelineMerges(MergingMediaSource.java:169)
at com.google.android.exoplayer2.source.MergingMediaSource.handleSourceInfoRefreshed(MergingMediaSource.java:144)
at com.google.android.exoplayer2.source.MergingMediaSource.access$000(MergingMediaSource.java:34)
at com.google.android.exoplayer2.source.MergingMediaSource$1.onSourceInfoRefreshed(MergingMediaSource.java:102)
at com.google.android.exoplayer2.source.ConcatenatingMediaSource.handleSourceInfoRefreshed(ConcatenatingMediaSource.java:142)
at com.google.android.exoplayer2.source.ConcatenatingMediaSource.access$000(ConcatenatingMediaSource.java:34)
at com.google.android.exoplayer2.source.ConcatenatingMediaSource$1.onSourceInfoRefreshed(ConcatenatingMediaSource.java:81)
at com.google.android.exoplayer2.source.hls.HlsMediaSource.onPrimaryPlaylistRefreshed(HlsMediaSource.java:142)
at com.google.android.exoplayer2.source.hls.playlist.HlsPlaylistTracker.onPlaylistUpdated(HlsPlaylistTracker.java:385)
at com.google.android.exoplayer2.source.hls.playlist.HlsPlaylistTracker.access$1200(HlsPlaylistTracker.java:41)
at com.google.android.exoplayer2.source.hls.playlist.HlsPlaylistTracker$MediaPlaylistBundle.processLoadedPlaylist(HlsPlaylistTracker.java:590)
at com.google.android.exoplayer2.source.hls.playlist.HlsPlaylistTracker$MediaPlaylistBundle.onLoadCompleted(HlsPlaylistTracker.java:539)
at com.google.android.exoplayer2.source.hls.playlist.HlsPlaylistTracker$MediaPlaylistBundle.onLoadCompleted(HlsPlaylistTracker.java:472)
at com.google.android.exoplayer2.upstream.Loader$LoadTask.handleMessage(Loader.java:383)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:154)
at android.os.HandlerThread.run(HandlerThread.java:61)
I have 2 questions:
How can I mute incoming HLS stream? I'd preferably not load the audio at all to save data usage.
How can I play a seperate audiotrack under a ConcatenatingMediaSource?
u can disable audio , in exo player Demo application, you can select audio button and choose disable.
you can see the demo code to see how disable the audio