Explorar o código

调整上传文件

yfh hai 1 semana
pai
achega
9e234b8a63

+ 0 - 3
src/views/course/userCourse/index.vue

@@ -234,9 +234,6 @@
             </el-form-item>
           </el-col>
         </el-row>
-        <el-form-item label="排序" prop="sort">
-          <el-input-number v-model="form.sort"  :min="0" label="请输入排序"></el-input-number>
-        </el-form-item>
         <el-form-item label="课程封面" prop="imgUrl">
           <ImageUpload v-model="form.imgUrl" type="image" :num="10" :width="150" :height="150"/>
         </el-form-item>

+ 78 - 95
src/views/course/videoResource/index.vue

@@ -293,7 +293,7 @@
                         :percentage="currentUploadProgress.line1"
                         :show-text="false"
                         :width="30"
-                        :status="currentUploadProgress.line1Status === 'success' ? 'success' : 
+                        :status="currentUploadProgress.line1Status === 'success' ? 'success' :
                                 currentUploadProgress.line1Status === 'failed' ? 'exception' : ''"
                       ></el-progress>
                       <span class="line-status-text">{{ Math.round(currentUploadProgress.line1) }}%</span>
@@ -304,7 +304,7 @@
                         :percentage="currentUploadProgress.line2"
                         :show-text="false"
                         :width="30"
-                        :status="currentUploadProgress.line2Status === 'success' ? 'success' : 
+                        :status="currentUploadProgress.line2Status === 'success' ? 'success' :
                                 currentUploadProgress.line2Status === 'failed' ? 'exception' : ''"
                       ></el-progress>
                       <span class="line-status-text">{{ Math.round(currentUploadProgress.line2) }}%</span>
@@ -412,8 +412,8 @@
             <div class="batch-upload-progress">
               <div class="total-progress-row">
                 <span class="progress-label">总进度:</span>
-                <el-progress 
-                  :percentage="scope.row.progress || 0" 
+                <el-progress
+                  :percentage="scope.row.progress || 0"
                   :status="getProgressStatus(scope.row)"
                   :show-text="true"
                   :format="() => `${Math.round(scope.row.progress || 0)}%`"
@@ -422,9 +422,9 @@
               <div v-if="scope.row.uploadDetails" class="line-progress-rows">
                 <div class="line-progress-row">
                   <span class="line-label">线路1:</span>
-                  <el-progress 
+                  <el-progress
                     :percentage="scope.row.uploadDetails.line1 || 0"
-                    :status="scope.row.uploadDetails.line1Status === 'success' ? 'success' : 
+                    :status="scope.row.uploadDetails.line1Status === 'success' ? 'success' :
                             scope.row.uploadDetails.line1Status === 'failed' ? 'exception' : 'warning'"
                     :show-text="false"
                     style="width: 60px;"
@@ -433,9 +433,9 @@
                 </div>
                 <div class="line-progress-row">
                   <span class="line-label">线路2:</span>
-                  <el-progress 
+                  <el-progress
                     :percentage="scope.row.uploadDetails.line2 || 0"
-                    :status="scope.row.uploadDetails.line2Status === 'success' ? 'success' : 
+                    :status="scope.row.uploadDetails.line2Status === 'success' ? 'success' :
                             scope.row.uploadDetails.line2Status === 'failed' ? 'exception' : 'warning'"
                     :show-text="false"
                     style="width: 60px;"
@@ -445,7 +445,7 @@
               </div>
             </div>
           </template>
-          
+
         </el-table-column>
         <el-table-column label="操作" align="center" width="150">
           <template slot-scope="scope">
@@ -465,7 +465,7 @@
               type="text"
               icon="el-icon-refresh"
               @click="retryBatchUpload(scope.row)"
-              style="color: #E6A23C;">重试</el-button>  
+              style="color: #E6A23C;">重试</el-button>
           </template>
         </el-table-column>
       </el-table>
