Commit c90aa1a9 by lijiabin

feat: 新增 useMediaInfo 用于检测视频编码格式

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
parent 1c01b880
......@@ -5,3 +5,4 @@ export * from './useHintAnimation'
export * from './useUploadImg'
export * from './useNavigation'
export * from './useMessageBox.tsx'
export * from './useMediaInfo'
import mediaInfoFactory, { type MediaInfo } from 'mediainfo.js'
// mediainfo.js 的 wasm 体积较大 走 CDN 加载 避免打包进主包
const MEDIAINFO_VERSION = '0.3.7'
const MEDIAINFO_CDN_BASE = `https://cdn.jsdelivr.net/npm/mediainfo.js@${MEDIAINFO_VERSION}/dist/`
export const useMediaInfo = () => {
let mediainfoPromise: Promise<MediaInfo<'object'>> | null = null
function getMediaInfo() {
if (!mediainfoPromise) {
mediainfoPromise = mediaInfoFactory({
format: 'object',
locateFile: (path) => `${MEDIAINFO_CDN_BASE}${path}`,
})
}
return mediainfoPromise
}
/**
* 读取视频轨道的编码格式 如 AVC(H264)、HEVC(H265)
* 只读取文件的必要片段 不会把整个文件读进内存
*/
async function getVideoCodec(file: File) {
const mediainfo = await getMediaInfo()
const getSize = () => file.size
const readChunk = (size: number, offset: number) =>
file
.slice(offset, offset + size)
.arrayBuffer()
.then((buffer) => new Uint8Array(buffer))
const result = await mediainfo.analyzeData(getSize, readChunk)
const tracks = result?.media?.track || []
const videoTrack = tracks.find((track) => track['@type'] === 'Video')
return (videoTrack as { Format?: string } | undefined)?.Format || ''
}
/**
* 判断是否为 H.265(HEVC) 编码 这类视频浏览器普遍无法直接播放
*/
async function isH265Video(file: File) {
const codec = await getVideoCodec(file)
return /HEVC|H\.?265/i.test(codec)
}
// 释放 wasm 实例 组件卸载时调用
function cleanup() {
mediainfoPromise?.then((instance) => instance.close())
mediainfoPromise = null
}
return {
getVideoCodec,
isH265Video,
cleanup,
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment