gongxiangp2/scripts/manual-trigger-transcode.ts

131 lines
4.0 KiB
TypeScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* 手动触发视频转码
* 用于修复未触发转码的素材
*/
import { PrismaClient } from '@prisma/client'
import { enqueueVideoTranscodeTask } from '../lib/video-transcode-task'
const prisma = new PrismaClient()
async function triggerTranscode(materialId: string) {
console.log(`\n==== 手动触发转码: ${materialId} ====\n`)
try {
// 查询素材信息
const material = await prisma.material.findUnique({
where: { id: materialId },
}) as any
if (!material) {
console.error('❌ 素材不存在')
return
}
console.log('📋 素材信息:')
console.log(` 素材ID: ${material.id}`)
console.log(` 素材类型: ${material.materialType}`)
console.log(` 转码状态: ${material.videoProcessingStatus || 'null'}`)
console.log(` videoSourceUrl: ${material.videoSourceUrl || 'null'}`)
// 检查是否为视频类型
const videoTypes = ['主图视频', '安装视频', '种草视频', '视频', 'VIDEO']
const materialType = String(material?.materialType || '')
if (!videoTypes.includes(materialType)) {
console.log('\n⚠️ 此素材不是视频类型,不需要转码')
return
}
// 检查 videoSourceUrl
if (!material?.videoSourceUrl) {
console.log('\n❌ 错误:videoSourceUrl 为空,无法转码')
return
}
// 判断是否需要生成封面图
const needsCoverImage = !material?.videoCoverUrl || String(material.videoCoverUrl || '').trim() === ''
const hasPreviewUrl = material?.previewUrl && String(material.previewUrl || '').trim() !== ''
console.log(`\n🔄 转码配置:`)
console.log(` 需要生成封面: ${needsCoverImage}`)
console.log(` 已有预览图: ${hasPreviewUrl}`)
// 如果状态是 processing,先重置为 pending
const currentStatus = String(material?.videoProcessingStatus || '')
if (currentStatus === 'processing') {
console.log('\n⚠️ 当前状态是 processing,重置为 pending...')
await prisma.material.update({
where: { id: materialId },
data: {
videoProcessingStatus: 'pending',
transcodeLastError: null,
} as any,
})
console.log('✅ 状态已重置')
}
// 触发转码
console.log(`\n🚀 触发转码任务...`)
try {
await enqueueVideoTranscodeTask(
material.id,
String(material.videoSourceUrl || ''),
needsCoverImage
)
console.log('✅ 转码任务已入队')
// 更新状态为 pending(如果之前是 null)
if (!currentStatus || currentStatus === 'null') {
await prisma.material.update({
where: { id: materialId },
data: {
videoProcessingStatus: 'pending',
} as any,
})
console.log('✅ 状态已更新为 pending')
}
} catch (error: any) {
console.error('❌ 入队失败:', error)
console.error('错误详情:', error?.message || String(error))
console.error('堆栈:', error?.stack)
// 记录错误到数据库
await prisma.material.update({
where: { id: materialId },
data: {
videoProcessingStatus: 'pending',
transcodeLastError: `手动触发失败: ${error?.message || String(error)}`,
} as any,
})
throw error
}
console.log(`\n✅ 转码任务已成功触发`)
console.log(` 素材ID: ${materialId}`)
console.log(` 视频源: ${material.videoSourceUrl}`)
console.log(` 状态: pending -> 将转为 processing`)
} catch (error) {
console.error('\n❌ 操作失败:', error)
throw error
} finally {
await prisma.$disconnect()
}
}
// 主函数
async function main() {
const materialId = process.argv[2]
if (!materialId) {
console.error('用法: tsx scripts/manual-trigger-transcode.ts <materialId>')
console.error('示例: tsx scripts/manual-trigger-transcode.ts 0895f84d-8837-465e-be50-4db57b5eab9e')
process.exit(1)
}
await triggerTranscode(materialId)
}
main().catch(console.error)