项目场景:

在开发过程中,遇到上传视频的场景,往往需要,压缩视频,以及获取视频第一帧缩略图,本文提供四个函数分别用于 打开相册获取视频 将视频写到沙箱目录 压缩视频 获取视频缩略图,附上效果图,以及完整实例


打开相册获取视频

调用原生能力获取到视频原路径

  // 弹出相册选择器
  async selectUri(type: photoAccessHelper.PhotoViewMIMETypes, max?: number) {
    let imgList: string[] = []
    // 创建相册选择器
    let photoPicker = new photoAccessHelper.PhotoViewPicker();
    // 创建选择参数
    const photoSelectOptions = new photoAccessHelper.PhotoSelectOptions()
    photoSelectOptions.MIMEType = type
    photoSelectOptions.maxSelectNumber = max
    // 获取相册选择结果
    const result = await photoPicker.select(photoSelectOptions)
    // 获取相册选择结果
    imgList.push(...result.photoUris)
    return imgList
  }

将视频写到沙箱目录

将视频写到沙箱目录,压缩时需要沙箱目录

  // 将文件拷贝到cache目录下
  fileToCache(filePath: string) {
    const saveDir = getContext().cacheDir // cache目录
    // 生成一个唯一的名字
    let filename = util.generateRandomUUID() + ".mp4"
    // item.url 相册路径  => 拷贝到cache目录下
    const file = fileIo.openSync(filePath, fileIo.OpenMode.READ_ONLY)
    // 拷贝文件到cache目录下
    fileIo.copyFileSync(file.fd, saveDir + "/" + filename)
    return saveDir + "/" + filename
  }

压缩视频

压缩视频需要用到一个第三方的工具包 ,这个第三方工具包为可对沙箱路径里的文件进行压缩

使用前需要创建视频压缩器 new VideoCompressor()  从工具包中导入

OpenHarmony三方库中心仓https://ohpm.openharmony.cn/#/cn/detail/@ohos%2Fvideocompressor终端运行以下命令安装

ohpm i @ohos/videocompressor

   Button('压缩视频').onClick(async () => {
        // 创建视频压缩器
        let videoCompressor = new VideoCompressor();
        const data =
          // this.selectFilePath 为沙箱路径
          await videoCompressor.compressVideo(getContext(), this.selectFilePath, CompressQuality.COMPRESS_QUALITY_HIGH)
        const file = fileIo.openSync(data.outputPath, fileIo.OpenMode.READ_ONLY)
        this.fd = file.fd
        AlertDialog.show({ message: '压缩成功' + JSON.stringify(data) })
      })

获取视频缩略图

这里参考了官方文档:

使用AVImageGenerator提取视频指定时间图像(ArkTS)-媒体信息查询-媒体开发指导(ArkTS)-Media Kit(媒体服务)-媒体 - 华为HarmonyOS开发者https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/avimagegenerator

  // 获取缩略图
  async testFetchFrameByTime() {
    // 创建AVImageGenerator对象。
    let avImageGenerator: media.AVImageGenerator = await media.createAVImageGenerator();
    // 设置fdSrc。
    avImageGenerator.fdSrc = { fd: this.fd }

    // 初始化入参。
    let timeUs = 0;
    let queryOption = media.AVImageQueryOptions.AV_IMAGE_QUERY_NEXT_SYNC;
    let param: media.PixelMapParams = {
      width: 200,
      height: 200
    };

    // 获取缩略图(promise模式)。
    this.pixelMap = await avImageGenerator.fetchFrameByTime(timeUs, queryOption, param);

    // 释放资源(promise模式)。
    avImageGenerator.release();
  }

以下是完整案例:

效果图:

完整代码:

import { camera, cameraPicker } from '@kit.CameraKit';
import { photoAccessHelper } from '@kit.MediaLibraryKit';
import { CompressQuality, VideoCompressor } from '@ohos/videocompressor';
import { util } from '@kit.ArkTS';
import { fileIo } from '@kit.CoreFileKit';
import { media } from '@kit.MediaKit';
import { image } from '@kit.ImageKit';

