# [鸿蒙从零到一] HarmonyOS 媒体能力实战:图片、音频与视频处理
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 '';
}
}import { image } from '@kit.ImageKit';
@Entry
@Component
struct 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));
}
}import { media } from '@kit.MediaKit';
@Component
export 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();
}
}import { media } from '@kit.MediaKit';
import { fileIo } from '@kit.CoreFileKit';
@Component
export 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();
}
}import { media } from '@kit.MediaKit';
@Entry
@Component
struct 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;
})
}
}
}import { camera } from '@kit.CameraKit';
@Component
export 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
@Component
struct 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();
}
}原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。