This repository has been archived on 2026-09-16. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
Sylpheed-Godot/tools/verify-video-audio
Sylpheed port agent 8d7373b16c video: state the 5.1 downmix instead of inheriting it, and write atomically
A real defect in the P4 output, found by the human on ADV.wmv and widened by the
RE agent to the whole disc: the disc ships 28 movies in 5.1 WMA Pro (every
cutscene, INCLUDING both movies this port needs) and 69 already in stereo. A
bare `-ac 2` therefore does two different things and records neither -- stereo
passes through, and 5.1 is folded by ffmpeg's DEFAULT matrix. How loudly
centre-channel dialogue sits against the music is a content decision, and it was
being made by accident and could move under an ffmpeg upgrade.

Now stated: ITU-R BS.775, LFE dropped, normalised by 1/(1+2*sqrt(1/2)) = 0.4142.
It appears in the recorded command, so the manifest determines the output.

MEASURED rather than chosen by taste, and the measurement is the interesting
part: the explicit matrix and ffmpeg's inherited default differ by a residual of
-91 dB -- about one LSB at 16-bit -- with peak and mean agreeing to 0.1 dB. So
ffmpeg's default IS this matrix, and the audio does not change; what changes is
that the manifest now says which matrix. The UNnormalised textbook form was
measured too and clips at 0.0 dBFS, which is why the scaling is there.

The filter is applied only to 6-channel sources, probed per file with ffprobe,
so a stereo source is never run through a matrix referencing channels it lacks.

Also: encode to a temp name and rename on success. ffprobe read a mid-write
.ogv as 33 s against a 137 s source -- no error, no warning, the exact shape of
catastrophic truncation. The filesystem is shared with the RE agent, so that is
a race, not an edge case, and a half-written file must never be visible under
its final name.

tools/verify-video-audio answers the second of the three questions
docs/AUDIO-VERIFICATION.md separates: does GODOT route the audio. An
AudioEffectRecord on the Master bus writes Godot's own mixed output to a WAV
from a headless run, so "no sound card" was never the obstacle I claimed. It
deliberately checks non-silence and level only -- a difference-signal RMS
against the source is inconclusive without cross-correlation alignment and an
agreed downmix, and would produce a confident wrong number.
2026-08-29 09:04:47 +00:00

87 lines
3.5 KiB
Bash
Executable File

#!/usr/bin/env bash
# Prove Godot actually emits a transcoded movie's audio -- with no audio device.
#
# tools/verify-video-audio ADV
#
# This container has no sound card and Godot falls back to the dummy driver, so
# "does it play" looked unanswerable from here. It is not: an AudioEffectRecord
# on the Master bus makes Godot write its own mixed output to a WAV from inside
# a headless run. That is Godot rendering audio to a file instead of a device --
# no new dependency, no image rebuild, and it tests the real playback path
# rather than the file the encoder produced.
#
# What this checks is that GODOT EMITS NON-SILENCE from the movie. It is
# deliberately NOT a fidelity comparison against the source: a difference-signal
# RMS between a transcode and its source is inconclusive without cross-
# correlation alignment and an agreed downmix -- a one-sample offset makes the
# residual nearly as loud as the signal. Level and non-silence are what this
# claims.
set -euo pipefail
cd "${PROJECT_DIR:-/work}"
name="${1:-ADV}"
OUT="${OUT:-${TMPDIR:-/tmp}/verify-video-audio}"
export DISPLAY="${DISPLAY:-:97}"
mkdir -p "$OUT"
[ -d port/.godot ] || godot --headless --path port --import >/dev/null 2>&1
wav="$OUT/$name.godot.wav"
rm -f "$wav"
cat > "$OUT/probe.gd" <<'GD'
extends SceneTree
func _init() -> void:
var args := {}
for a in OS.get_cmdline_user_args():
if a.begins_with("--") and a.contains("="):
var p := a.substr(2).split("=", true, 1)
args[p[0]] = p[1]
var tree_ := ExportTree.locate()
if tree_.root == "":
push_error(tree_.error); quit(2); return
var v: Dictionary = tree_.video(args.get("video", "ADV"))
if v.is_empty():
push_error(tree_.error); quit(2); return
# Record the MASTER bus: whatever Godot mixes, including the dummy driver's
# output. This is the real playback path, not the encoded file.
var rec := AudioEffectRecord.new()
AudioServer.add_bus_effect(0, rec)
var stream := VideoStreamTheora.new()
stream.file = v["path"]
var p := VideoStreamPlayer.new()
p.stream = stream
get_root().add_child(p)
await process_frame
rec.set_recording_active(true)
p.play()
var seconds := float(args.get("seconds", "6"))
var t := 0.0
while t < seconds and p.is_playing():
await process_frame
t += get_root().get_process_delta_time()
rec.set_recording_active(false)
var clip := rec.get_recording()
if clip == null:
push_error("no recording came back from the Master bus"); quit(3); return
clip.save_to_wav(args.get("out", "/tmp/godot-audio.wav"))
print("recorded %.2f s, %d Hz, stereo=%s -> %s" % [
t, clip.mix_rate, clip.stereo, args.get("out", "")])
quit(0)
GD
godot --path port --resolution 320x180 --script "$OUT/probe.gd" -- \
"--video=$name" "--out=$wav" "--seconds=${SECONDS_TO_RECORD:-6}" 2>&1 \
| grep -viE "ALSA|Vulkan|V-Sync|OpenGL|audio driver|^ *at: |Condition|^$" || true
[ -s "$wav" ] || { echo "verify-video-audio: Godot wrote no WAV" >&2; exit 1; }
echo "--- what Godot emitted ---"
ffmpeg -hide_banner -i "$wav" -af volumedetect -f null - 2>&1 \
| grep -oE "(max_volume|mean_volume): [-0-9.]+ dB" | sed 's/^/ /'
mean=$(ffmpeg -hide_banner -i "$wav" -af volumedetect -f null - 2>&1 \
| grep -oE "mean_volume: [-0-9.]+" | grep -oE -- "-?[0-9.]+")
# Digital silence reports around -91 dB at 16-bit. Anything near that is nothing.
awk -v m="$mean" 'BEGIN{ if (m < -80) { print " VERDICT: silence -- Godot is not emitting this movie\047s audio"; exit 1 }
else { printf " VERDICT: audio present (mean %.1f dB)\n", m } }'