☰
MediaMTX 移动端流媒体播放:WebRTC 与 LL-HLS 双路线的选型、配置与排障
2026/10/17 2:16:10 网站建设 项目流程

MediaMTX 移动端流媒体播放:WebRTC 与 LL-HLS 双路线的选型、配置与排障

【免费下载链接】mediamtxReady-to-use Media-over-QUIC / SRT / WebRTC / RTSP / RTMP / LL-HLS / MPEG-TS / RTP live media server and media proxy that allows to read, publish, proxy, record and playback real-time video and audio streams.项目地址: https://gitcode.com/GitHub_Trending/me/mediamtx

MediaMTX 是一个开源的实时流媒体服务器,内置 WebRTC(WHEP)与 HLS 读取端点,能把同一路流同时分发给 iOS 与 Android 客户端。本文面向在移动应用里接入它的开发者,覆盖移动端流媒体播放的两条路线:WebRTC 低延迟直播与 HLS 大规模分发,按「选型 → 服务端配置 → 客户端代码 → 排障」的顺序给出最小可运行方案。

协议选型:一张表决定走 WebRTC 还是 HLS

先按场景做决定,再写代码。

维度WebRTC(WHEP)HLS(mpegts 变体)LL-HLS
端到端延迟亚秒级,首帧约 0.5s5~10s1~3s
并发规模受服务器限制,每个观众一条 peer connection可经 CDN 扩展,观众数不设限同 HLS,分片请求频率更高
安全DTLS-SRTP 强制加密,握手可叠加 HTTPS明文或 HTTPS 可选建议 HTTPS,Apple 设备要求 HTTPS
设备要求需引入 WebRTC SDK,且媒体端口对客户端可达系统播放器直接支持,无需 SDK系统播放器可播,低版本系统按普通 HLS 的延迟表现

选择标准:一对一查看、实时互动、延迟敏感的场景走 WebRTC;观众量大、需要 CDN 或只需分钟级时效的场景走 HLS,其中追求秒级延迟时选 LL-HLS。

服务端准备:MediaMTX 最小可用配置

