LabCodeHub öffentliche Ansicht
Anmelden
Küpper / ehc-tvwall öffentlich
Branch: main
ehc-tvwall / scripts / bisect-mpv.sh
Verlauf Rohdaten
R Rüdiger Küpper fix: v1.0.0
14518d05 vor 11 Tagen
scripts/bisect-mpv.sh 187 Zeilen · 7.7 KB · Shell
1
#!/usr/bin/env bash
2
# ===========================================================================
3
#  Findet heraus, WELCHE mpv-Option (oder welcher Ablauf) einen Haenger
4
#  ausloest. Statt zu raten wird jede Variante gemessen.
5
#
6
#  Aufruf:  sudo /opt/tvwall/scripts/bisect-mpv.sh /var/lib/tvwall/media/<video>
7
#
8
#  Der Bildschirm flackert waehrenddessen - das ist normal, jede Variante
9
#  spielt acht Sekunden. Der Dienst wird angehalten und danach neu gestartet.
10
# ===========================================================================
11
set -uo pipefail
12
13
CONF="/etc/tvwall/tvwall.conf"
14
LIMIT=25          # Sekunden, nach denen eine Variante als "haengt" gilt
15
PLAYSEC=8         # so lange soll jede Variante spielen
16
17
hdr()  { printf '\n\033[1;36m── %s ──────────────────────────\033[0m\n' "$*"; }
18
ok()   { printf '  \033[1;32mLAEUFT\033[0m  %-46s %ss\n' "$1" "$2"; }
19
bad()  { printf '  \033[1;31mHAENGT\033[0m  %-46s Abbruch nach %ss\n' "$1" "$2"; }
20
odd()  { printf '  \033[1;33mFEHLER\033[0m  %-46s Code %s\n' "$1" "$2"; }
21
note() { printf '    %s\n' "$*"; }
22
die()  { printf '\033[1;31mFehler:\033[0m %s\n' "$*" >&2; exit 1; }
23
24
[[ $EUID -eq 0 ]] || die "bitte mit sudo starten"
25
26
VIDEO="${1:-}"
27
[[ -n "$VIDEO" && -f "$VIDEO" ]] || die "Bitte eine Videodatei angeben:
28
       sudo $0 /var/lib/tvwall/media/<datei>.mp4"
29
30
RUN_USER="tvwall"; STATE_DIR="/var/lib/tvwall"; DISPLAY_MODE="auto"
31
[[ -f "$CONF" ]] && { set -a; . "$CONF" 2>/dev/null; set +a; }
32
RUN_USER="${RUN_USER:-tvwall}"; STATE_DIR="${STATE_DIR:-/var/lib/tvwall}"
33
RUN_UID="$(id -u "$RUN_USER" 2>/dev/null)" || die "Benutzer $RUN_USER gibt es nicht"
34
35
# --- Umgebung wie beim Dienst ---------------------------------------------
36
ENV_ARGS=(XDG_RUNTIME_DIR="/run/user/$RUN_UID")
37
VO_ARGS=(--vo=gpu)
38
if ! ls "/run/user/$RUN_UID"/wayland-* >/dev/null 2>&1 && [[ -z "${DISPLAY:-}" ]]; then
39
  VO_ARGS=(--vo=gpu --gpu-context=drm)      # kein Desktop -> direkt auf den Schirm
40
fi
41
42
# Die Optionen, die der Dienst setzt (ohne --idle/--loop, sonst endet nichts).
43
SERVICE_ARGS=(
44
  --fullscreen --force-window=yes --keep-open=no
45
  --image-display-duration=2
46
  --no-osc --osd-level=0 --cursor-autohide=always
47
  --no-input-default-bindings --input-vo-keyboard=no
48
  --stop-screensaver=yes --no-input-terminal
49
  "${VO_ARGS[@]}"
50
)
51
52
# --- Testmaterial ----------------------------------------------------------
53
IMAGE="$(find "$STATE_DIR/media" -maxdepth 1 -type f \
54
         \( -iname '*.jpg' -o -iname '*.jpeg' -o -iname '*.png' \) | sort | head -1)"
