引言:解决开发者的核心痛点
作为一名开发者,你是否曾在构建流媒体服务时面临这样的困境:为了兼容苹果的 HLS 协议,需要生成一套 .ts 文件;同时为了支持 DASH 协议,又得准备另一套 .mp4 文件。这种格式割裂不仅使编码流水线复杂不堪,更导致了存储成本和带宽开销的成倍增长。
CMAF 的诞生,正是为了终结这一局面。这篇技术指南将带你深入理解 通用媒体应用格式,如何通过“一次编码、一次存储,多协议交付”的先进理念,彻底优化你的流媒体架构。
CMAF,全称 Common Media Application Format,是由国际标准组织MPEG和ISO联合制定的一种媒体文件格式标准。它的核心目标非常明确:
充当HLS和DASH之间共享的通用媒体容器,实现流媒体交付的标准化与统一化。
对于开发者而言,可以将CMAF视为一个高度优化和标准化的 碎片化MP4 容器。它定义了如何将音视频内容分割成独立的、可通过CDN高效分发的媒体块(文件后缀通常为 .cmf 或 .m4s)。
理解CMAF的工作机制,关键在于掌握其两大组成部分:
1. CMAF媒体对象这是最基本的媒体数据单元,例如一个2秒时长的视频或音频碎片。每个对象都是自描述的,包含必要的元数据和媒体数据。
2. 革命性的设计:初始化段与媒体段分离这是CMAF实现高效传输的核心:
初始化段:一个体积很小的文件,包含了解码整个媒体轨道所需的所有元数据(如 moov box)。只需在播放开始时下载一次。
媒体段:仅包含纯媒体数据(如 moof + mdat boxes)。客户端在获取初始化段后,即可持续请求这些媒体段进行无缝播放。
这种设计消除了传统格式中每个片段都重复元数据的冗余,显著降低了传输开销。
以下是一个典型的CMAF工作流程,展示了其如何简化开发者的工作:
编码与封装源视频被编码为多码率,并直接封装成 CMAF格式的碎片化MP4,生成 .m4s 媒体段和初始化文件。
CDN存储这套统一的CMAF文件被上传至CDN。至此,你只需维护一套媒体文件。
动态清单生成
面向HLS客户端:服务器生成 .m3u8 清单,通过 #EXT-X-MAP 标签指向CMAF初始化段。
#EXTM3U #EXT-X-VERSION:7 #EXT-X-TARGETDURATION:2 #EXT-X-MAP:URI="init-video-1.mp4" #EXTINF:2.0, segment-1.m4s #EXTINF:2.0, segment-2.m4s ...
面向DASH客户端:服务器生成 .mpd 清单,其 <SegmentURL> 元素指向同一套CMAF媒体段。
<Representation bandwidth="2000000"> <BaseURL>init-video-1.mp4</BaseURL> <SegmentBase><Initialization range="0-687"/></SegmentBase> <SegmentList duration="2"> <SegmentURL media="segment-1.m4s"/> </SegmentList> </Representation>
客户端播放HLS或DASH播放器根据各自的清单文件,从同一个CDN源获取相同的CMAF文件进行播放,实现了真正的“源文件统一”。
存储与带宽成本减半:最直接的收益,无需再为HLS和DASH存储两套媒体文件,预计可降低约50%的存储与CDN成本。
架构简化:编码流水线只需输出一种格式,极大降低了系统的复杂度和运维负担。
赋能低延迟流媒体:CMAF是实现 LL-HLS 和 LL-DASH 的基石。其轻量的碎片结构是实现秒级延迟的关键。
无缝DRM集成:CMAF与 CENC 通用加密标准完美结合,支持“一次加密,多DRM系统(Widevine, PlayReady, FairPlay)解密”,简化了版权保护流程。
理论需要实践的验证。在WWDC25开发者大会上,苹果官网就采用了CMAF技术发布会议视频,这为CMAF的优越性提供了最具说服力的例证。
案例地址: https://devstreaming-cdn.apple.com/videos/meet-with-apple/2025/201/5/597cbd02-a20e-4124-9596-a8acc21e96af/cmaf.m3u8
以下对m3u8文件进行技术分析。
顶级cmaf.m3u8文件是一个主播放列表,其中包含了指向不同码率版本的流,内容如下:
#EXTM3U #EXT-X-VERSION:6 #EXT-X-INDEPENDENT-SEGMENTS #EXT-X-STREAM-INF:RESOLUTION=1280x720,CODECS="avc1.64001f,mp4a.40.2",BANDWIDTH=2441393,AVERAGE-BANDWIDTH=612930,FRAME-RATE=29.970,AUDIO="program_audio_0",SUBTITLES="subs" cmaf/avc/720p_3000/avc_720p_3000.m3u8 ...... #EXT-X-STREAM-INF:RESOLUTION=1280x720,CODECS="hvc1.2.4.H150.B0,mp4a.40.2",BANDWIDTH=2231985,AVERAGE-BANDWIDTH=470650,FRAME-RATE=29.970,AUDIO="program_audio_0",SUBTITLES="subs" cmaf/hvc/720p_3400/hvc_720p_3400.m3u8 ...... #EXT-X-MEDIA:TYPE=SUBTITLES,GROUP-ID="subs",LANGUAGE="en",NAME="English",AUTOSELECT=YES,DEFAULT=YES,URI="subtitles/eng/prog_index.m3u8",FORCED=NO #EXT-X-MEDIA:TYPE=SUBTITLES,GROUP-ID="subs",LANGUAGE="zh",NAME="简体中文",AUTOSELECT=YES,DEFAULT=NO,URI="subtitles/zho/prog_index.m3u8",FORCED=NO #EXT-X-MEDIA:TYPE=SUBTITLES,GROUP-ID="subs",LANGUAGE="ja",NAME="日本語",AUTOSELECT=YES,DEFAULT=NO,URI="subtitles/jpn/prog_index.m3u8",FORCED=NO #EXT-X-MEDIA:TYPE=SUBTITLES,GROUP-ID="subs",LANGUAGE="fr",NAME="Français",AUTOSELECT=YES,DEFAULT=NO,URI="subtitles/fra/prog_index.m3u8",FORCED=NO
可以看到包含H264、H265多个码率;英文、中文等多个字幕
zwplayer js网页播放器对m3u8文件多码流、多字幕有比较好的支持,通过zwplayer查看,有直观感受,界面如下:
内嵌多字幕

