Files
xsh-assistant-next/app/composables/useVideoSubtitleEmbedding.ts

82 lines
1.8 KiB
TypeScript

import {
Combinator,
EmbedSubtitlesClip,
MP4Clip,
OffscreenSprite,
} from '@webav/av-cliper'
export interface SubtitleEmbeddingOptions {
color?: string
textBgColor?: string | null
type?: 'srt'
fontFamily?: string
fontSize?: number
letterSpacing?: string | null
bottomOffset?: number
strokeStyle?: string
lineWidth?: number | null
lineCap?: CanvasLineCap | null
lineJoin?: CanvasLineJoin | null
textShadow?: {
offsetX: number
offsetY: number
blur: number
color: string
}
videoWidth?: number
videoHeight?: number
}
export const useVideoSubtitleEmbedding = async (
videoUrl: string,
srtUrl: string,
options?: SubtitleEmbeddingOptions
) => {
if (!options) {
options = {
videoWidth: 1920,
videoHeight: 1080,
}
}
console.log(`video clip: ${videoUrl}`)
const videoClip = new MP4Clip((await fetch(videoUrl)).body!)
const videoSprite = new OffscreenSprite(videoClip)
videoSprite.time = { duration: videoClip.meta.duration, offset: 0 }
await videoSprite.ready
const srtSprite = new OffscreenSprite(
new EmbedSubtitlesClip(await (await fetch(srtUrl)).text(), {
videoWidth: 1920,
videoHeight: 1080,
fontSize: 36,
fontFamily: 'Noto Sans SC',
strokeStyle: 'none',
textShadow: {
offsetX: 2,
offsetY: 2,
blur: 6,
color: 'rgba(0, 0, 0, 0.35)',
},
...options,
})
)
await srtSprite.ready
srtSprite.time = { duration: videoClip.meta.duration, offset: 0 }
const combinator = new Combinator({
width: 1920,
height: 1080,
})
await combinator.addSprite(videoSprite)
await combinator.addSprite(srtSprite)
const srcBlob = URL.createObjectURL(
await new Response(combinator.output()).blob()
)
return srcBlob
}