使用媒体轨道

MediaTrack 表示媒体轨道,可以是音频流、视频串流或文本(如字幕)。您的应用可以对媒体轨道进行分组、设置样式以及激活媒体轨道。

配置轨道

您可以配置轨道并为其分配唯一 ID。以下代码会创建一个英语文本轨道、一个法语文本轨道和一个法语音轨,并且每个轨道都有自己的 ID:

Kotlin
val englishSubtitle = MediaTrack.Builder(1 /* ID */, MediaTrack.TYPE_TEXT)
    .setName("English Subtitle")
    .setSubtype(MediaTrack.SUBTYPE_SUBTITLES)
    .setContentId("https://some-url/caption_en.vtt")
    /* language is required for subtitle type but optional otherwise */
    .setLanguage("en-US")
    .build()

val frenchSubtitle = MediaTrack.Builder(2, MediaTrack.TYPE_TEXT)
    .setName("French Subtitle")
    .setSubtype(MediaTrack.SUBTYPE_SUBTITLES)
    .setContentId("https://some-url/caption_fr.vtt")
    .setLanguage("fr")
    .build()

val frenchAudio = MediaTrack.Builder(3, MediaTrack.TYPE_AUDIO)
    .setName("French Audio")
    .setContentId("trk0001")
    .setLanguage("fr")
    .build()
Java
MediaTrack englishSubtitle = new MediaTrack.Builder(1 /* ID */,
MediaTrack.TYPE_TEXT)
  .setName("English Subtitle")
  .setSubtype(MediaTrack.SUBTYPE_SUBTITLES)
  .setContentId("https://some-url/caption_en.vtt")
  /* language is required for subtitle type but optional otherwise */
  .setLanguage("en-US")
  .build();

MediaTrack frenchSubtitle = new MediaTrack.Builder(2, MediaTrack.TYPE_TEXT)
  .setName("French Subtitle")
  .setSubtype(MediaTrack.SUBTYPE_SUBTITLES)
  .setContentId("https://some-url/caption_fr.vtt")
  .setLanguage("fr")
  .build();

MediaTrack frenchAudio = new MediaTrack.Builder(3, MediaTrack.TYPE_AUDIO)
  .setName("French Audio")
  .setContentId("trk0001")
  .setLanguage("fr")
  .build();

群组轨道

您可以将多个轨道组合为一个媒体项(由 MediaInfo 表示)。MediaInfo 的实例可接受轨道数组,并汇总有关媒体内容的其他信息。在该示例的基础上,您的应用可以将这三个媒体轨道添加到媒体项,只需将这三个轨道的列表传入 MediaInfo.Builder.setMediaTracks(List) 即可。您的应用需要以这种方式在 MediaInfo 中关联曲目,然后才能将媒体加载到接收端。

Kotlin
val tracks: MutableList<MediaTrack> = ArrayList<MediaTrack>()
tracks.add(englishSubtitle)
tracks.add(frenchSubtitle)
tracks.add(frenchAudio)
val mediaInfo = MediaInfo.Builder(url)
    .setStreamType(MediaInfo.STREAM_TYPE_BUFFERED)
    .setContentType(getContentType())
    .setMetadata(getMetadata())
    .setMediaTracks(tracks)
    .build()
Java
List tracks = new ArrayList();
tracks.add(englishSubtitle);
tracks.add(frenchSubtitle);
tracks.add(frenchAudio);
MediaInfo mediaInfo = MediaInfo.Builder(url)
  .setStreamType(MediaInfo.STREAM_TYPE_BUFFERED)
  .setContentType(getContentType())
  .setMetadata(getMetadata())
  .setMediaTracks(tracks)
  .build();

移除轨道

如需从当前媒体中移除所有轨道(例如关闭示例中的三个字幕),请调用 MediaInfo.Builder.setMediaTracks(List) 并传递一个空的 ID 列表。

更新轨道

您的应用可以通过调用 RemoteMediaClient.setActiveMediaTracks(long[]) 并传递要激活的轨道的 ID,激活与媒体内容相关联的一个或多个轨道。以下示例启用了法语字幕和法语音频:

Kotlin
// the ID for the French subtitle is '2' and for the French audio '3'
remoteMediaClient.setActiveMediaTracks(longArrayOf(2, 3))
    .setResultCallback(ResultCallback {
            mediaChannelResult: RemoteMediaClient.MediaChannelResult ->
                if (!mediaChannelResult.status.isSuccess) {
                    Log.e(TAG, "Failed with status code:" +
                            mediaChannelResult.status.statusCode
                    )
                }
    })
