82 lines
1.8 KiB
TypeScript
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
|
|
}
|