魔兽世界先祖战熊获取方式详细说明
2026-08-14
2026-08-19 0
[鸿蒙从零到一] 鸿蒙媒体能力实战:图片、音频与视频处理并不只看表面做法,关键还要理解相关条件、限制和后续影响。
在移动应用开发中,媒体能力是核心功能之一。HarmonyOS 提供了完整的媒体框架,覆盖图片选择、音频播放、视频录制等场景。下文会从实战角度出发,带你掌握 HarmonyOS 的媒体能力。
![[鸿蒙从零到一] 鸿蒙媒体能力实战:图片、音频与视频处理](https://www.0405.net/uploads/20260819/img_6a855210b05e230.webp)
HarmonyOS 提供了统一的 Picker API,支持从相册选择图片:
import {picker } from '@kit.CoreFileKit';import {BusinessError } from '@kit.BasicServicesKit';async function pickImage(): Promise { try { const photoSelectOptions = new picker.PhotoSelectOptions();photoSelectOptions.MIMEType = picker.PhotoViewMIMETypes.IMAGE_TYPE;photoSelectOptions.maxSelectNumber = 1;const photoViewPicker = new picker.PhotoViewPicker();const result = await photoViewPicker.select(photoSelectOptions);if (result && result.photoUris.length > 0) { return result.photoUris[0];}return '';} catch (err) { console.error('选择图片失败:', JSON.stringify(err));return '';}} 获取图片 URI 后,使用 Image 组件显示:
import {image } from '@kit.ImageKit';@Entry@Componentstruct ImageDemo { @State imageUri: string = '';build() { Column() { Button('选择图片').onClick(async () => { this.imageUri = await pickImage();})if (this.imageUri) { Image(this.imageUri).width('100%').height(300).objectFit(ImageFit.Contain)}}.padding(20)}}处理大图时需要压缩:
import {image } from '@kit.ImageKit';import {fileIo } from '@kit.CoreFileKit';async function compressImage(sourceUri: string, targetPath: string): Promise { try { const imageSource = image.createImageSource(sourceUri);const imageInfo = await imageSource.getImageInfo();console.info(`原始尺寸: ${ imageInfo.size.width}x${ imageInfo.size.height}`);const decodingOptions: image.DecodingOptions = { desiredSize: {width: 800, height: 800 },desiredPixelFormat: image.PixelMapFormat.RGBA_8888};const pixelMap = await imageSource.createPixelMap(decodingOptions);const imagePacker = image.createImagePacker();const packOpts: image.PackingOption = { format: 'image/jpeg',quality: 80};const buffer = await imagePacker.packing(pixelMap, packOpts);const file = fileIo.openSync(targetPath, fileIo.OpenMode.CREATE | fileIo.OpenMode.WRITE_ONLY);fileIo.writeSync(file.fd, buffer);fileIo.closeSync(file);console.info('图片压缩完成');} catch (err) { console.error('压缩失败:', JSON.stringify(err));}} 使用 AVPlayer 播放音频:
import {media } from '@kit.MediaKit';@Componentexport struct AudioPlayer { private avPlayer?: media.AVPlayer;@State isPlaying: boolean = false;@State currentTime: number = 0;@State duration: number = 0;async initPlayer(audioUri: string) { try { this.avPlayer = await media.createAVPlayer();this.avPlayer.on('stateChange', (state: string) => { console.info(`播放器状态: ${ state}`);});this.avPlayer.on('timeUpdate', (time: number) => { this.currentTime = time;});this.avPlayer.on('durationUpdate', (duration: number) => { this.duration = duration;});this.avPlayer.url = audioUri;} catch (err) { console.error('初始化播放器失败:', JSON.stringify(err));}}async play() { await this.avPlayer?.play();this.isPlaying = true;}async pause() { await this.avPlayer?.pause();this.isPlaying = false;}build() { Column() { Text(`${ this.formatTime(this.currentTime)} / ${ this.formatTime(this.duration)}`)Row() { Button(this.isPlaying ? '暂停' : '播放').onClick(() => { if (this.isPlaying) { this.pause();} else { this.play();}})}}}formatTime(ms: number): string { const seconds = Math.floor(ms / 1000);const min = Math.floor(seconds / 60);const sec = seconds % 60;return `${ min}:${ sec.toString().padStart(2, '0')}`;}aboutToDisappear() { this.avPlayer?.release();}}使用 AVRecorder 录制音频:
import {media } from '@kit.MediaKit';import {fileIo } from '@kit.CoreFileKit';@Componentexport struct AudioRecorder { private avRecorder?: media.AVRecorder;@State isRecording: boolean = false;private outputPath: string = '';async initRecorder() { try { this.avRecorder = await media.createAVRecorder();this.avRecorder.on('stateChange', (state: string) => { console.info(`录制器状态: ${ state}`);});const context = getContext(this);this.outputPath = `${ context.cacheDir}/audio_${ Date.now()}.m4a`;const config: media.AVRecorderConfig = { audioSourceType: media.AudioSourceType.AUDIO_SOURCE_TYPE_MIC,profile: { audioBitrate: 128000,audioChannels: 2,audioCodec: media.CodecMimeType.AUDIO_AAC,audioSampleRate: 48000,fileFormat: media.ContainerFormatType.CFT_MPEG_4A},url: `fd://${ fileIo.openSync(this.outputPath, fileIo.OpenMode.CREATE | fileIo.OpenMode.WRITE_ONLY).fd}`};await this.avRecorder.prepare(config);} catch (err) { console.error('初始化录制器失败:', JSON.stringify(err));}}async startRecord() { await this.avRecorder?.start();this.isRecording = true;}async stopRecord() { await this.avRecorder?.stop();this.isRecording = false;console.info('录音已保存:', this.outputPath);}build() { Column() { Button(this.isRecording ? '停止录音' : '开始录音').onClick(() => { if (this.isRecording) { this.stopRecord();} else { this.startRecord();}})}}aboutToDisappear() { this.avRecorder?.release();}}使用 AVPlayerXComponent 播放视频:
import {media } from '@kit.MediaKit';@Entry@Componentstruct VideoPlayer { private avPlayer?: media.AVPlayer;private surfaceId: string = '';@State isPlaying: boolean = false;async initPlayer(videoUri: string) { try { this.avPlayer = await media.createAVPlayer();this.avPlayer.on('stateChange', (state: string) => { console.info(`播放器状态: ${ state}`);});this.avPlayer.url = videoUri;this.avPlayer.surfaceId = this.surfaceId;} catch (err) { console.error('初始化播放器失败:', JSON.stringify(err));}}build() { Column() { XComponent({ id: 'video_surface',type: XComponentType.SURFACE,controller: new XComponentController()}).onLoad((context?: object) => { this.surfaceId = (context as {surfaceId: string }).surfaceId;this.initPlayer('file://...');}).width('100%').height(300)Button(this.isPlaying ? '暂停' : '播放').onClick(async () => { if (this.isPlaying) { await this.avPlayer?.pause();} else { await this.avPlayer?.play();}this.isPlaying = !this.isPlaying;})}}}使用相机 API 录制视频:
import {camera } from '@kit.CameraKit';@Componentexport struct VideoRecorder { private cameraManager?: camera.CameraManager;private videoOutput?: camera.VideoOutput;@State isRecording: boolean = false;async initCamera() { try { this.cameraManager = camera.getCameraManager(getContext(this));const cameras = this.cameraManager.getSupportedCameras();if (cameras.length === 0) { console.error('没有可用相机');return;}const cameraInput = this.cameraManager.createCameraInput(cameras[0]);await cameraInput.open();const profile: camera.VideoProfile = { format: camera.CameraFormat.CAMERA_FORMAT_YUV_420_SP,size: {width: 1920, height: 1080 },frameRateRange: {min: 30, max: 30 }};this.videoOutput = this.cameraManager.createVideoOutput(profile, 'fd://...');const session = this.cameraManager.createSession(camera.SceneMode.NORMAL_VIDEO);session.beginConfig();session.addInput(cameraInput);session.addOutput(this.videoOutput);await session.commitConfig();await session.start();console.info('相机初始化完成');} catch (err) { console.error('初始化相机失败:', JSON.stringify(err));}}async startRecord() { await this.videoOutput?.start();this.isRecording = true;}async stopRecord() { await this.videoOutput?.stop();this.isRecording = false;}build() { Column() { Button(this.isRecording ? '停止录制' : '开始录制').onClick(() => { if (this.isRecording) { this.stopRecord();} else { this.startRecord();}})}}}媒体功能需要申请相应权限:
{"module": {"requestPermissions": [{"name": "ohos.permission.READ_IMAGEVIDEO","reason": "$string:permission_read_media","usedScene": { "when": "inuse" }},{"name": "ohos.permission.WRITE_IMAGEVIDEO","reason": "$string:permission_write_media","usedScene": { "when": "inuse" }},{"name": "ohos.permission.MICROPHONE","reason": "$string:permission_microphone","usedScene": { "when": "inuse" }},{"name": "ohos.permission.CAMERA","reason": "$string:permission_camera","usedScene": { "when": "inuse" }}]}}import {abilityAccessCtrl, Permissions } from '@kit.AbilityKit';async function requestPermissions(): Promise { const permissions: Permissions[] = ['ohos.permission.READ_IMAGEVIDEO','ohos.permission.MICROPHONE','ohos.permission.CAMERA'];const context = getContext(this);const atManager = abilityAccessCtrl.createAtManager();try { const result = await atManager.requestPermissionsFromUser(context, permissions);return result.authResults.every(r => r === 0);} catch (err) { console.error('权限申请失败:', JSON.stringify(err));return false;}} import {media } from '@kit.MediaKit';import {picker } from '@kit.CoreFileKit';@Entry@Componentstruct MediaPlayerDemo { private avPlayer?: media.AVPlayer;@State mediaUri: string = '';@State isPlaying: boolean = false;@State currentTime: number = 0;@State duration: number = 0;async selectMedia() { try { const options = new picker.PhotoSelectOptions();options.MIMEType = picker.PhotoViewMIMETypes.VIDEO_TYPE;options.maxSelectNumber = 1;const photoPicker = new picker.PhotoViewPicker();const result = await photoPicker.select(options);if (result.photoUris.length > 0) { this.mediaUri = result.photoUris[0];await this.initPlayer();}} catch (err) { console.error('选择媒体失败:', JSON.stringify(err));}}async initPlayer() { this.avPlayer = await media.createAVPlayer();this.avPlayer.on('timeUpdate', (time: number) => { this.currentTime = time;});this.avPlayer.on('durationUpdate', (duration: number) => { this.duration = duration;});this.avPlayer.url = this.mediaUri;}build() { Column() { Text('HarmonyOS 媒体播放器').fontSize(24).fontWeight(FontWeight.Bold)Button('选择视频').onClick(() => this.selectMedia()).margin({top: 20 })if (this.mediaUri) { Text(`播放中: ${ this.mediaUri.split('/').pop()}`).margin({top: 10 })Row() { Button(this.isPlaying ? '暂停' : '播放').onClick(async () => { if (this.isPlaying) { await this.avPlayer?.pause();} else { await this.avPlayer?.play();}this.isPlaying = !this.isPlaying;})Button('停止').onClick(async () => { await this.avPlayer?.stop();this.isPlaying = false;})}.margin({top: 20 })}}.width('100%').height('100%').padding(20)}aboutToDisappear() { this.avPlayer?.release();}}本文系统介绍了 HarmonyOS 的媒体能力,涵盖:
图片处理 — Picker 选择、解码显示、压缩保存 音频能力 — AVPlayer 播放、AVRecorder 录制 视频能力 — 视频播放、相机录制 权限管理 — 静态声明与动态申请 实战案例 — 完整媒体播放器实现 性能优化 — 内存管理与加载优化掌握这些能力后,你就可以开发功能完整的媒体类应用了。