前言:

目前随着手机分辨率越来越高,几十秒的视频动不动就几百兆,为了减少传输大小,就需要对原有视频进行压缩,那么在鸿蒙中,如果不引入三方组件如何实现视频压缩呢。下面将介绍一种方法,使用鸿蒙的媒体库实现视频压缩

一、使用AVTranscoder实现视频压缩

主要步骤如下:

(1)设置压缩参数,比如设置比特率,通过设置比特率可以控制压缩后的视频大小,比如一个100M的视频,时长为30s,如果想要压缩到10M以内,则设置比特率为 10 * 8 * 1024 * 1024 / 30 约等于2500000,为了去除音频大小的影响,我们可以再乘以0.8,差不多为2000000

(2)设置压缩过程的回调函数,监听视频压缩是否成功

(3)设置待压缩的视频句柄,设置输出视频的路径句柄

二、下面展示从相册中选中视频,并压缩到10M以内的完整示例:

1、从相册中选择视频代码:

import { photoAccessHelper } from "@kit.MediaLibraryKit";

export class FileUtil {
  static async selectVideo() {
    const photoViewPicker = new photoAccessHelper.PhotoViewPicker()
    const photoSelectOptions = new photoAccessHelper.PhotoSelectOptions()
    photoSelectOptions.MIMEType = photoAccessHelper.PhotoViewMIMETypes.VIDEO_TYPE
    photoSelectOptions.maxSelectNumber = 1
    let result = await photoViewPicker.select(photoSelectOptions)
    let uris = result.photoUris || []
    if (uris.length) {
      return uris[0]
    }
    return ""
  }
}

2、使用AVTranscoder压缩视频,并将压缩后的视频存入应用沙箱

import { media } from '@kit.MediaKit';
import { BusinessError } from '@kit.BasicServicesKit';
import { common } from '@kit.AbilityKit';
import { FileUtil } from './FileUtil';
import {fileIo as fs} from '@kit.CoreFileKit'


export class AVTranscoderDemo {
  private avTranscoder: media.AVTranscoder | undefined = undefined;

  private avConfig: media.AVTranscoderConfig = {
    audioCodec: media.CodecMimeType.AUDIO_AAC, // 音频编码格式。
    fileFormat: media.ContainerFormatType.CFT_MPEG_4, // 封装格式。
    videoBitrate: 2000000, // 视频比特率。
    videoCodec: media.CodecMimeType.VIDEO_AVC, // 视频编码格式。
  };


  // 注册avTranscoder回调函数。
  setAVTranscoderCallback() {
    if (canIUse("SystemCapability.Multimedia.Media.AVTranscoder")) {
      if (this.avTranscoder != undefined) {
        // 转码完成回调函数。
        this.avTranscoder.on('complete', async () => {
          console.log(`AVTranscoder is completed`);
          await this.releaseTranscoderingProcess();
        });
        // 错误上报回调函数。
        this.avTranscoder.on('error', (err: BusinessError) => {
          console.error(`AVTranscoder failed, code is ${err.code}, message is ${err.message}`);
        });
      }
    }
  }


  // 开始转码对应的流程。
  async startTranscoderingProcess() {
    if (canIUse("SystemCapability.Multimedia.Media.AVTranscoder")) {
      if (this.avTranscoder != undefined) {
        await this.avTranscoder.release();
        this.avTranscoder = undefined;
      }
      // 1.创建转码实例。
      this.avTranscoder = await media.createAVTranscoder();
      this.setAVTranscoderCallback();
      // 2.从相册选取视频
      let viedoInput = await FileUtil.selectVideo();
      let fileDescriptor = await fs.open(viedoInput, fs.OpenMode.READ_ONLY)
      this.avTranscoder.fdSrc = fileDescriptor;
      // 3、指定压缩后的视频路径
      let context = getContext(this) as common.UIAbilityContext
      let targetPath = context?.filesDir + '/' + new Date().getTime()+'test.mp4'
      let targetFile = await fs.open(targetPath,fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE)
      this.avTranscoder.fdDst = targetFile.fd;

      // 3.配置转码参数完成准备工作。
      await this.avTranscoder.prepare(this.avConfig);
      // 4.开始转码。
      await this.avTranscoder.start();
    }
  }


  // 暂停转码对应的流程。
  async pauseTranscoderingProcess() {
    if (canIUse("SystemCapability.Multimedia.Media.AVTranscoder")) {
      if (this.avTranscoder != undefined) { // 仅在调用start返回后调用pause为合理调用。
        await this.avTranscoder.pause();
      }
    }
  }


  // 恢复对应的转码流程。
  async resumeTranscoderingProcess() {
    if (canIUse("SystemCapability.Multimedia.Media.AVTranscoder")) {
      if (this.avTranscoder != undefined) { // 仅在调用pause返回后调用resume为合理调用。
        await this.avTranscoder.resume();
      }
    }
  }


  // 释放转码流程。
  async releaseTranscoderingProcess() {
    if (canIUse("SystemCapability.Multimedia.Media.AVTranscoder")) {
      if (this.avTranscoder != undefined) {
        // 1.释放转码实例。
        await this.avTranscoder.release();
        this.avTranscoder = undefined;
        // 2.关闭转码目标文件fd。
      }
    }
  }


  // 一个完整的【开始转码-暂停转码-恢复转码-转码完成】示例。
  async avTranscoderDemo() {
    await this.startTranscoderingProcess(); // 开始转码。
    await this.pauseTranscoderingProcess(); //暂停转码。
    await this.resumeTranscoderingProcess(); // 恢复转码。
    await this.releaseTranscoderingProcess(); // 释放转码。
  }
}

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