mux: add video:// sink (video-only per-track elementary streams)
Completes the per-track-class trio with audio:// / sub://. video:// is the demux path with a TrackKind::Video kind filter — each video track to its own native elementary stream (.hevc/.h264/.vc1/.m2v/.obu), no audio or subtitles. Reuses the existing kind_filter machinery and extension map; scheme/parse/output/write-only-guard arms added symmetrically.
This commit is contained in:
+5
-1
@@ -4,8 +4,12 @@
|
||||
|
||||
### Added
|
||||
|
||||
- **Four extraction sinks — dissect a title, don't just rip it.** New write-only
|
||||
- **Five extraction sinks — dissect a title, don't just rip it.** New write-only
|
||||
destinations that pull one facet of a title out on its own:
|
||||
- **`video://dir/`** — every video track to its own file, as a raw elementary
|
||||
stream in the codec's native form (`.hevc`, `.h264`, `.vc1`, `.m2v`, `.obu`).
|
||||
No audio, no subtitles. Completes the per-track-class trio with `audio://` /
|
||||
`sub://`.
|
||||
- **`audio://dir/`** — every audio track to its own file in a directory, each in
|
||||
its native container (`.thd`, `.dts` / `.dtshd`, `.ac3`, `.eac3`, `.aac`,
|
||||
`.flac`). No video, no subtitles. BD/DVD LPCM has no container of its own and is
|
||||
|
||||
@@ -159,6 +159,7 @@ mod tests {
|
||||
assert_eq!(parse_url("iso://f").scheme(), "iso");
|
||||
assert_eq!(parse_url("null://").scheme(), "null");
|
||||
assert_eq!(parse_url("demux://out/").scheme(), "demux");
|
||||
assert_eq!(parse_url("video://out/").scheme(), "video");
|
||||
assert_eq!(parse_url("audio://out/").scheme(), "audio");
|
||||
assert_eq!(parse_url("sub://out/").scheme(), "sub");
|
||||
assert_eq!(parse_url("chapters://c.xml").scheme(), "chapters");
|
||||
|
||||
+20
-4
@@ -62,6 +62,10 @@ pub enum StreamUrl {
|
||||
/// chapters + delay metadata). Like `dir://` it targets a directory; the
|
||||
/// CLI constructs the `DemuxSink` with full options before the mux loop.
|
||||
Demux { dir: PathBuf },
|
||||
/// Video-only per-track output directory (`video://`) — a `demux://`
|
||||
/// restricted to video tracks (native elementary streams: `.hevc`, `.h264`,
|
||||
/// `.vc1`, `.m2v`, …). One file per video track; no audio/subtitles.
|
||||
Video { dir: PathBuf },
|
||||
/// Audio-only per-track output directory (`audio://`) — a `demux://`
|
||||
/// restricted to audio tracks (native containers: `.thd`, `.dts`, `.ac3`,
|
||||
/// `.eac3`, `.pcm`, …). One file per audio track; no video/subtitles.
|
||||
@@ -100,6 +104,7 @@ impl StreamUrl {
|
||||
StreamUrl::Dir { .. } => "dir",
|
||||
StreamUrl::Null => "null",
|
||||
StreamUrl::Demux { .. } => "demux",
|
||||
StreamUrl::Video { .. } => "video",
|
||||
StreamUrl::Audio { .. } => "audio",
|
||||
StreamUrl::Sub { .. } => "sub",
|
||||
StreamUrl::Fvi { .. } => "fvi",
|
||||
@@ -119,6 +124,7 @@ impl StreamUrl {
|
||||
| StreamUrl::Iso { path }
|
||||
| StreamUrl::Dir { path }
|
||||
| StreamUrl::Demux { dir: path }
|
||||
| StreamUrl::Video { dir: path }
|
||||
| StreamUrl::Audio { dir: path }
|
||||
| StreamUrl::Sub { dir: path }
|
||||
| StreamUrl::Fvi { path }
|
||||
@@ -196,6 +202,11 @@ pub fn parse_url(url: &str) -> StreamUrl {
|
||||
dir: PathBuf::from(rest),
|
||||
};
|
||||
}
|
||||
if let Some(rest) = url.strip_prefix("video://") {
|
||||
return StreamUrl::Video {
|
||||
dir: PathBuf::from(rest),
|
||||
};
|
||||
}
|
||||
if let Some(rest) = url.strip_prefix("audio://") {
|
||||
return StreamUrl::Audio {
|
||||
dir: PathBuf::from(rest),
|
||||
@@ -493,6 +504,7 @@ pub fn input(url: &str, opts: &InputOptions) -> io::Result<Box<dyn crate::pes::S
|
||||
StreamUrl::Null => Err(crate::error::Error::StreamWriteOnly.into()),
|
||||
// `demux://` is an output-only sink (per-track ES files); never a source.
|
||||
StreamUrl::Demux { .. }
|
||||
| StreamUrl::Video { .. }
|
||||
| StreamUrl::Audio { .. }
|
||||
| StreamUrl::Sub { .. }
|
||||
| StreamUrl::Chapters { .. }
|
||||
@@ -575,11 +587,15 @@ pub fn output(
|
||||
dir, title, &opts,
|
||||
)?))
|
||||
}
|
||||
// `audio://` and `sub://` are `demux://` restricted to one track class —
|
||||
// audio in native containers, or subtitles as `.sup`/`.idx+.sub`/`.srt`.
|
||||
// No chapters sidecar (that's a `demux://` / `chapters://` concern).
|
||||
StreamUrl::Audio { ref dir } | StreamUrl::Sub { ref dir } => {
|
||||
// `video://`, `audio://`, and `sub://` are `demux://` restricted to one
|
||||
// track class — video as native elementary streams, audio in native
|
||||
// containers, or subtitles as `.sup`/`.idx+.sub`/`.srt`. No chapters
|
||||
// sidecar (that's a `demux://` / `chapters://` concern).
|
||||
StreamUrl::Video { ref dir }
|
||||
| StreamUrl::Audio { ref dir }
|
||||
| StreamUrl::Sub { ref dir } => {
|
||||
let (scheme, kind) = match parsed {
|
||||
StreamUrl::Video { .. } => ("video", super::demux_sink::TrackKind::Video),
|
||||
StreamUrl::Audio { .. } => ("audio", super::demux_sink::TrackKind::Audio),
|
||||
_ => ("sub", super::demux_sink::TrackKind::Subtitle),
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user