In my application I want use exoplayer to play video and for this I added this dependency:
implementation 'com.google.android.exoplayer:exoplayer:2.18.0'
with simple way I can play video with this code:
player = ExoPlayer.Builder(this).build()
binding.player.player = player
// Build the media item.
val mediaItem: MediaItem = MediaItem.fromUri(url)
// Set the media item to be played.
player.setMediaItem(mediaItem)
// Prepare the player.
player.prepare()
// Start the playback.
player.play()
But I want add Header for video and for this I write below codes:
val dataSourceFactory: DataSource.Factory = DataSource.Factory {
val dataSource: HttpDataSource = httpDataSourceFactory.createDataSource()
// Set a custom authentication request header.
dataSource.setRequestProperty("Header", "Value")
dataSource
}
But in my code not found httpDataSourceFactory.
I used this link tutorial : https://exoplayer.dev/customization.html#customizing-server-interactions
How can I add header for exoplayer?
val dataSourceFactory = DefaultHttpDataSource.Factory()
.setDefaultRequestProperties(hashMapOf("Header" to "Value"))
val audioSource: MediaSource = ProgressiveMediaSource.Factory(dataSourceFactory)
Use the "DefaultHttpDataSource"
Related
I am using ConcatenatingMediaSource to make hls urls playlist for my ExoPlayer.
when playing media sources by local files, it works fine without gap.
However, when playing media sources by hls urls, It noticeably shows gap while transition (first video to second one)
I want my media source transit smoothly in ConcatenatingMediaSource.
How can I achieve this?
Guide me please.
This below is my init code.
val playerView = findViewById<PlayerView>(R.id.playerView)
val concatenatedSource = ConcatenatingMediaSource()
val trackSelector = DefaultTrackSelector(mContext!!)
trackSelector.parameters = trackSelector.buildUponParameters().build()
val dataSourceFactory = DefaultHttpDataSource.Factory()
val hlsMediaSource: HlsMediaSource = HlsMediaSource.Factory(dataSourceFactory)
.setAllowChunklessPreparation(true)
.createMediaSource(MediaItem.fromUri("https://multiplatform-f.akamaihd.net/i/multi/april11/sintel/sintel-hd_,512x288_450_b,640x360_700_b,768x432_1000_b,1024x576_1400_m,.mp4.csmil/master.m3u8"))
concatenatedSource.addMediaSource(hlsMediaSource)
val player = ExoPlayer.Builder(mContext)
.setTrackSelector(trackSelector)
.build()
player.setMediaSource(concatenatedSource)
player.addAnalyticsListener(EventLogger(trackSelector))
player.addListener(object : Player.Listener {
override fun onPlayerError(error: PlaybackException) {
super.onPlayerError(error)
}
})
playerView?.player = player
playerView?.player?.prepare()
playerView?.player?.playWhenReady = true
For those who have this kind of issues, you should try CacheDataSource while building MediaItem objects. This resolved my issues. Thanks
So I am trying to show subtitles from my .srt file in exoplayer but it does not work.
Do I need to use a seperate SubtitleView to get my subtitles to show up?
Is the subtitleView in the PlayerView is not enough?
I use PlayerView btw.
The exoplayer version I use is 2.14.0.
The addTextOutput method.
simpleExoPlayer.addTextOutput(cues -> {
playerView.getSubtitleView().setCues(cues);
playerView.getSubtitleView().setVisibility(View.VISIBLE);
playerView.getSubtitleView().onCues(cues);
assert cues.get(0).text != null;
Log.d("subtitles", cues.get(0).text.toString());
});
I also tried to implement to TextOutput but that did not work too.
The contents of my sample.srt file:
1
00:00:00,000 --> 00:00:01,500
For www.forom.com
2
00:00:01,500 --> 00:00:02,500
<i>Tonight's the night.</i>
3
00:00:03,000 --> 00:00:15,000
<i>And it's going to happen
again and again --</i>
The function I use to load my subtitles:
public void buildMediaSourceV3(Uri uri){
String subtitlesUri = sharedPreferencesSubtitles.getString(videoName.getText().toString(), "");
DataSource.Factory factory = new DefaultDataSourceFactory(VideoPlayer.this, getPackageName(), new DefaultBandwidthMeter());
MediaItem mediaItem = MediaItem.fromUri(uri);
MediaSource videoSource = new ProgressiveMediaSource.Factory(factory).createMediaSource(mediaItem);
if(subtitlesUri.equals(""))
{
simpleExoPlayer.addMediaSource(videoSource);
}
else
{
MediaItem.Subtitle subtitle = new MediaItem.Subtitle(Uri.parse(subtitlesUri), MimeTypes.APPLICATION_SUBRIP, "en");
MediaSource textMediaSource = new SingleSampleMediaSource.Factory(factory).createMediaSource(subtitle, C.TIME_UNSET);
textMediaSource.getMediaItem().mediaMetadata.subtitle.toString();
MergingMediaSource mergingMediaSource = new MergingMediaSource(videoSource, textMediaSource);
simpleExoPlayer.addMediaSource(mergingMediaSource);
}
}
I know you've already implemented a workaround.
I've just encountered the same issue, and found a solution:
trackSelector.setPreferredTextLanguage
This helped me. Full context:
val trackSelector = DefaultTrackSelector(context)
trackSelector.setParameters(trackSelector.buildUponParameters().setPreferredTextLanguage("en"))
Update:
I was wrong. That solution shows only video embedded captions, not the sideloading ones.
This works for me now:
val mediaItemBuilder = MediaItem.Builder()
.setUri(uri))
videoCaption?.vtt?.let {
val uriSubtitle = Uri.parse(it)
val mediaItemSubtitle = MediaItem.Subtitle(uriSubtitle,
MimeTypes.TEXT_VTT,
"en",
C.SELECTION_FLAG_DEFAULT)
mediaItemBuilder.setSubtitles(mutableListOf(mediaItemSubtitle))
}
val mediaItem = mediaItemBuilder.build()
val mediaSource = DefaultMediaSourceFactory(dataSourceFactory, extractoryFactory).createMediaSource(mediaItem)
Here is minimal example for video/mp4 with SRT subtitles. For XML layout is used com.google.android.exoplayer2.ui.StyledPlayerView and there is no need for additional subtitle layout. Files are located in assets directory inside the project.
val playerView = view.findViewById<StyledPlayerView>(R.id.video_pv)
val exoPlayer = ExoPlayer.Builder(requireActivity()).build()
playerView.player = exoPlayer
val assetSrtUri = Uri.parse(("file:///android_asset/subtitle.srt"))
val subtitle = SubtitleConfiguration.Builder(assetSrtUri)
.setMimeType(MimeTypes.APPLICATION_SUBRIP)
.setLanguage("en")
.setSelectionFlags(C.SELECTION_FLAG_DEFAULT)
.build()
val assetVideoUri = Uri.parse(("file:///android_asset/video.mp4"))
val mediaItem = MediaItem.Builder()
.setUri(assetVideoUri)
.setSubtitleConfigurations(ImmutableList.of(subtitle))
.build()
exoPlayer.setMediaItem(mediaItem)
exoPlayer.prepare()
exoPlayer.play()
Gradle dependencies:
implementation "com.google.android.exoplayer:exoplayer:2.17.1"
implementation "com.google.android.exoplayer:exoplayer-core:2.17.1"
implementation "com.google.android.exoplayer:exoplayer-ui:2.17.1"
How can I set and show subtitles from url with ExoPlayer2 in Android? Currently, I write in Kotlin, I'm using following code for setting up ExoPlayer with subtitles:
exoPlayer = SimpleExoPlayer.Builder(this).build()
val subtitle = MediaItem.Subtitle(Uri.parse(SUBTITLES_URL), MimeTypes.TEXT_VTT, "en")
val subtitles = arrayListOf(subtitle)
val mediaItem = MediaItem.Builder()
.setUri(movieSrc)
.setSubtitles(subtitles)
.build()
exoPlayer.setMediaItem(mediaItem)
exoPlayer.addListener(this)
exoPlayer.prepare()
And following code to display them in ExoPlayer SubtitleView:
exoPlayer.addTextOutput {
binding.exoSubtitles.onCues(it)
}
I don't get any exception, it just does not show anything idk...
Nothing really works... Really need some help, Thank You in Advance!
Here is the code I used (I got these from the Internet somewhere I forgot)
// create the simple cache
val leastRecentlyUsedCacheEvictor = LeastRecentlyUsedCacheEvictor(MAX_CACHE_SIZE)
val databaseProvider: DatabaseProvider = ExoDatabaseProvider(this)
val simpleCache = SimpleCache(cacheDir, leastRecentlyUsedCacheEvictor, databaseProvider)
// create http datasource
val defaultBandwidthMeter = DefaultBandwidthMeter.Builder(context).build()
val dataSourceFactory: DataSource.Factory = DefaultDataSourceFactory(
context,
DefaultHttpDataSourceFactory(
System.getProperty("http.agent"),
defaultBandwidthMeter
)
)
// create the player
val simplePlayer = ExoPlayerFactory.newSimpleInstance(context)
simplePlayer.addListener(playerCallback)
cacheDataSourceFactory = CacheDataSourceFactory(
simpleCache,
DefaultHttpDataSourceFactory(
Util.getUserAgent(
context,
"exo"
)
)
)
// create subtitle text format
val textFormat = Format.createTextSampleFormat(
null,
MimeTypes.TEXT_VTT,
C.SELECTION_FLAG_DEFAULT,
null
)
// create the subtitle source
val subtitleSource = SingleSampleMediaSource.Factory(dataSourceFactory)
.createMediaSource(Uri.parse(it), textFormat, C.TIME_UNSET)
// create the media source based from video/audio url
val mediaSource = ProgressiveMediaSource.Factory(cacheDataSourceFactory).createMediaSource(uri)
// merge subtitle source and media source
val mediaSourceWithsubtitle = MergingMediaSource(mediaSource, subtitleSource)
// setup the player
simplePlayer.prepare(mediaSourceWithsubtitle, true, true)
I would like to know how to be able to play more than two songs back to back in ExoPlayer using MediaSources I have in an ArrayList.
I can use ConcatenatingMediaSource to be able to play two songs back to back, but I have to load them into this fundtion as separate paramters. I do not want to do this for a whole list of songs. I have tried to find an answer to this and seem to have some fundemental misunderstanding as I can't seem to replicate the efforts of others in other StackOverflow questions or blogs etc. (Many blogs show the simple two media source playlist as in the ExoPlayer docs).
This code is for context:
private fun prepareExoPlayer(songs: ListSongs) {
val uris = parseUris(songs)
val mediaSource = buildMediaSource(uris)
applyAudioAttributes()
simpleExoPlayer!!.prepare(mediaSource, false, false)
}
This code is where the issue is:
private fun buildMediaSource(uris: ArrayList<Uri>): MediaSource {
val userAgent = Util.getUserAgent(this, "MusicPlayer")
val defaultMediaSource = DefaultDataSourceFactory(this, userAgent)
val progressiveMediaSource = ProgressiveMediaSource.Factory(defaultMediaSource)
val mediaSources = ArrayList<MediaSource>()
for (uri in uris) {
mediaSources.add(progressiveMediaSource.createMediaSource(uri))
}
return if (mediaSources.size == 1) {
mediaSources[0]
} else {
val concatenatingMediaSource = ConcatenatingMediaSource()
concatenatingMediaSource.addMediaSources(mediaSources)
// ConcatenatingMediaSource(mediaSources[0], mediaSources[1])
}
}
In the else statement I get a failure as the return type is not a MediaSource, but a Unit. However, the commented code on the last line works fine. How do I modify the 2nd and 3rd last line to be able to play my list of songs?
Ok, so I just found this video: https://www.youtube.com/watch?v=svdq1BWl4r8
Turns out prepare for ExoPlayer does not have to have a MediaSource as a parameter, but can have a ConcatenatingMediaSource as a parameter as well. These aren't the same but are both accepted by the prepare function.
It's also worth noting that ConcatenatingMediaSource can recieve a single MediaSource. This means the if statement check on the size of the MediaSource ArrayList isn't necessary.
The solution is therefore to change the return type of buildMediaSource to ConcatenatingMediaSource and remove the if statement. Like this:
private fun buildMediaSource(uris: ArrayList<Uri>): ConcatenatingMediaSource {
val userAgent = Util.getUserAgent(this, "MusicPlayer")
val defaultMediaSource = DefaultDataSourceFactory(this, userAgent)
val progressiveMediaSource = ProgressiveMediaSource.Factory(defaultMediaSource)
val mediaSources = ArrayList<MediaSource>()
for (uri in uris) {
mediaSources.add(progressiveMediaSource.createMediaSource(uri))
}
val concatenatingMediaSource = ConcatenatingMediaSource()
concatenatingMediaSource.addMediaSources(mediaSources)
return concatenatingMediaSource
}
I am trying to play a video with exoplayer but it's taking too long to play.
How do I fix this issue?
PS - internet speed is not (so no speed issue)
private fun exoPlayerSetupVideo() {
var trackSelector = DefaultTrackSelector()
//var loadControl = DefaultLoadControl()
var exoPlayer = ExoPlayerFactory.newSimpleInstance(this, trackSelector)
simpleExoPlayerView.player = exoPlayer
var dataSourceFactory = DefaultDataSourceFactory(this, Util.getUserAgent(this, "VideoPlayer"))
var videoSource = ExtractorMediaSource.Factory(dataSourceFactory).createMediaSource(Uri.parse(url1))
exoPlayer.prepare(videoSource)
exoPlayer.playWhenReady = true
}
Have you tried some video urls inside the assets folder that the exoplayer demo project provide? If they play normally means that exoplayer is not the problem.