mirror of
https://github.com/ksyasuda/SubMiner.git
synced 2026-09-22 17:16:19 -07:00
feat(subtitles): optimize anime stream audio extraction
- Prefer matching audio and lower-resolution sources with HLS sampling - Reuse verified audio within sessions and clean temporary files on shutdown - Allow character dictionary sync without loaded subtitles
This commit is contained in:
@@ -43,14 +43,16 @@ extension APK → bridge (JVM) → { url, headers } → mpv → SubMiner
|
||||
```
|
||||
|
||||
Because the extension resolves the stream, whichever sources you install decide
|
||||
what is available. SubMiner only hosts them.
|
||||
what is available. SubMiner runs the installed extensions locally and nothing
|
||||
more.
|
||||
|
||||
## Installing extensions
|
||||
|
||||
**SubMiner ships no extension repositories and bundles no sources.** There is no
|
||||
default repository, no suggested list, and no discovery. Until you add one, the
|
||||
browser has nothing to search — that is deliberate, and it is what keeps SubMiner
|
||||
a neutral host rather than a distributor.
|
||||
browser has nothing to search — that is deliberate. Every repository and
|
||||
extension comes from you, and SubMiner is not affiliated with any of the sites
|
||||
they connect to.
|
||||
|
||||
There are two ways to add extensions.
|
||||
|
||||
|
||||
@@ -35,6 +35,8 @@ Character dictionary sync is disabled by default. To turn it on:
|
||||
|
||||
::: tip
|
||||
The first sync for a media title takes a few seconds while character data and portraits are fetched from AniList. Subsequent launches reuse the cached media match and snapshot without a fresh AniList lookup.
|
||||
|
||||
Dictionary sync does not require a loaded Japanese subtitle track. Once Yomitan is ready, SubMiner can reuse an installed character dictionary even before the first subtitle is processed. If Yomitan readiness times out, the status reports a failure instead of staying on **Checking**.
|
||||
:::
|
||||
|
||||
::: info
|
||||
@@ -168,7 +170,7 @@ These phases are emitted through the configured notification surface. Some phase
|
||||
2. **generating** - No cache hit: fetch characters from AniList GraphQL, download portraits (250ms throttle between image requests), save snapshot JSON.
|
||||
3. MRU update (no notification) - add the media ID to the most-recently-used list and evict old entries beyond `maxLoaded`.
|
||||
4. **building** - Merge active snapshots into a single Yomitan ZIP. A SHA-1 revision hash is computed from the media set - if it matches the previously imported revision, the import is skipped.
|
||||
5. **importing** - Push the ZIP into Yomitan. Waits for Yomitan mutation readiness (7-second timeout per operation).
|
||||
5. **importing** - Push the ZIP into Yomitan when the installed revision differs. Dictionary checks and settings updates wait for the extension to be ready, independently of subtitle processing. Readiness and quick operations have bounded timeouts; imports have a separate budget that grows with the ZIP size.
|
||||
6. **ready** - Dictionary is live. Character names will match on the next subtitle line.
|
||||
|
||||
**State tracking** is persisted in `character-dictionaries/auto-sync-state.json`. AniList media matches are cached separately in `character-dictionaries/anilist-resolution-cache.json` so snapshot hits do not need another AniList search.
|
||||
|
||||
@@ -65,11 +65,19 @@ SubMiner saves `<video>.ja.generated.srt` beside the media, adding a numeric suf
|
||||
|
||||
### Generating for anime streams
|
||||
|
||||
Start the episode from the [anime browser](/anime-browser), then open the generation modal as usual. HTTP and HTTPS episode streams, including HLS through the anime browser's proxy, can use the same models and dialogue options as local files. The selected audio track must be inside the stream; separately attached audio tracks are not supported.
|
||||
Start the episode from the [anime browser](/anime-browser), then open the generation modal as usual. HTTP and HTTPS episode streams, including HLS through the anime browser's proxy, can use the same models and dialogue options as local files. The selected audio may be inside the stream or a separately attached HTTP/HTTPS audio track. For a selected external audio stream, SubMiner downloads that track directly and includes mpv's current audio delay in the subtitle timing. Local external audio files remain unsupported.
|
||||
|
||||
SubMiner fetches the episode's audio into a temporary WAV before transcription. It reuses mpv's supported request headers, referrer, and user agent. The existing media-fetch policy excludes Cookie and Authorization headers, so sources requiring those directly may fail unless the anime bridge handles authentication. Expired URLs or a stopped bridge can also interrupt extraction; reopen the episode and retry.
|
||||
|
||||
Generated SRT files are retained under `cache/generated-subtitles` in SubMiner's application data directory, using a URL hash for the filename and a numeric suffix for repeated generation. The result shows the saved path. Temporary audio is removed after success, failure, or cancellation. Playback can continue during generation; the completed SRT is selected only if the same stream is still playing. Cached results are not automatically loaded on a later visit.
|
||||
For anime-browser episodes, extraction first considers separate Japanese audio tracks returned by the source, then video streams with lower resolution than playback. It checks duration, starting offset, and short audio samples at three points against the selected playback audio. Different dialogue, shifted timing, silence, or failed checks keep the original stream. Checking alternatives has a 20-second budget. For plain HLS, it downloads only the segments covering each sample and aligns their timestamps to playback before comparing audio. Empty original samples are retried once and never reused. Failed checks log the candidate number, phase, reason, and elapsed time without exposing stream URLs or request headers. Progress names the source used for extraction; playback keeps its selected quality. Sources that expose only one combined stream still require downloading its video bytes.
|
||||
|
||||
For plain HLS episodes with MPEG-TS segments, SubMiner downloads up to four segments at once, then extracts audio in playback order. Progress shows segment downloading followed by audio extraction. The temporary segments require space for the episode's combined video and audio and are removed after extraction, or when generation fails or is cancelled. Encrypted playlists, variant playlists, byte ranges, and other complex stream formats use the existing FFmpeg extraction path. Download speed still depends on the source and proxy.
|
||||
|
||||
Generated SRT files are retained under `cache/generated-subtitles` in SubMiner's application data directory, using a URL hash for the filename and a numeric suffix for repeated generation. The result shows the saved path. Playback can continue during generation; the completed SRT is selected only if the same stream is still playing. Cached SRT results are not automatically loaded on a later visit.
|
||||
|
||||
Completed audio extracts can be reused for retries and model changes during the current app session. They live with temporary job files under `cache/generated-subtitles/sessions`, separate from saved SRT files. The cache distinguishes the stream URL, selected audio track, and request headers, verifies contents before reuse, and evicts older audio above 512 MiB. Partial downloads are not cached.
|
||||
|
||||
Quitting cancels the active job, waits for its cleanup, and removes the session's downloaded audio and working files. On startup, SubMiner removes abandoned session directories from processes that have exited, plus audio retained by the older persistent cache. Audio is never reused across app restarts. Generated SRT files and installed speech models remain available.
|
||||
|
||||
This processes the complete episode, so subtitles appear after extraction and transcription finish. Streams must report a finite duration; live streams are not supported. A stream with combined video and audio segments may require downloading those segments even though only audio is retained.
|
||||
|
||||
@@ -87,4 +95,4 @@ With no file argument, the command uses the current local mpv media and its sele
|
||||
|
||||
The SRT includes whisper.cpp's timestamps, adjusted for the audio stream's position on the media timeline and, when speech detection is configured, each passage's original start time. No alass step is required to load it. This version uses native Whisper timing; it does not run WhisperX or another forced aligner. Recognition can repeat or invent lines, and timing can be imperfect, especially with music or overlapping speech. Review generated text and audio boundaries when mining.
|
||||
|
||||
The overlay supports local files and finite HTTP/HTTPS streams with internal audio tracks. The launcher remains local-file only. Subtitle translation and transcription of a separately attached mpv audio track are not supported by the modal. Pass a separate local audio file to the launcher if needed. The destination directory needs writable space for subtitles; temporary storage needs enough space for the extracted mono audio. Cached local subtitle tracks and embedded text subtitles can guide stream transcription; unreadable references fall back to audio timing.
|
||||
The overlay supports local files and finite HTTP/HTTPS streams with internal or selected external HTTP audio tracks. The launcher remains local-file only. Subtitle translation and separately attached local audio files are not supported by the modal. Pass a separate local audio file to the launcher if needed. The destination directory needs writable space for subtitles; temporary storage needs enough space for the extracted mono audio. Cached local subtitle tracks and embedded text subtitles can guide stream transcription; unreadable references fall back to audio timing.
|
||||
|
||||
Reference in New Issue
Block a user