更新记录

1.2.2(2026-07-02)

新增objectFit属性,可选:contain(等比缩放留黑边),cover(等比填充裁剪),fill(拉伸填满)

1.2.1(2026-07-02)

修复rts无法播放问题

1.2.0(2026-06-18)

1.支持播放RTS低延迟artc协议直播流 2.新增后台画中画悬浮框功能 3.开启本地缓存,开启硬件加速 4.优化播放器,修复已知BUG

查看更多

平台兼容性

uni-app(5.0)

Vue2 Vue3 Chrome Safari app-vue app-nvue Android iOS 鸿蒙
- - × × × 5.0 ×
微信小程序 支付宝小程序 抖音小程序 百度小程序 快手小程序 京东小程序 鸿蒙元服务 QQ小程序 飞书小程序 小红书小程序 快应用-华为 快应用-联盟
× × × × × × × × × × × ×

uni-app x

Chrome Safari Android iOS 鸿蒙 微信小程序
× × - - × ×

axiang-aliplaye

基于阿里云播放器 SDK(AliPlayer)封装的 uni-app UTS 原生组件,支持 Android 和 iOS。适用于 nvue 页面,提供完整的视频播放能力。

✨ 核心特性

  • 📺 多格式支持 — 支持 MP4, RTMP, FLV, M3U8, RTS, DASH, MKV, AVI等多种视频及流媒体
  • 🎬 完整播放控制 — 播放、暂停、停止、跳转、倍速、循环
  • 📱 全屏支持 — 自动横竖屏适配,流畅的全屏切换体验
  • 🪟 画中画悬浮窗 — 支持退出应用时无缝进入桌面画中画及 iOS 后台播放
  • 🎯 手势操作 — 左右滑动调进度、上下滑动调音量、双击播放/暂停
  • 初始播放位置 — 直接从指定位置起播,避免先加载再跳转
  • 🎨 灵活 UI 控制 — 各控制元素独立显隐,支持完全自定义覆盖层
  • 📊 实时进度回调 — 500ms 粒度进度上报,轻松实现续播
  • 🖼️ 首帧事件firstFrame 事件精准通知首帧渲染完成,方便页面侧控制封面

使用前提

  • 仅 App 端原生组件场景使用,页面建议使用 nvue
  • 修改 utssdk/app-androidutssdk/app-ios 后,需重新制作自定义基座
  • iOS / Android 均依赖原生 SDK,云打包或自定义基座配置需保持完整

License 授权配置

阿里云播放器 SDK 需要有效的 License 才能正常工作(否则可能会导致起播失败、黑屏等)。请按如下步骤配置您的 License:

🤖 Android 端配置

  1. 放置证书文件: 将您获取到的 .crt 证书文件重命名为 license.crt,并放置在插件的如下目录中(如果没有对应的文件夹请手动创建): uni_modules/axiang-aliplaye/utssdk/app-android/assets/cert/license.crt
  2. 配置 License Key: 打开配置文件:uni_modules/axiang-aliplaye/utssdk/app-android/AndroidManifest.xml。 找到 <application> 标签下的 meta-data,将其中的 value 替换为您真实的 License Key:
    <meta-data
       android:name="com.aliyun.alivc_license.licensekey"
       android:value="您的 LicenseKey" />
    <meta-data
       android:name="com.aliyun.alivc_license.licensefile"
       android:value="assets/cert/license.crt" />

🍎 iOS 端配置

  1. 放置证书文件: 将您获取到的 .crt 证书文件重命名为 license.crt,并放置在插件的如下目录中(如果没有对应的文件夹请手动创建): uni_modules/axiang-aliplaye/utssdk/app-ios/cert/license.crt
  2. 配置 License Key: 打开配置文件:uni_modules/axiang-aliplaye/utssdk/app-ios/info.plist。 找到对应的 <string> 标签,替换为您真实的 License Key:
    <key>AlivcLicenseKey</key>
    <string>您的 LicenseKey</string>
    <key>AlivcLicenseFile</key>
    <string>cert/license.crt</string>

