Merge branch '4.0.9' of geimist/synOTR into master

This commit is contained in:
Stephan 2019-02-01 14:35:58 +00:00 committed by Gitea
commit c26df36517
9 changed files with 226 additions and 25 deletions

View file

@ -51,6 +51,7 @@ dsmtextnotify="on"
MessageTo="admin"
dsmbeepnotify="on"
LOGlevel="1"
LOGmax=""
reindex=1
#--------------------------------------------------------------------

View file

@ -28,7 +28,9 @@ if [[ "$page" == "edit-save" ]]; then
"$set_var" "$dir/app/etc/Konfiguration.txt" "dsmtextnotify" "$dsmtextnotify"
"$set_var" "$dir/app/etc/Konfiguration.txt" "MessageTo" "$MessageTo"
"$set_var" "$dir/app/etc/Konfiguration.txt" "dsmbeepnotify" "$dsmbeepnotify"
"$set_var" "$dir/app/etc/Konfiguration.txt" "PBTOKEN" "$PBTOKEN"
"$set_var" "$dir/app/etc/Konfiguration.txt" "LOGlevel" "$LOGlevel"
"$set_var" "$dir/app/etc/Konfiguration.txt" "LOGmax" "$LOGmax"
"$set_var" "$dir/app/etc/Konfiguration.txt" "endgueltigloeschen" "$endgueltigloeschen"
"$set_var" "$dir/app/etc/Konfiguration.txt" "reindex" "$reindex"
"$set_var" "$dir/app/etc/Konfiguration.txt" "cutlistat_ID" "$cutlistat_ID"
@ -86,7 +88,9 @@ if [[ "$page" == "edit-import-query" ]] || [[ "$page" == "edit-import" ]]; then
"$set_var" "$dir/app/etc/Konfiguration.txt" "dsmtextnotify" "$dsmtextnotify"
"$set_var" "$dir/app/etc/Konfiguration.txt" "MessageTo" "$MessageTo"
"$set_var" "$dir/app/etc/Konfiguration.txt" "dsmbeepnotify" "$dsmbeepnotify"
"$set_var" "$dir/app/etc/Konfiguration.txt" "PBTOKEN" "$PBTOKEN"
"$set_var" "$dir/app/etc/Konfiguration.txt" "LOGlevel" "$LOGlevel"
"$set_var" "$dir/app/etc/Konfiguration.txt" "LOGmax" "$LOGmax"
"$set_var" "$dir/app/etc/Konfiguration.txt" "endgueltigloeschen" "$endgueltigloeschen"
"$set_var" "$dir/app/etc/Konfiguration.txt" "reindex" "$reindex"
"$set_var" "$dir/app/etc/Konfiguration.txt" "cutlistat_ID" "$cutlistat_ID"
@ -607,14 +611,14 @@ if [[ "$page" == "edit" ]]; then
</p>
</details>'
# -> Abschnitt .avi's in native MP4's (MAC OS tauglich) umwandeln
# -> Abschnitt .avi's in native MP4's umwandeln
echo '<fieldset>
<hr style="border-style: dashed; size: 1px;">
<br />
<details><p>
<summary>
<span class="detailsitem">AVI-Filme in native MP4-Filme (macOS tauglich) umwandeln</span>
<span class="detailsitem">AVI-Filme in native MP4-Filme umwandeln</span>
</summary></p>
<p>'
@ -743,6 +747,22 @@ if [[ "$page" == "edit" ]]; then
<br>Auf diese Art kann man sich in Verbindung mit dem Paket "Notification Forwarder" über synOTR-Ereignisse z.B. über einen Pushdienst benachrichtigen lassen.
<br>Bleibt der Wert leer, so wird die Gruppe "administrators" benachrichtigt.
</span></a></p>'
# PushBullet-Token
echo '
<p>
<label>PushBullet-Token</label>'
if [ -n "$PBTOKEN" ]; then
echo '<input type="text" name="PBTOKEN" value="'$PBTOKEN'" />'
else
echo '<input type="text" name="PBTOKEN" value="" />'
fi
echo '
<a class="helpbox" href="#HELP">
<img src="images/icon_information_mini@geimist.svg" height="25" width="25"/>
<span>Dein persönlicher PushBullet-Token.
<br>Benachrichtigungen werden an den entsprechenden Account gesendet.
<br>Bei Nichtgebrauch leer lassen.
</span></a></p>'
# dsmbeepnotify
echo '
<p>
@ -792,6 +812,22 @@ if [[ "$page" == "edit" ]]; then
<span>0 => es wird keine Log-Datei erstellt<br>1 => normales Log (standard)<br>2 => erweitertes Log
<br>Die Logs befinden sich im Dekodierverzeichnis/_LOGsynOTR/</span></a>
</p>'
# LOGmax
echo '
<p>
<label>max. Anzahl LOGfiles</label>'
if [ -n "$LOGmax" ]; then
echo '<input type="text" name="LOGmax" value="'$LOGmax'" />'
else
echo '<input type="text" name="LOGmax" value="" />'
fi
echo '
<a class="helpbox" href="#HELP">
<img src="images/icon_information_mini@geimist.svg" height="25" width="25"/>
<span>LOG-Files können automatisch gelöscht werden, indem hier die maximal gewünschte Anzahl angegeben wird.
<br>Sobald hier ein Wert vergeben wird, werden grundsätzlich alle leeren LOGs gelöscht.
<br>(Die Anzahl bezieht sich also nur auf LOGs mit Einträgen)
</span></a></p>'
# reindex
echo '
<p>