内嵌多码流

获取H264码流avc_720p_3000.m3u8
wget https://devstreaming-cdn.apple.com/videos/meet-with-apple/2025/201/5/597cbd02-a20e-4124-9596-a8acc21e96af/cmaf/avc/720p_3000/avc_720p_3000.m3u8
CMAF核心特征显现:在H264播放列表avc_720p_3000.m3u8中,我们看到了CMAF的典型实现:
#EXTM3U #EXT-X-VERSION:6 #EXT-X-TARGETDURATION:7 #EXT-X-MAP:URI="avc_720p_3000init.cmfv" <!-- CMAF初始化段 --> #EXTINF:6.006, avc_720p_3000_000000001.cmfv <!-- CMAF媒体段 --> #EXTINF:6.006, avc_720p_3000_000000002.cmfv ...
#EXT-X-MAP:这个标签明确指向了CMAF的初始化段 (avc_720p_3000init.cmfv),这是CMAF工作流区别于传统HLS+TS的关键标志。初始化段通常是一个独立的、小巧的文件,其中包含了ISO Base Media File Format(即MP4容器格式)中的 moov 原子。
获取avc_720p_3000init.cmfv
wget https://devstreaming-cdn.apple.com/videos/meet-with-apple/2025/201/5/597cbd02-a20e-4124-9596-a8acc21e96af/cmaf/avc/720p_3000/avc_720p_3000init.cmfv
可以用ffprobe等工具查看其详细信息。命令如下:
ffprobe -v error -show_format -show_streams avc_720p_3000init.cmfv
显示内容为:
[STREAM] index=0 codec_name=h264 codec_long_name=H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10 ... [FORMAT] filename=avc_720p_3000init.cmfv format_name=mov,mp4,m4a,3gp,3g2,mj2 format_long_name=QuickTime / MOV ... [/FORMAT]
查看codec_name,为h264格式
查看输出中的format_name字段,
若为mp4或mov,mp4,m4a,3gp,3g2,mj2,即为fMP4。
若为mpegts,则为TS封装。
关键信息
媒体段:文件avc_720p_3000_000000001.cmfv等就是CMAF格式的视频媒体段。文件扩展名.cmfv明确标识了其CMAF视频流的身份。
获取H265码流avc_720p_3000.m3u8
wget https://devstreaming-cdn.apple.com/videos/meet-with-apple/2025/201/5/597cbd02-a20e-4124-9596-a8acc21e96af/cmaf/hvc/720p_3400/hvc_720p_3400.m3u8
内容如下: 格式同H264
#EXTM3U #EXT-X-VERSION:6 #EXT-X-TARGETDURATION:7 #EXT-X-MEDIA-SEQUENCE:1 #EXT-X-PLAYLIST-TYPE:VOD #EXT-X-MAP:URI="hvc_720p_3400init.cmfv" <!-- CMAF初始化段 --> #EXTINF:6.006, hvc_720p_3400_000000001.cmfv <!-- CMAF媒体段 --> #EXTINF:6.006, hvc_720p_3400_000000002.cmfv .....
下载CMAF的初始化段 (hvc_720p_3400init.cmfv)。
wget https://devstreaming-cdn.apple.com/videos/meet-with-apple/2025/201/5/597cbd02-a20e-4124-9596-a8acc21e96af/cmaf/hvc/720p_3400/hvc_720p_3400init.cmfv
ffprobe等工具查看其详细信息。命令如下:
ffprobe -v error -show_format -show_streams hvc_720p_3400init.cmfv
显示内容为:
[STREAM] index=0 codec_name=hevc codec_long_name=H.265 / HEVC (High Efficiency Video Coding) profile=Main 10 ... [FORMAT] filename=hvc_720p_3400init.cmfv format_name=mov,mp4,m4a,3gp,3g2,mj2 format_long_name=QuickTime / MOV [/FORMAT]
查看codec_name,为hevc格式,即 H.265 格式
查看输出中的format_name字段,
若为mp4或mov,mp4,m4a,3gp,3g2,mj2,即为fMP4。
若为mpegts,则为TS封装。
关键信息
媒体段:文件avc_720p_3000_000000001.cmfv等就是CMAF格式的视频媒体段。文件扩展名.cmfv明确标识了其CMAF视频流的身份。
编码最佳实践
视频编码推荐使用 H.264/AVC 或 H.265/HEVC。
至关重要:所有码率版本的 GOP必须对齐,确保每个媒体段的起始点都是IDR帧,以实现无缝码率切换。
兼容性考量
现代设备:2017年后的iOS、Android设备及现代浏览器均能良好支持。
老旧设备:对于极旧的设备(如iOS 9之前),可能仍需保留TS格式作为降级方案,但此部分流量已可忽略不计。
CMAF 已成为现代流媒体技术栈中不可或缺的标准。对于开发者而言,采纳CMAF意味着构建更高效、更经济、面向未来的流媒体架构。它不仅是解决当前多协议交付难题的最佳方案,也为迎接8K、VR等下一代沉浸式媒体体验奠定了坚实的基础。
为了方便你在实际项目中应用HLS,我们整理了一份从官方文档到实用工具的资源清单。
苹果HLS官方规范: 最权威的第一手资料,包含最新的协议特性、最佳实践和作者工具。
IETF RFC 8216标准文档: HLS的官方国际标准,适合需要深入理解协议细节的开发者。
FFmpeg: 音视频处理的“瑞士军刀”,支持HLS的转码、切片、加密等全流程操作。
Shaka Packager: Google出品的强大打包工具,专注于将编码后的媒体文件打包成DASH和HLS所需的CMAF/fMP4片段。
