修改了readme文件

This commit is contained in:
2026-02-06 12:39:11 +06:00
parent ff4b6a149a
commit d7cfb044d5
20 changed files with 26378 additions and 1 deletions

123
src/thumbnail-helper.js Normal file
View File

@@ -0,0 +1,123 @@
/**
* 缩略图生成辅助函数
* 当后端 FFmpeg 生成失败时,使用浏览器原生能力作为兜底
*/
/**
* 使用浏览器原生 API 生成视频缩略图
* @param {File} file - 视频文件对象
* @param {number} seekTime - 截取时间点(秒)
* @returns {Promise<string>} base64 图片数据
*/
export async function generateVideoThumbnailNative(file, seekTime = 0.1) {
return new Promise((resolve, reject) => {
const video = document.createElement('video');
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
// 设置视频源
const url = URL.createObjectURL(file);
video.src = url;
video.muted = true;
video.playsInline = true;
video.addEventListener('loadeddata', () => {
// seek 到指定时间
video.currentTime = Math.min(seekTime, video.duration * 0.1 || 0.1);
});
video.addEventListener('seeked', () => {
try {
// 计算缩放后的尺寸(最大宽度 320
const maxWidth = 320;
const scale = Math.min(1, maxWidth / video.videoWidth);
canvas.width = video.videoWidth * scale;
canvas.height = video.videoHeight * scale;
// 绘制帧
ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
// 转换为 base64
const dataUrl = canvas.toDataURL('image/jpeg', 0.85);
URL.revokeObjectURL(url);
resolve(dataUrl);
} catch (e) {
URL.revokeObjectURL(url);
reject(e);
}
});
video.addEventListener('error', (e) => {
URL.revokeObjectURL(url);
reject(new Error('视频加载失败'));
});
// 开始加载
video.load();
});
}
/**
* 使用浏览器原生 API 生成图片缩略图
* @param {File} file - 图片文件对象
* @returns {Promise<string>} base64 图片数据
*/
export async function generateImageThumbnailNative(file) {
return new Promise((resolve, reject) => {
const img = new Image();
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
const url = URL.createObjectURL(file);
img.onload = () => {
try {
// 计算缩放后的尺寸(最大宽度 320
const maxWidth = 320;
const scale = Math.min(1, maxWidth / img.naturalWidth);
canvas.width = img.naturalWidth * scale;
canvas.height = img.naturalHeight * scale;
// 绘制图片
ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
// 转换为 base64
const dataUrl = canvas.toDataURL('image/jpeg', 0.85);
URL.revokeObjectURL(url);
resolve(dataUrl);
} catch (e) {
URL.revokeObjectURL(url);
reject(e);
}
};
img.onerror = () => {
URL.revokeObjectURL(url);
reject(new Error('图片加载失败'));
};
img.src = url;
});
}
/**
* 智能缩略图生成
* 优先使用后端 FFmpeg失败时尝试浏览器原生方案
*/
export async function generateThumbnailSmart(filePath, fileType, fileObj = null) {
// 首先尝试使用后端 FFmpeg如果有 file 对象的话)
if (fileObj && fileObj instanceof File) {
try {
if (fileType === 'video') {
return await generateVideoThumbnailNative(fileObj);
} else if (fileType === 'image') {
return await generateImageThumbnailNative(fileObj);
}
} catch (e) {
console.log('浏览器原生缩略图生成失败,使用后端:', e);
}
}
// 返回 null让后端处理
return null;
}