@Entry
@Component
struct VideoPage {
  array: string[] = []
  selectFilePath: string = ''
  fd: number = 1
  // pixelMap对象声明,用于图片显示。
  @State pixelMap: image.PixelMap | undefined = undefined;
  

  // 弹出相册选择器
  async selectUri(type: photoAccessHelper.PhotoViewMIMETypes, max?: number) {
    let imgList: string[] = []
    // 创建相册选择器
    let photoPicker = new photoAccessHelper.PhotoViewPicker();
    // 创建选择参数
    const photoSelectOptions = new photoAccessHelper.PhotoSelectOptions()
    photoSelectOptions.MIMEType = type
    photoSelectOptions.maxSelectNumber = max
    // 获取相册选择结果
    const result = await photoPicker.select(photoSelectOptions)
    // 获取相册选择结果
    imgList.push(...result.photoUris)
    return imgList
  }

  // 将文件拷贝到cache目录下
  fileToCache(filePath: string) {
    const saveDir = getContext().cacheDir // cache目录
    // 生成一个唯一的名字
    let filename = util.generateRandomUUID() + ".mp4"
    // item.url 相册路径  => 拷贝到cache目录下
    const file = fileIo.openSync(filePath, fileIo.OpenMode.READ_ONLY)
    // 拷贝文件到cache目录下
    fileIo.copyFileSync(file.fd, saveDir + "/" + filename)
    return saveDir + "/" + filename
  }

  // 获取缩略图
  async testFetchFrameByTime() {
    // 创建AVImageGenerator对象。
    let avImageGenerator: media.AVImageGenerator = await media.createAVImageGenerator();
    // 设置fdSrc。
    avImageGenerator.fdSrc = { fd: this.fd }

    // 初始化入参。
    let timeUs = 0;
    let queryOption = media.AVImageQueryOptions.AV_IMAGE_QUERY_NEXT_SYNC;
    let param: media.PixelMapParams = {
      width: 200,
      height: 200
    };

    // 获取缩略图(promise模式)。
    this.pixelMap = await avImageGenerator.fetchFrameByTime(timeUs, queryOption, param);

    // 释放资源(promise模式)。
    avImageGenerator.release();
  }

  build() {
    Column({ space: 30 }) {

      Button('打开相册,获取视频')
        .onClick(async () => {
          // 打开相机
          this.array = await this.selectUri(photoAccessHelper.PhotoViewMIMETypes.VIDEO_TYPE, 2)
          // const arr = await this.openCamera(cameraPicker.PickerMediaType.VIDEO)
          AlertDialog.show({ message: '视频路径' + JSON.stringify(this.array) })
        })

      Button('写到沙箱')
        .onClick(() => {
          this.selectFilePath = this.fileToCache(this.array[0])
          AlertDialog.show({ message: '沙箱路径' + this.selectFilePath })
        })
      Button('压缩视频').onClick(async () => {
        // 创建视频压缩器
        let videoCompressor = new VideoCompressor();
        const data =
          // this.selectFilePath 为沙箱路径
          await videoCompressor.compressVideo(getContext(), this.selectFilePath, CompressQuality.COMPRESS_QUALITY_HIGH)
        const file = fileIo.openSync(data.outputPath, fileIo.OpenMode.READ_ONLY)
        this.fd = file.fd
        AlertDialog.show({ message: '压缩成功' + JSON.stringify(data) })
      })

      Button('缩略图')
        .onClick(() => {
          try {
            this.testFetchFrameByTime()
          } catch (e) {
            AlertDialog.show({ message: JSON.stringify(e) })
          }

        })
      Image(this.pixelMap)
        .width(300)
        .height(300)
    }
    .justifyContent(FlexAlign.Center)
    .alignItems(HorizontalAlign.Center)
    .height('100%')
    .width('100%')
  }
}

Logo

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

更多推荐