View file

@ -16,7 +16,8 @@ echo '
<li>Um synOTR regelmäßig laufen zu lassen (was sich empfiehlt), erstelle als
nächstes <br>einen automatisierten Programmaufruf.
<div class="tab"><br>
Dazu hast du 2 Möglichkeiten:<br>verwende den <a href="index.cgi?page=timer" style="'$synotrred';">Zeitplaner</a> für einen programmierten synOTR-Start.</p><hr>
Dazu hast du 2 Möglichkeiten:<br>verwende den <a href="index.cgi?page=timer" style="'$synotrred';">Zeitplaner</a> für einen programmierten synOTR-Start.
<br><br>Hierbei ist zu beachten, dass der DSM-Sicherheitsbereater den Zusätzlichen Croneintrag (da für DSM unbekannt) bemängelt!</p><hr>
<p>Oder, erstelle alternativ im Aufgabenplaner einen neuen Task mit diesem
Programmpfad<br>(zu empfehlen, sofern du kürzere Intervalle als "stündlich" benötigst):</p>
<p style="margin-left: 40px;"><code>/usr/syno/synoman/webman/3rdparty/synOTR/synOTR-start.sh</code></p>

View file

@ -85,17 +85,11 @@ func_main_LastLog () {
# Dateistatus auslesen:
# ---------------------------------------------------------------------
# .otrkey-Files:
count_otrkey=0
for i in $(find "$OTRkeydir" -maxdepth 1 -name "*.otrkey" -type f)
do
count_otrkey=$(( count_otrkey + 1 ))
done
count_otrkey=$( ls -t "${OTRkeydir}" | egrep -o '.*.otrkey$' | wc -l ) # wie viele Dateien
# wait of cutlist:
count_waitofcutlist=0
for i in $(find "$DECODIR" -maxdepth 1 -name "*.avi" -o -name "*.mp4" -type f)
do
count_waitofcutlist=$(( count_waitofcutlist + 1 ))
done
count_waitofcutlist=$( expr $( ls -t "${DECODIR}" | egrep -o '.*.avi$' | wc -l ) + $( ls -t "${DECODIR}" | egrep -o '.*.mp4$' | wc -l ) ) # wie viele Dateien
# manueller synOTR-Start:
# ---------------------------------------------------------------------

View file

@ -8,8 +8,8 @@
echo " -----------------------------------"
echo -e
CLIENTVERSION="4.0.8" # [2018-12-17]
DevChannel="Release" # beta
CLIENTVERSION=`get_key_value /var/packages/synOTR/INFO version`
DevChannel="Release" # beta [2019-01-07]
# ---------------------------------------------------------------------------------
# GRUNDKONFIGRUATIONEN / INDIVIDUELLE ANPASSUNGEN / Standardwerte |
@ -685,6 +685,18 @@ if [ $decoderactiv = "on" ] && [ ! -z "$filetest" ] ; then
echo 2 > /dev/ttyS1 #short beep
sleep 1
fi
if [ ! -z $PBTOKEN ] ; then
PB_LOG=`curl $cURLloglevel --header "Access-Token:${PBTOKEN}" https://api.pushbullet.com/v2/pushes -d type=note -d title="synOTR" -d body="Film [$filename] ist fertig."`
if [ $LOGlevel = "2" ] ; then
echo " PushBullet-LOG:"
echo "$PB_LOG"
elif echo "$PB_LOG" | grep -q "error"; then # für Loglevel 1 nur Errorausgabe
echo -n " PushBullet-Error: "
echo "$PB_LOG" | jq -r '.error_code'
fi
else
echo " (PushBullet-TOKEN nicht gesetzt)"
fi
wget --timeout=30 --tries=2 -q -O - "http://${synotrdomain}/synOTR/synOTR_FILECOUNT" >/dev/null 2>&1
needindex=1
fi
@ -1577,6 +1589,18 @@ if [ $OTRcutactiv = "on" ] ; then
if [ $dsmbeepnotify = "on" ] ; then
echo 2 > /dev/ttyS1 #short beep
fi
if [ ! -z $PBTOKEN ] ; then
PB_LOG=`curl $cURLloglevel --header "Access-Token:${PBTOKEN}" https://api.pushbullet.com/v2/pushes -d type=note -d title="synOTR" -d body="Film [$filedestname] ist fertig."`
if [ $LOGlevel = "2" ] ; then
echo " PushBullet-LOG:"
echo "$PB_LOG"
elif echo "$PB_LOG" | grep -q "error"; then # für Loglevel 1 nur Errorausgabe
echo -n " PushBullet-Error: "
echo "$PB_LOG" | jq -r '.error_code'
fi
else
echo " (PushBullet-TOKEN nicht gesetzt)"
fi
wget --timeout=30 --tries=2 -q -O - "http://${synotrdomain}/synOTR/synOTR_FILECOUNT" >/dev/null 2>&1
needindex=1
fi
@ -1749,7 +1773,7 @@ if [ $OTRcutactiv = "on" ] ; then
if [ $dsmtextnotify = "on" ] ; then
title=${filename%.*}
sleep 1
synodsmnotify $MessageTo "synOTR" "[$title] ist fertig"
synodsmnotify $MessageTo "synOTR" "Film [$title] ist fertig"
sleep 1
fi
if [ $dsmbeepnotify = "on" ] ; then
@ -1757,6 +1781,18 @@ if [ $OTRcutactiv = "on" ] ; then
echo 2 > /dev/ttyS1 #short beep
sleep 1
fi
if [ ! -z $PBTOKEN ] ; then
PB_LOG=`curl $cURLloglevel --header "Access-Token:${PBTOKEN}" https://api.pushbullet.com/v2/pushes -d type=note -d title="synOTR" -d body="Film [$title] ist fertig."`
if [ $LOGlevel = "2" ] ; then
echo " PushBullet-LOG:"
echo "$PB_LOG"
elif echo "$PB_LOG" | grep -q "error"; then # für Loglevel 1 nur Errorausgabe
echo -n " PushBullet-Error: "
echo "$PB_LOG" | jq -r '.error_code'
fi
else
echo " (PushBullet-TOKEN nicht gesetzt)"
fi
wget --timeout=30 --tries=2 -q -O - "http://${synotrdomain}/synOTR/synOTR_FILECOUNT" >/dev/null 2>&1
needindex=1
fi
@ -1880,7 +1916,7 @@ if [ $OTRavi2mp4active = "on" ] && [ ! -z "$filetest" ] ; then
fi
elif $(echo "$encoders" | grep -q "AAC (Advanced Audio Coding)" ) ; then # Native FFmpeg AAC encoder
echo "Erkannter Encoder: nativ (ffmpeg > 3.0) [2.Wahl]"
if [ $normalizeAudio = "on_" ] ; then
if [ $normalizeAudio = "on" ] ; then
# ------- Audio normalisieren:
volumeinfo=$(ffmpeg -i "$audiofile" -af "volumedetect" -f null - 2>&1 | awk '-F: ' '/max_volume/ { gsub(/ .*/, "", $2); print $2 }' | sed 's/-//g') # |grep max_volume | awk -F: '{ print $2 }' | sed 's/ dB//g' | sed 's/ -//g')
echo "Lautstärkeanhebung um: $volumeinfo dB"
@ -1969,7 +2005,7 @@ if [ $OTRavi2mp4active = "on" ] && [ ! -z "$filetest" ] ; then
synoindex -a "${pfad}${title}.mp4"
if [ $dsmtextnotify = "on" ] ; then
sleep 1
synodsmnotify $MessageTo "synOTR" "[$title] ist fertig"
synodsmnotify $MessageTo "synOTR" "Film [$title] ist fertig"
sleep 1
fi
if [ $dsmbeepnotify = "on" ] ; then
@ -1977,6 +2013,18 @@ if [ $OTRavi2mp4active = "on" ] && [ ! -z "$filetest" ] ; then
echo 2 > /dev/ttyS1 #short beep
sleep 1
fi
if [ ! -z $PBTOKEN ] ; then
PB_LOG=`curl $cURLloglevel --header "Access-Token:${PBTOKEN}" https://api.pushbullet.com/v2/pushes -d type=note -d title="synOTR" -d body="Film [$title] ist fertig."`
if [ $LOGlevel = "2" ] ; then
echo " PushBullet-LOG:"
echo "$PB_LOG"
elif echo "$PB_LOG" | grep -q "error"; then # für Loglevel 1 nur Errorausgabe
echo -n " PushBullet-Error: "
echo "$PB_LOG" | jq -r '.error_code'
fi
else
echo " (PushBullet-TOKEN nicht gesetzt)"
fi
wget --timeout=30 --tries=2 -q -O - "http://${synotrdomain}/synOTR/synOTR_FILECOUNT" >/dev/null 2>&1
needindex=1
fi
@ -2285,7 +2333,7 @@ for i in $(find "$WORKDIR" -maxdepth 1 -name "*TVOON*avi" -o -name "*TVOON*mp4"
synoindex -a "${WORKDIR}${NewName}"
if [ $dsmtextnotify = "on" ] ; then
sleep 1
synodsmnotify $MessageTo "synOTR" "[$title] ist fertig"
synodsmnotify $MessageTo "synOTR" "Film [$title] ist fertig"
sleep 1
fi
if [ $dsmbeepnotify = "on" ] ; then
@ -2293,6 +2341,18 @@ for i in $(find "$WORKDIR" -maxdepth 1 -name "*TVOON*avi" -o -name "*TVOON*mp4"
echo 2 > /dev/ttyS1 #short beep
sleep 1
fi
if [ ! -z $PBTOKEN ] ; then
PB_LOG=`curl --header "Access-Token:${PBTOKEN}" https://api.pushbullet.com/v2/pushes -d type=note -d title="synOTR" -d body="Filme [$film] ist fertig."`
if [ $LOGlevel = "2" ] ; then
echo "PushBullet-LOG:"
echo "$PB_LOG"
elif echo "$PB_LOG" | grep -q "error"; then # für Loglevel 1 nur Errorausgabe
echo -n "PushBullet-Error: "
echo "$PB_LOG" | jq -r '.error_code'
fi
else
echo "PushBullet-TOKEN nicht erkannt"
fi
wget --timeout=30 --tries=2 -q -O - "http://${synotrdomain}/synOTR/synOTR_FILECOUNT" >/dev/null 2>&1
needindex=1
fi
@ -2404,7 +2464,7 @@ if [ $OTRrenameactiv = "on" ] && [ $firstrunonday == "1" ] ; then
if jq -e . >/dev/null 2>&1 <<<"$serieninfo"; then # prüfen, ob korrektes JSON-Format verarbeitet werden kann (https://stackoverflow.com/questions/46954692/check-if-string-is-a-valid-json-with-jq)
echo -e "gefunden:"
echo "OTRID: $OTRID"
serietitle=`echo "$serieninfo" | jq -r '.Serie' | sed "s/://g" ` # jq ist ein Kommandozeilen-JSON-Parser
serietitle=`echo "$serieninfo" | jq -r '.Serie' | sed "s/://g" `
echo "serietitle: $serietitle"
season=`echo "$serieninfo" | awk -F, '{print $3}' | awk -F: '{print $2}' | sed "s/\"//g"`
season="$(printf '%02d' "$season")" # 2stellig mit führender Null
@ -2513,7 +2573,7 @@ if [ $OTRrenameactiv = "on" ] && [ $firstrunonday == "1" ] ; then
if [ $dsmtextnotify = "on" ] ; then
sleep 1
synodsmnotify $MessageTo "synOTR" "[$title] ist fertig"
synodsmnotify $MessageTo "synOTR" "Film [$title] ist fertig"
sleep 1
fi
if [ $dsmbeepnotify = "on" ] ; then
@ -2712,7 +2772,7 @@ if [ $useWORKDIR == "yes" ] && [ ! -z "$filetest" ]; then
if [ $dsmtextnotify = "on" ] ; then
sleep 1
synodsmnotify $MessageTo "synOTR" "[$filename] ist fertig"
synodsmnotify $MessageTo "synOTR" "Film [$filename] ist fertig"
sleep 1
fi
if [ $dsmbeepnotify = "on" ] ; then
@ -2720,6 +2780,18 @@ if [ $useWORKDIR == "yes" ] && [ ! -z "$filetest" ]; then
echo 2 > /dev/ttyS1 #short beep
sleep 1
fi
if [ ! -z $PBTOKEN ] ; then
PB_LOG=`curl $cURLloglevel --header "Access-Token:${PBTOKEN}" https://api.pushbullet.com/v2/pushes -d type=note -d title="synOTR" -d body="Film [$filename] ist fertig."`
if [ $LOGlevel = "2" ] ; then
echo " PushBullet-LOG:"
echo "$PB_LOG"
elif echo "$PB_LOG" | grep -q "error"; then # für Loglevel 1 nur Errorausgabe
echo -n " PushBullet-Error: "
echo "$PB_LOG" | jq -r '.error_code'
fi
else
echo " (PushBullet-TOKEN nicht gesetzt)"
fi
wget --timeout=30 --tries=2 -q -O - "http://${synotrdomain}/synOTR/synOTR_FILECOUNT" >/dev/null 2>&1
needindex=1
@ -2744,7 +2816,7 @@ if [ $useWORKDIR == "yes" ] && [ ! -z "$filetest" ]; then
if [ $dsmtextnotify = "on" ] ; then
sleep 1
synodsmnotify $MessageTo "synOTR" "[$filename] ist fertig"
synodsmnotify $MessageTo "synOTR" "Film [$filename] ist fertig"
sleep 1
fi
if [ $dsmbeepnotify = "on" ] ; then
@ -2752,6 +2824,18 @@ if [ $useWORKDIR == "yes" ] && [ ! -z "$filetest" ]; then
echo 2 > /dev/ttyS1 #short beep
sleep 1
fi
if [ ! -z $PBTOKEN ] ; then
PB_LOG=`curl $cURLloglevel --header "Access-Token:${PBTOKEN}" https://api.pushbullet.com/v2/pushes -d type=note -d title="synOTR" -d body="Film [$filename] ist fertig."`
if [ $LOGlevel = "2" ] ; then
echo " PushBullet-LOG:"
echo "$PB_LOG"
elif echo "$PB_LOG" | grep -q "error"; then # für Loglevel 1 nur Errorausgabe
echo -n " PushBullet-Error: "
echo "$PB_LOG" | jq -r '.error_code'
fi
else
echo " (PushBullet-TOKEN nicht gesetzt)"
fi
wget --timeout=30 --tries=2 -q -O - "http://${synotrdomain}/synOTR/synOTR_FILECOUNT" >/dev/null 2>&1
needindex=1
else
@ -2781,6 +2865,73 @@ if [ -f "/usr/syno/bin/synoindex" ] && [ $firstrunonday == "1" ] && [ $reindex =
fi
}
PURGELOG()
{
#########################################################################################
# Diese Funktion löscht zu erst alle leeren Logs und anschließend die überzähligen #
#########################################################################################
if [ -z $LOGmax ]; then
return
fi
logdir="${DECODIR}/_LOGsynOTR/"
# leere Logs löschen:
for i in `ls -tr "${logdir}" | egrep -o '^synOTR.*.log$' ` # Auflistung aller LOG-Dateien
do
if [ $( cat "${logdir}$i" | tail -n7 | head -n4 | wc -c ) -le 15 ] && cat "${logdir}$i" | grep -q "synOTR ENDE" ; then
if [ $endgueltigloeschen = "on" ] ; then
rm "${logdir}$i"
else
mv "${logdir}$i" "$OTRkeydeldir"
fi
fi
done
# überzählige Logs löschen:
count2del=$( expr $( ls -t "${logdir}" | egrep -o '^synOTR.*.log$' | wc -l ) - $LOGmax ) # wie viele Dateien sind überzählig
if [ $count2del -ge 0 ]; then
for i in `ls -tr "${logdir}" | egrep -o '^synOTR.*.log$' | head -n${count2del} `
do
if [ $endgueltigloeschen = "on" ] ; then
rm "${logdir}$i"
else
mv "${logdir}$i" "$OTRkeydeldir"
fi
done
fi
# überzählige searches löschen:
count2del=$( expr $(ls -t "${logdir}" | egrep -o '^search.*.xml$' | wc -l) - $LOGmax )
if [ ${count2del} -ge 0 ]; then
for i in `ls -tr "${logdir}" | egrep -o '^search.*.xml$' | head -n${count2del} `
do
if [ $endgueltigloeschen = "on" ] ; then
rm "${logdir}$i"
else
mv "${logdir}$i" "$OTRkeydeldir"
fi
done
fi
# überzählige cutlists löschen:
count2del=$( expr $(ls -t "${logdir}" | egrep -o '.*.cutlist$' | wc -l) - $LOGmax )
if [ ${count2del} -ge 0 ]; then
for i in `ls -tr "${logdir}" | egrep -o '.*.cutlist$' | head -n${count2del} `
do
if [ $endgueltigloeschen = "on" ] ; then
rm "${logdir}$i"
else
mv "${logdir}$i" "$OTRkeydeldir"
fi
done
fi
}
# _______________________________________________________________________________
# | |
# | AUFRUF DER FUNKTIONEN |
@ -2799,6 +2950,7 @@ fi
OTRopenrename
MOVE2DESTDIR
FRESHUPMEDIAINDEX
PURGELOG
echo -e; echo -e

View file

@ -28,9 +28,15 @@
if ! cat ./$CONFIG | grep -q "dsmbeepnotify" ; then
echo "dsmbeepnotify=\"on\"" >> ./$CONFIG
fi
if ! cat ./$CONFIG | grep -q "PBTOKEN" ; then
echo "PBTOKEN=\"\"" >> ./$CONFIG
fi
if ! cat ./$CONFIG | grep -q "LOGlevel" ; then
echo "LOGlevel=\"1\"" >> ./$CONFIG
fi
if ! cat ./$CONFIG | grep -q "LOGmax" ; then
echo "LOGmax=\"1\"" >> ./$CONFIG
fi
if ! cat ./$CONFIG | grep -q "reindex" ; then
echo "reindex=\"1\"" >> ./$CONFIG
fi

View file

@ -49,8 +49,10 @@ MP4BOX_DELAY="100"
#--------------------------------------------------------------------
dsmtextnotify="on"
MessageTo="admin"
PBTOKEN=""
dsmbeepnotify="on"
LOGlevel="1"
LOGmax=""
reindex=1
#--------------------------------------------------------------------

View file

@ -1,4 +1,13 @@
Release Notes
Release Notes
4.1.0 (RELEASE)
IMPLEMENTIERUNGEN:
- PushBullet integriert. Dazu muss lediglich der persönliche Token in der Konfiguration hinterlegt werden
- Die max. Anzahl von LOGs kann nun begrenzt werden. Dadurch werden zu erst alle leeren Logs und anschließend die überzähligen gelöscht
BUGFIXES:
- es wurde ein Fehler behoben, dass bei aktivem nativen aac-Encoder keine Normalisierung der Tonspur möglich war
- Detailänderungen in der GUI
- Detailänderungen der Benachrichtigungstexte
4.0.8 (RELEASE)
BUGFIXES:

View file

@ -1,6 +1,6 @@
package="synOTR"
displayname="synOTR"
version="4.0.8"
version="4.0.9"
thirdparty="yes"
description="SynOTR liefert einen Workflow für TV-Aufnahmen von onlineTVrecorder (OTR) auf Synology NAS. synOTR übernimmt *decodieren *AC3-muxing (BETA) *schneiden *MP4-Konvertierung und *umbenennung (inkl. Serieninformationen von www.thetvdb.com und www.otr-serien.de). onlineTVrecorder (OTR) ist der freie Videorecorder im Internet, der rund um die Uhr fast alle Sendungen von rund 100 TV-Sender aus Deutschland, USA, UK und anderen Lädern aufnimmt."
maintainer="geimist"