79 lines
1.6 KiB
TypeScript
79 lines
1.6 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,
|
|
};
|
|
}
|
|
|
|
const videoSprite = new OffscreenSprite(
|
|
new MP4Clip((await fetch(videoUrl)).body!)
|
|
);
|
|
videoSprite.time = { duration: 10e6, offset: 0 };
|
|
|
|
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,
|
|
})
|
|
);
|
|
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;
|
|
};
|