guoyu/log/批量更新视频duration说明.md
2025-12-11 23:28:07 +08:00

4.9 KiB
Raw Blame History

批量更新视频duration说明

📊 当前问题

查询结果:

总视频数859个
- 未配置duration: 858个 (99.9%)
- 配置为0: 1个
- 已配置: 0个

影响:

  • 无法准确判断视频是否真正完成
  • 只能根据观看时长和学习次数粗略判断
  • 可能导致进度计算不准确

当前临时解决方案

分级判断标准(已实现):

根据观看时长动态调整要求:

观看时长 最少观看 最少记录数 说明
< 3分钟 60秒 3次 短视频
3-10分钟 180秒 5次 中等视频
≥ 10分钟 600秒 8次 长视频

优点:

  • 防止看几秒就算完成
  • 考虑了不同长度的视频
  • 要求多次学习记录(防快进)

缺点:

  • 仍然无法精确判断完成
  • 长视频可能要求太严格
  • 短视频可能要求太宽松

🎯 最佳解决方案配置正确的duration

方式1前端上传时获取推荐

修改上传组件:

// 上传视频时自动获取时长
function handleVideoUpload(file) {
    const video = document.createElement('video');
    video.preload = 'metadata';
    
    video.onloadedmetadata = function() {
        const duration = Math.floor(video.duration); // 秒
        
        // 上传时携带duration参数
        uploadFile(file, {
            duration: duration
        });
    };
    
    video.src = URL.createObjectURL(file);
}

方式2后端自动获取服务器端

使用FFmpeg获取视频信息

# 安装FFmpeg
# Windows: 下载 https://ffmpeg.org/download.html
# Linux: apt-get install ffmpeg

# 获取视频时长
ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 video.mp4

Java代码示例

public int getVideoDuration(String filePath) {
    try {
        ProcessBuilder pb = new ProcessBuilder(
            "ffprobe",
            "-v", "error",
            "-show_entries", "format=duration",
            "-of", "default=noprint_wrappers=1:nokey=1",
            filePath
        );
        Process process = pb.start();
        BufferedReader reader = new BufferedReader(
            new InputStreamReader(process.getInputStream())
        );
        String durationStr = reader.readLine();
        return (int) Float.parseFloat(durationStr);
    } catch (Exception e) {
        return 0;
    }
}

方式3批量扫描现有视频一次性处理

创建Python脚本扫描所有视频

# scan_video_duration.py
import os
import subprocess
import mysql.connector

# 连接数据库
db = mysql.connector.connect(
    host="localhost",
    user="root",
    password="root",
    database="study"
)
cursor = db.cursor()

# 查询所有视频
cursor.execute("SELECT id, file_path FROM courseware WHERE type='video'")
videos = cursor.fetchall()

# 基础路径
base_path = "D:/wwwroot/study_web/web"  # 根据实际情况修改

update_count = 0
for video_id, file_path in videos:
    # 构建完整路径
    full_path = base_path + file_path
    
    if not os.path.exists(full_path):
        print(f"文件不存在: {full_path}")
        continue
    
    try:
        # 使用ffprobe获取时长
        result = subprocess.run([
            'ffprobe',
            '-v', 'error',
            '-show_entries', 'format=duration',
            '-of', 'default=noprint_wrappers=1:nokey=1',
            full_path
        ], capture_output=True, text=True)
        
        duration = int(float(result.stdout.strip()))
        
        # 更新数据库
        cursor.execute(
            "UPDATE courseware SET duration = %s WHERE id = %s",
            (duration, video_id)
        )
        db.commit()
        
        update_count += 1
        print(f"✅ ID:{video_id} - {duration}秒")
        
    except Exception as e:
        print(f"❌ ID:{video_id} - 错误: {e}")

print(f"\n完成!更新了 {update_count} 个视频的duration")
cursor.close()
db.close()

执行:

python scan_video_duration.py

📋 推荐执行步骤

短期方案(当前已实现):

  1. 使用分级判断标准
  2. 重新编译部署
  3. 测试验证

长期方案(建议实施):

  1. 前端修改 - 上传视频时自动获取duration
  2. 现有视频 - 使用Python脚本批量扫描更新
  3. 后端验证 - 确保所有新上传视频都有duration

⚠️ 注意事项

  1. 批量更新前先备份数据库
  2. 确认视频文件路径正确
  3. 服务器需要安装FFmpeg
  4. 更新可能需要较长时间859个视频

当前状态

  • 已修复"3秒即完成"的bug
  • 已实现分级判断标准
  • 可以正常使用(虽然不是最精确)
  • 建议后续批量更新duration

可以先编译部署使用后续再批量更新duration