Files
crm-calls/jitsi/finalize.sh

65 lines
3.6 KiB
Bash
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/bin/bash
# Jibri finalize-скрипт (CRM Tvorymo, модуль «Дзвінки»).
# Jibri викликає його після завершення запису з каталогом сесії ($1), де лежить відео *.mp4.
# 1. Лише звук: моно, 16 кГц, низький бітрейт (mp3, якщо є libmp3lame, інакше opus).
# 2. Відео одразу видаляється.
# 3. Звук ріжеться на частини (CALLS_CHUNK_SECONDS) для Whisper (ліміт API 25 МБ).
# 4. meta.json: тривалості, частини, статистика якості; маркер ready.
# Далі файли забирає модуль «Дзвінки» (спільний каталог записів) і видаляє після успішної обробки.
set -u
DIR="${1:?каталог запису}"
LOG="$DIR/finalize.log"
exec >>"$LOG" 2>&1
echo "$(date -Is) finalize $DIR"
BITRATE="${CALLS_AUDIO_BITRATE:-32k}"
CHUNK="${CALLS_CHUNK_SECONDS:-1200}"
fail() { echo "$(date -Is) ПОМИЛКА: $*"; echo "$*" > "$DIR/failed"; exit 0; }
VIDEO="$(ls -1 "$DIR"/*.mp4 2>/dev/null | head -1)"
[ -n "$VIDEO" ] || fail "немає відеофайлу"
if ffmpeg -hide_banner -encoders 2>/dev/null | grep -q libmp3lame; then
EXT=mp3; MIME=audio/mpeg; CODEC=(-c:a libmp3lame -b:a "$BITRATE")
else
EXT=ogg; MIME=audio/ogg; CODEC=(-c:a libopus -application voip -b:a "$BITRATE")
fi
AUDIO="$DIR/audio.$EXT"
ffmpeg -nostdin -hide_banner -loglevel error -y -i "$VIDEO" -vn -ac 1 -ar 16000 "${CODEC[@]}" "$AUDIO" \
|| fail "ffmpeg не зміг витягти звук"
VIDEO_BYTES=$(stat -c %s "$VIDEO" 2>/dev/null || echo 0)
rm -f "$VIDEO" "$DIR"/*.mp4
echo "$(date -Is) відео видалено ($VIDEO_BYTES байт), звук: $AUDIO"
mkdir -p "$DIR/parts"
ffmpeg -nostdin -hide_banner -loglevel error -y -i "$AUDIO" -f segment -segment_time "$CHUNK" -reset_timestamps 1 -c copy \
"$DIR/parts/part-%03d.$EXT" || fail "ffmpeg не зміг розрізати звук"
dur() { ffprobe -v error -show_entries format=duration -of default=nw=1:nk=1 "$1" 2>/dev/null || echo 0; }
PARTS='[]'
for p in "$DIR"/parts/part-*."$EXT"; do
[ -f "$p" ] || continue
PARTS=$(jq -c --arg f "parts/$(basename "$p")" --argjson d "$(dur "$p")" --argjson s "$(stat -c %s "$p")" \
'. + [{file:$f, duration:$d, bytes:$s}]' <<<"$PARTS")
done
# Якість: тиша (поріг -50 dB, від 2 с), гучність.
STATS=$(ffmpeg -nostdin -hide_banner -i "$AUDIO" -af silencedetect=n=-50dB:d=2,volumedetect -f null - 2>&1)
SIL_COUNT=$(grep -c 'silence_end' <<<"$STATS")
SIL_TOTAL=$(grep -o 'silence_duration: [0-9.]*' <<<"$STATS" | awk '{s+=$2} END {printf "%.1f", s+0}')
MEAN_DB=$(grep -o 'mean_volume: [-0-9.]*' <<<"$STATS" | awk '{print $2}')
MAX_DB=$(grep -o 'max_volume: [-0-9.]*' <<<"$STATS" | awk '{print $2}')
jq -n --arg audio "audio.$EXT" --arg mime "$MIME" --argjson duration "$(dur "$AUDIO")" \
--argjson bytes "$(stat -c %s "$AUDIO")" --argjson videoBytes "$VIDEO_BYTES" --argjson parts "$PARTS" \
--argjson silences "${SIL_COUNT:-0}" --argjson silenceSeconds "${SIL_TOTAL:-0}" \
--arg meanDb "${MEAN_DB:-}" --arg maxDb "${MAX_DB:-}" --arg finishedAt "$(date -Is)" \
'{audio:$audio, mime:$mime, duration:$duration, bytes:$bytes, videoBytes:$videoBytes, parts:$parts,
quality:{silences:$silences, silenceSeconds:$silenceSeconds, meanDb:$meanDb, maxDb:$maxDb}, finishedAt:$finishedAt}' \
> "$DIR/meta.json.tmp" && mv "$DIR/meta.json.tmp" "$DIR/meta.json" || fail "не вдалося записати meta.json"
chmod -R a+rwX "$DIR" 2>/dev/null
touch "$DIR/ready"
echo "$(date -Is) готово: $(cat "$DIR/meta.json")"