@@ -1141,13 +1141,21 @@ export default {
     async getFirstThumbnail(file, form){
       try {
         //截取小文件
+        // 打印原始文件名和大小
+        console.log("原始文件名:", file.name);
+        console.log("原始文件大小:", file.size, "bytes");
+        console.log("原始文件类型:", file.type);
+
+        // 截取小文件
         const clippedBlob = await this.clipVideoFirstTwoSeconds(file);
+        console.log("clippedBlob:::::::::", clippedBlob);
+        console.log("截取后的Blob大小:", clippedBlob.size, "bytes");
+        console.log("截取后的Blob类型:", clippedBlob.type);
 
         const clippedFile = new File([clippedBlob], 'clipped_video.mp4', {
           type: 'video/mp4',
           lastModified: Date.now()
         });
-        console.log("调用请请求---------------》",response)
         // 3. 调用接口获取封面
         const response = await getThumbnail(clippedFile);
         console.log("获取封面请求---------------》",response)
@@ -1156,63 +1164,38 @@ export default {
         console.error('获取封面失败:', error);
       }
     },
+
     //截取大文件视频
-    clipVideoFirstTwoSeconds(file) {
+    async clipVideoFirstTwoSeconds(file) {
       return new Promise((resolve, reject) => {
-        // 创建视频元素用于处理
         const video = document.createElement('video');
         video.src = URL.createObjectURL(file);
-        video.crossOrigin = 'anonymous';
-        video.preload = 'metadata';
-
-        // 视频元数据加载完成后开始处理
-        video.onloadedmetadata = async () => {
-          try {
-            // 计算截取时长
-            const duration = Math.min(2, video.duration);
-
-            // 直接从视频元素捕获流
-            const stream = video.captureStream();
-
-            // 创建 MediaRecorder 录制截取的片段
-            const mediaRecorder = new MediaRecorder(stream);
-            const chunks = [];
-
-            // 收集录制的视频数据
-            mediaRecorder.ondataavailable = (e) => chunks.push(e.data);
-
-            // 录制结束后处理结果
-            mediaRecorder.onstop = () => {
-              // 合并数据为 Blob(MP4 格式)
-              const blob = new Blob(chunks, { type: 'video/mp4' });
-              resolve(blob);
-
-              // 清理资源
-              URL.revokeObjectURL(video.src);
-              stream.getTracks().forEach(track => track.stop());
-            };
-
-            // 开始录制
-            mediaRecorder.start();
-
-            // 播放视频并在指定时间后停止录制
-            video.currentTime = 0; // 从开头开始
-            video.play();
-
-            // 到达截取时长后停止录制
-            setTimeout(() => {
-              video.pause();
-              mediaRecorder.stop();
-            }, duration * 1000); // 转换为毫秒
-
-          } catch (error) {
-            reject(new Error('视频截取失败: ' + error.message));
-          }
+        video.muted = true;
+        video.playsInline = true;
+
+        video.onloadedmetadata = () => {
+          video.currentTime = 0; // 定位到第一帧
+          video.onseeked = () => {
+            const canvas = document.createElement('canvas');
+            canvas.width = video.videoWidth;
+            canvas.height = video.videoHeight;
+            const ctx = canvas.getContext('2d');
+            ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
+
+            canvas.toBlob(
+              (blob) => {
+                URL.revokeObjectURL(video.src);
+                resolve(blob); // 返回 JPEG Blob
+              },
+              'image/jpeg',
+              0.8 // 质量
+            );
+          };
         };
 
-        // 视频加载错误处理
         video.onerror = () => {
-          reject(new Error('视频加载失败,请检查文件格式'));
+          URL.revokeObjectURL(video.src);
+          reject(new Error('视频加载失败'));
         };
       });
     },
@@ -1221,11 +1204,11 @@ export default {
       try {
         // 更新线路1状态为上传中
         this.updateUploadProgress('line1Status', 'uploading');
-        
+
         const data = await uploadObject(file, (progress) => {
           const progressPercent = Math.floor(progress.percent * 100);
           this.updateUploadProgress('line1', progressPercent);
-          
+
           const progressEvent = {
             percent: progressPercent,
             loaded: progress.loaded,
@@ -1234,16 +1217,16 @@ export default {
           };
           onProgress(progressEvent);
         }, 1);
-        
+
         let line_1 = `${process.env.VUE_APP_VIDEO_LINE_1}${data.urlPath}`;
         form.fileKey = data.urlPath.substring(1);
         form.videoUrl = line_1;
         form.line1 = line_1;
-        
+
         // 更新线路1状态为成功
         this.updateUploadProgress('line1Status', 'success');
         this.updateUploadProgress('line1', 100);
-        
+
         this.$message.success("线路一上传成功");
         return { success: true, url: line_1 };
       } catch (error) {
@@ -1258,11 +1241,11 @@ export default {
       try {
         // 更新线路2状态为上传中
         this.updateUploadProgress('line2Status', 'uploading');
-        
+
         const data = await uploadToOBS(file, (progress) => {
           const progressPercent = Math.floor(progress);
           this.updateUploadProgress('line2', progressPercent);
-          
+
           const progressEvent = {
             percent: progressPercent,
             loaded: progress,
@@ -1271,13 +1254,13 @@ export default {
           };
           onProgress(progressEvent);
         }, 1);
-        
+
         form.line2 = `${process.env.VUE_APP_VIDEO_LINE_2}/${data.urlPath}`;
-        
+
         // 更新线路2状态为成功
         this.updateUploadProgress('line2Status', 'success');
         this.updateUploadProgress('line2', 100);
-        
+
         this.$message.success("线路二上传成功");
         return { success: true, url: form.line2 };
       } catch (error) {
@@ -1290,12 +1273,12 @@ export default {
     // 更新上传进度的辅助方法
     updateUploadProgress(key, value) {
       this.currentUploadProgress[key] = value;
-      
+
       // 计算总进度:只有两个线路都成功才算100%
-      if (this.currentUploadProgress.line1Status === 'success' && 
+      if (this.currentUploadProgress.line1Status === 'success' &&
           this.currentUploadProgress.line2Status === 'success') {
         this.currentUploadProgress.total = 100;
-      } else if (this.currentUploadProgress.line1Status === 'failed' || 
+      } else if (this.currentUploadProgress.line1Status === 'failed' ||
                  this.currentUploadProgress.line2Status === 'failed') {
         // 如果任一线路失败,总进度保持当前状态
         this.currentUploadProgress.total = Math.min(
@@ -1314,10 +1297,10 @@ export default {
     async videoUpload(options) {
       this.isUploading = true;
       this.form.uploadStatus = 'uploading';
-      
+
       const file = options.file;
       this.getMediaDuration(file);
-      
+
       // 重置进度
       this.currentUploadProgress = {
         total: 0,
@@ -1363,17 +1346,17 @@ export default {
             line1Status: this.currentUploadProgress.line1Status,
             line2Status: this.currentUploadProgress.line2Status
           };
-          
+
           const failedLines = [];
           if (!line1Success) failedLines.push('线路1');
           if (!line2Success) failedLines.push('线路2');
-          
+
           this.$message.error(`视频上传失败!${failedLines.join('、')} 上传失败,请重试`);
         }
 
         this.form.fileName = file.name;
         this.form.fileSize = file.size;
-        
+
       } catch (error) {
         this.form.uploadStatus = 'failed';
         this.$message.error("视频上传过程中发生错误,请重试");
@@ -1612,11 +1595,11 @@ export default {
             // 失败时保持当前进度,不设为100%
             this.updateBatchProgress(index);
           }
-          
+
           const failedLines = [];
           if (!line1Success) failedLines.push('线路1');
           if (!line2Success) failedLines.push('线路2');
-          
+
           this.$message.error(`文件 ${file.name} 在 ${failedLines.join('、')} 上传失败`);
         }
 
@@ -1914,12 +1897,12 @@ export default {
         const item = this.videoList[index];
         const line1Progress = item.uploadDetails.line1 || 0;
         const line2Progress = item.uploadDetails.line2 || 0;
-        
+
         // 只有两个线路都成功才算100%
-        if (item.uploadDetails.line1Status === 'success' && 
+        if (item.uploadDetails.line1Status === 'success' &&
             item.uploadDetails.line2Status === 'success') {
           item.progress = 100;
-        } else if (item.uploadDetails.line1Status === 'failed' || 
+        } else if (item.uploadDetails.line1Status === 'failed' ||
                    item.uploadDetails.line2Status === 'failed') {
           // 如果任一线路失败,总进度保持当前状态,不超过99%
           item.progress = Math.min((line1Progress + line2Progress) / 2, 99);
@@ -1936,7 +1919,7 @@ export default {
 
       // const {line1, line2,line1Status,line2Status} = this.videoList[index].uploadDetails
 
-      
+
 
       // // 重置状态
       // this.videoList[index].uploadStatus = 'uploading';
@@ -1949,7 +1932,7 @@ export default {
       // };
 
       // const tempVideo = this.videoList[index];
-      
+
       // try {
       //   // 重新上传
       //   // const [line1Result, line2Result] = await Promise.allSettled([
@@ -2008,11 +1991,11 @@ export default {
 
       const tempVideo = this.videoList[index];
       const uploadDetails = tempVideo.uploadDetails || {};
-      
+
       // 检查哪些线路需要重试
       const needRetryLine1 = uploadDetails.line1Status === 'failed' || uploadDetails.line1Status === 'pending';
       const needRetryLine2 = uploadDetails.line2Status === 'failed' || uploadDetails.line2Status === 'pending';
-      
+
       if (!needRetryLine1 && !needRetryLine2) {
         this.$message.info('所有线路都已上传成功,无需重试');
         return;
@@ -2020,7 +2003,7 @@ export default {
 
       // 更新整体状态为上传中
       this.videoList[index].uploadStatus = 'uploading';
-      
+
       // 只重置需要重试的线路状态
       if (needRetryLine1) {
         this.videoList[index].uploadDetails.line1 = 0;
@@ -2033,7 +2016,7 @@ export default {
 
       try {
         const uploadPromises = [];
-        
+
         // 根据需要重试的线路创建上传任务
         if (needRetryLine1) {
           uploadPromises.push(
@@ -2045,7 +2028,7 @@ export default {
           // 如果线路1不需要重试,创建一个已成功的Promise
           uploadPromises.push(Promise.resolve({ line: 'line1', result: { success: true } }));
         }
-        
+
         if (needRetryLine2) {
           uploadPromises.push(
             this.uploadVideoToHwObsBatch(tempVideo.file, tempVideo)
@@ -2059,12 +2042,12 @@ export default {
 
         // 等待所有上传任务完成
         const results = await Promise.all(uploadPromises);
-        
+
         // 处理结果
         let line1Success = true;
         let line2Success = true;
         let retryMessages = [];
-        
+
         results.forEach(({ line, result }) => {
           if (line === 'line1') {
             line1Success = result.success;
@@ -2104,7 +2087,7 @@ export default {
           this.updateBatchProgress(index);
           this.$message.error(`文件 ${tempVideo.fileName} 重试完成:${retryMessages.join(',')}`);
         }
-        
+
       } catch (error) {
         this.videoList[index].uploadStatus = 'failed';
         this.$message.error(`文件 ${tempVideo.fileName} 重试过程中发生错误:${error.message || '未知错误'}`);
@@ -2201,7 +2184,7 @@ export default {
       }
       return '';
     },
-    
+
   }
 }
 </script>