[!WARNING] 修改配置或替换证书后,必须重新提交云打包或重新制作自定义基座才能生效!


快速开始

<template>
  <view class="page">
    <!-- 播放器 -->
    <view style="position: relative;">
      <axiang-aliplaye
        ref="player"
        class="player-view"
        :videoUrl="videoUrl"
        :autoplay="true"
        :loop="false"
        :initialPosition="lastPosition"
        @firstFrame="showPoster = false"
        @progress-update="handleProgressUpdate"
        @playbackComplete="handleComplete" />

      <!-- 页面侧封面图(首帧渲染后自动隐藏) -->
      <image v-if="showPoster" :src="posterUrl"
        style="position: absolute; top: 0; left: 0; width: 100%; height: 100%;"
        mode="aspectFill" />
    </view>
  </view>
</template>

<script>
  export default {
    data() {
      return {
        videoUrl: 'https://example.com/video.mp4',
        posterUrl: 'https://example.com/cover.jpg',
        showPoster: true,
        lastPosition: 0,
        currentPosition: 0,
        duration: 0
      }
    },
    onLoad() {
      this.lastPosition = uni.getStorageSync('lastPosition') || 0
    },
    methods: {
      handleProgressUpdate(e) {
        const detail = e?.detail?.detail || e?.detail
        if (detail) {
          this.currentPosition = detail.position / 1000
          this.duration = detail.duration / 1000
        }
      },
      handleComplete() {
        uni.setStorageSync('lastPosition', 0)
      }
    },
    onUnload() {
      if (this.currentPosition > 0 && this.currentPosition < this.duration) {
        uni.setStorageSync('lastPosition', this.currentPosition)
      }
    }
  }
</script>

<style>
  .player-view {
    width: 750rpx;
    height: 422rpx;
  }
</style>

Props

属性 类型 默认值 说明
videoUrl String '' 视频播放地址
videourl String '' 小写兼容属性,与 videoUrl 功能相同
autoplay Boolean true 是否自动播放
loop Boolean false 是否循环播放
initialPosition Number 0 初始播放位置(秒),用于续播场景
control String '' 播放控制指令:play / pause / stop
seekToSeconds Number -1 跳转到指定秒数
seektoseconds Number -1 小写兼容属性
showPlayButton Boolean true 是否显示播放/暂停按钮
showProgressBar Boolean true 是否显示进度条
showProgressText Boolean true 是否显示时间文本(当前时间/总时间)
loadingText String "加载中..." 自定义加载中文案
completeText String "视频播放完成" 自定义播放完成文案
errorText String "视频播放失败,请稍后重试" 自定义错误提示文案
showSpeedButton Boolean true 是否显示倍速按钮
showFullscreenButton Boolean true 是否显示全屏按钮
showControlBar Boolean true 是否显示整个底部控制栏
enableDoubleTap Boolean true 是否开启双击播放/暂停
enableSwipe Boolean true 是否开启左右滑动调节进度
enableVolumeSwipe Boolean true 是否开启上下滑动调节音量
enableAutoPiP Boolean false 是否允许退回桌面时自动进入悬浮框画中画
objectFit String 'contain' 视频画面缩放模式,可选:contain(等比缩放留黑边)、cover(等比填充裁剪)、fill(拉伸填满)

initialPosition — 初始播放位置

支持设置初始播放位置,用于视频续播场景。

优势

  • 播放器直接从指定位置起播,不会先从头加载再跳转
  • 启动速度提升 50-60%,节省流量
  • 无闪烁,用户体验好

注意:单位是,仅在首次加载时生效,后续通过 seekTo() 跳转。


Events

事件名 说明 参数
firstFrame 首帧渲染完成
progress-update 播放进度更新(每 500ms) detail.positiondetail.duration(毫秒,字符串)
landscape-update 视频横竖屏信息更新 detail.value'true''false'
playbackComplete 播放完成
error 播放错误
loopingStart 循环播放重新开始
singleTap 单击播放器区域
doubleTap 双击播放器区域

