HarmonyOS 鸿蒙Next中视频中提取音频,不使用第三方库@ohos/mp4parser

HarmonyOS 鸿蒙Next中视频中提取音频,不使用第三方库@ohos/mp4parser 第三方库体积较大,有没有直接调用系统api的方式

8 回复

开发者您好,可以参考视频解析流程,单独提取音频轨道(MEDIA_TYPE_AUD)并将音频轨道数据读取后(OH_AVDemuxer_ReadSampleBuffer)单独保存,具体您可以参考官网文档:媒体数据解析。

更多关于HarmonyOS 鸿蒙Next中视频中提取音频,不使用第三方库@ohos/mp4parser的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


prepare

prepare(config: AVTranscoderConfig): Promise<void>

异步方式进行视频转码的参数设置。通过Promise获取返回值。

系统能力: SystemCapability.Multimedia.Media.AVTranscoder

参数:

参数名 类型 必填 说明
config AVTranscoderConfig 是 配置视频转码的相关参数。

返回值:

类型 说明
Promise<void> 异步视频转码prepare方法的Promise返回值。

错误码:

以下错误码的详细介绍请参见媒体错误码。

错误码ID 错误信息
401 The parameter check failed. Return by promise.
5400102 Operation not allowed. Return by promise.
5400105 Service died. Return by promise.
5400106 Unsupported format. Returned by promise.

示例:

import { BusinessError } from '@kit.BasicServicesKit';
// 配置参数以实际硬件设备支持的范围为准
let avTranscoderConfig: media.AVTranscoderConfig = {
audioBitrate : 200000,
audioCodec : media.CodecMimeType.AUDIO_AAC,
fileFormat : media.ContainerFormatType.CFT_MPEG_4,
videoBitrate : 3000000,
videoCodec : media.CodecMimeType.VIDEO_AVC,
videoFrameWidth : 1280,
videoFrameHeight : 720,
}
avTranscoder.prepare(avTranscoderConfig).then(() => {
console.info('prepare success');
}).catch((err: BusinessError) => {
console.error('prepare failed and catch error is ' + err.message);
});

https://developer.huawei.com/consumer/cn/doc/harmonyos-references-V5/js-apis-media-V5#avtranscoder10

