实现思路:
- 使用 XComponent 创建视频渲染表面:
XComponent({
id: 'videoPlayer',
type: XComponentType.SURFACE,
controller: this.xComponentController
})
.onLoad(() => {
this.surfaceId = this.xComponentController.getXComponentSurfaceId();
})
- 将 surfaceId 绑定到 AVPlayer:
avPlayer.surfaceId = this.surfaceId;
avPlayer.url = 'https://example.com/video.mp4';
- 监听状态变化并控制播放:
avPlayer.on('stateChange', (state: string) => {
if (state === 'initialized') {
avPlayer.prepare();
} else if (state === 'prepared') {
avPlayer.play();
}
});
- 完整示例代码:
import { media } from '@kit.MediaKit';
@Entry
@Component
struct VideoPlayerPage {
private avPlayer: media.AVPlayer | null = null;
private xComponentController: XComponentController = new XComponentController();
private surfaceId: string = '';
@State isPlaying: boolean = false;
@State currentTime: number = 0;
@State duration: number = 0;
@State isFullScreen: boolean = false;
async aboutToAppear() {
this.avPlayer = await media.createAVPlayer();
this.setupPlayerCallbacks();
}
aboutToDisappear() {
if (this.avPlayer) {
this.avPlayer.release();
this.avPlayer = null;
}
}
setupPlayerCallbacks() {
if (!this.avPlayer) return;
this.avPlayer.on('stateChange', (state: string) => {
console.info(`Video state: ${state}`);
if (state === 'initialized') {
this.avPlayer!.surfaceId = this.surfaceId;
this.avPlayer!.prepare();
} else if (state === 'prepared') {
this.duration = this.avPlayer!.duration || 0;
this.avPlayer!.play();
this.isPlaying = true;
} else if (state === 'completed') {
this.isPlaying = false;
}
});
this.avPlayer.on('timeUpdate', (time: number) => {
this.currentTime = time;
});
}
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')}`;
}
build() {
Stack() {
Column() {
// 视频画面
XComponent({
id: 'videoPlayer',
type: XComponentType.SURFACE,
controller: this.xComponentController
})
.width('100%')
.height(this.isFullScreen ? '100%' : 220)
.onLoad(() => {
this.surfaceId = this.xComponentController.getXComponentSurfaceId();
if (this.avPlayer) {
this.avPlayer.url = 'https://example.com/video.mp4';
}
})
// 控制栏
if (!this.isFullScreen) {
Column({ space: 12 }) {
// 进度条
Row() {
Text(this.formatTime(this.currentTime)).fontSize(12)
Slider({
value: this.duration > 0 ? (this.currentTime / this.duration) * 100 : 0,
min: 0,
max: 100
})
.layoutWeight(1)
.onChange((value: number) => {
const seekTime = (value / 100) * this.duration;
this.avPlayer?.seek(seekTime);
})
Text(this.formatTime(this.duration)).fontSize(12)
}
.width('100%')
.padding({ left: 16, right: 16 })
// 按钮
Row({ space: 20 }) {
Button(this.isPlaying ? '暂停' : '播放')
.onClick(() => {
if (this.isPlaying) {
this.avPlayer?.pause();
} else {
this.avPlayer?.play();
}
this.isPlaying = !this.isPlaying;
})
Button('全屏').onClick(() => {
this.isFullScreen = true;
})
}
}
.padding(16)
}
}
// 全屏时的返回按钮
if (this.isFullScreen) {
Button('退出全屏')
.position({ x: 16, y: 16 })
.onClick(() => {
this.isFullScreen = false;
})
}
}
.width('100%')
.height('100%')
}
}