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, }; } const videoSprite = new OffscreenSprite( new MP4Clip((await fetch(videoUrl)).body!) ); videoSprite.time = { duration: 10e6, 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: 4, color: "rgba(0, 0, 0, 0.25)", }, ...options, }) ); await srtSprite.ready; srtSprite.time = { duration: 10e6, 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; };