Find the Bug/Finde den Fehler: In der OSMC “ARD Mediathek”

Ich habe im vergangenen Jahr gerne auf dem Raspberry Pi das Kodi/OSMC-Plugin für den Zugriff auf die “ARD Mediathek” genutzt, um Sendungen tatsächlich genau dann anschauen zu können wann ich es auch möchte. Leider erscheint schon seit einiger Zeit bei Auswahl der Menüpunkte “Meistgesehen” oder “Sendungen A-Z” nur noch eine kurze Fehlermeldung: “ARD Mediathek Fehler – Für mehr Informationen, Logdatei einsehen”.

BugFehlerArdMediathek

ARD Mediathek Fehleranzeige

Während man im Sommer den Fehler noch einfach ignorieren und – statt den letzten “Tatort” zu schauen – einfach mit Freunden raus in den Park gehen konnte, ist nun im Herbst wieder die richtige Zeit für lange Fernsehabende auf dem Sofa gekommen. Es ist an der Zeit sich auf die Suche nach dem Bug zu machen. Also, Helm aufziehen, ab in den Maschinenraum, die Stablampe eingeschaltet und dann schauen wir uns das einmal genauer an.

Die erwähnte Logdatei finden wir auf einem Raspberry unter

/home/osmc/.kodi/temp/kodi.log

falls Kodi unter Windows oder Mac OS läuft, werden die internen Dateien an anderer Stelle abgelegt, auf einem Mac finden wir die Logdatei beispielsweise unter

/Users/[Username]/Library/Logs/kodi.log

Optional können wir für Kodi noch das detaillierte Logging aktivieren, dazu gehen wir im Kodi-Menü zu “Optionen” / “Einstellungen” -> “System” -> “Logging” und wählen den Punkt “Debug-Logging aktivieren” aus. Daraufhin werden uns fortlaufend in der Oberfläche unter anderem die Speicherbelegung oder die CPU-Auslastung angezeigt, in der Logdatei erscheinen nun auch Debug-Meldungen neben den Fehlern.

Entweder prüfen wir das Log mit einem Texteditor, oder wir hängen uns mit einem

> tail -f /home/osmc/.kodi/temp/kodi.log

direkt an die Ausgabe des Logs an und klicken dann nochmals im Mediathek-Plugin auf den “Meistgesehen”-Menüpunkt. Im Kodi-Fenster erscheint wieder nur die gleiche Fehlermeldung wie oben schon im Screenshot zu sehen, im Log finden wir nun aber zusätzlich einen detaillierteren “ERROR”-Eintrag mit weiteren Details:

20:57:59 79845.984375 T:952271856   DEBUG: get: http://www.ardmediathek.de/tv/Meistabgerufene-Videos/mehr?documentId=21282514&m23644322=quelle.tv&rss=true

20:57:59 79845.984375 T:952271856   ERROR: EXCEPTION Thrown (PythonToCppException) : -->Python callback/script returned the following error
 Error Contents: list index out of range
 Traceback (most recent call last):
 File "/home/osmc/.kodi/addons/plugin.video.ardmediathek_de/default.py", line 615, in 
 listVideosRss(url,showName,hideShowName,nextPage,einsLike)
 File "/home/osmc/.kodi/addons/plugin.video.ardmediathek_de/default.py", line 136, in listVideosRss
 c = rssParser(content)
 File "/home/osmc/.kodi/addons/plugin.video.ardmediathek_de/default.py", line 190, in rssParser
 runtime = runtimeToInt(part)
 File "/home/osmc/.kodi/addons/plugin.video.ardmediathek_de/default.py", line 197, in runtimeToInt
 return int(HHMM[0])*60 + int(HHMM[1])
 IndexError: list index out of range
 -->End of Python script error report<--