Java
// the ID for the French subtitle is '2' and for the French audio '3'
remoteMediaClient.setActiveMediaTracks(new long[]{2, 3})
    .setResultCallback(mediaChannelResult -> {
        if (!mediaChannelResult.getStatus().isSuccess()) {
            Log.e(TAG, "Failed with status code:" +
                    mediaChannelResult.getStatus().getStatusCode());
        }
    });

设置文字轨道的样式

TextTrackStyle 封装文本轨道的样式设置信息。创建或更新现有 TextTrackStyle 后,您可以通过调用 RemoteMediaClient.setTextTrackStyle 将该样式应用于当前正在播放的媒体项,如下所示:

Kotlin
// the ID for the French subtitle is '2' and for the French audio '3'
remoteMediaClient.setTextTrackStyle(style)
    .setResultCallback(ResultCallback {
            mediaChannelResult: RemoteMediaClient.MediaChannelResult ->
                if (!mediaChannelResult.status.isSuccess) {
                    Log.e(TAG, "Failed to set the style, status code: " +
                            mediaChannelResult.status.statusCode
                    )
                }
    })
Java
remoteMediaClient.setTextTrackStyle(style)
    .setResultCallback(mediaChannelResult -> {
        if (!mediaChannelResult.getStatus().isSuccess()) {
            Log.e(TAG, "Failed to set the style, status code: " +
                    mediaChannelResult.getStatus().getStatusCode());
        }
    });

您的应用应允许用户使用系统或应用本身提供的设置更新文本轨道的样式。在 Android KitKat 及更高版本中,您可以使用框架提供的系统级字幕设置:

Kotlin
val textTrackStyle = TextTrackStyle.fromSystemSettings(context)
Java
TextTrackStyle textTrackStyle = TextTrackStyle.fromSystemSettings(context);

对于 KitKat 之前的版本,上述调用将返回一个字段未定义的对象,因此您需要根据用户选择和一些默认值在应用中填充这些字段。您可以为以下文本轨道样式元素设置样式:

  • 前景(文本)颜色和不透明度
  • 背景颜色和不透明度
  • 边缘类型
  • 边缘颜色
  • 字体缩放
  • 字体系列
  • 字体样式

例如,将文本颜色设为红色 (FF),不透明度为 50% (80),如下所示:

Kotlin
textTrackStyle.foregroundColor = Color.parseColor("#80FF0000")
Java
textTrackStyle.setForegroundColor(Color.parseColor("#80FF0000"));

在 KitKat 及更高版本中,您应该注册应用,以便在系统级字幕设置更新时收到通知。为此,您需要在应用中实现 CaptioningManager.CaptioningChangeListener,并通过调用以下函数注册此监听器:

Kotlin
CaptioningManager.addCaptioningChangeListener(yourChangeListener)
Java
CaptioningManager.addCaptioningChangeListener(yourChangeListener);

当应用收到字幕设置已更改的回调时,您需要提取新设置,并通过调用 RemoteMediaClient.setTextTrackStyle 并传入新样式,为当前正在播放的媒体更新文本字幕的样式。

接收状态更新

当多个发送者连接到同一接收者时,每个发送者都务必要了解接收者的变化,即使这些更改是由其他发送者发起的。

为此,您的应用应注册 RemoteMediaClient.ListenerRemoteMediaClient.ProgressListener

如果当前媒体的 TextTrackStyle 发生更改,则所有连接的发送者将通过上述两个已注册的监听器收到通知。在这种情况下,接收器 SDK 不会验证新样式是否与前一个样式不同,并且会向所有已连接的发送方发送通知。不过,如果活跃轨道的状态发生更改,系统仅会通知已连接的发送器中的 RemoteMediaClient.ProgressListener

满足 CORS 要求

对于自适应媒体流式传输,Google Cast 要求具有 CORS 标头;但即使是简单的 mp4 媒体流,如果其包含轨道,也需要 CORS。如果要为任何媒体启用跟踪,您必须同时为跟踪流和媒体流启用 CORS。因此,如果您的服务器上没有适用于简单 mp4 媒体的 CORS 标头,然后您添加了简单的字幕轨道,那么您将无法流式传输您的媒体,除非您更新服务器以包含相应的 CORS 标头。此外,您至少需要允许以下标头:Content-Type、Accept-Encoding 和 Range。请注意,最后两个头文件是您之前可能不需要的其他头文件。