mirror of
https://github.com/HiMeditator/auto-caption.git
synced 2026-02-04 12:24:42 +08:00
feat(renderer):实现多行字幕显示功能
- 在 CaptionStyle 组件中添加字幕行数设置选项 - 修改组件以支持多行字幕显示 - 优化字幕数据处理逻辑,支持按时间顺序显示多条字幕
This commit is contained in:
@@ -63,7 +63,7 @@ class SosvRecognizer:
|
||||
vad_config.silero_vad.threshold = 0.5
|
||||
vad_config.silero_vad.min_silence_duration = 0.1
|
||||
vad_config.silero_vad.min_speech_duration = 0.25
|
||||
vad_config.silero_vad.max_speech_duration = 8
|
||||
vad_config.silero_vad.max_speech_duration = 5
|
||||
vad_config.sample_rate = 16000
|
||||
self.window_size = vad_config.silero_vad.window_size
|
||||
self.vad = sherpa_onnx.VoiceActivityDetector(vad_config, buffer_size_in_seconds=100)
|
||||
|
||||
@@ -17,8 +17,11 @@ def audio_recording(stream: AudioStream, resample: bool, record = False, path =
|
||||
wf = None
|
||||
full_name = ''
|
||||
if record:
|
||||
if path != '' and path[-1] != '/':
|
||||
path += '/'
|
||||
if path != '':
|
||||
if path.startswith('"') and path.endswith('"'):
|
||||
path = path[1:-1]
|
||||
if path[-1] != '/':
|
||||
path += '/'
|
||||
cur_dt = datetime.datetime.now()
|
||||
name = cur_dt.strftime("audio-%Y-%m-%dT%H-%M-%S")
|
||||
full_name = f'{path}{name}.wav'
|
||||
|
||||
@@ -23,6 +23,7 @@ export interface Controls {
|
||||
}
|
||||
|
||||
export interface Styles {
|
||||
lineNumber: number,
|
||||
lineBreak: number,
|
||||
fontFamily: string,
|
||||
fontSize: number,
|
||||
|
||||
@@ -19,6 +19,7 @@ function getDesktopPath() {
|
||||
}
|
||||
|
||||
const defaultStyles: Styles = {
|
||||
lineNumber: 1,
|
||||
lineBreak: 1,
|
||||
fontFamily: 'sans-serif',
|
||||
fontSize: 24,
|
||||
|
||||
@@ -66,7 +66,7 @@ export class CaptionEngine {
|
||||
this.command.push('-a', allConfig.controls.audio ? '1' : '0')
|
||||
if(allConfig.controls.recording) {
|
||||
this.command.push('-r', '1')
|
||||
this.command.push('-rp', allConfig.controls.recordingPath)
|
||||
this.command.push('-rp', `"${allConfig.controls.recordingPath}"`)
|
||||
}
|
||||
this.port = Math.floor(Math.random() * (65535 - 1024 + 1)) + 1024
|
||||
this.command.push('-p', this.port.toString())
|
||||
|
||||
@@ -6,6 +6,16 @@
|
||||
<a @click="resetStyle">{{ $t('style.resetStyle') }}</a>
|
||||
</template>
|
||||
|
||||
<div class="input-item">
|
||||
<span class="input-label">{{ '字幕行数' }}</span>
|
||||
<a-radio-group v-model:value="currentLineNumber">
|
||||
<a-radio-button :value="1">1</a-radio-button>
|
||||
<a-radio-button :value="2">2</a-radio-button>
|
||||
<a-radio-button :value="3">3</a-radio-button>
|
||||
<a-radio-button :value="4">4</a-radio-button>
|
||||
</a-radio-group>
|
||||
</div>
|
||||
|
||||
<div class="input-item">
|
||||
<span class="input-label">{{ $t('style.longCaption') }}</span>
|
||||
<a-select
|
||||
@@ -178,28 +188,57 @@
|
||||
textShadow: currentTextShadow ? `${currentOffsetX}px ${currentOffsetY}px ${currentBlur}px ${currentTextShadowColor}` : 'none'
|
||||
}"
|
||||
>
|
||||
<p :class="[currentLineBreak?'':'left-ellipsis']"
|
||||
:style="{
|
||||
fontFamily: currentFontFamily,
|
||||
fontSize: currentFontSize + 'px',
|
||||
color: currentFontColor,
|
||||
fontWeight: currentFontWeight * 100
|
||||
}">
|
||||
<span v-if="captionData.length">{{ captionData[captionData.length-1].text }}</span>
|
||||
<span v-else>{{ $t('example.original') }}</span>
|
||||
</p>
|
||||
<p :class="[currentLineBreak?'':'left-ellipsis']"
|
||||
v-if="currentTransDisplay"
|
||||
:style="{
|
||||
fontFamily: currentTransFontFamily,
|
||||
fontSize: currentTransFontSize + 'px',
|
||||
color: currentTransFontColor,
|
||||
fontWeight: currentTransFontWeight * 100
|
||||
}"
|
||||
>
|
||||
<span v-if="captionData.length">{{ captionData[captionData.length-1].translation }}</span>
|
||||
<span v-else>{{ $t('example.translation') }}</span>
|
||||
</p>
|
||||
<template v-if="captionData.length">
|
||||
<template
|
||||
v-for="val in revArr[Math.min(currentLineNumber, captionData.length)]"
|
||||
:key="captionData[captionData.length - val].time_s"
|
||||
>
|
||||
<p :class="[currentLineBreak?'':'left-ellipsis']"
|
||||
:style="{
|
||||
fontFamily: currentFontFamily,
|
||||
fontSize: currentFontSize + 'px',
|
||||
color: currentFontColor,
|
||||
fontWeight: currentFontWeight * 100
|
||||
}">
|
||||
<span>{{ captionData[captionData.length - val].text }}</span>
|
||||
</p>
|
||||
<p :class="[currentLineBreak?'':'left-ellipsis']"
|
||||
v-if="currentTransDisplay && captionData[captionData.length - val].translation"
|
||||
:style="{
|
||||
fontFamily: currentTransFontFamily,
|
||||
fontSize: currentTransFontSize + 'px',
|
||||
color: currentTransFontColor,
|
||||
fontWeight: currentTransFontWeight * 100
|
||||
}"
|
||||
>
|
||||
<span>{{ captionData[captionData.length - val].translation }}</span>
|
||||
</p>
|
||||
</template>
|
||||
</template>
|
||||
<template v-else>
|
||||
<template v-for="val in currentLineNumber" :key="val">
|
||||
<p :class="[currentLineBreak?'':'left-ellipsis']"
|
||||
:style="{
|
||||
fontFamily: currentFontFamily,
|
||||
fontSize: currentFontSize + 'px',
|
||||
color: currentFontColor,
|
||||
fontWeight: currentFontWeight * 100
|
||||
}">
|
||||
<span>{{ $t('example.original') }}</span>
|
||||
</p>
|
||||
<p :class="[currentLineBreak?'':'left-ellipsis']"
|
||||
v-if="currentTransDisplay"
|
||||
:style="{
|
||||
fontFamily: currentTransFontFamily,
|
||||
fontSize: currentTransFontSize + 'px',
|
||||
color: currentTransFontColor,
|
||||
fontWeight: currentTransFontWeight * 100
|
||||
}"
|
||||
>
|
||||
<span>{{ $t('example.translation') }}</span>
|
||||
</p>
|
||||
</template>
|
||||
</template>
|
||||
</div>
|
||||
</Teleport>
|
||||
|
||||
@@ -212,6 +251,14 @@ import { storeToRefs } from 'pinia'
|
||||
import { notification } from 'ant-design-vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { useCaptionLogStore } from '@renderer/stores/captionLog';
|
||||
|
||||
const revArr = {
|
||||
1: [1],
|
||||
2: [2, 1],
|
||||
3: [3, 2, 1],
|
||||
4: [4, 3, 2, 1],
|
||||
}
|
||||
|
||||
const captionLog = useCaptionLogStore();
|
||||
const { captionData } = storeToRefs(captionLog);
|
||||
|
||||
@@ -220,6 +267,7 @@ const { t } = useI18n()
|
||||
const captionStyle = useCaptionStyleStore()
|
||||
const { changeSignal } = storeToRefs(captionStyle)
|
||||
|
||||
const currentLineNumber = ref<number>(1)
|
||||
const currentLineBreak = ref<number>(0)
|
||||
const currentFontFamily = ref<string>('sans-serif')
|
||||
const currentFontSize = ref<number>(24)
|
||||
@@ -253,6 +301,7 @@ function useSameStyle(){
|
||||
}
|
||||
|
||||
function applyStyle(){
|
||||
captionStyle.lineNumber = currentLineNumber.value;
|
||||
captionStyle.lineBreak = currentLineBreak.value;
|
||||
captionStyle.fontFamily = currentFontFamily.value;
|
||||
captionStyle.fontSize = currentFontSize.value;
|
||||
@@ -282,6 +331,7 @@ function applyStyle(){
|
||||
}
|
||||
|
||||
function backStyle(){
|
||||
currentLineNumber.value = captionStyle.lineNumber;
|
||||
currentLineBreak.value = captionStyle.lineBreak;
|
||||
currentFontFamily.value = captionStyle.fontFamily;
|
||||
currentFontSize.value = captionStyle.fontSize;
|
||||
|
||||
@@ -4,6 +4,7 @@ import { Styles } from '@renderer/types'
|
||||
import { breakOptions } from '@renderer/i18n'
|
||||
|
||||
export const useCaptionStyleStore = defineStore('captionStyle', () => {
|
||||
const lineNumber = ref<number>(1)
|
||||
const lineBreak = ref<number>(1)
|
||||
const fontFamily = ref<string>('sans-serif')
|
||||
const fontSize = ref<number>(24)
|
||||
@@ -38,6 +39,7 @@ export const useCaptionStyleStore = defineStore('captionStyle', () => {
|
||||
|
||||
function sendStylesChange() {
|
||||
const styles: Styles = {
|
||||
lineNumber: lineNumber.value,
|
||||
lineBreak: lineBreak.value,
|
||||
fontFamily: fontFamily.value,
|
||||
fontSize: fontSize.value,
|
||||
@@ -65,6 +67,7 @@ export const useCaptionStyleStore = defineStore('captionStyle', () => {
|
||||
}
|
||||
|
||||
function setStyles(args: Styles){
|
||||
lineNumber.value = args.lineNumber
|
||||
lineBreak.value = args.lineBreak
|
||||
fontFamily.value = args.fontFamily
|
||||
fontSize.value = args.fontSize
|
||||
@@ -91,6 +94,7 @@ export const useCaptionStyleStore = defineStore('captionStyle', () => {
|
||||
})
|
||||
|
||||
return {
|
||||
lineNumber, // 显示字幕行数
|
||||
lineBreak, // 换行方式
|
||||
fontFamily, // 字体族
|
||||
fontSize, // 字体大小
|
||||
|
||||
@@ -23,6 +23,7 @@ export interface Controls {
|
||||
}
|
||||
|
||||
export interface Styles {
|
||||
lineNumber: number,
|
||||
lineBreak: number,
|
||||
fontFamily: string,
|
||||
fontSize: number,
|
||||
|
||||
@@ -12,26 +12,53 @@
|
||||
textShadow: captionStyle.textShadow ? `${captionStyle.offsetX}px ${captionStyle.offsetY}px ${captionStyle.blur}px ${captionStyle.textShadowColor}` : 'none'
|
||||
}"
|
||||
>
|
||||
<p :class="[captionStyle.lineBreak?'':'left-ellipsis']" :style="{
|
||||
fontFamily: captionStyle.fontFamily,
|
||||
fontSize: captionStyle.fontSize + 'px',
|
||||
color: captionStyle.fontColor,
|
||||
fontWeight: captionStyle.fontWeight * 100
|
||||
}">
|
||||
<span v-if="captionData.length">{{ captionData[captionData.length-1].text }}</span>
|
||||
<span v-else>{{ $t('example.original') }}</span>
|
||||
</p>
|
||||
<p :class="[captionStyle.lineBreak?'':'left-ellipsis']"
|
||||
v-if="captionStyle.transDisplay"
|
||||
:style="{
|
||||
fontFamily: captionStyle.transFontFamily,
|
||||
fontSize: captionStyle.transFontSize + 'px',
|
||||
color: captionStyle.transFontColor,
|
||||
fontWeight: captionStyle.transFontWeight * 100
|
||||
}">
|
||||
<span v-if="captionData.length">{{ captionData[captionData.length-1].translation }}</span>
|
||||
<span v-else>{{ $t('example.translation') }}</span>
|
||||
</p>
|
||||
<template v-if="captionData.length">
|
||||
<template
|
||||
v-for="val in revArr[Math.min(captionStyle.lineNumber, captionData.length)]"
|
||||
:key="captionData[captionData.length - val].time_s"
|
||||
>
|
||||
<p :class="[captionStyle.lineBreak?'':'left-ellipsis']" :style="{
|
||||
fontFamily: captionStyle.fontFamily,
|
||||
fontSize: captionStyle.fontSize + 'px',
|
||||
color: captionStyle.fontColor,
|
||||
fontWeight: captionStyle.fontWeight * 100
|
||||
}">
|
||||
<span>{{ captionData[captionData.length - val].text }}</span>
|
||||
</p>
|
||||
<p :class="[captionStyle.lineBreak?'':'left-ellipsis']"
|
||||
v-if="captionStyle.transDisplay && captionData[captionData.length - val].translation"
|
||||
:style="{
|
||||
fontFamily: captionStyle.transFontFamily,
|
||||
fontSize: captionStyle.transFontSize + 'px',
|
||||
color: captionStyle.transFontColor,
|
||||
fontWeight: captionStyle.transFontWeight * 100
|
||||
}">
|
||||
<span>{{ captionData[captionData.length - val].translation }}</span>
|
||||
</p>
|
||||
</template>
|
||||
</template>
|
||||
<template v-else>
|
||||
<template v-for="val in captionStyle.lineNumber" :key="val">
|
||||
<p :class="[captionStyle.lineBreak?'':'left-ellipsis']" :style="{
|
||||
fontFamily: captionStyle.fontFamily,
|
||||
fontSize: captionStyle.fontSize + 'px',
|
||||
color: captionStyle.fontColor,
|
||||
fontWeight: captionStyle.fontWeight * 100
|
||||
}">
|
||||
<span>{{ $t('example.original') }}</span>
|
||||
</p>
|
||||
<p :class="[captionStyle.lineBreak?'':'left-ellipsis']"
|
||||
v-if="captionStyle.transDisplay"
|
||||
:style="{
|
||||
fontFamily: captionStyle.transFontFamily,
|
||||
fontSize: captionStyle.transFontSize + 'px',
|
||||
color: captionStyle.transFontColor,
|
||||
fontWeight: captionStyle.transFontWeight * 100
|
||||
}">
|
||||
<span>{{ $t('example.translation') }}</span>
|
||||
</p>
|
||||
</template>
|
||||
</template>
|
||||
</div>
|
||||
|
||||
<div class="title-bar" :style="{color: captionStyle.fontColor}">
|
||||
@@ -56,6 +83,14 @@ import { ref, onMounted } from 'vue';
|
||||
import { useCaptionStyleStore } from '@renderer/stores/captionStyle';
|
||||
import { useCaptionLogStore } from '@renderer/stores/captionLog';
|
||||
import { storeToRefs } from 'pinia';
|
||||
|
||||
const revArr = {
|
||||
1: [1],
|
||||
2: [2, 1],
|
||||
3: [3, 2, 1],
|
||||
4: [4, 3, 2, 1],
|
||||
}
|
||||
|
||||
const captionStyle = useCaptionStyleStore();
|
||||
const captionLog = useCaptionLogStore();
|
||||
const { captionData } = storeToRefs(captionLog);
|
||||
|
||||
Reference in New Issue
Block a user