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 应用。

回到顶部