| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302 |
- <template>
- <view class="video-player-container">
- <!-- H5环境使用Jessibuca -->
- <view v-if="isH5" class="h5-player">
- <view ref="jessibucaContainer" class="jessibuca-container"></view>
- <view v-if="loadError" class="error-message">
- <text>视频加载失败,请刷新重试</text>
- </view>
- </view>
-
- <!-- 小程序环境使用live-player -->
- <view v-else class="mp-player">
- <live-player
- id="videoPlayer"
- :src="videoUrl"
- mode="live"
- :autoplay="autoplay"
- :muted="isMuted"
- object-fit="contain"
- @statechange="onStateChange"
- @error="onError"
- @fullscreenchange="onFullscreenChange"
- class="live-player"
- ></live-player>
- </view>
- </view>
- </template>
- <script>
- export default {
- name: 'VideoPlayer',
- props: {
- videoUrl: {
- type: String,
- required: true
- },
- hasAudio: {
- type: Boolean,
- default: true
- },
- autoplay: {
- type: Boolean,
- default: true
- }
- },
- data() {
- return {
- isH5: false,
- isMuted: false,
- isPlaying: false,
- isFullscreen: false,
- jessibucaPlayer: null,
- livePlayerContext: null,
- loadError: false
- }
- },
- mounted() {
- // 判断当前环境
- // #ifdef H5
- this.isH5 = true;
- this.$nextTick(() => {
- this.initJessibucaPlayer();
- });
- // #endif
-
- // #ifdef MP-WEIXIN
- this.isH5 = false;
- this.initLivePlayer();
- // #endif
- },
- beforeDestroy() {
- this.destroyPlayer();
- },
- watch: {
- videoUrl: {
- handler(newUrl) {
- if (this.isH5 && this.jessibucaPlayer) {
- this.destroyPlayer();
- this.$nextTick(() => {
- this.initJessibucaPlayer();
- });
- }
- }
- }
- },
- methods: {
- // 初始化Jessibuca播放器(H5环境)
- initJessibucaPlayer() {
- if (!this.isH5 || !this.$jessibuca) {
- console.error('H5环境或Jessibuca插件未初始化');
- this.loadError = true;
- return;
- }
-
- console.log('正在初始化Jessibuca播放器,URL:', this.videoUrl);
-
- // 使用Jessibuca插件
- this.$jessibuca.createPlayer({
- container: this.$refs.jessibucaContainer,
- url: this.videoUrl,
- hasAudio: this.hasAudio,
- autoplay: this.autoplay,
- decoder: './static/js/jessibuca/decoder.js',
- wasmUrl: './static/js/jessibuca/decoder.wasm'
- }).then(player => {
- if (!player) {
- console.error('Jessibuca播放器创建失败');
- this.loadError = true;
- return;
- }
-
- this.jessibucaPlayer = player;
- console.log('Jessibuca播放器创建成功');
-
- // 监听事件
- player.on('play', () => {
- this.isPlaying = true;
- this.loadError = false;
- this.$emit('play');
- });
-
- player.on('pause', () => {
- this.isPlaying = false;
- this.$emit('pause');
- });
-
- player.on('error', (err) => {
- console.error('Jessibuca播放错误:', err);
- this.loadError = true;
- this.$emit('error', err);
- });
- }).catch(err => {
- console.error('Jessibuca播放器初始化失败:', err);
- this.loadError = true;
- });
- },
-
- // 初始化小程序live-player
- initLivePlayer() {
- if (this.isH5) return;
-
- // #ifdef MP-WEIXIN
- this.livePlayerContext = uni.createLivePlayerContext('videoPlayer', this);
- if (this.autoplay) {
- this.play();
- }
- // #endif
- },
-
- // 播放
- play() {
- if (this.isH5 && this.jessibucaPlayer) {
- this.jessibucaPlayer.play();
- } else if (this.livePlayerContext) {
- this.livePlayerContext.play({
- success: () => {
- this.isPlaying = true;
- this.$emit('play');
- },
- fail: (err) => {
- console.error('播放失败:', err);
- this.$emit('error', err);
- }
- });
- }
- },
-
- // 暂停
- pause() {
- if (this.isH5 && this.jessibucaPlayer) {
- this.jessibucaPlayer.pause();
- } else if (this.livePlayerContext) {
- this.livePlayerContext.pause({
- success: () => {
- this.isPlaying = false;
- this.$emit('pause');
- }
- });
- }
- },
-
- // 截图
- screenshot() {
- if (this.isH5 && this.jessibucaPlayer) {
- return this.jessibucaPlayer.screenshot();
- } else if (this.livePlayerContext) {
- return new Promise((resolve, reject) => {
- this.livePlayerContext.snapshot({
- success: (res) => {
- resolve(res.tempImagePath);
- },
- fail: (err) => {
- reject(err);
- }
- });
- });
- }
- },
-
- // 静音
- mute() {
- this.isMuted = true;
- if (this.isH5 && this.jessibucaPlayer) {
- this.jessibucaPlayer.mute();
- }
- },
-
- // 取消静音
- cancelMute() {
- this.isMuted = false;
- if (this.isH5 && this.jessibucaPlayer) {
- this.jessibucaPlayer.cancelMute();
- }
- },
-
- // 全屏
- fullscreenSwich() {
- if (this.isH5 && this.jessibucaPlayer) {
- this.jessibucaPlayer.fullscreen();
- } else if (this.livePlayerContext) {
- if (this.isFullscreen) {
- this.livePlayerContext.exitFullScreen();
- } else {
- this.livePlayerContext.requestFullScreen({
- direction: 90
- });
- }
- }
- },
-
- // 重置大小
- resize() {
- if (this.isH5 && this.jessibucaPlayer) {
- this.jessibucaPlayer.resize();
- }
- },
-
- // 检查是否全屏
- isFullscreen() {
- return this.isFullscreen;
- },
-
- // live-player状态变化
- onStateChange(e) {
- console.log('播放器状态变化:', e.detail);
- const state = e.detail.code;
- if (state === 2003) { // 播放中
- this.isPlaying = true;
- this.$emit('play');
- } else if (state === 2004) { // 暂停
- this.isPlaying = false;
- this.$emit('pause');
- }
- },
-
- // live-player错误
- onError(e) {
- console.error('播放器错误:', e.detail);
- this.$emit('error', e.detail);
- },
-
- // 全屏状态变化
- onFullscreenChange(e) {
- this.isFullscreen = e.detail.fullScreen;
- this.$emit('fullscreenchange', this.isFullscreen);
- },
-
- // 销毁播放器
- destroyPlayer() {
- if (this.isH5 && this.jessibucaPlayer) {
- this.jessibucaPlayer.destroy();
- this.jessibucaPlayer = null;
- }
- }
- }
- }
- </script>
- <style>
- .video-player-container {
- width: 100%;
- height: 100%;
- background-color: #000;
- position: relative;
- }
- .h5-player, .mp-player, .jessibuca-container, .live-player {
- width: 100%;
- height: 100%;
- }
- .error-message {
- position: absolute;
- top: 50%;
- left: 50%;
- transform: translate(-50%, -50%);
- color: #fff;
- background-color: rgba(0, 0, 0, 0.5);
- padding: 10px 20px;
- border-radius: 4px;
- }
- </style>
|