随着 UniApp X 的推出,其全新的语言 UTS(Uni TypeScript) 为开发者带来了更深层次的原生能力调用支持。相比传统的 uni.createNativeView + 原生模块通信的方式,UTS 允许我们在接近原生开发体验的同时,依然保持跨端开发的便利性。
本文将带你使用 UTS 在 iOS 端 实现一个轻量级的原生视频播放器插件 —— IvVideo,基于 AVFoundation 框架,支持基础播放控制、视频加载、音量调节等功能,适用于需要高性能视频播放的场景。
为什么选择 UTS 实现原生视频播放?
在传统 UniApp 开发中,<video> 组件虽然简单易用,但在复杂场景下存在诸多限制:
- 不支持自定义播放器 UI 层级
- 无法精确控制播放行为(如 seek 精度、缓冲策略)
- 性能瓶颈(尤其在列表中大量视频播放时)
- 缺乏对原生 AVPlayer高级特性的调用能力
而通过 UTS,我们可以直接调用 iOS 的 AVFoundation 框架,实现真正意义上的原生级视频播放体验,同时无缝集成到 UniApp X 的视图系统中。
技术栈概览
| 技术 | 说明 | 
|---|---|
| UniApp X | 新一代跨平台应用开发框架 | 
| UTS | 跨平台原生语言,支持直接调用 iOS/Android 原生 API | 
| AVFoundation | iOS 媒体播放核心框架 | 
| UIKit | 构建原生视图容器 | 
| CoreFoundation | 处理几何结构(如 CGRect) | 
核心类设计:IvVideo
我们封装了一个名为 IvVideo 的类,负责管理视频播放的生命周期。以下是核心结构:
export class IvVideo {
	element: UniNativeViewElement | null = null
	player: AVPlayer | null = null
	playerLayer: AVPlayerLayer | null = null
	playerItem: AVPlayerItem | null = null
	videoContainerView: UIView | null = null
	width: Int = 100
	height: Int = 100
	constructor(element: UniNativeViewElement, width: number = 100, height: number = 100) {
		this.element = element
		this.setVideoSize(width, height)
		this.bindView()
	}
}成员说明
- element: 对应 UTS 中的原生视图元素,用于绑定原生- UIView
- player:- AVPlayer实例,控制播放逻辑
- playerLayer:- AVPlayerLayer,负责视频画面渲染
- playerItem: 包装视频资源的播放项
- videoContainerView: 容器视图,承载- playerLayer
视图绑定:bindView()
通过 UIView 创建一个原生容器,并将 AVPlayerLayer 添加为其子图层:
bindView(): void {
	const cgRect = CGRect.init(0, 0, this.width, this.height)
	this.videoContainerView = UIView.init(frame: cgRect)
	this.player = AVPlayer.init()
	this.playerLayer = AVPlayerLayer.init(player: this.player)
	this.playerLayer!.frame = this.videoContainerView!.bounds
	this.playerLayer!.videoGravity = AVLayerVideoGravity.resizeAspect // 保持宽高比
	this.videoContainerView!.layer.addSublayer(this.playerLayer!)
	if (this.element != null) {
		this.element.bindIOSView(this.videoContainerView!)
	}
}注意:必须通过
bindIOSView()将原生UIView绑定到UniNativeViewElement,否则无法在页面上显示。
加载视频:setVideoUrl(url: string)
使用 AVAsset 和 AVPlayerItem 加载远程视频资源:
setVideoUrl(url: string): void {
	try {
		const urlString: URL = URL.init(string: url)!
		if (!urlString) {
			console.error(`Invalid URL: ${url}`)
			return
		}
		const asset: AVAsset = AVAsset.init(url: urlString)
		this.playerItem = AVPlayerItem.init(asset: asset)
		this.player!.replaceCurrentItem(with: this.playerItem)
	} catch (error) {
		console.error(`Failed to set video URL: ${error}`)
	}
}该方法支持 HTTP/HTTPS 视频流,后续可扩展支持本地文件或 HLS 流。
播放控制 API
我们封装了常用播放控制方法:
| 方法 | 功能 | 
|---|---|
| play() | 开始播放 | 
| pause() | 暂停播放 | 
| seekTo(time: number) | 跳转到指定时间(秒) | 
| getCurrentTime() | 获取当前播放时间 | 
| getDuration() | 获取视频总时长 | 
| setVolume(volume) | 设置音量(0.0 ~ 1.0) | 
| destroy() | 销毁播放器,释放资源 | 
资源释放:destroy()
防止内存泄漏,必须在组件销毁时调用:
destroy(): void {
	console.log('video player destroy')
	this.pause()
	this.player = null
	this.playerLayer = null
	this.playerItem = null
}建议在 onUnload 或 onDetached 钩子中调用。
如何在 UniApp X 中使用?
1. 注册原生视图
<template>
	<native-view class="iv-video" @init="onViewInit"></native-view>
</template>
<script setup lang="uts">
	import { IvVideo } from '@/uni_modules/iv-video'
	let videoPlayer : IvVideo | null = null
	const props = withDefaults(defineProps<{ src ?: string }>(), {
		src: ''
	})
	function onViewInit(e : UniNativeViewInitEvent) {
		const width : number = Math.floor(uni.rpx2px(750))
		const height : number = Math.floor(uni.rpx2px(421))
		videoPlayer = new IvVideo(e.detail.element, width, height)
		if (videoPlayer != null) {
			videoPlayer.setVideoUrl(props.src)
			videoPlayer.play()
		}
	}
	onUnmounted(() => {
		if (videoPlayer != null) {
			videoPlayer?.destroy()
		}
	})
</script>
<style lang="scss">
	.iv-video {
		width: 750rpx;
		height: 421rpx;
	}
</style>2. 页面中使用
<iv-video src="https://alivod.qujingm.com/a078b8556c4971ef837f4531858c0102/71677ca99a4a628b6217b75b8655e95d-sd.m3u8"></iv-video>优势总结
- ✅ 原生性能:基于 AVPlayer,播放流畅,支持硬件解码
- ✅ 灵活控制:可精确控制播放、跳转、音量等
- ✅ 无缝集成:通过 UniNativeViewElement与前端视图系统融合
- ✅ 可扩展性强:后续可支持弹幕、画中画、倍速播放等
当前限制与后续优化
⚠️ 已知限制
- UTS 对 CMTime、NSNotification等类型支持尚不完善,部分功能需等待官方完善
- 暂未实现播放状态监听(如播放结束、缓冲状态)
- 未处理横竖屏适配与自动旋转
🔮 后续优化方向
- 封装事件回调(如 onPlay,onPause,onEnded)
- 支持 HLS / DASH 流媒体
- 添加加载状态 UI(loading 指示器)
- 实现画中画(PiP)模式
- Android 端兼容实现(使用 MediaPlayer或ExoPlayer)
参考文档
通过 UTS,我们得以在 UniApp X 中实现真正意义上的原生级功能扩展。本文实现的 IvVideo 播放器只是一个起点,未来我们可以构建更复杂的多媒体应用,如短视频播放器、直播推流、滤镜处理等。
UTS 正在打开一扇通往“跨端 + 原生”融合开发的新大门,值得每一位跨端开发者深入探索。
 
			