/** * 手动触发视频素材转码脚本 * * 用于修复转码状态停留在 pending 的视频素材 * * 使用方法: * npx ts-node scripts/trigger-video-transcode.ts FLNXI2025121373113 */ import { PrismaClient } from '@prisma/client' const prisma = new PrismaClient() async function triggerVideoTranscode(materialId: string) { console.log(`\n开始处理素材: ${materialId}\n`) try { // 1. 查询素材信息 console.log('步骤 1: 查询素材信息...') const material = await prisma.material.findUnique({ where: { id: materialId }, select: { id: true, materialType: true, materialKind: true, videoSourceUrl: true, videoCoverUrl: true, videoProcessingStatus: true, videoPreview540Url: true, videoPreviewClipUrl: true, videoDuration: true, }, }) if (!material) { console.error(`✗ 素材不存在: ${materialId}`) return false } console.log('素材信息:', { id: material.id, materialType: material.materialType, materialKind: (material as any).materialKind, videoSourceUrl: material.videoSourceUrl ? '✓' : '✗', videoCoverUrl: material.videoCoverUrl ? '✓' : '✗', videoProcessingStatus: material.videoProcessingStatus, videoPreview540Url: material.videoPreview540Url ? '✓' : '✗', videoPreviewClipUrl: material.videoPreviewClipUrl ? '✓' : '✗', videoDuration: material.videoDuration, }) // 2. 验证是否为视频素材 const materialKind = (material as any).materialKind || '' const isVideo = materialKind.toUpperCase() === 'VIDEO' || material.materialType === '视频' if (!isVideo) { console.error(`✗ 此素材不是视频类型: ${material.materialType}`) return false } // 3. 检查是否有源视频 if (!material.videoSourceUrl) { console.error('✗ 未找到源视频文件') return false } console.log('\n步骤 2: 重置转码状态...') // 4. 重置转码状态为 pending await prisma.material.update({ where: { id: materialId }, data: { videoProcessingStatus: 'pending', videoPreview540Url: null, videoPreviewClipUrl: null, }, }) console.log('✓ 转码状态已重置为 pending') console.log('\n步骤 3: 触发转码任务...') // 5. 调用转码API const apiUrl = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:3000' const response = await fetch(`${apiUrl}/api/materials/transcode`, { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ materialId, forceRetry: true, }), }) if (!response.ok) { const error = await response.json() console.error('✗ 转码API调用失败:', error) return false } const result = await response.json() console.log('✓ 转码任务已触发:', result) console.log('\n步骤 4: 等待转码完成...') console.log('提示: 转码可能需要几分钟时间,请稍后查看素材状态') console.log(`查询状态: GET ${apiUrl}/api/materials/transcode?materialId=${materialId}`) return true } catch (error) { console.error('\n✗ 处理失败:', error) return false } finally { await prisma.$disconnect() } } // 执行脚本 if (require.main === module) { const materialId = process.argv[2] if (!materialId) { console.error('错误: 请提供素材ID') console.log('使用方法: npx ts-node scripts/trigger-video-transcode.ts <素材ID>') console.log('示例: npx ts-node scripts/trigger-video-transcode.ts FLNXI2025121373113') process.exit(1) } triggerVideoTranscode(materialId) .then((success) => { process.exit(success ? 0 : 1) }) .catch((error) => { console.error('脚本执行失败:', error) process.exit(1) }) } export { triggerVideoTranscode }