feat(ffmpeg): add ffmpeg-core.wasm for video processing capabilities

This commit is contained in:
2025-11-14 19:49:37 +08:00
parent 18df10c7af
commit fb68b6a3cb
10 changed files with 1966 additions and 768 deletions

103
composables/useFFmpeg.ts Normal file
View File

@@ -0,0 +1,103 @@
import { FFmpeg } from '@ffmpeg/ffmpeg'
import { toBlobURL } from '@ffmpeg/util'
let ffmpegInstance: FFmpeg | null = null
let loadPromise: Promise<FFmpeg> | null = null
/**
* 获取或初始化 FFmpeg 实例(单例模式)
*/
export const useFFmpeg = async () => {
// 如果已经加载过,直接返回
if (ffmpegInstance && ffmpegInstance.loaded) {
return ffmpegInstance
}
// 如果正在加载中,等待加载完成
if (loadPromise) {
return loadPromise
}
loadPromise = initializeFFmpeg()
return loadPromise
}
async function initializeFFmpeg(enableMT: boolean = false): Promise<FFmpeg> {
try {
const ffmpeg = new FFmpeg()
ffmpeg.on('log', ({ message, type }) => {
console.log(`[ffmpeg - ${type}]`, message)
})
ffmpeg.on('progress', ({ progress, time }) => {
console.log(`[ffmpeg] P: ${(progress * 100).toFixed(2)}%, T: ${time}ms`)
})
const baseURL = enableMT
? 'https://cdn.jsdelivr.net/npm/@ffmpeg/core-mt@0.12.10/dist/esm'
: 'https://cdn.jsdelivr.net/npm/@ffmpeg/core@0.12.10/dist/esm'
const coreURL = await toBlobURL(
`${baseURL}/ffmpeg-core.js`,
'text/javascript'
)
const wasmURL = await toBlobURL(
`${baseURL}/ffmpeg-core.wasm`,
'application/wasm'
)
let loadPayload = {
coreURL,
wasmURL,
}
if (enableMT) {
const workerURL = await toBlobURL(
`${baseURL}/ffmpeg-core.worker.js`,
'text/javascript'
)
Object.assign(loadPayload, { workerURL })
}
const isLoaded = await ffmpeg.load(loadPayload)
console.log('[FFmpeg] FFmpeg 加载完成isLoaded:', isLoaded)
ffmpegInstance = ffmpeg
loadPromise = null
return ffmpeg
} catch (error) {
console.error('[FFmpeg] 初始化失败:', error)
loadPromise = null
throw error
}
}
/**
* 清理 FFmpeg 资源
*/
export const cleanupFFmpeg = () => {
if (ffmpegInstance && ffmpegInstance.loaded) {
console.log('[FFmpeg] 清理 FFmpeg 资源...')
ffmpegInstance.terminate()
ffmpegInstance = null
loadPromise = null
}
}
/**
* 将 Blob/File 转换为 Uint8Array
*/
export const fileToUint8Array = async (
file: File | Blob
): Promise<Uint8Array> => {
return new Promise((resolve, reject) => {
const reader = new FileReader()
reader.onload = (e) => {
const arrayBuffer = e.target?.result as ArrayBuffer
resolve(new Uint8Array(arrayBuffer))
}
reader.onerror = reject
reader.readAsArrayBuffer(file)
})
}