媒体数据封装
======

开发者可以调用本模块的Native API接口，完成音视频封装，即将音频、视频等编码后的媒体数据，按一定的格式存储到文件里。

当前支持的封装能力请参考AVCodec支持的格式中的[媒体数据封装](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/avcodec-support-formats#媒体数据封装)。

如果需要对HDRVivid视频码流进行封装，需要配置MimeType为H265 (OH\_AVCODEC\_MIMETYPE\_VIDEO\_HEVC)，本功能从API version 11开始支持。

**适用场景**

*   录像、录音
    
    保存录像、录音文件时，需要先对音视频流进行编码，再封装为文件。
    
*   音视频编辑
    
    完成编辑后的音视频，需要封装为文件。
    
*   音视频转码
    
    转码后，保存文件时需要封装。
    

#### 开发指导

详细的API说明请参考[native\_avmuxer.h](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/capi-native-avmuxer-h)。

![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/39/v3/RD5AbYIAS22MFZ9fQMqsnA/note_3.0-zh-cn.png?HW-CC-KV=V1&HW-CC-Date=20260709T132518Z&HW-CC-Expire=86400&HW-CC-Sign=1DDEE62EE0D3C9658F3E664A03C01FE01A95E937FB308E4EBB70551A5DA93508)

如果调用封装模块写本地文件，需要[向用户申请授权](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/request-user-authorization)：ohos.permission.READ\_MEDIA, ohos.permission.WRITE\_MEDIA。

#### \[h2\]在 CMake 脚本中链接动态库

target\_link\_libraries(sample PUBLIC libnative\_media\_avmuxer.so)
target\_link\_libraries(sample PUBLIC libnative\_media\_core.so)

#### \[h2\]mp4格式封装开发步骤

参考以下示例代码，完成音视频封装mp4的全流程。

不同的封装格式需要配置的key请参考AVCodec支持的格式中的[媒体数据封装](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/avcodec-support-formats#媒体数据封装)。

1.  添加头文件。
    
    #include <multimedia/player\_framework/native\_avmuxer.h>
    #include <multimedia/player\_framework/native\_avcodec\_base.h>
    #include <multimedia/player\_framework/native\_avformat.h>
    #include <multimedia/player\_framework/native\_avbuffer.h>
    #include <fcntl.h>
    
2.  调用OH\_AVMuxer\_Create()创建封装器实例对象。
    
    // 设置封装格式为mp4。
    OH\_AVOutputFormat format = AV\_OUTPUT\_FORMAT\_MPEG\_4;
    // 以读写方式创建fd。
    int32\_t fd = open("test.mp4", O\_CREAT | O\_RDWR | O\_TRUNC, S\_IRUSR | S\_IWUSR);
    OH\_AVMuxer \*muxer = OH\_AVMuxer\_Create(fd, format);
    
3.  （可选）调用OH\_AVMuxer\_SetRotation()设置旋转角度。
    
    // 旋转角度，视频画面需要旋转的时候设置。
    OH\_AVMuxer\_SetRotation(muxer, 0);
    
4.  添加文件级数据。
    
    文件级数据已定义的key详见AVCodec支持的格式中的[媒体数据封装](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/avcodec-support-formats#媒体数据封装)。
    
    用户自定义的key必须以"com.openharmony."为开头。值类型可以为int32\_t、float、string，从API version 20开始增加支持uint8\_t\*。
    
    ![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/2d/v3/Rrj1kJ-iS_-GOtCFQjD4cw/note_3.0-zh-cn.png?HW-CC-KV=V1&HW-CC-Date=20260709T132518Z&HW-CC-Expire=86400&HW-CC-Sign=1D1C6A9201735EAAE87A637527A8CCB638DE7A78EA05EFA44B9646C4836A93BC)
    
    已定义的key必须在OH\_AVMuxer\_Start()前设置，用户自定义的key可以在OH\_AVMuxer\_Stop()前设置。
    
    OH\_AVFormat \*format = OH\_AVFormat\_Create(); // 使用OH\_AVFormat\_Create创建format。
    
    // 设置已定义的key。
    OH\_AVFormat\_SetStringValue(format, OH\_MD\_KEY\_CREATION\_TIME, "2024-12-28T00:00:00.000000Z"); // 从API version 14开始支持设置创建时间（使用ISO 8601标准的时间格式且为UTC时间）。
    OH\_AVFormat\_SetStringValue(format, OH\_MD\_KEY\_COMMENT, "comment test"); // 从API version 20开始支持设置备注。值类型为string。
    OH\_AVFormat\_SetIntValue(format, OH\_MD\_KEY\_ENABLE\_MOOV\_FRONT, 1); // 从API version 20开始支持moov box位于mdat box前。默认值为0，设置1代表moov box位于mdat box前。
    OH\_AVFormat\_SetFloatValue(format, OH\_MD\_KEY\_LATITUDE, 39.9); // 从API version 24开始支持设置纬度，值类型为float，范围为\[-90.0, 90.0\]。当需要设置地理位置信息时，纬度和经度是必选的，不能仅设置一种。
    OH\_AVFormat\_SetFloatValue(format, OH\_MD\_KEY\_LONGITUDE, 116.3); // 从API version 24开始支持设置经度，值类型为float，范围为\[-180.0, 180.0\]。当需要设置地理位置信息时，纬度和经度是必选的，不能仅设置一种。
    OH\_AVFormat\_SetFloatValue(format, OH\_MD\_KEY\_ALTITUDE, 44.4); // 从API version 24开始支持设置海拔，值类型为float，设置地理位置信息时海拔是可选的。
    
    // 设置用户自定义key（需要com.openharmony.开头）。
    OH\_AVFormat\_SetIntValue(format, "com.openharmony.testInt", 1024); // 值类型为int32\_t。
    OH\_AVFormat\_SetFloatValue(format, "com.openharmony.testFloat", 1.024); // 值类型为float。
    OH\_AVFormat\_SetStringValue(format, "com.openharmony.testString", "string test"); // 值类型为string，长度不超过256个字符。
    uint8\_t testData\[\] = {1, 2, 3};
    OH\_AVFormat\_SetBuffer(format, "com.openharmony.testBuffer", testData, sizeof(testData)); // 从API version 20开始支持值类型为uint8\_t\*。
    
    int ret = OH\_AVMuxer\_SetFormat(muxer, format); // 设置封装的format。
    if (ret != AV\_ERR\_OK) {
       // 设置format失败，未找到有效待写入的key数据。
    }
    OH\_AVFormat\_Destroy(format); // 销毁。
    
5.  添加音频轨。
    
    **方法一：用OH\_AVFormat\_Create创建format**
    
    int audioTrackId = -1;
    uint8\_t \*buffer = ...; // 编码config data，如果没有可以不传。
    size\_t size = ...;  // 编码config data的长度，根据实际情况配置。
    OH\_AVFormat \*formatAudio = OH\_AVFormat\_Create(); // 使用OH\_AVFormat\_Create创建format，这里以封装44100Hz采样率、2声道的AAC-LC音频为例。
    OH\_AVFormat\_SetStringValue(formatAudio, OH\_MD\_KEY\_CODEC\_MIME, OH\_AVCODEC\_MIMETYPE\_AUDIO\_AAC); // 必填。
    OH\_AVFormat\_SetIntValue(formatAudio, OH\_MD\_KEY\_AUD\_SAMPLE\_RATE, 44100); // 必填。
    OH\_AVFormat\_SetIntValue(formatAudio, OH\_MD\_KEY\_AUD\_CHANNEL\_COUNT, 2); // 必填。
    OH\_AVFormat\_SetIntValue(formatAudio, OH\_MD\_KEY\_PROFILE, AAC\_PROFILE\_LC); // 选填。
    OH\_AVFormat\_SetBuffer(formatAudio, OH\_MD\_KEY\_CODEC\_CONFIG, buffer, size); // 选填。
    
    int ret = OH\_AVMuxer\_AddTrack(muxer, &audioTrackId, formatAudio);
    if (ret != AV\_ERR\_OK || audioTrackId < 0) {
        // 音频轨添加失败。
    }
    OH\_AVFormat\_Destroy(formatAudio); // 销毁。
    
    **方法二：用OH\_AVFormat\_CreateAudioFormat创建format**
    
    int audioTrackId = -1;
    uint8\_t \*buffer = ...; // 编码config data，如果没有可以不传。
    size\_t size = ...;  // 编码config data的长度，根据实际情况配置。
    OH\_AVFormat \*formatAudio = OH\_AVFormat\_CreateAudioFormat(OH\_AVCODEC\_MIMETYPE\_AUDIO\_AAC, 44100, 2);
    OH\_AVFormat\_SetIntValue(formatAudio, OH\_MD\_KEY\_PROFILE, AAC\_PROFILE\_LC); // 选填。
    OH\_AVFormat\_SetBuffer(formatAudio, OH\_MD\_KEY\_CODEC\_CONFIG, buffer, size); // 选填。
    
    int ret = OH\_AVMuxer\_AddTrack(muxer, &audioTrackId, formatAudio);
    if (ret != AV\_ERR\_OK || audioTrackId < 0) {
        // 音频轨添加失败。
    }
    OH\_AVFormat\_Destroy(formatAudio); // 销毁。
    
6.  添加视频轨。
    
    ![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/c3/v3/DLMWWYcqSHSQ34bni54DRw/note_3.0-zh-cn.png?HW-CC-KV=V1&HW-CC-Date=20260709T132518Z&HW-CC-Expire=86400&HW-CC-Sign=152228E7956CAC431E78967B5F41CDF0A35EA8B6D247B0B37FE9AF3C18179635)
    
    *   当开发者需要设置色彩信息时，必须保证OH\_MD\_KEY\_COLOR\_PRIMARIES、OH\_MD\_KEY\_TRANSFER\_CHARACTERISTICS、OH\_MD\_KEY\_MATRIX\_COEFFICIENTS三个key设置的值都在其各自的参数范围内，系统才会识别这是有效色彩信息数据。参数设置范围可参考[OH\_ColorPrimary](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/capi-native-avcodec-base-h#oh_colorprimary)、[OH\_TransferCharacteristic](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/capi-native-avcodec-base-h#oh_transfercharacteristic)和[OH\_MatrixCoefficient](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/capi-native-avcodec-base-h#oh_matrixcoefficient)。
    *   当开发者输入的色彩信息与视频码流的参数集中的色彩信息不一致时，系统以视频码流中的色彩信息为准。
    
    **方法一：用OH\_AVFormat\_Create创建format**
    
    int videoTrackId = -1;
    uint8\_t \*buffer = ...; // 编码config data，如果没有可以不传。
    size\_t size = ...;  // 编码config data的长度，根据实际情况配置。
    OH\_AVFormat \*formatVideo = OH\_AVFormat\_Create();
    OH\_AVFormat\_SetStringValue(formatVideo, OH\_MD\_KEY\_CODEC\_MIME, OH\_AVCODEC\_MIMETYPE\_VIDEO\_AVC); // 必填。
    OH\_AVFormat\_SetIntValue(formatVideo, OH\_MD\_KEY\_WIDTH, 1280); // 必填。
    OH\_AVFormat\_SetIntValue(formatVideo, OH\_MD\_KEY\_HEIGHT, 720); // 必填。
    OH\_AVFormat\_SetBuffer(formatVideo, OH\_MD\_KEY\_CODEC\_CONFIG, buffer, size); // 选填。
    OH\_AVFormat\_SetIntValue(formatVideo, OH\_MD\_KEY\_COLOR\_PRIMARIES, OH\_ColorPrimary::COLOR\_PRIMARY\_BT709); // 色彩信息，选填。
    OH\_AVFormat\_SetIntValue(formatVideo, OH\_MD\_KEY\_TRANSFER\_CHARACTERISTICS, OH\_TransferCharacteristic::TRANSFER\_CHARACTERISTIC\_BT709); // 色彩信息，选填。
    OH\_AVFormat\_SetIntValue(formatVideo, OH\_MD\_KEY\_MATRIX\_COEFFICIENTS, OH\_MatrixCoefficient::MATRIX\_COEFFICIENT\_BT709); // 色彩信息，选填。
    OH\_AVFormat\_SetIntValue(formatVideo, OH\_MD\_KEY\_RANGE\_FLAG, 1); // 色彩信息，选填。值为0代表limited range，值为1代表full range。
    
    int ret = OH\_AVMuxer\_AddTrack(muxer, &videoTrackId, formatVideo);
    if (ret != AV\_ERR\_OK || videoTrackId < 0) {
        // 视频轨添加失败。
    }
    OH\_AVFormat\_Destroy(formatVideo); // 销毁。
    
    **方法二：用OH\_AVFormat\_CreateVideoFormat创建format**
    
    int videoTrackId = -1;
    uint8\_t \*buffer = ...; // 编码config data，如果没有可以不传。
    size\_t size = ...;  // 编码config data的长度，根据实际情况配置。
    OH\_AVFormat \*formatVideo = OH\_AVFormat\_CreateVideoFormat(OH\_AVCODEC\_MIMETYPE\_VIDEO\_AVC, 1280, 720);
    OH\_AVFormat\_SetBuffer(formatVideo, OH\_MD\_KEY\_CODEC\_CONFIG, buffer, size); // 选填。
    OH\_AVFormat\_SetIntValue(formatVideo, OH\_MD\_KEY\_COLOR\_PRIMARIES, OH\_ColorPrimary::COLOR\_PRIMARY\_BT709); // 色彩信息，选填。
    OH\_AVFormat\_SetIntValue(formatVideo, OH\_MD\_KEY\_TRANSFER\_CHARACTERISTICS, OH\_TransferCharacteristic::TRANSFER\_CHARACTERISTIC\_BT709); // 色彩信息，选填。
    OH\_AVFormat\_SetIntValue(formatVideo, OH\_MD\_KEY\_MATRIX\_COEFFICIENTS, OH\_MatrixCoefficient::MATRIX\_COEFFICIENT\_BT709); // 色彩信息，选填。
    OH\_AVFormat\_SetIntValue(formatVideo, OH\_MD\_KEY\_RANGE\_FLAG, 1); // 色彩信息，选填。值为0代表limited range，值为1代表full range。
    
    int ret = OH\_AVMuxer\_AddTrack(muxer, &videoTrackId, formatVideo);
    if (ret != AV\_ERR\_OK || videoTrackId < 0) {
        // 视频轨添加失败。
    }
    OH\_AVFormat\_Destroy(formatVideo); // 销毁。
    
7.  添加辅助轨。
    
    ![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/42/v3/25OrBoALT_ORcOE8OTU22g/note_3.0-zh-cn.png?HW-CC-KV=V1&HW-CC-Date=20260709T132518Z&HW-CC-Expire=86400&HW-CC-Sign=43E0EF672486C823823540D1AE13D3CCAFF492C3EB1040CC62425040E15C69CD)
    
    设置OH\_MD\_KEY\_TRACK\_TYPE时，值为MEDIA\_TYPE\_AUXILIARY代表添加辅助轨。
    
    设置OH\_MD\_KEY\_TRACK\_REFERENCE\_TYPE时，值必须为"hint"、"cdsc"、"font"、"hind"、"vdep"、"vplx"、"subt"、"thmb"、"auxl"、"cdtg"、"shsc"或"aest"其中一项。
    
    设置OH\_MD\_KEY\_TRACK\_DESCRIPTION时，值必须为"com.openharmony."开头且长度不超过256个字符的字符串。
    
    设置OH\_MD\_KEY\_REFERENCE\_TRACK\_IDS时，track id值必须大于等于0，且必须是已经存在的track id。
    
    **添加音频辅助轨**
    
    int32\_t audioAuxlTrackId = -1;
    std::vector<int32\_t> audioTrackIDsVector = {0}; // 根据实际情况设置被辅助音频轨的编号，可填写多个值。
    int32\_t \*audioAuxlTrackIDs = audioTrackIDsVector.data();
    OH\_AVFormat \*audioAuxlFormat = OH\_AVFormat\_Create();
    OH\_AVFormat\_SetStringValue(audioAuxlFormat, OH\_MD\_KEY\_CODEC\_MIME, OH\_AVCODEC\_MIMETYPE\_AUDIO\_AAC); // 必填。
    OH\_AVFormat\_SetIntValue(audioAuxlFormat, OH\_MD\_KEY\_AUD\_SAMPLE\_RATE, 44100); // 必填。
    OH\_AVFormat\_SetIntValue(audioAuxlFormat, OH\_MD\_KEY\_AUD\_CHANNEL\_COUNT, 2); // 必填。
    OH\_AVFormat\_SetIntValue(audioAuxlFormat, OH\_MD\_KEY\_PROFILE, AAC\_PROFILE\_LC); // 选填。
    OH\_AVFormat\_SetIntValue(audioAuxlFormat, OH\_MD\_KEY\_TRACK\_TYPE, static\_cast<int32\_t>(OH\_MediaType::MEDIA\_TYPE\_AUXILIARY)); // 必填。
    OH\_AVFormat\_SetStringValue(audioAuxlFormat, OH\_MD\_KEY\_TRACK\_REFERENCE\_TYPE, "auxl"); // 必填。
    OH\_AVFormat\_SetStringValue(audioAuxlFormat, OH\_MD\_KEY\_TRACK\_DESCRIPTION, "com.openharmony.audiomode.auxiliary"); // 必填。
    OH\_AVFormat\_SetIntBuffer(audioAuxlFormat, OH\_MD\_KEY\_REFERENCE\_TRACK\_IDS, audioAuxlTrackIDs, audioTrackIDsVector.size()); // 必填。
    
    int ret = OH\_AVMuxer\_AddTrack(muxer, &audioAuxlTrackId, audioAuxlFormat);
    if (ret != AV\_ERR\_OK || audioAuxlTrackId < 0) {
        // 音频辅助轨添加失败。
    }
    
    **添加视频辅助轨**
    
    int32\_t videoAuxlTrackId = -1;
    std::vector<int32\_t> videoTrackIDsVector = {0}; // 根据实际情况设置被辅助视频轨的编号，可填写多个值。
    int32\_t \*videoAuxlTrackIDs = videoTrackIDsVector.data();
    OH\_AVFormat \*videoAuxlFormat = OH\_AVFormat\_Create();
    OH\_AVFormat\_SetStringValue(videoAuxlFormat, OH\_MD\_KEY\_CODEC\_MIME, OH\_AVCODEC\_MIMETYPE\_VIDEO\_AVC); // 必填。
    OH\_AVFormat\_SetIntValue(videoAuxlFormat, OH\_MD\_KEY\_WIDTH, 1280); // 必填。
    OH\_AVFormat\_SetIntValue(videoAuxlFormat, OH\_MD\_KEY\_HEIGHT, 720); // 必填。
    OH\_AVFormat\_SetIntValue(videoAuxlFormat, OH\_MD\_KEY\_TRACK\_TYPE, static\_cast<int32\_t>(OH\_MediaType::MEDIA\_TYPE\_AUXILIARY)); // 必填。
    OH\_AVFormat\_SetStringValue(videoAuxlFormat, OH\_MD\_KEY\_TRACK\_REFERENCE\_TYPE, "vdep"); // 必填。
    OH\_AVFormat\_SetStringValue(videoAuxlFormat, OH\_MD\_KEY\_TRACK\_DESCRIPTION, "com.openharmony.moviemode.depth"); // 必填。
    OH\_AVFormat\_SetIntBuffer(videoAuxlFormat, OH\_MD\_KEY\_REFERENCE\_TRACK\_IDS, videoAuxlTrackIDs, videoTrackIDsVector.size()); // 必填。
    
    int ret = OH\_AVMuxer\_AddTrack(muxer, &videoAuxlTrackId, videoAuxlFormat);
    if (ret != AV\_ERR\_OK || videoAuxlTrackId < 0) {
        // 视频辅助轨添加失败。
    }
    
8.  添加封面轨。
    
    **方法一：用OH\_AVFormat\_Create创建format**
    
    int coverTrackId = -1;
    OH\_AVFormat \*formatCover = OH\_AVFormat\_Create();
    OH\_AVFormat\_SetStringValue(formatCover, OH\_MD\_KEY\_CODEC\_MIME, OH\_AVCODEC\_MIMETYPE\_IMAGE\_JPG);
    OH\_AVFormat\_SetIntValue(formatCover, OH\_MD\_KEY\_WIDTH, 1280);
    OH\_AVFormat\_SetIntValue(formatCover, OH\_MD\_KEY\_HEIGHT, 720);
    
    int ret = OH\_AVMuxer\_AddTrack(muxer, &coverTrackId, formatCover);
    if (ret != AV\_ERR\_OK || coverTrackId < 0) {
        // 添加封面失败。
    }
    OH\_AVFormat\_Destroy(formatCover); // 销毁。
    
    **方法二：用OH\_AVFormat\_CreateVideoFormat创建format**
    
    int coverTrackId = -1;
    OH\_AVFormat \*formatCover = OH\_AVFormat\_CreateVideoFormat(OH\_AVCODEC\_MIMETYPE\_IMAGE\_JPG, 1280, 720);
    
    int ret = OH\_AVMuxer\_AddTrack(muxer, &coverTrackId, formatCover);
    if (ret != AV\_ERR\_OK || coverTrackId < 0) {
        // 添加封面失败。
    }
    OH\_AVFormat\_Destroy(formatCover); // 销毁。
    
9.  调用OH\_AVMuxer\_Start()开始封装。
    
    // 调用start写封装文件头。start后，不能设置媒体参数、不能添加音视频轨。
    if (OH\_AVMuxer\_Start(muxer) != AV\_ERR\_OK) {
        // 异常处理。
    }
    
10.  调用OH\_AVMuxer\_WriteSampleBuffer()，写入封装数据。
     
     封装数据包括视频、音频、封面等数据。
     
     // start后，才能开始写入数据。
     int size = ...;
     OH\_AVBuffer \*sample = OH\_AVBuffer\_Create(size); // 创建AVBuffer。
     // 通过OH\_AVBuffer\_GetAddr(sample)往sampleBuffer里写入数据参考OH\_AVBuffer的使用方法。
     // 封装封面，必须一次写完一张图片。
     
     // 创建buffer info。
     OH\_AVCodecBufferAttr info = {0};
     info.pts = ...; // 当前数据的开始播放的时间，单位微秒，相对时间。
     info.size = size; // 当前数据的长度。
     info.offset = 0; // 偏移，一般为0。
     info.flags |= AVCODEC\_BUFFER\_FLAGS\_SYNC\_FRAME; // 当前数据的标志。具体参考OH\_AVCodecBufferFlags。
     info.flags |= AVCODEC\_BUFFER\_FLAGS\_CODEC\_DATA; // 当annex-b格式的avc包含codec config的标志。
     OH\_AVBuffer\_SetBufferAttr(sample, &info); // 设置buffer的属性。
     int trackId = audioTrackId; // 选择写的音视频轨。
     
     int ret = OH\_AVMuxer\_WriteSampleBuffer(muxer, trackId, sample);
     if (ret != AV\_ERR\_OK) {
         // 异常处理。
     }
     
11.  调用OH\_AVMuxer\_Stop()，停止封装。
     
     // 调用stop，写封装文件尾。stop后不能写入媒体数据。
     if (OH\_AVMuxer\_Stop(muxer) != AV\_ERR\_OK) {
         // 异常处理。
     }
     
12.  调用OH\_AVMuxer\_Destroy()销毁实例，释放资源。
     
     注意不能重复销毁，否则将会导致程序崩溃。
     
     if (OH\_AVMuxer\_Destroy(muxer) != AV\_ERR\_OK) {
         // 异常处理。
     }
     muxer = NULL;
     close(fd); // 关闭文件描述符。
     

#### \[h2\]flv格式封装开发步骤

从API版本26.0.0开始支持flv格式封装。

flv格式仅支持一个音频轨和一个视频轨，不支持设置旋转角度、封面轨和辅助轨。

flv格式封装需要配置的key请参考AVCodec支持的格式中的[媒体数据封装](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/avcodec-support-formats#媒体数据封装)。

1.  添加头文件。
    
    #include <multimedia/player\_framework/native\_avmuxer.h>
    #include <multimedia/player\_framework/native\_avcodec\_base.h>
    #include <multimedia/player\_framework/native\_avformat.h>
    #include <multimedia/player\_framework/native\_avbuffer.h>
    #include <fcntl.h>
    
2.  调用OH\_AVMuxer\_Create()创建封装器实例对象。
    
    // 以读写方式创建fd。
    int32\_t fd = open("test.flv", O\_CREAT | O\_RDWR | O\_TRUNC, S\_IRUSR | S\_IWUSR);
    // 设置封装格式为flv。
    OH\_AVMuxer \*muxer = OH\_AVMuxer\_Create(fd, AV\_OUTPUT\_FORMAT\_FLV);
    
3.  flv格式不支持调用OH\_AVMuxer\_SetRotation()设置旋转角度，调用将返回错误。
    
4.  添加文件级数据。
    
    文件级数据已定义的key详见AVCodec支持的格式中的[媒体数据封装](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/avcodec-support-formats#媒体数据封装)。
    
    用户自定义的key必须以"com.openharmony."为开头。值类型为string。
    
    ![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/94/v3/HhsPIY8IT4yRRt9Dbb2J_w/note_3.0-zh-cn.png?HW-CC-KV=V1&HW-CC-Date=20260709T132518Z&HW-CC-Expire=86400&HW-CC-Sign=590B22A717788B1C83AB3C3698249F18D373328DBF5A27F48F19AF2CC807D287)
    
    *   已定义的key必须在OH\_AVMuxer\_Start()前设置，用户自定义的key可以在OH\_AVMuxer\_Stop()前设置。
    *   flv格式不支持OH\_MD\_KEY\_ENABLE\_MOOV\_FRONT。
    
    OH\_AVFormat \*format = OH\_AVFormat\_Create(); // 使用OH\_AVFormat\_Create创建format。
    
    // 设置已定义的key。
    OH\_AVFormat\_SetStringValue(format, OH\_MD\_KEY\_CREATION\_TIME, "2024-12-28T00:00:00.000000Z"); // 从API version 14开始支持设置创建时间（使用ISO 8601标准的时间格式且为UTC时间）。
    OH\_AVFormat\_SetStringValue(format, OH\_MD\_KEY\_COMMENT, "comment test"); // 从API version 20开始支持设置备注。值类型为string。
    
    // 设置用户自定义key（需要com.openharmony.开头）。
    OH\_AVFormat\_SetStringValue(format, "com.openharmony.testString", "string test"); // 值类型为string，长度不超过256个字符。
    
    int ret = OH\_AVMuxer\_SetFormat(muxer, format); // 设置封装的format。
    if (ret != AV\_ERR\_OK) {
       // 设置format失败，未找到有效待写入的key数据。
    }
    OH\_AVFormat\_Destroy(format); // 销毁。
    
5.  添加音频轨（仅支持添加一个音频轨）。
    
    **添加AAC音频轨**
    
    ![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/7e/v3/c9We0BrERme7clOGonOzzw/note_3.0-zh-cn.png?HW-CC-KV=V1&HW-CC-Date=20260709T132518Z&HW-CC-Expire=86400&HW-CC-Sign=5AB5E4C16AF392D08A2382A6CF1A352361C7658AA0539001C7FF59DB56D2BD88)
    
    音频编解码类型为HE-AAC（AAC\_PROFILE\_HE或AAC\_PROFILE\_HE\_V2）时，仅支持采样率大于等于16000Hz。
    
    int audioTrackId = -1;
    // 以封装44100Hz采样率、2声道的AAC-LC音频为例。
    OH\_AVFormat \*formatAudio = OH\_AVFormat\_CreateAudioFormat(OH\_AVCODEC\_MIMETYPE\_AUDIO\_AAC, 44100, 2);
    OH\_AVFormat\_SetIntValue(formatAudio, OH\_MD\_KEY\_PROFILE, AAC\_PROFILE\_LC); // 选填。
    
    int ret = OH\_AVMuxer\_AddTrack(muxer, &audioTrackId, formatAudio);
    OH\_AVFormat\_Destroy(formatAudio);
    if (ret != AV\_ERR\_OK || audioTrackId < 0) {
        // 音频轨添加失败。
    }
    

**添加Audio Vivid音频轨**

int audioTrackId = -1;
// 以封装48000Hz采样率、2声道的Audio Vivid音频为例。
OH\_AVFormat \*formatAudio = OH\_AVFormat\_CreateAudioFormat(OH\_AVCODEC\_MIMETYPE\_AUDIO\_VIVID, 48000, 2);
OH\_AVFormat\_SetIntValue(formatAudio, OH\_MD\_KEY\_BIT\_RATE, 128000); // 选填。

int ret = OH\_AVMuxer\_AddTrack(muxer, &audioTrackId, formatAudio);
OH\_AVFormat\_Destroy(formatAudio);
if (ret != AV\_ERR\_OK || audioTrackId < 0) {
    // 音频轨添加失败。
}

1.  添加视频轨（仅支持添加一个视频轨）。
    
    ![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/52/v3/dY8iS4J6RZazw3KNpvH8HQ/note_3.0-zh-cn.png?HW-CC-KV=V1&HW-CC-Date=20260709T132518Z&HW-CC-Expire=86400&HW-CC-Sign=C6AA5D550350BF80DB9A4BCDC15C8C468F061CC34003F11FF0FE5325A0D01522)
    
    当开发者需要设置色彩信息时，必须保证OH\_MD\_KEY\_COLOR\_PRIMARIES、OH\_MD\_KEY\_TRANSFER\_CHARACTERISTICS、OH\_MD\_KEY\_MATRIX\_COEFFICIENTS三个key设置的值都在其各自的参数范围内，系统才会识别这是有效色彩信息数据。参数设置范围可参考[OH\_ColorPrimary](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/capi-native-avcodec-base-h#oh_colorprimary)、[OH\_TransferCharacteristic](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/capi-native-avcodec-base-h#oh_transfercharacteristic)和[OH\_MatrixCoefficient](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/capi-native-avcodec-base-h#oh_matrixcoefficient)。
    
    int videoTrackId = -1;
    OH\_AVFormat \*formatVideo = OH\_AVFormat\_CreateVideoFormat(OH\_AVCODEC\_MIMETYPE\_VIDEO\_AVC, 1280, 720);
    OH\_AVFormat\_SetDoubleValue(formatVideo, OH\_MD\_KEY\_FRAME\_RATE, 30.0); // 选填。
    
    int ret = OH\_AVMuxer\_AddTrack(muxer, &videoTrackId, formatVideo);
    OH\_AVFormat\_Destroy(formatVideo);
    if (ret != AV\_ERR\_OK || videoTrackId < 0) {
        // 视频轨添加失败。
    }
    
    当视频轨需要设置色彩信息时，在使用OH\_AVMuxer\_AddTrack()之前先设置色彩信息相关key。
    
    OH\_AVFormat\_SetIntValue(formatVideo, OH\_MD\_KEY\_COLOR\_PRIMARIES, OH\_ColorPrimary::COLOR\_PRIMARY\_BT709); // 选填。
    OH\_AVFormat\_SetIntValue(formatVideo, OH\_MD\_KEY\_TRANSFER\_CHARACTERISTICS, OH\_TransferCharacteristic::TRANSFER\_CHARACTERISTIC\_BT709); // 选填。
    OH\_AVFormat\_SetIntValue(formatVideo, OH\_MD\_KEY\_MATRIX\_COEFFICIENTS, OH\_MatrixCoefficient::MATRIX\_COEFFICIENT\_BT709); // 选填。
    OH\_AVFormat\_SetIntValue(formatVideo, OH\_MD\_KEY\_RANGE\_FLAG, 1); // 选填。值为0代表limited range，值为1代表full range。
    
2.  调用OH\_AVMuxer\_Start()开始封装。
    
    // 调用start写封装文件头。start后，不能设置媒体参数、不能添加音视频轨。
    if (OH\_AVMuxer\_Start(muxer) != AV\_ERR\_OK) {
        // 异常处理。
    }
    
3.  调用OH\_AVMuxer\_WriteSampleBuffer()，写入封装数据。
    
    封装数据包括视频、音频数据。
    
    // start后，才能开始写入数据。以下以写入一帧48000Hz采样率、1024采样点的音频数据为例。
    int32\_t size = 1024; // 当前编码帧的数据长度，单位为字节。
    OH\_AVBuffer \*sample = OH\_AVBuffer\_Create(size); // 创建AVBuffer。
    // 通过OH\_AVBuffer\_GetAddr(sample)往sampleBuffer里写入数据参考OH\_AVBuffer的使用方法。
    
    // 创建buffer info。
    OH\_AVCodecBufferAttr attr = {0};
    attr.pts = 0; // 当前数据的开始播放的时间，单位微秒，相对时间。首帧为0，后续按“采样点数\*1000000/采样率”递增。
    attr.size = size; // 当前数据的长度，单位为字节。
    attr.offset = 0; // 偏移，一般为0。
    attr.flags |= AVCODEC\_BUFFER\_FLAGS\_SYNC\_FRAME; // 当前数据的标志。具体参考OH\_AVCodecBufferFlags。
    attr.flags |= AVCODEC\_BUFFER\_FLAGS\_CODEC\_DATA; // 当annex-b格式的avc/hevc包含codec config的标志。
    OH\_AVBuffer\_SetBufferAttr(sample, &attr);
    int trackId = audioTrackId; // 选择写的音视频轨。
    
    int ret = OH\_AVMuxer\_WriteSampleBuffer(muxer, trackId, sample);
    if (ret != AV\_ERR\_OK) {
        // 异常处理。
    }
    OH\_AVBuffer\_Destroy(sample); // 写入完成后销毁buffer。
    
4.  调用OH\_AVMuxer\_Stop()，停止封装。
    
    // 调用stop，写封装文件尾。stop后不能写入媒体数据。
    int ret = OH\_AVMuxer\_Stop(muxer);
    if (ret != AV\_ERR\_OK) {
        // 异常处理。
    }
    
5.  调用OH\_AVMuxer\_Destroy()销毁实例，释放资源。
    
    注意不能重复销毁，否则将会导致程序崩溃。
    
    OH\_AVMuxer\_Destroy(muxer);
    muxer = nullptr;
    close(fd); // 关闭文件描述符。