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.7.1")
Groovy
implementation "androidx.media3:media3-exoplayer-rtsp:1.7.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://<用户名>:<密码>@<主机地址>
。
使用 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 重试的超时时间。例如,如果超时时间设置为四秒,播放器将在 UDP 不活动四秒后使用 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));