你好,可以看看三方库中心仓的 [https://ohpm.openharmony.cn/#/cn/detail/@prq%2Fffmpeg-tools](https://ohpm.openharmony.cn/#/cn/detail/@prq%2Fffmpeg-tools)

在鸿蒙中调用 FFmpeg 命令行工具(fftools),最终驱动 FFmpeg.so 执行音视频处理任务。

/**
 * FFmpegTools 从视频中提取音频 使用示例
 */
import {  
  FFmpegManager,
  FFmpegFactory,
  FFmpegCommandBuilder,
  TaskCallback,
  ContainerFormat 
} from '[@prq](/user/prq)/ffmpeg-tools';

export class BasicUsageExample {
  private manager: FFmpegManager = FFmpegManager.getInstance();

  /** 提取音频 */
  extractAudio(): void {
    const cmd = FFmpegFactory.extractAudio('/video.mp4', '/audio.aac');
    this.run(cmd);
  }

  private run(cmd: string[]): void {
    const callback: TaskCallback = {
      onStart: (): void => { console.info('开始'); },
      onProgress: (p: number): void => { console.info(`进度: ${(p * 100).toFixed(1)}%`); },
      onSuccess: (): void => { console.info('成功'); },
      onFailure: (): void => { console.info('失败'); }
    };
    this.manager.execute(cmd, 120000, callback);
  }
}

目前暂时无法调用系统API

还真没有哦!

官方示例代码中也是推荐的使用第三方库[@ohos/mp4parser](https://ohpm.openharmony.cn/#/cn/detail/@ohos%2Fmp4parser)实现提取视频中音频的功能。

这个prepare应该可以满足他的需求吧

prepare(config: AVTranscoderConfig): Promise<void>

异步方式进行视频转码的参数设置。通过Promise获取返回值。

系统能力: SystemCapability.Multimedia.Media.AVTranscoder

参数:

参数名 类型 必填 说明
config AVTranscoderConfig 是 配置视频转码的相关参数。

返回值:

类型 说明
Promise<void> 异步视频转码prepare方法的Promise返回值。

错误码:

以下错误码的详细介绍请参见媒体错误码。

错误码ID 错误信息
401 The parameter check failed. Return by promise.
5400102 Operation not allowed. Return by promise.
5400105 Service died. Return by promise.
5400106 Unsupported format. Returned by promise.

示例:

import { BusinessError } from '@kit.BasicServicesKit';
// 配置参数以实际硬件设备支持的范围为准
let avTranscoderConfig: media.AVTranscoderConfig = {
audioBitrate : 200000,
audioCodec : media.CodecMimeType.AUDIO_AAC,
fileFormat : media.ContainerFormatType.CFT_MPEG_4,
videoBitrate : 3000000,
videoCodec : media.CodecMimeType.VIDEO_AVC,
videoFrameWidth : 1280,
videoFrameHeight : 720,
}
avTranscoder.prepare(avTranscoderConfig).then(() => {
console.info('prepare success');
}).catch((err: BusinessError) => {
console.error('prepare failed and catch error is ' + err.message);
});

在HarmonyOS Next中,可使用@ohos.multimedia.media中的AVDemuxer分离视频中的音频轨道,再通过AVCodec解码并输出为所需格式。无需第三方库,仅调用系统多媒体API即可完成提取。

可以使用系统 API 完成,无需引入第三方库。HarmonyOS Next 提供了媒体解封装(AVDemuxer)和封装(AVMuxer)能力,直接从视频中提取音频并封装为独立文件。

简要步骤:

  1. 创建 AVSource 并打开视频文件。
  2. 创建 AVDemuxer,获取音频轨道信息(audioTracks),选中目标轨道并开始解封装。
  3. 创建 AVMuxer,设置输出格式(如 m4a)并添加音频轨。
  4. 循环从 AVDemuxer 读取音频 AVBuffer,再写入 AVMuxer。
  5. 完成后销毁资源。

核心代码示例(精简版):

import { media } from '@kit.MediaKit';
import { fileIo } from '@kit.CoreFileKit';

async function extractAudio(videoPath: string, audioPath: string) {
  let source: media.AVSource = await media.createAVSource();
  await source.open(videoPath);
  
  let demuxer: media.AVDemuxer = await media.createAVDemuxer();
  await demuxer.setSource(source);
  
  let tracks = demuxer.getTrackVCodecInfo();
  let audioTrackIndex = -1;
  for (let i = 0; i < tracks.length; i++) {
    if (tracks[i].trackType === media.MediaType.MEDIA_TYPE_AUD) {
      audioTrackIndex = tracks[i].trackId;
      break;
    }
  }
  if (audioTrackIndex < 0) {
    throw new Error('no audio track');
  }
  await demuxer.selectTrackByID(audioTrackIndex);
  
  let muxer: media.AVMuxer = await media.createAVMuxer();
  let fd = fileIo.openSync(audioPath, fileIo.OpenMode.CREATE | fileIo.OpenMode.WRITE_ONLY);
  await muxer.setOutput(fd.fd);
  await muxer.setMuxerFormat('m4a');
  // 添加音频轨道参数(可从demuxer获取具体编码信息)
  await muxer.addTrack({ codec: 'mp4a-latm', ... });
  await muxer.start();
  
  while (true) {
    let buffer: media.AVBuffer = await demuxer.readSampleData(audioTrackIndex);
    if (!buffer) break;
    // 可写入时间戳等信息
    await muxer.writeSampleData(audioTrackIndex, buffer, buffer.presentationTimeUs, buffer.flags);
    demuxer.releaseBuffer(audioTrackIndex, buffer);
  }
  
  await muxer.stop();
  await muxer.release();
  await demuxer.release();
  await source.release();
  fileIo.closeSync(fd);
}

这套 API 体积小,纯系统实现,适合 HarmonyOS Next 应用。

回到顶部