Systems and subsystems
Container and metadata
Reads the header facts of a file (format, codec, rate, bit depth, tags) and applies a few rules. On this test set it returns a constant score by design, because on our training data the container is the label; its facts route the compression detector instead.
In plain words
We measured the container before using it: LibriSpeech is FLAC, LJ Speech is 22 kHz WAV, two commercial generators are MP3, and PlayHT's MP3s carry the exact encoder tag every one of the 1,671source: README.md, section what-did-not-work test files carries. A learned metadata model would ace our holdout for the wrong reason and then call the whole test set PlayHT. So the detector is rule-based, never learned, scores every test file at the neutral value, and hands its facts to the router. It never reads filenames or filesystem timestamps, which git, zip and Docker rewrite.
What goes in and comes out
In: the file path (it runs ffprobe itself). Out: format, codec, sample rate, channels, bits, duration, tag count and selected tag values as features; routing facts lossy, is_pcm_wav, ffmpeg_written; a rule score; and a sentence such as wav/pcm_s16le 16000 Hz mono 16-bit, 1 tag(s) [encoder=Lavf58.29.100]: no class evidence in the container; written by FFmpeg (libavformat), so the file was re-muxed or transcoded at least once.
Where it lives
detectors/container.py: probe_container, classify_tags, the detector; inventory_container.py for the corpus crosstab.
Rules and where each is set
- Tag values (never keys) are lower-cased and joined; a hit on a list of synthesis-tool names scores 0.9source: src/hearsay/detectors/container.py line 93 (GitHub; assumes main is public), a hit on a list of synthesis words ("synthetic", "cloned", "ai voice", …) scores 0.75source: src/hearsay/detectors/container.py line 95 (GitHub; assumes main is public), otherwise 0.5source: src/hearsay/detectors/container.py line 97 (GitHub; assumes main is public) with "no class evidence in the container" (container.py, lines 88–97). "tts" must match as a whole word.
- A codec in the lossy list sets
lossy; a WAV with a PCM codec setsis_pcm_wav; an encoder tag starting with "lavf" setsffmpeg_written(container.py, lines 117–128). - A probe failure is an error result, not a crash.
Status
Built; routing only. The rubric's timestamps and MAC times are deliberately not read.
Numbers
A constant 0.5source: README.md, section what-did-not-work on all 21,671source: README.md, section the-detector-contract rows of the training and test exports. Every test file is 16 kHz mono 16-bit PCM WAV with one FFmpeg encoder tag.
Known limits
By design it cannot score this test set. A tag naming a synthesis tool would score a file toward synthetic, but no test file carries one.
Tests that pin it
tests/test_container_detector.py: a plain PCM WAV is neutral and carries the routing facts, a lossy codec is flagged but stays neutral, a tool tag scores 0.9source: src/hearsay/detectors/container.py line 93 (GitHub; assumes main is public), a synthesis claim 0.75source: src/hearsay/detectors/container.py line 96 (GitHub; assumes main is public), a table of tag rules (the FFmpeg tag, an empty tag, "Watts per channel", "Coqui TTS", "ai-generated", a key named tts), an unreadable file is an error, deterministic and filename-blind, no filesystem fields, registration.
Sources
The CPU detectors report, "Trap 1"; README, "The container is the label".