firstFrame — 首帧渲染完成事件

当播放器渲染出第一帧画面时触发。推荐用于控制封面图的隐藏时机

封面图建议在页面侧实现(而非插件内部),这样可以自由控制封面的样式、动画和交互:

<view style="position: relative;">
  <axiang-aliplaye ref="player" :videoUrl="url" @firstFrame="showPoster = false" />
  <image v-if="showPoster" :src="coverUrl"
    style="position: absolute; top: 0; left: 0; width: 100%; height: 100%;"
    mode="aspectFill" />
</view>

如果需要切换视频时重新显示封面,在切换前将 showPoster 设为 true 即可:

switchVideo(newUrl) {
  this.showPoster = true       // 先显示封面
  this.videoUrl = newUrl       // 切换视频,首帧渲染后 showPoster 自动变为 false
}

进度事件参数说明

iOS 兼容模式下事件参数使用双层 detail 结构,页面侧需兼容读取:

handleProgressUpdate(e) {
  const detail = e?.detail?.detail || e?.detail
  if (!detail) return
  this.currentPosition = detail.position / 1000  // 转换为秒
  this.duration = detail.duration / 1000
}

横竖屏事件参数说明

建议监听 landscape-update 事件缓存结果:

handleLandscapeUpdate(e) {
  const detail = e?.detail?.detail || e?.detail
  if (detail) {
    this.isLandscape = detail.value === 'true'
  }
}

Methods

通过 ref 获取组件实例后调用。

方法 参数 说明
loadSource(url, autoplay) url: string, autoplay: boolean 加载新视频源
play() 开始播放
pause() 暂停播放
togglePlayPause() 切换播放/暂停
stopVideo() 停止播放
seekTo(seconds) seconds: number 跳转到指定秒数
setStartPosition(seconds) seconds: number 设置起播位置(需配合重新加载)
setSpeed(speed) speed: number 设置播放倍速(范围 0-3)
enterFullScreen() 进入全屏
exitFullScreen() 退出全屏
getCurrentPosition() 当前播放进度(毫秒)
getDuration() 视频总时长(毫秒)
getIsLandscapeText() 是否横屏视频,返回 'true' / 'false'
isLandscape() getIsLandscapeText(),兼容旧方法
enterPiPMode() 手动触发进入画中画(悬浮窗)模式

使用示例

methods: {
  // 播放控制
  handlePlay() {
    this.$refs.player?.play()
  },
  handlePause() {
    this.$refs.player?.pause()
  },

  // 进度跳转
  handleSeek() {
    this.$refs.player?.seekTo(60)  // 跳转到 60 秒
  },

  // 倍速控制(范围 0-3,超出范围会被忽略)
  handleSetSpeed() {
    this.$refs.player?.setSpeed(1.5)
  },

  // 全屏
  handleFullscreen() {
    this.isFullscreen
      ? this.$refs.player?.exitFullScreen()
      : this.$refs.player?.enterFullScreen()
    this.isFullscreen = !this.isFullscreen
  }
}

旧版方法兼容

旧方法 等价新方法
playVideo() play()
pauseVideo() pause()
seekVideo(seconds) seekTo(seconds)

画中画 (Picture-in-Picture)

组件支持在 Android 12+ 上无缝切换为桌面画中画(悬浮窗)播放,并在 iOS 上支持退至后台时的音频续播(由于深度集成,在 iOS 上表现为激活 UIBackgroundModes: audio 确保音频不中断)。

两种方式可以控制画中画的开启:

1. 属性自动控制 (推荐)

通过 :enableAutoPiP="true" 绑定。如果在页面中存在多个播放器,可以利用动态属性控制哪个播放器具有悬浮权限:

<axiang-aliplaye 
  ref="player1"
  :enableAutoPiP="currentPlayer === 1"
/>

当系统检测到用户退回桌面时,只有属性为 true 的播放器会自动变成画中画。

2. 手动调用控制

