mux: chapters:// and json:// metadata sinks

Two write-only file sinks that ignore the PES stream and emit the title
metadata at construction (fvi-style, wired through output()):
- chapters:// — chapter markers in the format the extension picks: .xml
  (Matroska, default), .txt/.ogm (OGM simple), .vtt (WebVTT). Reuses the
  existing chapters_xml/chapters_ogm writers; adds a WebVTT writer.
- json:// — one title's model (playlist, duration, size, format, streams,
  chapters) as pretty JSON via serde_json.

New mux/meta_sink.rs; StreamUrl gains Chapters/Json; codec_label +
chapters_xml/ogm promoted to pub(crate) for reuse.

Tests: chapters_format_selected_by_extension, title_json_carries_streams_and_chapters.
This commit is contained in:
Matthew Jackson
2026-07-18 17:45:39 -07:00
parent 9f33306a0a
commit 63f6909ff0
4 changed files with 280 additions and 7 deletions
+3 -3
View File
@@ -150,7 +150,7 @@ fn extension_for(codec: Codec) -> &'static str {
}
/// Short codec label for friendly filenames.
fn codec_label(codec: Codec) -> &'static str {
pub(crate) fn codec_label(codec: Codec) -> &'static str {
match codec {
Codec::Hevc => "HEVC",
Codec::H264 => "AVC",
@@ -548,7 +548,7 @@ fn fmt_chapter_time_ns(time_secs: f64) -> String {
}
/// Serialize chapters as mkvmerge chapter XML.
fn chapters_xml(chapters: &[Chapter]) -> String {
pub(crate) fn chapters_xml(chapters: &[Chapter]) -> String {
let mut s = String::new();
s.push_str("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
s.push_str("<!DOCTYPE Chapters SYSTEM \"matroskachapters.dtd\">\n");
@@ -578,7 +578,7 @@ fn chapters_xml(chapters: &[Chapter]) -> String {
}
/// Serialize chapters as OGM/simple chapter text.
fn chapters_ogm(chapters: &[Chapter]) -> String {
pub(crate) fn chapters_ogm(chapters: &[Chapter]) -> String {
let mut s = String::new();
for (i, c) in chapters.iter().enumerate() {
let n = i + 1;