#!/bin/bash # Altbestand von VBR- auf CBR-MP3 umstellen. # # Warum: der Browser springt in einer VBR-Datei über die Xing-Tabelle (100 # Stützstellen — bei einer Stunde Audio ein 36-Sekunden-Raster) und landet # systematisch zu früh, meldet aber die angefragte Zeit. Genau daher lief die # Wortmarkierung im Transkript dem Ton voraus. Bei CBR ist die Byte-Position # proportional zur Zeit, jeder Sprung sitzt. Die Xing-Tabelle muss dabei WEG # (-write_xing 0): sie speichert Byte-Positionen nur in 1/256 der Dateigröße, # das sind bei einer Stunde Audio ~15 s Rundung. Ohne sie rechnet der Decoder # linear — bei CBR nachgemessen auf 0,02 s genau. # # Quelle ist die WAV, wo es sie noch gibt (gleiche Filterkette wie beim # Aufnehmen). Für die alten Aufnahmen ohne WAV bleibt nur die MP3 selbst — # dann OHNE Filter, die stecken dort ja schon drin. # # `-f mp3` ist Pflicht: die Zieldatei heisst *.mp3.tmp, und aus dieser Endung # leitet ffmpeg kein Format ab ("Unable to choose an output format"). # # Sicherheit: erst in eine .tmp schreiben, Dauer gegen das Original prüfen # (±2 s), dann erst ersetzen. Ein Abbruch lässt die alte Datei unangetastet. set -u cd /opt/callrec/recordings || exit 1 MAXTEMP=88000 # °C*1000 — darüber wird pausiert (kein aktiver Lüfter) ok=0; skip=0; fail=0 dur() { ffprobe -v error -show_entries format=duration -of default=nw=1:nk=1 "$1" 2>/dev/null; } for m in rec_*.mp3; do [ -f "$m" ] || continue # schon fertig = 64 kbit konstant UND ohne Xing-Tabelle (die ist selbst bei # CBR nur auf 1/256 der Dateigröße genau, bei einer Stunde also ~15 s). if ffprobe -v error -show_entries stream=bit_rate -of default=nw=1:nk=1 "$m" 2>/dev/null | grep -q '^64000$' && ! head -c 2048 "$m" | grep -qa Xing; then skip=$((skip+1)); continue fi # Thermik: das Board hat keinen Lüfter, also vor jeder Datei kurz nachsehen. while :; do t=$(cat /sys/class/thermal/thermal_zone0/temp 2>/dev/null || echo 0) [ "$t" -lt "$MAXTEMP" ] && break echo " … $((t/1000)) °C, warte 30 s"; sleep 30 done w="${m%.mp3}.wav" d0=$(dur "$m") if [ -f "$w" ]; then nice -n 10 ffmpeg -v error -y -i "$w" \ -af 'highpass=f=80,loudnorm=I=-16:TP=-1.5:LRA=11' \ -codec:a libmp3lame -b:a 64k -ar 48000 -ac 1 -write_xing 0 -f mp3 "$m.tmp" 2)?"1":"0"}') if [ "$diff" = "1" ]; then echo "FEHLER $m: Dauer weicht ab ($d0 -> $d1)"; rm -f "$m.tmp"; fail=$((fail+1)); continue fi chown callrec:callrec "$m.tmp" mv -f "$m.tmp" "$m" ok=$((ok+1)) echo "ok $m ($d0 s, Quelle: $([ -f "$w" ] && echo wav || echo mp3))" done echo "fertig: $ok neu kodiert, $skip schon CBR, $fail fehlgeschlagen"