app视频预览方案

更新时间: 2025-09-19 10:23:48

# 完整代码实现

<template>
  <view class="video-preview-container">
    <!-- 视频播放器 -->
    <video
          id="videoPlayer"
          class="video-player"
          :src="videoSrc"
          controls
          autoplay
          :loop="false"
          :muted="false"
          :enable-progress-gesture="true"
          :show-fullscreen-btn="true"
          :show-play-btn="true"
          :show-center-play-btn="true"
          object-fit="contain"
          @error="handleVideoError"
          @loadedmetadata="onLoadedMetadata"
        ></video>
        
        <!-- 加载提示 -->
        <view class="loading-tip" v-if="loading">
          <uni-icons type="spinner-cycle" size="36" color="#007AFF" class="loading-icon"></uni-icons>
          <text class="loading-text">加载中...</text>
        </view>
  </view>
</template>

<script>
export default {
  data() {
    return {
      videoSrc: '',
      loading: true,
      videoInfo: {
        duration: 0,
        width: 0,
        height: 0
      }
    };
  },
  components:{
	  navBarTitle : navBarTitle
  },
  onLoad(options) {
    // 获取视频路径并解码
    this.videoSrc = decodeURIComponent(options.src);
    console.log('视频路径:', this.videoSrc);
    
    // 创建视频上下文
    this.videoContext = uni.createVideoContext('videoPlayer', this);
  },
  methods: {
    // 视频元数据加载完成
    onLoadedMetadata(e) {
      this.loading = false;
      this.videoInfo = {
        duration: e.detail.duration,
        width: e.detail.width,
        height: e.detail.height
      };
      console.log('视频信息:', this.videoInfo);
    },
    
    // 处理视频播放错误
    handleVideoError(e) {
      this.loading = false;
      console.error('视频播放错误:', e);
      
      // 错误提示
      uni.showModal({
        title: '播放失败',
        content: `错误码: ${e.detail.errCode}\n请检查视频格式是否支持`,
        showCancel: false
      });
      
      // 常见错误码说明
      const errorTips = {
        1: '不支持的视频格式',
        2: '网络错误',
        3: '视频解码失败',
        4: '视频资源不存在',
        5: '视频加载超时'
      };
      
      if (errorTips[e.detail.errCode]) {
        uni.showToast({
          title: errorTips[e.detail.errCode],
          icon: 'none'
        });
      }
    }
  }
};
</script>

<style lang="scss" scoped>
.video-preview-container {
  position: relative;
  width: 100%;
  height: 100vh;
  background-color: #000000;
  display: flex;
  flex-direction: column;
  .video-player {
    width: 100%;
    flex:1;
	min-height: 0;
  }
  
  .loading-tip {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    display: flex;
    flex-direction: column;
    align-items: center;
  }
  
  .loading-icon {
    animation: spin 1s linear infinite;
  }
  
  .loading-text {
    color: #ffffff;
    margin-top: 20rpx;
    font-size: 28rpx;
  }
  
  @keyframes spin {
    0% { transform: rotate(0deg); }
    100% { transform: rotate(360deg); }
  }
}
</style>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137

# 关键技术点解析

# 视频上下文创建与使用

uni.createVideoContext(videoId, componentInstance)
是控制视频播放的核心API,需要注意:

  • videoId必须与video组件的id属性一致
  • 在自定义组件中使用时,必须传递第二个参数(组件实例)
  • Vue3环境需使用getCurrentInstance()获取实例:
import { getCurrentInstance } from 'vue';
const instance = getCurrentInstance();
const videoContext = uni.createVideoContext("videoPlayer", instance);
1
2
3

# 视频路径处理

由于URL参数传递时会对特殊字符编码,需要使用decodeURIComponent解码:

// 错误示例:未解码导致路径错误(常见于含中文/空格的视频URL)
this.videoSrc = options.src; // 可能得到 "https://example.com/%E6%B5%8B%E8%AF%95.mp4"

// 正确示例
this.videoSrc = decodeURIComponent(options.src); // 解码为 "https://example.com/测试.mp4"
1
2
3
4
5

# 动态加载状态管理

  • 页面初始化时loading: true
  • loadedmetadata事件触发后设为false
  • 错误发生时立即隐藏加载动画