RTSP

ExoPlayer 支持直播和点播 RTSP。下面列出了支持的样本格式和网络类型。

支持的样本格式

  • H264(SDP 媒体描述必须在 fmtp 属性中包含 SPS/PPS 数据以进行解码器初始化)。
  • AAC(带 ADTS 比特流)。
  • AC3。

支持的网络类型

  • 通过 UDP 单播的 RTP(不支持多播)。
  • 交错 RTSP,通过 TCP 使用 RTSP 的 RTP。

使用 MediaItem

要播放 RTSP 流,您需要依赖 RTSP 模块。

Kotlin

implementation("androidx.media3:media3-exoplayer-rtsp:1.4.1")

Groovy

implementation "androidx.media3:media3-exoplayer-rtsp:1.4.1"

然后,您可以为 RTSP URI 创建一个 MediaItem 并将其传递给播放器。

Kotlin

// Create a player instance.
val player = ExoPlayer.Builder(context).build()
// Set the media item to be played.
player.setMediaItem(MediaItem.fromUri(rtspUri))
// Prepare the player.
player.prepare()

Java

// Create a player instance.
ExoPlayer player = new ExoPlayer.Builder(context).build();
// Set the media item to be played.
player.setMediaItem(MediaItem.fromUri(rtspUri));
// Prepare the player.
player.prepare();

身份验证

ExoPlayer 支持使用 RTSP BASIC 和 DIGEST 身份验证进行播放。要播放受保护的 RTSP 内容,必须使用身份验证信息配置 MediaItem 的 URI。具体来说,URI 应采用 rtsp://<username>:<password>@<host address> 的形式。

使用 RtspMediaSource

为了获得更多自定义选项,您可以创建一个 RtspMediaSource 并将其直接传递给播放器,而不是传递 MediaItem

Kotlin

// Create an RTSP media source pointing to an RTSP uri.
val mediaSource: MediaSource =
RtspMediaSource.Factory().createMediaSource(MediaItem.fromUri(rtspUri))
// Create a player instance.
val player = ExoPlayer.Builder(context).build()
// Set the media source to be played.
player.setMediaSource(mediaSource)
// Prepare the player.
player.prepare()

Java

// Create an RTSP media source pointing to an RTSP uri.
MediaSource mediaSource =
    new RtspMediaSource.Factory().createMediaSource(MediaItem.fromUri(rtspUri));
// Create a player instance.
ExoPlayer player = new ExoPlayer.Builder(context).build();
// Set the media source to be played.
player.setMediaSource(mediaSource);
// Prepare the player.
player.prepare();

在 NAT 后使用 RTSP(RTP/TCP 支持)

ExoPlayer 使用 UDP 作为 RTP 传输的默认协议。

在 NAT 层后面流式传输 RTSP 时,NAT 可能无法将传入的 RTP/UDP 数据包转发到设备。如果 NAT 缺少必要的 UDP 端口映射,就会发生这种情况。如果 ExoPlayer 检测到一段时间内没有传入的 RTP 数据包并且播放尚未开始,ExoPlayer 将拆除当前的 RTSP 播放会话,并尝试使用 RTP-over-RTSP(使用为 RTSP 打开的 TCP 连接传输 RTP 数据包)进行播放。

可以使用 RtspMediaSource.Factory.setTimeoutMs() 方法自定义使用 TCP 重试的超时时间。例如,如果将超时时间设置为 4 秒,则播放器将在 UDP 不活动 4 秒后尝试使用 TCP。

设置超时时间也会影响流结束检测逻辑。也就是说,如果在设置的超时时间内未收到任何数据,ExoPlayer 将报告播放已结束。在网络状况不佳的情况下,如果将此值设置得太小,可能会导致过早发出流结束信号。

RTP/TCP 在某些网络设置下提供了更好的兼容性。您可以使用 RtspMediaSource.Factory.setForceUseRtpTcp() 将 ExoPlayer 配置为默认使用 RTP/TCP。

传递自定义 SocketFactory

当需要特定路由时(例如,当 RTSP 流量需要通过特定接口或套接字需要其他连接标志时),自定义 SocketFactory 实例很有用。

默认情况下,RtspMediaSource 将使用 Java 的标准套接字工厂(SocketFactory.getDefault())来创建到远程端点的连接。可以使用 RtspMediaSource.Factory.setSocketFactory() 覆盖此行为。

Kotlin

// Create an RTSP media source pointing to an RTSP uri and override the socket
// factory.
val mediaSource: MediaSource =
RtspMediaSource.Factory()
    .setSocketFactory(...)
    .createMediaSource(MediaItem.fromUri(rtspUri))

Java

// Create an RTSP media source pointing to an RTSP uri and override the socket
// factory.
MediaSource mediaSource =
    new RtspMediaSource.Factory()
        .setSocketFactory(...)
        .createMediaSource(MediaItem.fromUri(rtspUri));