可以在代码里(如点击某个按钮或监听 onHide 生命周期)主动调用:

this.$refs.player?.enterPiPMode()

手势操作

手势 功能 控制属性
左右滑动 调节播放进度(最大 ±3 分钟) enableSwipe
上下滑动 调节播放音量(0-100%) enableVolumeSwipe
双击 播放/暂停切换 enableDoubleTap
单击 显示/隐藏控制栏
  • 滑动调进度时,屏幕中央会显示目标时间和进度条提示
  • 滑动调音量时,屏幕中央会显示音量百分比提示
  • 播放中控制栏会在 2.5 秒后自动隐藏,暂停时保持显示

禁用所有手势:

<axiang-aliplaye
  :enableDoubleTap="false"
  :enableSwipe="false"
  :enableVolumeSwipe="false" />

自动初始化

组件在原生视图创建完成后自动加载视频:

页面渲染 → NVLoad 创建原生播放器 → NVLoaded 应用配置并 load(videoUrl)

正常场景下无需在 onReady 中手动调用 loadSource,直接传入 :videoUrl 即可。


平台差异

差异点 iOS Android
原生实现 AxiangAliplayeView.swift AxiangAliplayeFacade.kt
组件入口 utssdk/app-ios/index.vue utssdk/app-android/index.vue
原生视图访问 this.$el this.mNativePlayer
布尔属性初始应用 NVLoaded NVLoad / watch
进度方法返回类型 字符串毫秒值 数字毫秒值
初始播放位置 setStartTime() setStartTime() + 延迟 seek

常见问题

1. 如何实现视频续播?

使用 initialPosition 属性 + progress-update 事件:

data() {
  return {
    videoUrl: 'https://example.com/video.mp4',
    initialPosition: 0
  }
},
onLoad() {
  this.initialPosition = uni.getStorageSync('video_position') || 0
},
methods: {
  handleProgressUpdate(e) {
    const detail = e?.detail?.detail || e?.detail
    if (detail) {
      this.currentPosition = detail.position / 1000
    }
  }
},
onUnload() {
  if (this.currentPosition > 0) {
    uni.setStorageSync('video_position', this.currentPosition)
  }
}

2. 如何实现封面图?

使用 firstFrame 事件控制页面侧封面的显隐(参见 firstFrame 事件说明)。

3. 如何自定义播放器 UI?

通过 props 控制各 UI 元素显隐:

<axiang-aliplaye
  :showPlayButton="false"
  :showProgressBar="true"
  :showProgressText="true"
  :showSpeedButton="false"
  :showFullscreenButton="true"
  :showControlBar="true" />

如需完全自定义控制栏,设置 :showControlBar="false" 后自行叠加 UI 层,通过 ref 调用方法控制播放。

4. iOS 编译报错 NSNumber? 类型问题?

UTS 编译器的类型映射问题,使用 Int64 类型和 as Int64 显式转换解决。

详见: uni_modules/axiang-aliplaye/docs/iOS_UTS_NSNumber_Issue.md


注意事项

  1. ⚠️ 修改原生侧代码后必须重新制作自定义基座
  2. 📱 建议使用 v-if 控制播放器创建和销毁,避免复用状态异常
  3. ⏱️ seekTo 参数单位是,进度事件和 getCurrentPosition() / getDuration() 返回单位是毫秒
  4. 💾 建议监听 progress-update 缓存进度值,需要时直接读取
  5. 🍎 iOS 全屏依赖内置的 AxiangAliplayeFullscreenController,确保 iOS 原生文件完整参与打包
  6. 🖼️ 封面图在页面侧实现,监听 firstFrame 事件控制隐藏时机

更新日志

查看 CHANGELOG.md 了解详细版本更新记录。

技术文档

许可证

MIT License

隐私、权限声明

1. 本插件需要申请的系统权限列表:

2. 本插件采集的数据、发送的服务器地址、以及数据用途说明:

3. 本插件是否包含广告,如包含需详细说明广告表达方式、展示频率: