Open danielk117 opened 5 years ago
Hallo Daniel,
es ist an sich eine interessante Idee, allerdings ist es eher eine Linux-/Netzwerk-Frage und da kenne ich mich nicht so gut aus. Zudem sind mehrere LANs eher für Link Aggregation gedacht, das ist wieder eine andere Geschichte... Was ich aber gerade gelesen habe, sieht in etwa so aus:
Die Regel, welches Netzwerkadapter verwendet wird (route), kann nur in Linux direkt eingestellt werden; https://superuser.com/questions/1355077/ffmpeg-choose-outbound-ip-eth0-or-eth1 Das sehe dann in etwa so aus:
root@DiskStation:~# route
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
IP1 0.0.0.0 255.255.255.0 U 0 0 0 eth0
IP2 0.0.0.0 255.255.255.0 U 0 0 0 eth1
Diese Route muss aber eigentlich an die Empfänger-Adresse (IP1/IP2) geknüpft werden. Ob man dem Repeater zwei Adressen beibringen kann, wage ich jedoch zu bezweifeln.
Weitere wage Ideen:
Also nach einer Stunde Recherche fand ich leider nichts, was ich umsetzen oder gar testen könnte. Wenn Du weiterführende Ideen hast, melde Dich gern wieder.
Gruß Pav
Hallo Pavion,
danke für deine Ideen, die Docker-Variante wäre mein letzter Ausweg.
Ich habe bereits zwei Möglichkeit erfolgreich testen können. Allerdings gelingt mir in beiden Fällen immer nur der direkte Aufruf von ffmpeg
über die Kommandozeile.
Variante 1
https://superuser.com/questions/241178/how-to-use-different-network-interfaces-for-different-processes
Über netns
einen Interface-Namespace erzeugen, in welchem dann ein ffmpeg-Prozess läuft.
sudo ip netns add eth1_ns
sudo ip link set eth1 netns eth1_ns
sudo ip netns exec eth1_ns sudo ifconfig eth1 10.1.1.10/24 up
sudo ip netns exec eth1_ns sudo ifconfig lo 127.0.0.1/8 up
sudo ip netns exec eth1_ns sudo route add default gw 10.1.1.1
sudo ip netns exec eth1_ns sudo dhclient eth1
sudo ip netns exec eth1_ns sudo /volume1/@appstore/VideoStation/bin/ffmpeg XXXXXXXXXX
Funktioniert, wenn komplett über die Kommandozeile ausgeführt. Anschließend: Alle Schritte bis zum dhclient habe ich direkt über die Kommandozeile gemacht. Den letzten Punkt wollte ich dann über tvstreamrecord starten. Egal ob in der tvstreamrecord.py oder über die Config (ffmpeg-Pfad), ich bekomme immer Meldungen:
2019-02-09 15:15:44.754 | FFMPEG could not be started. Error: [Errno 2] No such file or directory
2019-02-09 15:15:44.745 | [u'sudo ip netns exec eth1_ns sudo /volume1/@appstore/VideoStation/bin/ffmpeg', u'-i', 'rtsp://192.168.170.43:554/?avm=1&freq=346&bw=8&msys=dvbc&mtype=64qam&sr=6900&specinv=1&pids=0,16,17,18,20,1400,1401,1402,1403,1404,1406,1405,1470,1476,2171', u'-y', u'-t', u'675', u'-loglevel', u'fatal', u'-acodec', u'copy', u'-vcodec', u'copy', u'/volume2/Aufnahme/20190209151544 - dasbloghaus_tv___Grafitti_for_Love.ts']
Variante 2
https://daniel-lange.com/archives/53-Binding-applications-to-a-specific-IP.html
IP-Adresse des anderen Interfaces angeben und über das bind.so
-Skript ausführen.
BIND_ADDR="192.168.170.45" LD_PRELOAD=/usr/lib/bind.so sudo /volume1/@appstore/VideoStation/bin/ffmpeg XXXXXXXXXXXXX
Auch das funktioniert problemlos über Kommandozeile. Doch dann die selben Probleme wie oben. Über tvstreamrecord geht nix...
2019-02-09 18:18:47.514 | FFMPEG could not be started. Error: [Errno 2] No such file or directory
2019-02-09 18:18:47.506 | [u'BIND_ADDR="192.168.170.45" LD_PRELOAD=/usr/lib/bind.so /volume1/@appstore/VideoStation/bin/ffmpeg', u'-i', 'rtsp://192.168.170.43:554/?avm=1&freq=314&bw=8&msys=dvbc&mtype=64qam&sr=6900&specinv=1&pids=0,16,17,18,20,200,210,220,221,225,222,230,231,250', u'-y', u'-t', u'2592', u'-loglevel', u'fatal', u'-acodec', u'copy', u'-vcodec', u'copy', u'/volume2/Aufnahme/20190209181847 - Bl_tentr_ume.ts']
Es scheint sich um irgendein Rechte-Problem zu handeln. Kannst du vielleicht weiterhelfen?
VG Daniel
Nein. Nur die Leerzeichen im Befehl werden falsch interpretiert. Wenn Du ihn in eine .sh packst, sollte es funktionieren. Schaue ich mir morgen genauer an.
Die Idee hatte ich auch schon...
Variante 3
Ein Skript welches ich in der Config als Pfad zu ffmpeg
angebe.
Kompletter Pfad für ffmpeg sh /volume1/@appstore/VideoStation/bin/ffmpegbinder.sh
Das Skript wiederum startet ffmpeg
in der bind
-Variante:
#!/bin/sh
str="'$*'"
BIND_ADDR="192.168.170.45" LD_PRELOAD=/usr/lib/bind.so /volume1/@appstore/VideoStation/bin/ffmpeg "$str"
Und was soll ich sagen, das Resultat bleibt leider das selbe:
2019-02-09 18:43:14.081 | FFMPEG could not be started. Error: [Errno 2] No such file or directory
2019-02-09 18:43:14.073 | [u'sh /volume1/homes/admin/ffmpegbinder.sh', u'-i', 'rtsp://192.168.170.43:554/?avm=1&freq=314&bw=8&msys=dvbc&mtype=64qam&sr=6900&specinv=1&pids=0,16,17,18,20,200,210,220,221,225,222,230,231,250', u'-y', u'-t', u'1125', u'-loglevel', u'fatal', u'-acodec', u'copy', u'-vcodec', u'copy', u'/volume2/Aufnahme/20190209184314 - Bl_tentr_ume.ts']
Welche Leerzeichen meinst du?
Leerzeichen zwischen sh und /volume1 Vielleicht ./xxx.sh?
Leerzeichen war ein gutes Stichwort...
Folgendes hab ich an der tvstreamrecord.py
angepasst:
attr = [config.cfg_ffmpeg_path,"-i", ('"'+self.url+'"'), '-y', '-t', deltasec] + ffargs + [('"'+fn+'"')]
attr = " ".join(attr)
und
self.process = subprocess.Popen(attr, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
In der Config als ffmpeg
-Pfad:
BIND_ADDR="192.168.170.45" LD_PRELOAD=/usr/lib/bind.so /volume1/@appstore/VideoStation/bin/ffmpeg
Uns siehe da...
2019-02-10 00:04:26.290 | Record: Stopflag for 'Sportschau' received
2019-02-10 00:03:18.580 | FFMPEG (rtsp) record 'Sportschau' called with:
2019-02-10 00:03:18.580 | BIND_ADDR="192.168.170.45" LD_PRELOAD=/usr/lib/bind.so /volume1/@appstore/VideoStation/bin/ffmpeg -i "rtsp://192.168.170.43:554/?avm=1&freq=306&bw=8&msys=dvbc&mtype=64qam&sr=6900&specinv=1&pids=0,16,17,18,20,100,101,102,103,104,106,84,105,1176,2070,2171" -y -t 821 -loglevel fatal -acodec copy -vcodec copy "/volume2/Aufnahme/20190210000318 - Sportschau.ts"
Und in der Fritz steht auch tatsächlich die 192.168.170.45 (mein eth1
) als zugreifende IP da... Ich werde das morgen noch ein wenig erweitern und dynamisch machen. Immerhin will ich diesen Modus ja nur für eine zeitgleiche Aufnahme.
Theoretisch könnte man diese Methode auch für virtuelle Ethernet-Interfaces nutzen. Man bräuchte also nicht zwingend zusätzliche echte Interfaces... Gut für FritzBoxen mit 4 Tunern. Mein Repeater hat leider nur 2 ;-)
So, neue Erkenntnisse und Probleme...
Änderungen an der tvstreamrecord.py
wie in meinem letzten Kommentar.
In der Config als ffmpeg
-Pfad:
sh /volume1/@appstore/VideoStation/bin/ffmpegbinder.sh
Mein ffmpegbinder.sh
-Skript sieht so aus:
#!/bin/sh
for i in "192.168.170.21" "192.168.170.45"
do
runningfile="/volume1/@appstore/tvstreamrecord/running_$i.run"
if [ -f $runningfile ]; then
echo "file $runningfile exists"
else
echo "file $runningfile not exists"
echo "running now">$runningfile
echo "using bind adress $i"
BIND_ADDR="$i" LD_PRELOAD=/usr/lib/bind.so /volume1/@appstore/VideoStation/bin/ffmpeg "$@"
rm -- "$runningfile"
break
fi
done
Zeitgleiche Aufnahmen funktionieren einwandfrei. Aber das Beenden von Aufnahmen klappt nicht... :-(
Anscheinend wird das Skript wegen shell=True
nicht als Child-Prozess, sondern als eigener Prozess ausgeführt. Somit greifen terminate()
oder kill()
nicht.
So, jetzt bin ich wach und wieder am PC :)
Ich sehe, Du hast schon sehr viel Arbeit erledigt und sogar die richtige Stelle in meinem Code gefunden! Leider kann ich nicht wirklich viel davon testen, da ich nicht mal einen Tuner mehr habe, daher bleibe ich erstmal bei Theorie und freue mich auf eine Diskussion.
Durch die Verwendung von shell=True wird die Anwendung noch unsicherer, da damit absolut alle möglichen Befehle mit maximalen Admin-Rechten auf DS ausgeführt werden könnten... Dabei gibt es sogar Leute, die das Tool ohne Passwort im Internet freigeben oO
Eigentlich würde ich, wenn, den Pfad zuerst splitten und auf shell=True verzichten:
attr = shlex.split(config.cfg_ffmpeg_path) + ["-i", self.url, '-y', '-t', deltasec] + ffargs + [fn]
Bin mir aber nicht sicher, ob es mit Deinem Befehl funktioniert. Vielleicht könntest Du das testen? Würde es funktionieren, wenn Dein Befehl in einer .sh stünde?
Was die Implementierung der Schaltung angeht, fallen mir zwei Wege ein:
1. Über eine .sh
Eine Umschaltung in einer .sh realisieren (sorry für mein Linux, ist nicht meine Muttersprache ^^):
if [ -f "flag1" ]
then
touch flag2
BIND2
rm flag2
else
touch flag1
BIND1
rm flag1
fi
Wenn Du Dich darin auskennst, könnte ich mir vorstellen, dass so etwas auf mehr Interfaces erweitert und parametrisiert werden könnte. Ggf. könnte man die vorher erforderliche Einrichtung ebenfalls in die gleiche Datei packen und irgendwie nur bei Bedarf (oder erstem Start) ausführen. Das Ziel wäre eine Art Mega-Script, den ein Bediener auf DS downloaden, [ggf. geringfügig anpassen], seinen Pfad in TSR eintragen und sofort nutzen kann. Oder ist es zu viel gehofft?!
2. über TSR
Einführung und Verarbeitung eines neuen Parameters analog zu "Alternate URL": https://github.com/Pavion/tvstreamrecord/blob/f5d7d1bb0973b2d06986f16bd0f3a3a9caf279cc/tvstreamrecord.py#L1122 Vorteil: bequem anzupassen Nachteil: dadurch, dass dennoch einiges auf Linux-Ebene gemacht wird, ist der Vorteil geringer, dafür aber mehr Code und Optionen. Nicht dass ich die Arbeit von mir schieben würde ^^
Ich habe schon seit einer Stunde an meiner Nachricht geschrieben und wurde gerade fertig, als Du Deine abgeschickt hast...
Ich sehe, wir kamen auf ähnliche Ideen... Du hast schon den Script und ich habe vielleicht die Lösung für Dein Shell-Problem 🙂
Sehr gut, fast gleichzeitig geantwortet :D
Ich würde deine split
-Methode mal testen und shell=True
weglassen.
Also split
-Methode ohne shell=True
und als ffmpeg
-Pfad sh /volume1/@appstore/VideoStation/bin/ffmpegbinder.sh
funktioniert:
2019-02-10 10:39:05.105 | Record: Stopflag for 'NZZ Standpunkte - Die Hydra hebt ihr Haupt - der neue Judenhass' received
2019-02-10 10:38:45.247 | Record: Stopflag for 'Pauline am Strand' received
2019-02-10 10:37:36.328 | FFMPEG (rtsp) record 'Pauline am Strand' called with:
2019-02-10 10:37:36.328 | ['sh', '/volume1/@appstore/VideoStation/bin/ffmpegbinder.sh', u'-i', 'rtsp://192.168.170.43:554/?avm=1&freq=362&bw=8&msys=dvbc&mtype=64qam&sr=6900&specinv=1&pids=0,16,17,18,20,400,401,402,403,407,408,404,470,1276,2171', u'-y', u'-t', u'2063', u'-loglevel', u'fatal', u'-acodec', u'copy', u'-vcodec', u'copy', u'/volume2/Aufnahme/20190210103736 - Pauline_am_Strand.ts']
2019-02-10 10:37:36.326 | total records: 2 // running records: 2
2019-02-10 10:36:49.971 | FFMPEG (rtsp) record 'NZZ Standpunkte - Die Hydra hebt ihr Haupt - der neue Judenhass' called with:
2019-02-10 10:36:49.971 | ['sh', '/volume1/@appstore/VideoStation/bin/ffmpegbinder.sh', u'-i', 'rtsp://192.168.170.43:554/?avm=1&freq=314&bw=8&msys=dvbc&mtype=64qam&sr=6900&specinv=1&pids=0,16,17,18,20,200,210,220,221,225,222,230,231,250', u'-y', u'-t', u'1510', u'-loglevel', u'fatal', u'-acodec', u'copy', u'-vcodec', u'copy', u'/volume2/Aufnahme/20190210103649 - NZZ_Standpunkte___Die_Hydra_hebt_ihr_Haupt___der_neue_Judenhass.ts']
2019-02-10 10:36:49.969 | total records: 1 // running records: 1
Beenden funktioniert allerdings trotzdem nicht...
Hm. Ich nutze ja terminate(), da sollte nix mehr laufen. Kann es sein, dass Dein Script durch sh im separaten Thread gestartet wird? Geht es nicht mit ./ffmpegbinder.sh?
Ich vermute auch das mein Skript nicht als Kind-Prozess läuft. Mal gucken warum das so ist...
Also, das Skript wird als Kind ausgeführt...
$ sudo pstree -p
├─python(26950)─┬─sh(12510)───ffmpeg(12512)
│ ├─{python}(26960)
│ ├─{python}(26961)
│ ├─{python}(26962)
│ ├─{python}(26963)
│ ├─{python}(26964)
│ ├─{python}(26965)
│ ├─{python}(26966)
│ ├─{python}(26967)
│ ├─{python}(26968)
│ ├─{python}(26969)
│ ├─{python}(1998)
│ ├─{python}(12509)
│ └─{python}(12511)
$ sudo ps -ef | grep ffmpeg && sudo ps -ef | grep python
root 26950 1 0 10:35 ? 00:00:24 python tvstreamrecord.py
root 12510 26950 0 13:14 ? 00:00:00 sh /volume1/@appstore/VideoStation/bin/ffmpegbinder.sh -i rtsp://192.168.170.43:554/?avm=1&freq=306&bw=8&msys=dvbc&mtype=64qam&sr=6900&specinv=1&pids=0,16,17,18,20,100,101,102,103,104,106,84,105,1176,2070,2171 -y -t 18169 -loglevel fatal -acodec copy -vcodec copy /volume2/Aufnahme/20190210131410 - Sportschau.ts
root 12512 12510 2 13:14 ? 00:00:09 /volume1/@appstore/VideoStation/bin/ffmpeg -i rtsp://192.168.170.43:554/?avm=1&freq=306&bw=8&msys=dvbc&mtype=64qam&sr=6900&specinv=1&pids=0,16,17,18,20,100,101,102,103,104,106,84,105,1176,2070,2171 -y -t 18169 -loglevel fatal -acodec copy -vcodec copy /volume2/Aufnahme/20190210131410 - Sportschau.ts
Nach dem Beenden der Aufnahmen über tvstreamrecord ist nur noch der ffmpeg
-Prozess da. Somit wird das Bash-Skript anscheinend korrekt beendet.
root 20015 1 3 13:33 ? 00:00:01 /volume1/@appstore/VideoStation/bin/ffmpeg -i rtsp://192.168.170.43:554/?avm=1&freq=306&bw=8&msys=dvbc&mtype=64qam&sr=6900&specinv=1&pids=0,16,17,18,20,100,101,102,103,104,106,84,105,1176,2070,2171 -y -t 17011 -loglevel fatal -acodec copy -vcodec copy /volume2/Aufnahme/20190210133328 - Sportschau.ts
aber muss man wirklich sh
vorschreiben und extra shell erzeugen?
Mein .terminate() sendet SIGTERM nur an parent: https://unix.stackexchange.com/questions/146756/forward-sigterm-to-child-in-bash Wenn es ohne .sh nicht funktioniert, könnte das die Lösung sein.
So, funktioniert auch ohne sh
:
2019-02-10 13:59:13.147 | ['/volume1/@appstore/VideoStation/bin/ffmpegbinder.sh', u'-i', 'rtsp://192.168.170.43:554/?avm=1&freq=306&bw=8&msys=dvbc&mtype=64qam&sr=6900&specinv=1&pids=0,16,17,18,20,100,101,102,103,104,106,84,105,1176,2070,2171', u'-y', u'-t', u'15466', u'-loglevel', u'fatal', u'-acodec', u'copy', u'-vcodec', u'copy', u'/volume2/Aufnahme/20190210135913 - Sportschau.ts']
2019-02-10 13:59:13.146 | FFMPEG (rtsp) record 'Sportschau' called with:
$ sudo ps -ef | grep ffmpeg
root 19994 1 0 13:33 ? 00:00:08 python tvstreamrecord.py
root 30193 19994 0 13:59 ? 00:00:00 /bin/sh /volume1/@appstore/VideoStation/bin/ffmpegbinder.sh -i rtsp://192.168.170.43:554/?avm=1&freq=306&bw=8&msys=dvbc&mtype=64qam&sr=6900&specinv=1&pids=0,16,17,18,20,100,101,102,103,104,106,84,105,1176,2070,2171 -y -t 15466 -loglevel fatal -acodec copy -vcodec copy /volume2/Aufnahme/20190210135913 - Sportschau.ts
root 30195 30193 3 13:59 ? 00:00:00 /volume1/@appstore/VideoStation/bin/ffmpeg -i rtsp://192.168.170.43:554/?avm=1&freq=306&bw=8&msys=dvbc&mtype=64qam&sr=6900&specinv=1&pids=0,16,17,18,20,100,101,102,103,104,106,84,105,1176,2070,2171 -y -t 15466 -loglevel fatal -acodec copy -vcodec copy /volume2/Aufnahme/20190210135913 - Sportschau.ts
Aber nach dem Beenden:
$ sudo ps -ef | grep ffmpeg
root 30193 19994 0 13:59 ? 00:00:00 [ffmpegbinder.sh] <defunct>
root 30195 1 2 13:59 ? 00:00:04 /volume1/@appstore/VideoStation/bin/ffmpeg -i rtsp://192.168.170.43:554/?avm=1&freq=306&bw=8&msys=dvbc&mtype=64qam&sr=6900&specinv=1&pids=0,16,17,18,20,100,101,102,103,104,106,84,105,1176,2070,2171 -y -t 15466 -loglevel fatal -acodec copy -vcodec copy /volume2/Aufnahme/20190210135913 - Sportschau.ts
Der ffmpeg
-Prozess will ums Verrecken nicht mit sterben...
Da ich selbst mit Linux, bash und Co. nicht so fit bin, werde ich mich mal hier einlesen: https://riccomini.name/kill-subprocesses-linux-bash
Mein .terminate() sendet SIGTERM nur an parent: https://unix.stackexchange.com/questions/146756/forward-sigterm-to-child-in-bash Wenn es ohne .sh nicht funktioniert, könnte das die Lösung sein.
Wird probiert ;-)
So... Änderungen am Skript:
#!/bin/sh
_term() {
echo "caught SIGTERM signal"
echo "$(date)"
pkill -9 -P "$$" 2>/dev/null
}
trap _term SIGTERM
for i in "192.168.170.21" "192.168.170.45"
do
runningfile="/volume1/@appstore/tvstreamrecord/running_$i.run"
if [ -f $runningfile ]; then
echo "file $runningfile exists"
else
echo "file $runningfile not exists"
echo "running now" >> $runningfile
echo "using bind adress $i"
BIND_ADDR="$i" LD_PRELOAD=/usr/lib/bind.so /volume1/@appstore/VideoStation/bin/ffmpeg "$@"
rm -- "$runningfile"
break
fi
done
Beim Beenden über tvstreamrecord passiert nix. Alles läuft weiter. _term()
wird anscheinend gar nicht aufgerufen.
Rufe ich direkt in der Kommandozeile sudo pkill -9 -P $PID
auf, dann wird die _term()
-Funktion aufgerufen (erkenne ich an der dem Zeitstempel den mir die Funktion ausgibt).
Wird Dein Script wieder sh
aufgerufen? Damit wäre noch ein Shell drüber, wenn ich es richtig verstehe. Ansonsten bin ich mit meinem Latein am Ende...
Egal ob mit oder ohne sh
, das Verhalten bleibt gleich. Anscheinend wird der SIGTERM
-Befehl nicht korrekt gesendet oder empfangen...
So, ein erster Erfolg. Wie weiter oben angekündigt wollte ich mich hier https://riccomini.name/kill-subprocesses-linux-bash mal einlesen. Gesagt, getan und die dort beschriebene kill_child_processes()
mittels trap
angesprochen und es funktioniert.
#!/bin/sh
kill_child_processes() {
isTopmost=$1
curPid=$2
childPids=`ps -o pid --no-headers --ppid ${curPid}`
for childPid in $childPids
do
echo "try to kill child $childPid"
kill_child_processes 0 $childPid
done
if [ $isTopmost -eq 0 ]; then
echo "try to kill parent $curPid"
kill -9 $curPid 2> /dev/null
fi
if [ -f $runningfile ]; then
echo "try to delete $runningfile"
rm -- "$runningfile"
fi
}
trap "kill_child_processes 1 $$; exit 0" 0
for i in "192.168.170.21" "192.168.170.45"
do
runningfile="/volume1/@appstore/tvstreamrecord/running_$i.run"
if [ -f $runningfile ]; then
echo "file $runningfile exists"
else
echo "file $runningfile not exists"
echo "running now" >> $runningfile
echo "using bind adress $i"
BIND_ADDR="$i" LD_PRELOAD=/usr/lib/bind.so /volume1/@appstore/VideoStation/bin/ffmpeg "$@"
rm -- "$runningfile"
# exit
break
fi
done
Die kill_child_processes()
-Funktion killt erst alle Kinder, dann den Hauptprozess und in meinem Fall wird noch die Running-Datei gelöscht.
Sonderlich schön ist das Skript aktuell nicht, aber es funktioniert. Ich kann zwei gleichzeitge Aufnahmen über tvstreamrecord starten und beenden.
Gleichzeitig sorgt das Skript dafür, dass die angegebenen IPs nur einmal für diesem Zweck verwendet werden können. Normalerweise würden sich mehrere ffmpeg
-Prozesse über die gleiche IP zum FritzGerät nämlich in die Quere kommen und immer gegenseitig zum Abbruch führen.
Meine nächster Idee ist jetzt, mein eth1
um ein virtuelles Interface mit eigener IP zu erweitern und dann diese beiden Interfaces für die Aufnahmen zu nutzen. Somit wird eth0
nicht mit den Aufnahmen belastet und steht komplett für die anderen Aufgaben des NAS zur Verfügung.
Ich will nicht behaupten, alles verstanden zu haben, aber das klingt doch cool! :)
1) Ja klar, wenn ich komplett fertig bin. 😉
2) Die dritte Aufnahme wird über tvstreamrecord zwar theoretisch gestartet, aber es startet nie ein ffmpeg
, da mein Skript aufgrund der vorhanden Tickets normal zu Ende läuft.
Danach greift aktuell deine Retry-Logik. Wenn es x-mal erfolglos probiert wurde, hört tvstreamrecord ja dann auf es zu probieren.
Hier bin ich aktuell aber noch am Testen.
2019-02-11 12:55:57.017 | Something went wrong with 'Punkt 12 - Das RTL-Mittagsjournal', retry 1/20 in 10 seconds
2019-02-11 12:55:57.016 | FFMPEG record 'Punkt 12 - Das RTL-Mittagsjournal' ended
3) Theoretisch sollte auch hier die kill_child_processes()
getriggert und die Tickets gelöscht werden. Kann ich aber bei Gelegenheit mal testen.
Also auch mit virtuellen Interfaces (über ein reales Interface) klappt das wunderbar.
Einfach Interfaces erstellen:
sudo ifconfig eth1:1 192.168.170.46
sudo ifconfig eth1:2 192.168.170.47
In meinem Skript verwende ich dann die beiden neuen IPs und das klappt wunderbar. Der gesamte Traffic läuft nun ausschließlich über eth1
. 😄
Anderes Thema: Kannst du mit dieser Meldung etwas anfangen?
FFMPEG could not be started. Error: 'ascii' codec can't decode byte 0xe2 in position 275: ordinal not in range(128)
Die wird ab und zu mal geworfen und dann kommt ein erfolgreicher Retry.
coole Sache! ^^
Ich bin gespannt, wenn das mal den Endstand erreicht hat.
Die Fehlermeldung kommt mir schon bekannt vor und sollte eig. nur kommen, wenn der Titel unzulässige Zeichen enthält, und nur unter Python 2.x
So, da will ich mich auch mal wieder zu Wort melden... Mein Skript ist gewachsen, und ich erklär natürlich auch warum. 😉
Es gibt einige Themen die sich schwierig gestaltet haben:
ifconfig
neu erzeugen.ifconfig
wären die IPs vorgegeben und man muss vorher prüfen ob diese auch noch im Netz frei sind.Insgesamt alles "verbesserungswürdig"...
Exit-Händler definieren, falls Aufnahmen vorzeitig beendet werden soll.
ffmpeg
)running
-Ticket für IP löschenPrüfen ob meine virtuellen Interfaces vorhanden sind.
vrt0
bis vrt3
, welche allesamt über das reale Interface eth1
laufen. Alle vier haben unterschiedliche Dummy-MAC-Adressen (eigene MAC-Adressen sind notwendig, damit der Router per DCHP eigenständige IPs vergibt).dhclient
um per DHCP eine IP vom DHCP-Server zu bekommen.Freie IP (aus den ausgelesen vom zweiten Schritt) für Aufnahme finden anhand running
-Ticket.
running
-Ticket für IP vorhanden, dann nächste IP prüfen.running
-Ticket vorhanden...
running
-Ticket schreibenIch kann also nun 4 Aufnahmen auf 2 unterschiedlich Sendern gleichzeitig durchführen. Sollte eine der 4 Aufnahme einen dritten Sender aufnahmen wollen, schlägt dieser ffmpeg
-Prozess fehl und die Sendung wird nicht aufgenommen. Die anderen Prozesse laufen normal weiter. Es gilt: Wer zuerst kommt... 😄
#!/bin/sh
# exit or kill handler
kill_child_processes() {
isTopmost=$1
curPid=$2
childPids=`ps -o pid --no-headers --ppid ${curPid}`
for childPid in $childPids
do
echo "kill child $childPid"
kill_child_processes 0 $childPid
done
if [ $isTopmost -eq 0 ]; then
echo "kill parent $curPid"
kill -9 $curPid 2> /dev/null
fi
if [ ! -z "$deletefile" ] && [ -f $deletefile ]; then
echo "delete $deletefile"
rm -- "$deletefile"
fi
}
trap "kill_child_processes 1 $$; exit 0" 0
# create virtual interfaces
vrtip=$(ifconfig | awk -F"[: ]+" '/vrt/{getline; {print $4}}')
if [ -z "$vrtip" ]; then
echo "no vrt interfaces found"
for i in "0" "1" "2" "3"; do
echo "create vrt$i"
ip link add link eth1 address 00:11:22:33:44:"$i$i" vrt"$i" type macvlan
/usr/sbin/dhclient -4 -nw -lf /tmp/dhcpv4.leases.vrt"$i" -pf /tmp/dhcpcd-vrt"$i".pid -sf /var/run/dhclient-script vrt"$i"
done
sleep 10
vrtip=$(ifconfig | awk -F"[: ]+" '/vrt/{getline; {print $4}}')
fi
echo "vrtip: $vrtip"
# find free ip and try to record
for i in $vrtip; do
runningfile="running_$i.run"
if [ -f $runningfile ]; then
echo "$runningfile exists"
else
echo "$runningfile not exists"
echo "running now" >> $runningfile
echo "using bind adress $i"
deletefile="$runningfile"
BIND_ADDR="$i" LD_PRELOAD=/usr/lib/bind.so /volume1/\@appstore/ffmpeg/bin/ffmpeg "$@"
rm -- "$runningfile"
unset deletefile
break
fi
done
Das ist aber noch nicht die Endfassung des Skriptes. Aktuell benutze ich ein ffmpeg
über eine Community-Quelle und das ist fest im Skript angegeben. Dieses Setting könnte auch als Argument an das Skript gegeben werden. Außerdem könnte man auch die Anzahl der zu erzeugenden virtuellen Interfaces als Argument verarbeiten. Es ist also immer noch Luft noch oben.
Ich hoffe man blickt einigermaßen durch.
VG Daniel
Hi Daniel!
Also als Allererstes: WOW!
Deine Beschreibung klingt schlüssig, auch wenn ich Deinen Script nicht bis ins kleinste Detail verstehe 🤔 Einige Sachen fielen mir aber dabei ein:
stderr
zu schicken, so dass der Bediener z.B. die Meldung "Wer zuerst kommt..." auch im TSR-Log sieht, wenn keine Tickets frei sind?Jedenfalls eine feine Sache, die Du da aufgebaut hast, bin weiterhin gespannt. Wenn Du wobei Unterstützung brauchst, melde Dich!
Grüße Pav
Hi Pav,
ffmpeg
-Prozess gestartet wird. Die Retry-Logik probiert es dann (so oft wie definiert) nochmal und bricht irgendwann ab.bind.so
wollte ich eigentlich mit gcc
selbst kompilieren, bis ich fertig kompilierte Exemplare unter https://daniel-lange.com/archives/53-Binding-applications-to-a-specific-IP.html bzw. https://daniel-lange.com/software/bind_so_compiled.tar.gz gefunden habe. Danke für den Hinweis, die Library müsste natürlich auch woanders liegen dürfen. Das werde ich testen.stderr
. Ich habe momentan in der tvstreamrecord.py
ein print
vom stdout
drin, deshalb wird bei mir aktuell immer mitgeloggt. Aber das ist ja eher fürs Debugging.Wenn du nichts dagegen hast und offen für Erweiterungen/Neuerungen bist...
tvstreamrecord.py
: Aufnahmen deaktivieren, wenn die maximale Retry-Anzahl erreicht wurde.VG Daniel
Danke für die Rückmeldung! Bevor wir jedoch weiter über Änderungen sprechen, erstmal ein paar generelle Anmerkungen:
Hi!
zu 1: Verstehe ich vollkommen! War auch nicht als Vorwurf gemeint.
zu 2: Schade, aber toll dass du trotzdem dran bleibst. 👍 In meinem Fall nutze ich es nur um Sendungen für meine bessere Hälfte aufzunehmen. Durch das EPG-Chart findet man aber auch das ein oder andere was man dann doch mal aufnimmt.
zu 3: Es spricht doch auch nichts dagegen, ein Frontend für ein weit verbreitetes Tool zu betreiben. Wobei die ganze EPG-Auswertung schon über eine einfache Oberfläche hinaus geht...
zu 5: + 6.iv: Eine Neuentwicklung wäre sicherlich denkbar, aber ich wüsste nicht was an deinem Python-Backend "so schlimm ist". Das Frontend ist auch zu gebrauchen, kann aber ein Update vertragen. zu 6.i + 6.ii + 6.iii: Alles machbar. 😉
zu 7: Da ich Gefallen an deinem Tool gefunden, bleibe ich auch dran und möchte weiterhelfen.
Beste Grüße
Huhu!
Zu 2: Hast Du eigentlich schon TV-Browser probiert? Seit ich das Tool entdeckt habe, hatte ich keine Lust mehr groß am EPG-Chart zu arbeiten...
Zu 5: Python an sich ist eine feine Sache aber hast Du Dir schonmal meine SQL-Scripte angesehen, die in *.py sind?! 🙉
Was hältst Du nun für sinnvoll? Hast Du konkrete Ideen, die ich schnell umsetzen könnte? Soll ich Dich hierfür freischalten? Oder kannst Du natürlich gern einen Fork bei Dir machen und mit PR arbeiten. Wohl gemerkt, da es sich um GPL handelt, brauchst Du für letzteres noch nicht mal meine Erlaubnis 🙂
Hi,
zu 2: Ne, sieht ganz nett aus, aber ich bin ein Freund von programmunabhängigen Webtools. 😉 zu 5: Ja, ich versuche gerade dein Query mit den etlichen Joins für die EPG-Chart zu verstehen... 😆
Zur letzten Frage: Was ist dir lieber bzw. einfacher für uns beide?
VG
Jaja, die Joins... ich gebe zu, ich habe damit etwas übertrieben 🙂
Da ich immer noch nicht ganz weiß, was Du konkret vorhast, kann ich auch wenig konkretes sagen. Wenn Du eine klare Aufgabe für mich hast (z.B. in Python die und die Daten für GET bereitstellen), kann ich das - sofern es die DB hergibt - gern einprogrammieren. Erklärungen gibt's sowieso 🙂
Ansonsten, denke ich, ist es simpler, wenn Du einen Fork machst und mit PRs arbeitest, so kann man gut die Änderungen verfolgen und abgleichen. Außer Du hast andere Ideen/Erfahrungen?
So ich hab einen Fork gemacht. Ich denke du hast recht, über PRs läuft das am besten. Ich hab mal einen ersten PR als Test gemacht. #34
Hi Pavion,
hast du eine Version in höherer Auslösung von https://github.com/Pavion/tvstreamrecord/blob/master/images/apple-touch-icon.png?
VG
Hi Daniel!
Reicht Dir 288x288?
Sonst habe ich noch die PSD-Quelle davon, die man ggf. höher skalieren könnte.
Gruß Pav
Das reicht fürs erste 👍
VG Daniel
💡 Solution using Docker: https://github.com/Pavion/tvstreamrecord#running-multiple-instances-with-docker
Hallo,
wie ich bereits in dem Issue https://github.com/Pavion/tvstreamrecord/issues/22 lesen konnte, hat tvstreamrecord keine Begrenzung für zeitgleiche Aufnahmen. Die DVB-C fähigen Geräte von AVM hingegen streamen an ein Gerät aber immer nur einmal.
Ich habe tvstreamrecord auf einer DS415+ laufen. Diese hat zwei Ethernet-Interfaces, welche beide an meiner FritzBox hängen. Zusätzlich habe ich im Netz den FritzRepeater mit DVB-C. Das gleichzeitige Aufnehmen wäre also theoretisch möglich, da ich über zwei verschiedene IPs auf den Repeater zugreifen kann. Funktionieren tut das allerdings mit tvstreamrecord noch nicht. Wahrscheinlich deshalb, weil beide ffmpeg-Prozesse ihre Verbindung über das selbe Interface aufbauen wollen.
Gibt es hier eine Möglichkeit das Problem mit ffmpeg selbst zu lösen oder wäre da eine Lösung über tvstreamrecord möglich? Ein Beispiel: Wenn bereits eine Aufnahme läuft, dann sorgt tvstreamrecord dafür, dass der zweite ffmpeg-Prozess über das zweite Interface arbeitet.
Ich stelle mich auch gern als Versuchskaninchen zur Verfügung.
Beste Grüße Daniel