在混合 App 中,移動端使用 標簽播放視頻經常踩坑,尤其是格式兼容、跨域限制、WebView 差異等問題。
本文介紹一個通用的 Cordova 視頻播放組件:優先 HTML5 播放,播放失敗自動提示用戶使用系統播放器,并支持原生插件兜底播放。
? 功能亮點
- ? 支持 MP4 / M3U8(HLS.js)
- ? 播放失敗提示「點擊使用系統播放器」
- ? 原生播放器兜底(cordova-plugin-streaming-media)
- ? 可配置橫/豎屏、全屏、緩存下載
- ? 使用簡單,移動端穩定運行
🧩 安裝依賴
cordova plugin add cordova-plugin-streaming-media
npm install hls.js
🧱 組件源碼(CordovaVideo.vue)
<template><div class="video-wrapper" v-show="visible" @click="onMaskClick"><videov-if="!useNativePlayer"ref="video"class="video-player":src="videoSrc"controlsplaysinlinewebkit-playsinline:poster="poster"@click.stop@error="onVideoError"@waiting="$emit('buffering')"@playing="$emit('playing')"></video><div v-if="fallbackPrompt" class="fallback-tip" @click.stop><p>播放失敗,點擊使用系統播放器</p><button @click="useSystemPlayer">用系統播放器播放</button></div><button class="close-btn" @click.stop="onMaskClick" aria-label="關閉視頻">×</button><div v-if="downloading" class="download-progress" @click.stop><p>緩存中 {{ Math.round(progress * 100) }}%</p></div></div>
</template><script>
import Hls from 'hls.js'export default {name: 'CordovaVideo',props: {src: { type: String, required: true },cache: { type: Boolean, default: false },poster: String,landscape: { type: Boolean, default: true }},data () {return {visible: false,localPath: null,downloading: false,progress: 0,hls: null,useNativePlayer: false,fallbackPrompt: false}},computed: {videoSrc () {if (this.isM3U8) return ''return this.localPath || this.src},isM3U8 () {return this.src.endsWith('.m3u8')}},mounted () { this.prepare() },methods: {cleanupHtml5 () {if (this.hls) { this.hls.destroy(); this.hls = null }const v = this.$refs.videoif (v) { v.pause(); v.removeAttribute('src'); v.load() }},play () {if (this.visible) returnthis.visible = truethis.useNativePlayer = falsethis.fallbackPrompt = falsethis.$nextTick(() => {if (this.isM3U8 && Hls.isSupported()) {this.initHls()} else {this.tryHtml5Play()}})},tryHtml5Play () {const v = this.$refs.videoif (!v) return this.showFallback()const onSuccess = () => {v.removeEventListener('error', onError)clearTimeout(timer)}const onError = () => this.showFallback()v.addEventListener('error', onError, { once: true })v.addEventListener('playing', onSuccess, { once: true })v.play().catch(() => this.showFallback())const timer = setTimeout(() => this.showFallback(), 5000)},showFallback () {this.fallbackPrompt = true},useSystemPlayer () {this.fallbackPrompt = falsethis.playNative()},initHls () {this.hls?.destroy()this.hls = new Hls()this.hls.attachMedia(this.$refs.video)this.hls.loadSource(this.src)this.hls.on(Hls.Events.ERROR, () => this.showFallback())},onVideoError () {this.showFallback()},playNative () {const streaming = window.plugins?.streamingMediaif (!streaming) {this.visible = falsereturn}this.cleanupHtml5()this.useNativePlayer = truethis.visible = falsestreaming.playVideo(this.src, {orientation: this.landscape ? 'landscape' : 'portrait',shouldAutoClose: true,controls: true,initFullscreen: true})},prepare () {},download () {}},watch: {src () {this.localPath = nullthis.prepare()}}
}
</script><style scoped>
.video-wrapper {position: fixed; inset: 0;background: #000;z-index: 9999;display: flex; align-items: center; justify-content: center;
}
.video-player {width: 100%; max-height: 100%;
}
.fallback-tip {position: absolute; inset: 0;background: rgba(0,0,0,0.6);color: #fff; font-size: 16px;display: flex; flex-direction: column;align-items: center; justify-content: center;
}
.fallback-tip button {padding: 6px 12px;background: #409eff; color: #fff;border: none; border-radius: 4px;
}
.close-btn {position: absolute; top: 12px; right: 12px;width: 32px; height: 32px;background: rgba(255,255,255,0.15);color: white; font-size: 20px;border: none; border-radius: 50%;cursor: pointer;
}
</style>
🔍 插件對比:Cordova 常用視頻播放方案分析
插件名 | 是否全屏 | 是否支持橫豎屏 | 控件控制 | 兼容性 | 是否可自定義關閉 | 播放格式支持 | 綜合推薦 |
---|---|---|---|---|---|---|---|
<video> 標簽 | 否(受限) | 是 | 是 | 易出錯(Android 上格式限制多) | 是 | MP4(部分編碼)、HLS(需搭配 hls.js) | ? 前置嘗試 |
cordova-plugin-streaming-media | ? 是 | ? 是 | ? 支持 | 穩定 | ? 無關閉按鈕(需播放結束自動退出) | MP4 / M3U8 / AVI / 多格式(依賴系統播放器) | ? 推薦兜底方案 |
cordova-plugin-video-player | ? 是 | ? 僅豎屏 | ? 控制弱 | 支持好 | ? 無退出按鈕 | MP4 主流支持 | 🚫 不推薦 |
第三方播放器 WebView 方案(如騰訊視頻 iframe) | ? 取決于 Web 容器 | ? 受限 | ? 不統一 | 風險高,易失效 | ? | 限平臺 | ? 僅作補充 |
? 建議組合方案
播放順序 | 使用方式 |
---|---|
? 首選 HTML5 <video> 播放(支持 HLS 的話配合 hls.js ) | |
?? 監聽 play() 失敗 或 error 回調中主動 fallback | |
🔁 兜底切換為 cordova-plugin-streaming-media 原生播放,自動退出 |
📦 總結
- 移動端視頻播放兼容性較差,需考慮降級處理
- 使用原生播放器插件做兜底,是當前 Cordova 應用中可靠的解決方案
- 推薦使用 cordova-plugin-streaming-media,輕量穩定
如果你覺得有幫助,歡迎點贊收藏支持 👍