55
TMP="$(mktemp -d)"
56
trap 'rm -rf "$TMP"' EXIT
57
printf '%s\n' "$VIDEO" > "$TMP/nur-video.m3u"
58
if [[ -n "$IMAGE" ]]; then
59
  printf '%s\n%s\n' "$IMAGE" "$VIDEO" > "$TMP/bild-video.m3u"
60
fi
61
chmod -R a+rX "$TMP"
62
63
LOGDIR="$TMP/logs"; mkdir -p "$LOGDIR"
64
FAILED=()
65
declare -A RESULT
66
67
# Ein Durchlauf. LEN=0 laesst die Datei komplett laufen (ohne --length).
68
attempt() {
69
  local log="$1" limit="$2" len="$3"; shift 3
70
  local extra=()
71
  [[ "$len" != "0" ]] && extra=(--length="$len")
72
  sudo -u "$RUN_USER" env "${ENV_ARGS[@]}" \
73
    timeout -k 3 "$limit" mpv --no-config --msg-level=all=error "${extra[@]}" "$@" \
74
    >"$log" 2>&1
75
}
76
77
run_as() {
78
  local id="$1" label="$2" limit="$3" len="$4"; shift 4
79
  local log="$LOGDIR/$id.log"
80
  local start rc dur
81
  start=$(date +%s)
82
  attempt "$log" "$limit" "$len" "$@"
83
  rc=$?
84
  dur=$(( $(date +%s) - start ))
85
86
  # Fehlschlaege einmal wiederholen: der Compositor verweigert zwischen zwei
87
  # Laeufen gelegentlich kurz die Verbindung - das ist kein echter Befund.
88
  if [[ $rc -ne 0 ]]; then
89
    sleep 3
90
    attempt "$log" "$limit" "$len" "$@"
91
    local rc2=$?
92
    if [[ $rc2 -eq 0 ]]; then
93
      RESULT[$id]=ok
94
      printf '  \033[1;32mLAEUFT\033[0m  %-46s %ss (erster Versuch einmalig gescheitert)\n' "$id  $label" "$dur"
95
      return
96
    fi
97
    rc=$rc2
98
  fi
99
100
  case $rc in
101
    0)       RESULT[$id]=ok;   ok  "$id  $label" "$dur" ;;
102
    124|137) RESULT[$id]=hang; bad "$id  $label" "$dur"; FAILED+=("$id  $label|$log") ;;
103
    *)       RESULT[$id]=err;  odd "$id  $label" "$rc";  FAILED+=("$id  $label|$log") ;;
104
  esac
105
  sleep 2
106
}
107
108
run() { run_as "$1" "$2" "$LIMIT" "$PLAYSEC" "${@:3}"; }
109
110
hdr "Vorbereitung"
111
note "Datei:    $(basename "$VIDEO")"
112
note "Benutzer: $RUN_USER (uid $RUN_UID)"
113
note "Ausgabe:  ${VO_ARGS[*]}"
114
[[ -n "$IMAGE" ]] && note "Bild:     $(basename "$IMAGE")" || note "Bild:     keines gefunden - Uebergangstest entfaellt"
115
systemctl stop tvwall 2>/dev/null && note "Dienst angehalten"
116
sleep 1
117
118
hdr "Ist die Datei ueberhaupt vollstaendig?"
119
if command -v ffmpeg >/dev/null; then
120
  FFOUT="$(ffmpeg -v error -i "$VIDEO" -f null - 2>&1)"
121
  if [[ -z "$FFOUT" ]]; then
122
    printf '  \033[1;32mIN ORDNUNG\033[0m  komplett dekodierbar\n'
123
  else
124
    printf '  \033[1;31mBESCHAEDIGT\033[0m  ffmpeg meldet beim Durchlesen:\n'
125
    echo "$FFOUT" | head -6 | sed 's/^/      /'
126
    note "-> Dann hilft kein Einstellen: die Datei bitte neu hochladen."
127
  fi
128
  note "Groesse: $(stat -c %s "$VIDEO" 2>/dev/null) Bytes, md5: $(md5sum "$VIDEO" | cut -d" " -f1)"
