130 lines
4.7 KiB
TypeScript
130 lines
4.7 KiB
TypeScript
/**
|
||
* 检查素材URL中的bucket名称
|
||
* 用于诊断预览图加载失败问题
|
||
*
|
||
* 使用方法:
|
||
* npx tsx scripts/check-material-urls.ts <materialId>
|
||
*
|
||
* 示例:
|
||
* npx tsx scripts/check-material-urls.ts "3e9897ae-8844-446a-a5d6-fb78cf56bc38"
|
||
*/
|
||
|
||
import { PrismaClient } from '@prisma/client';
|
||
|
||
const DATABASE_URL = process.env.DATABASE_URL || 'postgresql://gongxiangpan:gongxiangpan123@192.168.58.20:5432/lobechat';
|
||
const prisma = new PrismaClient({
|
||
datasources: {
|
||
db: {
|
||
url: DATABASE_URL,
|
||
},
|
||
},
|
||
});
|
||
|
||
async function main() {
|
||
const materialId = process.argv[2];
|
||
|
||
if (!materialId) {
|
||
console.log('使用方法: npx tsx scripts/check-material-urls.ts <materialId>');
|
||
console.log('示例: npx tsx scripts/check-material-urls.ts "3e9897ae-8844-446a-a5d6-fb78cf56bc38"');
|
||
process.exit(1);
|
||
}
|
||
|
||
try {
|
||
const material = await prisma.material.findUnique({
|
||
where: { id: materialId },
|
||
select: {
|
||
id: true,
|
||
productModel: true,
|
||
materialType: true,
|
||
createdAt: true,
|
||
previewUrl: true,
|
||
videoCoverUrl: true,
|
||
videoPreview540Url: true,
|
||
videoPreviewClipUrl: true,
|
||
} as any,
|
||
});
|
||
|
||
if (!material) {
|
||
console.log(`❌ 素材不存在: ${materialId}`);
|
||
process.exit(1);
|
||
}
|
||
|
||
console.log('='.repeat(60));
|
||
console.log('素材URL检查');
|
||
console.log('='.repeat(60));
|
||
console.log();
|
||
|
||
console.log('素材信息:');
|
||
console.log(` ID: ${material.id}`);
|
||
console.log(` 产品型号: ${material.productModel}`);
|
||
console.log(` 素材类型: ${material.materialType}`);
|
||
console.log(` 创建时间: ${material.createdAt}`);
|
||
console.log();
|
||
|
||
console.log('URL信息:');
|
||
console.log(` previewUrl: ${(material as any).previewUrl || '(无)'}`);
|
||
console.log(` videoCoverUrl: ${(material as any).videoCoverUrl || '(无)'}`);
|
||
console.log(` videoPreview540Url: ${(material as any).videoPreview540Url || '(无)'}`);
|
||
console.log(` videoPreviewClipUrl: ${(material as any).videoPreviewClipUrl || '(无)'}`);
|
||
console.log();
|
||
|
||
// 解析URL中的bucket名称
|
||
const parseBucket = (url: string | null): string | null => {
|
||
if (!url) return null;
|
||
try {
|
||
const urlObj = new URL(url);
|
||
const pathParts = urlObj.pathname.split('/').filter(p => p);
|
||
return pathParts.length > 0 ? decodeURIComponent(pathParts[0]) : null;
|
||
} catch {
|
||
return null;
|
||
}
|
||
};
|
||
|
||
console.log('Bucket分析:');
|
||
const previewBucket = parseBucket((material as any).previewUrl);
|
||
const coverBucket = parseBucket((material as any).videoCoverUrl);
|
||
const preview540Bucket = parseBucket((material as any).videoPreview540Url);
|
||
const clipBucket = parseBucket((material as any).videoPreviewClipUrl);
|
||
|
||
console.log(` previewUrl bucket: ${previewBucket || '(无)'}`);
|
||
console.log(` videoCoverUrl bucket: ${coverBucket || '(无)'}`);
|
||
console.log(` videoPreview540Url bucket: ${preview540Bucket || '(无)'}`);
|
||
console.log(` videoPreviewClipUrl bucket: ${clipBucket || '(无)'}`);
|
||
console.log();
|
||
|
||
// 判断是否是新素材(根据路径前缀)
|
||
const hasPathPrefix = (url: string | null): boolean => {
|
||
if (!url) return false;
|
||
return url.includes('由壹点AI/') || url.includes('%E7%94%B1%E5%A3%B9%E7%82%B9AI/');
|
||
};
|
||
|
||
console.log('素材类型判断:');
|
||
const isOldMaterial = !hasPathPrefix((material as any).previewUrl) &&
|
||
!hasPathPrefix((material as any).videoCoverUrl);
|
||
console.log(` 是否老素材(无路径前缀): ${isOldMaterial}`);
|
||
console.log(` 是否有路径前缀: ${hasPathPrefix((material as any).previewUrl) || hasPathPrefix((material as any).videoCoverUrl)}`);
|
||
console.log();
|
||
|
||
console.log('问题分析:');
|
||
if (coverBucket === 'jsxiangche' && hasPathPrefix((material as any).videoCoverUrl)) {
|
||
console.log(' ⚠️ 发现异常:');
|
||
console.log(' - URL使用了旧bucket名称 "jsxiangche"');
|
||
console.log(' - 但URL包含路径前缀 "由壹点AI/"(新素材特征)');
|
||
console.log(' - 这可能是数据库中存储了错误的URL');
|
||
console.log(' - 建议:检查上传/转码时的URL生成逻辑');
|
||
} else if (coverBucket === 'gongxiangpan') {
|
||
console.log(' ✅ Bucket名称正确: gongxiangpan');
|
||
} else if (coverBucket === 'jsxiangche' && !hasPathPrefix((material as any).videoCoverUrl)) {
|
||
console.log(' ℹ️ 这是老素材(使用旧bucket,无路径前缀)');
|
||
}
|
||
|
||
} catch (error) {
|
||
console.error('执行失败:', error);
|
||
process.exit(1);
|
||
} finally {
|
||
await prisma.$disconnect();
|
||
}
|
||
}
|
||
|
||
main();
|