fix: Optimize subtitle translation

This commit is contained in:
Gabe
2025-11-11 23:36:06 +08:00
parent 3bfa12b61c
commit 343f529cac
3 changed files with 59 additions and 14 deletions

View File

@@ -1874,6 +1874,11 @@ export const I18N = {
en: `Throttling translation interval (1-3600s)`, en: `Throttling translation interval (1-3600s)`,
zh_TW: `节流翻译间隔 (1-3600s)`, zh_TW: `节流翻译间隔 (1-3600s)`,
}, },
show_origin_subtitle: {
zh: `显示原字幕`,
en: `Show original subtitles`,
zh_TW: `显示原字幕`,
},
}; };
export const newI18n = (lang) => (key) => I18N[key]?.[lang] || ""; export const newI18n = (lang) => (key) => I18N[key]?.[lang] || "";

View File

@@ -128,7 +128,7 @@ export function Menus({
return i18n("processing_subtitles"); return i18n("processing_subtitles");
}, [progressed, i18n]); }, [progressed, i18n]);
const { isAISegment, skipAd, isBilingual } = formData; const { isAISegment, skipAd, isBilingual, showOrigin } = formData;
return ( return (
<div <div
@@ -157,6 +157,12 @@ export function Menus({
value={isBilingual} value={isBilingual}
label={i18n("is_bilingual_view")} label={i18n("is_bilingual_view")}
/> />
<Switch
onChange={handleChange}
name="showOrigin"
value={showOrigin}
label={i18n("show_origin_subtitle")}
/>
<Switch <Switch
onChange={handleChange} onChange={handleChange}
name="skipAd" name="skipAd"

View File

@@ -42,7 +42,7 @@ class YouTubeCaptionProvider {
#menuEventName = "kiss-event"; #menuEventName = "kiss-event";
constructor(setting = {}) { constructor(setting = {}) {
this.#setting = { ...setting, isAISegment: false }; this.#setting = { ...setting, isAISegment: false, showOrigin: false };
this.#i18n = newI18n(setting.uiLang || "zh"); this.#i18n = newI18n(setting.uiLang || "zh");
this.#menuEventName = genEventName(); this.#menuEventName = genEventName();
} }
@@ -151,6 +151,10 @@ class YouTubeCaptionProvider {
if (node.matches(adLayoutSelector)) { if (node.matches(adLayoutSelector)) {
logger.debug("Youtube Provider: Ad ends!"); logger.debug("Youtube Provider: Ad ends!");
if (!this.#setting.showOrigin) {
this.#hideYtCaption();
}
if (videoEl && skipAd) { if (videoEl && skipAd) {
videoEl.playbackRate = 1; videoEl.playbackRate = 1;
} }
@@ -200,6 +204,16 @@ class YouTubeCaptionProvider {
this.#managerInstance?.updateSetting({ [name]: value }); this.#managerInstance?.updateSetting({ [name]: value });
} else if (name === "isAISegment") { } else if (name === "isAISegment") {
this.#reProcessEvents(); this.#reProcessEvents();
} else if (name === "showOrigin") {
this.#toggleShowOrigin();
}
}
#toggleShowOrigin() {
if (this.#setting.showOrigin) {
this.#destroyManager();
} else {
this.#startManager();
} }
} }
@@ -241,7 +255,8 @@ class YouTubeCaptionProvider {
toggleButton.appendChild(createLogoSVG()); toggleButton.appendChild(createLogoSVG());
kissControls.appendChild(toggleButton); kissControls.appendChild(toggleButton);
const { segApiSetting, isAISegment, skipAd, isBilingual } = this.#setting; const { segApiSetting, isAISegment, skipAd, isBilingual, showOrigin } =
this.#setting;
const menu = new ShadowDomManager({ const menu = new ShadowDomManager({
id: "kiss-subtitle-menus", id: "kiss-subtitle-menus",
className: "notranslate", className: "notranslate",
@@ -254,9 +269,10 @@ class YouTubeCaptionProvider {
hasSegApi: !!segApiSetting, hasSegApi: !!segApiSetting,
eventName: this.#menuEventName, eventName: this.#menuEventName,
initData: { initData: {
isAISegment, isAISegment, // AI智能断句
skipAd, skipAd, // 快进广告
isBilingual, isBilingual, // 双语显示
showOrigin, // 显示原字幕
}, },
}, },
}); });
@@ -268,6 +284,10 @@ class YouTubeCaptionProvider {
createLogoSVG({ isSelected: true }) createLogoSVG({ isSelected: true })
); );
menu.show(); menu.show();
this.#sendMenusMsg({
action: MSG_MENUS_PROGRESSED,
data: this.#progressed,
});
} else { } else {
this.#isMenuShow = false; this.#isMenuShow = false;
this.#toggleButton?.replaceChildren(createLogoSVG()); this.#toggleButton?.replaceChildren(createLogoSVG());
@@ -512,6 +532,9 @@ class YouTubeCaptionProvider {
} }
#reProcessEvents() { #reProcessEvents() {
this.#progressed = 0;
this.#subtitles = [];
const videoId = this.#videoId; const videoId = this.#videoId;
const flatEvents = this.#flatEvents; const flatEvents = this.#flatEvents;
const fromLang = this.#fromLang; const fromLang = this.#fromLang;
@@ -557,19 +580,19 @@ class YouTubeCaptionProvider {
return subtitlesFallback(); return subtitlesFallback();
} }
const chunkCount = eventChunks.length; if (eventChunks.length > 1) {
if (chunkCount > 1) {
const remainingChunks = eventChunks.slice(1); const remainingChunks = eventChunks.slice(1);
this.#processRemainingChunksAsync({ this.#processRemainingChunksAsync({
chunks: remainingChunks, chunks: remainingChunks,
chunkCount,
videoId, videoId,
fromLang, fromLang,
toLang, toLang,
segApiSetting, segApiSetting,
}); });
return [firstBatchSubtitles, 100 / eventChunks.length]; const processed = Math.floor(100 / eventChunks.length);
return [firstBatchSubtitles, processed];
} else { } else {
return [firstBatchSubtitles, 100]; return [firstBatchSubtitles, 100];
} }
@@ -583,6 +606,10 @@ class YouTubeCaptionProvider {
return; return;
} }
if (this.#setting.showOrigin) {
return;
}
if (!this.#subtitles.length) { if (!this.#subtitles.length) {
this.#showNotification(this.#i18n("waitting_for_subtitle")); this.#showNotification(this.#i18n("waitting_for_subtitle"));
return; return;
@@ -605,8 +632,7 @@ class YouTubeCaptionProvider {
this.#showNotification(this.#i18n("subtitle_load_succeed")); this.#showNotification(this.#i18n("subtitle_load_succeed"));
const ytCaption = document.querySelector(YT_CAPTION_SELECT); this.#hideYtCaption();
ytCaption && (ytCaption.style.display = "none");
} }
#destroyManager() { #destroyManager() {
@@ -619,6 +645,15 @@ class YouTubeCaptionProvider {
this.#managerInstance.destroy(); this.#managerInstance.destroy();
this.#managerInstance = null; this.#managerInstance = null;
this.#showYtCaption();
}
#hideYtCaption() {
const ytCaption = document.querySelector(YT_CAPTION_SELECT);
ytCaption && (ytCaption.style.display = "none");
}
#showYtCaption() {
const ytCaption = document.querySelector(YT_CAPTION_SELECT); const ytCaption = document.querySelector(YT_CAPTION_SELECT);
ytCaption && (ytCaption.style.display = "block"); ytCaption && (ytCaption.style.display = "block");
} }
@@ -920,7 +955,6 @@ class YouTubeCaptionProvider {
async #processRemainingChunksAsync({ async #processRemainingChunksAsync({
chunks, chunks,
chunkCount,
videoId, videoId,
fromLang, fromLang,
toLang, toLang,
@@ -968,7 +1002,7 @@ class YouTubeCaptionProvider {
} }
if (subtitlesForThisChunk.length > 0) { if (subtitlesForThisChunk.length > 0) {
const progressed = (chunkNum * 100) / chunkCount; const progressed = Math.floor((chunkNum * 100) / (chunks.length + 1));
this.#subtitles.push(...subtitlesForThisChunk); this.#subtitles.push(...subtitlesForThisChunk);
this.#progressed = progressed; this.#progressed = progressed;