1/* 2 * Copyright (c) 2025 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15import { media } from '@kit.MediaKit'; 16import { BusinessError } from '@kit.BasicServicesKit'; 17import { common } from '@kit.AbilityKit'; 18import fs from '@ohos.file.fs'; 19 20export class AVTranscoderDemo { 21 private avTranscoder: media.AVTranscoder | undefined = undefined; 22 private context: Context | undefined; 23 private currentProgress: number = 0; 24 constructor(context: Context | undefined) { 25 if (context != undefined) { 26 this.context = context; 27 } 28 } 29 private avConfig: media.AVTranscoderConfig = { 30 audioBitrate: 100000, // 音频比特率。 31 audioCodec: media.CodecMimeType.AUDIO_AAC, // 音频编码格式。 32 fileFormat: media.ContainerFormatType.CFT_MPEG_4, // 封装格式。 33 videoBitrate: 200000, // 视频比特率。 34 videoCodec: media.CodecMimeType.VIDEO_AVC, // 视频编码格式。 35 }; 36 37 // 注册avTranscoder回调函数。 38 setAVTranscoderCallback() { 39 if (canIUse('SystemCapability.Multimedia.Media.AVTranscoder')) { 40 if (this.avTranscoder != undefined) { 41 // 转码完成回调函数。 42 this.avTranscoder.on('complete', async () => { 43 console.log(`AVTranscoder is completed`); 44 await this.releaseTranscoderingProcess(); 45 }); 46 // 错误上报回调函数。 47 this.avTranscoder.on('error', (err: BusinessError) => { 48 console.error(`AVTranscoder failed, code is ${err.code}, message is ${err.message}`); 49 }); 50 // 进度上报回调函数 51 this.avTranscoder.on('progressUpdate', (progress: number) => { 52 console.info(`AVTranscoder progressUpdate = ${progress}`); 53 this.currentProgress = progress; 54 }) 55 } 56 } 57 } 58 59 // 开始转码对应的流程。 60 async startTranscoderingProcess() { 61 if (canIUse('SystemCapability.Multimedia.Media.AVTranscoder')) { 62 if (this.avTranscoder != undefined) { 63 await this.avTranscoder.release(); 64 this.avTranscoder = undefined; 65 } 66 // 1.创建转码实例。 67 this.avTranscoder = await media.createAVTranscoder(); 68 this.setAVTranscoderCallback(); 69 // 2.获取转码源文件fd和目标文件fd赋予avTranscoder;参考FilePicker文档。 70 if (this.context != undefined) { 71 try { 72 // 获取输入文件fd,H264_AAC.mp4为rawfile目录下的预置资源,需要开发者根据实际情况进行替换。 73 let fileDescriptor = await this.context.resourceManager.getRawFd('H264_AAC.mp4'); 74 this.avTranscoder.fdSrc = fileDescriptor; 75 } catch (error) { 76 console.error('Failed to get the file descriptor, please check the resource and path.'); 77 } 78 let outputFilePath = this.context.filesDir + '/output.mp4'; 79 let file = fs.openSync(outputFilePath, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE); 80 this.avTranscoder.fdDst = file.fd; 81 this.currentProgress = 0; 82 } 83 // 3.配置转码参数完成准备工作。 84 await this.avTranscoder.prepare(this.avConfig); 85 // 4.开始转码。 86 await this.avTranscoder.start(); 87 } 88 } 89 90 // 暂停转码对应的流程。 91 async pauseTranscoderingProcess() { 92 if (canIUse('SystemCapability.Multimedia.Media.AVTranscoder')) { 93 if (this.avTranscoder != undefined) { // 仅在调用start返回后调用pause为合理调用。 94 await this.avTranscoder.pause(); 95 } 96 } 97 } 98 99 // 恢复对应的转码流程。 100 async resumeTranscoderingProcess() { 101 if (canIUse('SystemCapability.Multimedia.Media.AVTranscoder')) { 102 if (this.avTranscoder != undefined) { // 仅在调用pause返回后调用resume为合理调用。 103 await this.avTranscoder.resume(); 104 } 105 } 106 } 107 108 // 释放转码流程。 109 async releaseTranscoderingProcess() { 110 if (canIUse('SystemCapability.Multimedia.Media.AVTranscoder')) { 111 if (this.avTranscoder != undefined) { 112 // 1.释放转码实例。 113 await this.avTranscoder.release(); 114 this.avTranscoder = undefined; 115 // 2.关闭转码目标文件fd。 116 fs.closeSync(this.avTranscoder!.fdDst); 117 } 118 } 119 } 120 121 // 获取当前进度 122 getCurrentProgress(): number { 123 console.info(`getCurrentProgress = ${this.currentProgress}`); 124 return this.currentProgress; 125 } 126 127 // 一个完整的【开始转码-暂停转码-恢复转码-转码完成】示例。 128 async avTranscoderDemo() { 129 await this.startTranscoderingProcess(); // 开始转码。 130 await this.pauseTranscoderingProcess(); //暂停转码。 131 await this.resumeTranscoderingProcess(); // 恢复转码。 132 } 133} 134