gongxiangp2/scripts/check-material-urls.ts

130 lines
4.7 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.

/**
* 检查素材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();