先让路径里有流:用任意客户端(如 FFmpeg 推 RTSP 到rtsp://服务器:8554/mystream)发布到某路径,移动端之后读取同一路径即可。

开启 WebRTC(WHEP)读取

在mediamtx.yml中:

# mediamtx.yml webrtc: true # 开启 WebRTC 服务,含 WHEP 读取端点 webrtcAddress: :8889 # WHEP 握手与网页播放的 HTTP 端口 webrtcEncryption: false # 握手层是否走 HTTPS;媒体流本身始终有 DTLS 加密 webrtcLocalUDPAddress: :8189 # ICE 媒体通道 UDP 端口,客户端必须能直连 webrtcAdditionalHosts: [192.168.1.100] # 下发给客户端的服务器可达地址,跨 NAT/容器场景必填 webrtcHandshakeTimeout: 10s # 握手等待上限,超时即断开

WHEP 端点固定为http://服务器:8889/路径/whep,客户端向它 POST 一个 SDP offer,服务器返回 answer。连接通不通,八成取决于webrtcAdditionalHosts和 UDP 端口放行,细节见 WebRTC 连接问题文档。

开启 HLS 读取(含 LL-HLS)

# mediamtx.yml hls: true # 开启 HLS 服务 hlsAddress: :8888 # HTTP 端口,播放入口为 http://服务器:8888/路径/index.m3u8 hlsEncryption: true # 启用 HTTPS;Apple 设备上 LL-HLS 要求 HTTPS hlsServerKey: server.key # 证书私钥路径 hlsServerCert: server.crt # 证书文件路径 hlsVariant: lowLatency # 三选一:mpegts / fmp4 / lowLatency hlsPartDuration: 200ms # LL-HLS 分片时长,直接决定延迟下限 hlsSegmentDuration: 1s # 完整分段时长,决定播放器缓冲粒度 hlsSegmentCount: 7 # 保留分段数,只影响可回看长度,不影响延迟

完整参数列表见 配置文件参考。

实时场景落地:iOS/Android 端 WHEP 最小接入代码

两端的流程一致:创建 PeerConnection → 生成 offer → POST 到 WHEP 端点 → 用响应里的 answer 设置远端描述 → 在 track 到达回调中渲染。

iOS 端 WHEP 最小接入代码

依赖 GoogleWebRTC(CocoaPods 引入GoogleWebRTC),核心如下:

import WebRTC final class WHEPPlayer: NSObject { private let pc = RTCPeerConnectionFactory() .peerConnection(with: RTCConfiguration(), constraints: nil, delegate: nil) func connect(_ whepUrl: String) { pc.offer(for: RTCMediaConstraints()) { [weak self] offer, _ in guard let offer else { return } self?.pc.setLocalDescription(offer) { _ in self?.post(offer.sdp, to: whepUrl) // 关键一步:POST offer } } } private func post(_ sdp: String, to url: String) { var req = URLRequest(url: URL(string: url)!) req.httpMethod = "POST" req.setValue("application/sdp", forHTTPHeaderField: "Content-Type") req.httpBody = sdp.data(using: .utf8) URLSession.shared.dataTask(with: req) { data, _, _ in guard let sdp = data.flatMap({ String(data: $0, encoding: .utf8) }) else { return } // 响应 body 即 answer,设置后媒体流开始到达 self.pc.setRemoteDescription(RTCSessionDescription(type: .answer, sdp: sdp)) { _ in } }.resume() } }

出画面:在RTCPeerConnectionDelegate的 track 到达回调中,把videoTrack加到RTCMTLVideoView上即可,其余样板代码从略。

Android 端 WHEP 最小接入代码

依赖org.webrtc:google-webrtc,核心如下:

class WHEPPlayer(private val surface: SurfaceViewRenderer) { private val pc = PeerConnectionFactory().createPeerConnection(RTCConfiguration(), observer) // observer 的 onAddTrack 回调里:track?.addSink(surface) fun connect(whepUrl: String) { val c = MediaConstraints().apply { mandatory["OfferToReceiveVideo"] = "true" mandatory["OfferToReceiveAudio"] = "true" } pc.createOffer(object : SdpObserver { override fun onCreateSuccess(sdp: SessionDescription) { pc.setLocalDescription(localCb, sdp) postOffer(sdp.description, whepUrl) // 成功后再执行 post } override fun onCreateFailure(e: String) {} override fun onSetSuccess() {} override fun onSetFailure(e: String) {} }, c) } // postOffer:POST application/sdp 到 whepUrl,响应 body 为 answer, // pc.setRemoteDescription(answer) 后媒体流触发 onAddTrack }

验证连接成功

  • 用 curl 向/whep发 POST,返回201 Created,且响应头Location给出会话地址,说明握手成功。
  • 客户端 PeerConnection 状态变为connected,track 回调开始触发并渲染画面。
  • 服务器日志出现该路径的 WebRTC 读取事件,说明服务器侧已建链。
  • 快速自检:浏览器直接打开http://服务器:8889/路径能播放,说明端点本身可用,问题可聚焦在客户端网络。

大规模分发落地:LL-HLS 低延迟模式怎么配

播放入口是http://服务器:8888/路径/index.m3u8。低延迟模式的取舍很直接:hlsPartDuration越小延迟越低,但分片请求频率越高,对服务器与 CDN 压力越大;mpegts变体兼容最旧,但延迟停留在 5 秒以上。弱网或需要兼容大量旧设备时退回mpegts,其余情况用lowLatency。要横向扩展观众数,把分片目录交给 CDN,并设置hlsCDNSecret识别 CDN 回源请求。

iOS 端 HLS 播放

系统 AVPlayer 即可,无需额外依赖:

let url = URL(string: "https://192.168.1.100:8888/mystream/index.m3u8")! let item = AVPlayerItem(url: url) item.preferredForwardBufferDuration = 2 // 压缩前向缓冲,让播放位置贴近直播边缘 let player = AVPlayer(playerItem: item) player.play()

Android 端 LL-HLS 低延迟播放

ExoPlayer 开启 chunkless preparation,playlist 就绪即可播放,不必等完整分段下载:

val dataSource = DefaultHttpDataSource.Factory() .setUserAgent("MTX-Player") .createDataSource() val source = HlsMediaSource.Factory(dataSource) .setAllowChunklessPreparation(true) // LL-HLS 关键开关:不等整段,分段/分片即播 .createMediaSource(MediaItem.fromUri("https://192.168.1.100:8888/mystream/index.m3u8")) exoPlayer.setMediaSource(source) exoPlayer.playWhenReady = true exoPlayer.prepare()

验证方式:curl 该.m3u8能返回含分段列表的 playlist(LL-HLS 下还会带#EXT-X-PART行),服务器日志出现 HLS 读取事件,即链路可用。

问题定位:连接失败、延迟高、播放卡顿排查表

现象可能原因处理动作
POST/whep返回 404该路径没有正在发布的流先向同路径发布流,或核对路径名与查询参数
POST/whep返回 403无 read 权限检查authInternalUsers中对应路径的read权限
WHEP 返回 201 但不出画面ICE 不通:UDP 8189 未放行,或webrtcAdditionalHosts缺少客户端可达地址填对webrtcAdditionalHosts、放行 8189/udp;仍不通则启用webrtcLocalTCPAddress,或配置 STUN/TURN
LL-HLS 延迟高于预期hlsPartDuration/hlsSegmentDuration过大,或播放器缓冲过大将 part 降到 200ms 左右;调小播放器缓冲(iOS 用preferredForwardBufferDuration)
iOS 上 LL-HLS 没有低延迟效果未启用 HTTPS将hlsEncryption设为 true,LL-HLS 在 Apple 设备上要求 HTTPS
播放间歇性卡顿UDP 丢包,或服务器出口带宽不足调大udpReadBufferSize;或改走 HLS 并由 CDN 分发(配合hlsCDNSecret)
首帧慢关键帧间隔过大在编码端缩短 GOP(如-g 30降到-g 15),每段需含 IDR 帧

WebRTC 连通性的更多排查顺序(UDP → TCP → STUN → TURN)见 WebRTC 特定特性文档。

两种场景的推荐组合

实时查看、互动类场景:WebRTC/WHEP,hlsVariant保持默认即可,把精力放在 UDP 端口与webrtcAdditionalHosts上。面向大量观众或需要 CDN 的场景:LL-HLS(hlsVariant: lowLatency,hlsPartDuration: 200ms),需要兼容旧设备时退回mpegts。协议与端点的完整说明见 读取流文档、WebRTC 客户端文档 与 HLS 文档。

【免费下载链接】mediamtxReady-to-use Media-over-QUIC / SRT / WebRTC / RTSP / RTMP / LL-HLS / MPEG-TS / RTP live media server and media proxy that allows to read, publish, proxy, record and playback real-time video and audio streams.项目地址: https://gitcode.com/GitHub_Trending/me/mediamtx

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询