From e4917d00536bd3003dfb159c7ea09b274ad517ba Mon Sep 17 00:00:00 2001 From: Timothy Yin Date: Mon, 6 Jan 2025 02:18:06 +0800 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20feat(subtitle=5Frendering):=20WIP:?= =?UTF-8?q?=20=E6=B7=BB=E5=8A=A0=E8=A7=86=E9=A2=91=E5=AD=97=E5=B9=95?= =?UTF-8?q?=E6=A0=B7=E5=BC=8F=E5=92=8C=E5=AF=BC=E5=87=BA=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/aigc/generation/SRTEditor.vue | 122 +++++++++++++++-------- composables/useVideoSubtitleEmbedding.ts | 6 +- 2 files changed, 83 insertions(+), 45 deletions(-) diff --git a/components/aigc/generation/SRTEditor.vue b/components/aigc/generation/SRTEditor.vue index 785ef24..0209ca0 100644 --- a/components/aigc/generation/SRTEditor.vue +++ b/components/aigc/generation/SRTEditor.vue @@ -10,8 +10,6 @@ interface Subtitle { active?: boolean } -type SubtitleStyleEdit = Pick - const props = defineProps({ course: { type: Object as PropType, @@ -35,28 +33,16 @@ const videoElement = ref(null) const subtitleStyleSchema = object({ color: string().required(), fontSize: number().required(), + effect: string().required(), bottomOffset: number().required(), - strokeStyle: string().required(), - textShadow: object({ - offsetX: number().required(), - offsetY: number().required(), - blur: number().required(), - color: string().required(), - }).required(), }) type subtitleStyleSchema = InferType -const subtitleStyleState = reactive({ - color: '#000', - fontSize: 20, - bottomOffset: 0, - strokeStyle: 'none', - textShadow: { - offsetX: 0, - offsetY: 0, - blur: 0, - color: '#000', - }, +const subtitleStyleState = reactive({ + color: '#fff', + effect: 'shadow', + fontSize: 24, + bottomOffset: 12, }) const loadSrt = async () => { @@ -188,6 +174,32 @@ const saveNewSubtitle = () => { }) } +const exportVideo = () => { + isSaving.value = true + useVideoSubtitleEmbedding(props.course.video_url, props.course.subtitle_url, { + color: subtitleStyleState.color, + fontSize: subtitleStyleState.fontSize, + textShadow: subtitleStyleState.effect === 'shadow' ? { + offsetX: 2, + offsetY: 2, + blur: 4, + color: "rgba(0, 0, 0, 0.25)", + } : { + offsetX: 0, + offsetY: 0, + blur: 0, + color: 'transparent', + }, + strokeStyle: subtitleStyleState.effect === 'stroke' ? '#000 2px' : 'none', + bottomOffset: subtitleStyleState.bottomOffset, + }).then(blobUrl => { + const { download } = useDownload(blobUrl, 'combined_video.mp4') + download() + }).finally(() => { + isSaving.value = false + }) +} + onMounted(() => { if (rawSrt.value) { parseSrt(rawSrt.value) @@ -250,11 +262,17 @@ defineExpose({
-
-
- - {{ subtitles.find(sub => sub.active)?.text }} - +
+
+ {{ subtitles.find(sub => sub.active)?.text }}