129
fi
130
131
hdr "Einzeldatei"
132
run 1 "nur --fullscreen (mpv-Standard)"          --fullscreen "$VIDEO"
133
run 2 "Dienst-Optionen"                          "${SERVICE_ARGS[@]}" "$VIDEO"
134
run 3 "Dienst-Optionen + --hwdec=auto-safe"      "${SERVICE_ARGS[@]}" --hwdec=auto-safe "$VIDEO"
135
run 4 "Dienst-Optionen + --no-audio"             "${SERVICE_ARGS[@]}" --no-audio "$VIDEO"
136
run 5 "Dienst-Optionen + --vo=gpu-next"          "${SERVICE_ARGS[@]/--vo=gpu/--vo=gpu-next}" "$VIDEO"
137
138
hdr "Als Playliste (so macht es der Dienst)"
139
run 6 "Playliste mit nur dem Video"              "${SERVICE_ARGS[@]}" --playlist="$TMP/nur-video.m3u"
140
if [[ -n "$IMAGE" ]]; then
141
  run 7 "Playliste Bild -> Video"                "${SERVICE_ARGS[@]}" --playlist="$TMP/bild-video.m3u"
142
  run 8 "Bild -> Video, ohne --force-window"     "${SERVICE_ARGS[@]/--force-window=yes/--force-window=no}" \
143
                                                 --playlist="$TMP/bild-video.m3u"
144
  run 9 "Bild -> Video, mit --gpu-context=auto"  "${SERVICE_ARGS[@]}" --gpu-context=auto \
145
                                                 --playlist="$TMP/bild-video.m3u"
146
  # Ohne --length, damit ausgeschlossen ist, dass diese Testoption stoert.
147
  run_as 10 "Bild -> Video, komplett bis zum Ende" 120 0 \
148
            "${SERVICE_ARGS[@]}" --playlist="$TMP/bild-video.m3u"
149
fi
150
151
hdr "Ergebnis"
152
r() { echo "${RESULT[$1]:-}"; }
153
154
if [[ ${#FAILED[@]} -gt 0 ]]; then
155
  note "Haengen geblieben:"
156
  for entry in "${FAILED[@]}"; do
157
    printf '      %s\n' "${entry%%|*}"
158
    tail -5 "${entry##*|}" 2>/dev/null | sed 's/^/          /'
159
  done
160
  echo
161
fi
162
163
note "Deutung:"
164
if [[ "$(r 1)" != "ok" ]]; then
165
  note "  Schon der nackte mpv-Aufruf haengt. Dann liegt es an der Datei oder"
166
  note "  am Grafiktreiber, nicht an den Einstellungen dieses Werkzeugs."
167
elif [[ "$(r 2)" != "ok" ]]; then
168
  note "  Der nackte Aufruf laeuft, die Dienst-Optionen nicht. Die Varianten 3-5"
169
  note "  zeigen, welche Option es ist."
170
elif [[ -n "$IMAGE" && "$(r 7)" != "ok" && "$(r 6)" == "ok" ]]; then
171
  note "  Die Einzeldatei laeuft, der Wechsel Bild -> Video nicht."
172
  if [[ "$(r 10)" == "ok" ]]; then
173
    note "  Variante 10 (ohne --length) laeuft aber durch - dann stoert nur die"
174
    note "  Testoption --length, und der Dienst selbst ist nicht betroffen."
175
  else
176
    note "  Auch ohne Testoptionen (Variante 10) scheitert es - echter Befund."
177
    note "  Meldet ffmpeg oben \"BESCHAEDIGT\", ist die Datei die Ursache."
178
  fi
179
  [[ "$(r 8)" == "ok" ]] && note "  --force-window=no behebt es -> genau das laesst sich einstellen."
180
  [[ "$(r 9)" == "ok" ]] && note "  --gpu-context=auto behebt es -> genau das laesst sich einstellen."
181
elif [[ ${#FAILED[@]} -eq 0 ]]; then
182
  note "  Keine Variante haengt. Dann liegt es nicht an mpv, sondern am"
183
  note "  Zusammenspiel mit dem Dienst - bitte 'journalctl -u tvwall -n 60' schicken."
184
fi
185
186
systemctl start tvwall 2>/dev/null
187
hdr "Dienst wieder gestartet"