ExoPlayer
ExoPlayer copied to clipboard
Video subtitles on chromecast
I use exoplayer with exoplayer-cast-extension in my android app. In the app its possible to play videos with subtitles (I have links on .srt files for each video source). And I want to cast these videos (on chromecast) with subtitles. For casting I use the following code:
castPlayer?.loadItem(MediaQueueItem.Builder(buildMediaInfo(videoUrl ?: "")).build(), 0L)
private fun buildMediaInfo(videoUrl: String): MediaInfo {
val movieMetadata = MediaMetadata(MediaMetadata.MEDIA_TYPE_MOVIE)
movieMetadata.putString(MediaMetadata.KEY_TITLE, getString(R.string.app_name))
return MediaInfo.Builder(videoUrl)
.setStreamType(MediaInfo.STREAM_TYPE_BUFFERED)
.setContentType("video/m3u8")
.setMetadata(movieMetadata)
.setStreamDuration(UNKNOWN_DURATION)
.build()
}
It plays video with chromecast well, but without subtitles. And I didnt find some method for adding subtitles for cast video. So, how to make them?
https://developers.google.com/cast/docs/android_sender/media_tracks
@amjadmasri thanks. But when I set MediaTraks, there is no subtitles in cast video, unfortunately:
private fun buildMediaInfo(): MediaInfo {
val movieMetadata = MediaMetadata(MediaMetadata.MEDIA_TYPE_MOVIE)
movieMetadata.putString(MediaMetadata.KEY_TITLE, getString(R.string.app_name))
val englishSubtitle = MediaTrack.Builder(1, MediaTrack.TYPE_TEXT)
.setName("English Subtitle")
.setSubtype(MediaTrack.SUBTYPE_SUBTITLES)
.setContentId("http://www.storiesinflight.com/js_videosub/jellies.srt")
.setLanguage("en-US")
.build()
return MediaInfo.Builder("https://clvod.itworkscdn.net/itwvod/smil:itwfcdn/admin/515002-R204MDrB22W6kG8.smil/playlist.m3u8")
.setStreamType(MediaInfo.STREAM_TYPE_BUFFERED)
.setContentType("video/m3u8")
.setMetadata(movieMetadata)
.setMediaTracks(listOf(englishSubtitle))
.setStreamDuration(UNKNOWN_DURATION)
.build()
}
The video plays well, but without subtitles. Is there a way to show subtitles successfully? I use Styled Media Receiver.
So, no one knows how to solve the problem?
I have the same problem any help?
Any update on this, I have the same issue.
Having the same issue. How could we add srt files to a stream?
I am facing the same issue. anyone, resolves this issue?
@amjadmasri , I have followed as per your posted link.
MediaTrack englishSubtitle = new MediaTrack.Builder(1 /* ID */,
MediaTrack.TYPE_TEXT)
.setName("English Subtitle")
.setSubtype(MediaTrack.SUBTYPE_SUBTITLES)
.setContentId("https://some-url/caption_en.vtt")
.setLanguage("en-US")
.build();
// the ID for the English Subtitle '1'
mRemoteMediaClient.setActiveMediaTracks(new long[]{1})
.setResultCallback(new ResultCallback() {
@Override
public void onResult(MediaChannelResult mediaChannelResult) {
if (!mediaChannelResult.getStatus().isSuccess()) {
Log.e(TAG, "Failed with status code:" +
mediaChannelResult.getStatus().getStatusCode());
}else{
Log.d("TAG", "Success with status code:" +
mediaChannelResult.getStatus().getStatusCode());
}
}
});
D/TAG: Success with status code:0
But the subtitle is not working on the cast player. @AquilesCanta , @ojw28
Same problem!!
Hey @mjmancuso can you provide advise here?
By the way @drayan85, can you share the media you are using:
- Link to the main content (video + audio)
- Link to sideloaded subtitles ? You can send them to [email protected] if you don't want to make them public.
@AquilesCanta , Sorry I have forgot to update here. The subtitle is working fine with below code;
public void setSelectedSubTitle(final String selectedSubTitleLang, final Resources resources) {
List<MediaTrack> tracks = new ArrayList<>();
MediaTrack englishSubtitle = new MediaTrack.Builder(1 /* ID */,
MediaTrack.TYPE_TEXT)
.setName("English(US)")
.setSubtype(MediaTrack.SUBTYPE_SUBTITLES)
.setContentId("https://some-url/us_english.srt")
.setLanguage("en-US")
.build();
tracks.clear();
tracks.add(mediaTrack);
}
The problem was calling the place, we have to call after the player got initialised
//PlayerManager.Listener
@Override
public void onTracksChanged(final TrackGroupArray trackGroups, final TrackSelectionArray trackSelections) {
updatePlayerButtonVisibilities();
TrackSelection trackSelection = trackSelections.get(2);
if (trackSelection != null) {
selectedSubtitleLang = trackSelection.getFormat(0).language;
playerManager.setSelectedSubTitle(selectedSubtitleLang, resource);
if (playerManager != null && trackGroups != lastSeenTrackGroupArray) {
MappedTrackInfo mappedTrackInfo = playerManager.getTrackSelector().getCurrentMappedTrackInfo();
if (mappedTrackInfo != null) {
if (mappedTrackInfo.getTypeSupport(C.TRACK_TYPE_VIDEO)
== MappedTrackInfo.RENDERER_SUPPORT_UNSUPPORTED_TRACKS) {
showToast(R.string.error_unsupported_video);
}
if (mappedTrackInfo.getTypeSupport(C.TRACK_TYPE_AUDIO)
== MappedTrackInfo.RENDERER_SUPPORT_UNSUPPORTED_TRACKS) {
showToast(R.string.error_unsupported_audio);
}
}
lastSeenTrackGroupArray = trackGroups;
}
}
I'll try experimenting this and figuring out what the final API should look like from the Cast extension perspective.
any news
@msxenon
Have you tried my solution as mentioned above
https://github.com/google/ExoPlayer/issues/5786#issuecomment-551622165
In the PlayerManager after Track Change got changed,
//PlayerManager.Listener
@Override
public void onTracksChanged(final TrackGroupArray trackGroups, final TrackSelectionArray trackSelections) {
updatePlayerButtonVisibilities();
TrackSelection trackSelection = trackSelections.get(2);
if (trackSelection != null) {
selectedSubtitleLang = trackSelection.getFormat(0).language;
playerManager.setSelectedSubTitle(selectedSubtitleLang, resource);
if (playerManager != null && trackGroups != lastSeenTrackGroupArray) {
MappedTrackInfo mappedTrackInfo = playerManager.getTrackSelector().getCurrentMappedTrackInfo();
if (mappedTrackInfo != null) {
if (mappedTrackInfo.getTypeSupport(C.TRACK_TYPE_VIDEO)
== MappedTrackInfo.RENDERER_SUPPORT_UNSUPPORTED_TRACKS) {
showToast(R.string.error_unsupported_video);
}
if (mappedTrackInfo.getTypeSupport(C.TRACK_TYPE_AUDIO)
== MappedTrackInfo.RENDERER_SUPPORT_UNSUPPORTED_TRACKS) {
showToast(R.string.error_unsupported_audio);
}
}
lastSeenTrackGroupArray = trackGroups;
}
}
Hi @drayan85 I'm interested with your suggest solution, can you provide full example code in add MediaItem before setMediaItems to load media by using CastPlayer?
@BayuWijayaPermanaPutra, I hope this will help you make it work.
List<MediaTrack> tracks;
MediaTrack mediaTrack = new MediaTrack.Builder(1 /* ID */,
MediaTrack.TYPE_TEXT)
.setName(new DefaultTrackNameProvider(resources).getTrackName(subtitleFormat))
.setSubtype(MediaTrack.SUBTYPE_SUBTITLES)
.setContentId(url)
/* language is required for subtitle type but optional otherwise */
.setLanguage(language)
.build();
tracks.clear();
tracks.add(mediaTrack);
JSONObject jsonObj = new JSONObject();
jsonObj.put("description", "Video Description");
MediaInfo mediaInfo =
new MediaInfo.Builder(item.uri.toString())
.setStreamType(MediaInfo.STREAM_TYPE_BUFFERED)
.setContentType(item.mimeType)
.setMetadata(movieMetadata)
.setMediaTracks(tracks) /*Selected SubTitle*/
.setCustomData(jsonObj)
.build();
new MediaQueueItem.Builder(mediaInfo).build()
@drayan85 Not working, I implemented the same way you suggested.