Aha! Wir reiben uns den Zeigefinger links und rechts an der Nase und erkennen: Das Python-Skript default.py liefert also in Zeile 197 in der Funktion runtimeToInt mit dem Befehl "return int(HHMM[0])*60 + int(HHMM[1])" einen "list index out of range"-Fehler - es wird also versucht, auf ein Element einer Liste zuzugreifen, obwohl dieses Element gar nicht in der Liste enthalten ist, da diese nicht die erwartete Länge hat. Hier im Code wird das vermutlich der Zugriff auf das zweite Listenelement HHMM[1] der Liste HHMM sein, während HHMM im Programmablauf aber nur eines oder vielleicht auch gar kein Element besitzt.

Schauen wir als nächstes direkt in den Programmcode des Plugins. Diesen finden wir auf dem Raspi, wie auch schon im Logeintrag erwähnt, unter

/home/osmc/.kodi/addons/plugin.video.ardmediathek_de/

Auf einem Mac wiederum im Ordner

/Users/[Username]/Library/Application Support/Kodi/addons/plugin.video.ardmediathek_de/

Aus der im Log genannten Programmdatei default.py hier noch einmal die ebenfalls genannte Zeile 197 im gesamten Kontext der Funktion:

193 
194 def runtimeToInt(runtime):
195         t = runtime.replace('Min','').replace('min','').replace('.','').replace(' ','')
196         HHMM = t.split(':')
197         return int(HHMM[0])*60 + int(HHMM[1])
198

Zur Sicherheit prüfen wir, ob die im Log genannte URL überhaupt noch gültig ist und welches Ergebnis sie zurückliefert:

URL: http://www.ardmediathek.de/tv/Meistabgerufene-Videos/mehr?documentId=21282514&m23644322=quelle.tv&rss=true

In einem passenden Browser bekommen wir hierüber das erwartete RSS-XML-Dokument mit den "Meistgesehenen Sendungen" der ARD zurückgeliefert. Beim genaueren Betrachten des Dokuments fällt aber bereits auf, dass die Spieldauer nicht in Stunden und Minuten ("HHMM"), sondern nur in Minuten (z.B. "87 Min."), zurückgegeben wird.

Als ersten Versuch ersetzen wir die problematische Zeile 197 im Programmcode durch einen Code, der nicht fehlschlagen kann. Beispielsweise liefern wir einfach immer konstant 15 Minuten als Spieldauer zurück.

193 
194 def runtimeToInt(runtime):
195         t = runtime.replace('Min','').replace('min','').replace('.','').replace(' ','')
196         HHMM = t.split(':')
197         return int(15)
198 #        return int(HHMM[0])*60 + int(HHMM[1])    # ERROR
199

Und siehe da! Bei Klick auf "Meistgesehen" stürzt das Plugin nun nicht mehr ab, sondern liefert uns wieder brav die heissersehnte Liste der meistgesehenen Sendungen der letzen Tage zur Auswahl. Alle Sendungen können auch wieder problemlos ausgewählt und abgespielt werden. So weit so wunderbar!

Aber wir haben noch das kleine Manko, dass nun, wie wir bereits erwarten konnten, bei jeder Sendung eine konstante Spieldauer von "0:15" angezeigt wird.

Nach einigem Herumprobieren stellen wir fest, dass für eine korrekte Anzeige der Spieldauer die Funktion nur den ersten und einzigen Minutenwert zurückgeben müsste, also "int(HHMM[0])", aber nicht wie bisher mit 60 multipliziert. Entweder gibt man also tatsächlich nur diesen Wert statt der konstanten "15" zurück, oder baut zusätzlich noch ein passendes if/else ein, welches die Ausgabe für beide Formate korrekt zurückgeben würde, und schon passt auch die Anzeige der Spieldauer wieder:

194 def runtimeToInt(runtime):
195         t = runtime.replace('Min','').replace('min','').replace('.','').replace(' ','')
196         HHMM = t.split(':')
197         if len(HHMM) == 1:
198                 return int(HHMM[0])   
199         else:
200                 return int(HHMM[0])*60 + int(HHMM[1])

Nimm das, Bug!

Darauf erstmal einen "Tatort"!

ARD Mediathek

ARD Mediathek ohne Fehler

Mein Kommentar...