mirror of
https://github.com/ksyasuda/SubMiner.git
synced 2026-11-10 04:46:07 -08:00
feat(subtitles): add regex subtitle filters with built-in presets (#318)
- Add `subtitleFilter` config with four presets: parentheses, brackets, speaker prefix and music symbols. Custom regex rules run after the presets. - Filter primary text where it enters the app (live `sub-text` and parsed cues), so the overlay, sidebar, mining and stats all get the same filtered text. - Changes hot-reload: the current line is read again and the active track is parsed again, using the filter config as the prefetch parse key. - Add a custom rule editor in Settings under Behavior → Subtitle Filters that checks patterns as you type. - Update the config example, the configuration docs and the architecture domains doc, and add a changelog fragment.
This commit is contained in:
1 parent
848a6c4021
commit
fa3051f9cb
28 files changed
+740
-11
No files matched your search
@@ -1,6 +1,8 @@
|
||||
import { MpvSubtitleRenderMetrics } from '../../types';
|
||||
import { sanitizeMediaTitle } from '../../shared/media-identity';
|
||||
import { widenHalfwidthKana } from '../utils/halfwidth-kana';
|
||||
import { filterSubtitleText } from '../../shared/subtitle-text-filter';
|
||||
import type { SubtitleFilterConfig } from '../../types/subtitle';
|
||||
import type { PluginMpvEventMap } from '../../plugin-api';
|
||||
import { toVideoClock } from './subtitle-clock';
|
||||
|
||||
@@ -68,6 +70,7 @@ export interface MpvProtocolParseResult {
|
||||
export interface MpvProtocolHandleMessageDeps {
|
||||
getResolvedConfig: () => {
|
||||
secondarySub?: { secondarySubLanguages?: Array<string> };
|
||||
subtitleFilter?: SubtitleFilterConfig;
|
||||
};
|
||||
getSubtitleMetrics: () => MpvSubtitleRenderMetrics;
|
||||
isVisibleOverlayVisible: () => boolean;
|
||||
@@ -263,13 +266,19 @@ export function splitMpvMessagesFromBuffer(
|
||||
};
|
||||
}
|
||||
|
||||
// Primary text enters the app here, so every consumer sees it widened and filtered.
|
||||
function toPrimarySubText(data: unknown, deps: MpvProtocolHandleMessageDeps): string {
|
||||
const text = widenHalfwidthKana(typeof data === 'string' ? data : '');
|
||||
return filterSubtitleText(text, deps.getResolvedConfig().subtitleFilter);
|
||||
}
|
||||
|
||||
export async function dispatchMpvProtocolMessage(
|
||||
msg: MpvMessage,
|
||||
deps: MpvProtocolHandleMessageDeps,
|
||||
): Promise<void> {
|
||||
if (msg.event === 'property-change') {
|
||||
if (msg.name === 'sub-text') {
|
||||
const nextSubText = widenHalfwidthKana((msg.data as string) || '');
|
||||
const nextSubText = toPrimarySubText(msg.data, deps);
|
||||
const overlayVisible = deps.isVisibleOverlayVisible();
|
||||
deps.emitSubtitleChange({
|
||||
text: nextSubText,
|
||||
@@ -498,7 +507,7 @@ export async function dispatchMpvProtocolMessage(
|
||||
}>,
|
||||
);
|
||||
} else if (msg.request_id === MPV_REQUEST_ID_SUBTEXT) {
|
||||
const nextSubText = widenHalfwidthKana((msg.data as string) || '');
|
||||
const nextSubText = toPrimarySubText(msg.data, deps);
|
||||
deps.setCurrentSubText(nextSubText);
|
||||
deps.emitSubtitleChange({
|
||||
text: nextSubText,
|
||||
|
||||
@@ -3,6 +3,7 @@ import { EventEmitter } from 'events';
|
||||
import { Config, MpvClient, MpvSubtitleRenderMetrics } from '../../types';
|
||||
import {
|
||||
dispatchMpvProtocolMessage,
|
||||
MPV_REQUEST_ID_SUBTEXT,
|
||||
MPV_REQUEST_ID_TRACK_LIST_AUDIO,
|
||||
MPV_REQUEST_ID_TRACK_LIST_SECONDARY,
|
||||
MpvMessage,
|
||||
@@ -585,6 +586,11 @@ export class MpvIpcClient implements MpvClient {
|
||||
});
|
||||
}
|
||||
|
||||
/** Re-reads `sub-text` so the current line passes through the protocol handler again. */
|
||||
refreshSubtitleText(): void {
|
||||
this.send({ command: ['get_property', 'sub-text'], request_id: MPV_REQUEST_ID_SUBTEXT });
|
||||
}
|
||||
|
||||
async requestProperty(name: string): Promise<unknown> {
|
||||
const response = await this.request(['get_property', name]);
|
||||
if (response.error && response.error !== 'success') {
|
||||
|
||||
Reference in new issue
Block a user