edEIT - EIT Editor
-
-
-
Hallo Juanito,
ich habe gerade meine ganzen .TRP Daten von einem Vantage 8000s auf eine Vu+Duo² ins TS-Format konvertiert und umgezogen, dort werden sie auch einwandfrei wiedergegeben, jedoch ohne die Programminfo.
Es handelt sich um ca 850 aufegzeichnete Filme wovon ich gerne die Programminfos übertragen sprich in EIT.Daten konvertieren möchte, dies jedoch nicht manuell mit copy und paste, sondern via Programm, wozu haben wir denn Computer.Die Daten aus meiner Vantage habe ich in einer MS-Access.mdb abgelegt, bin auch ganz gut darin mit VBA die EIT Daten zu erzeugen, blos habe ich bisher nichts gefunden wie die EIT-Datein genau aufgebaut sind.
Und jetzt die Frage an dich: nach dem du ja den edEIT geschrieben hast, könntest du mir bitte den Aufbau der EIT-Dateien zukommen lassen?
Danke im voraus
Joergl -
Hi,
Anbei die imho letzte Version.
-
Die Daten aus meiner Vantage habe ich in einer MS-Access.mdb abgelegt, bin auch ganz gut darin mit VBA die EIT Daten zu erzeugen, blos habe ich bisher nichts gefunden wie die EIT-Datein genau aufgebaut sind.
Und jetzt die Frage an dich: nach dem du ja den edEIT geschrieben hast, könntest du mir bitte den Aufbau der EIT-Dateien zukommen lassen?
Hallo Joergl,
Mit VBA kann ich nicht dienen, und mit schreiben von EIT Dateien auch nicht. Aber ich hab im April mir einen eigenen parser geschrieben um EIT Dateien zumindest auszulesen. Ist zwar C++ und Qt, aber vielleicht hilft es Dir zusammen mit der Dokumentation Deine EIT Dateien mit VBA zu erstellen. Ich hab das ganze mal hier online gestellt: parseEIT
(Rückfragen eventuell auch besser nur dort, das wäre hier etwas Offtopic, hier geht es um edEIT)Viel Erfolg und willkommen in der Welt von Enigma2.
-
Hallo Juanito,
erst einmal vielen Dank für dieses tolle Programm. Nutze es schon seit geraumer Zeit und bin sehr zufrieden.
Vor einigen Monaten fiel mir dann aber auf, dass die Sendungsdaten "Datum" und "Uhrzeit" aus der .eit und der ts.meta nicht mehr verarbeitet werden. Ich habe eine DM7080 mit aktuellem Newnigma2-Image. Da wird sich wahrscheinlich irgendwann irgend etwas geändert haben. Mich stört es deshalb, weil ich seit Jahren Aufnahmen mit dem TS-Doctor geschnitten und unter neuem Dateinamen (ohne Datums- und Uhrzeitangabe) gespeichert habe. Lässt sich da was in edEIT machen?
Gruß Dietmar
-
Hi,
Ich glaube nicht, dass dieses Problem etwas mit edEIT zu tun hat.
Das Format, wie Datum und Zeit in den .eit und in den .ts.metas gespeichert werden, ist fest vorgegeben.Für mich klingt das eher danach, dass bei deiner Box etwas nicht mehr stimmt.
Hast Du mal bei Newnigma2 nachgefragt, ob andere das Problem auch haben?
Gibt es irgendwas, womit man das Problem eingrenzen kann?
Tritt es auch mit .eit/.ts.metas auf, wenn Du die Dateien nicht umbenennst?Mach doch mal ein Vollbackup von deiner Installation und teste mit einem sauberen DreamOS Image ohne weitere Plugins gegen.
Ansonsten kann ich dir nur anbieten, dass du hier .eit/.ts.metas hinterlegst, die bei dir Probleme machen.
Die kann ich mir gerne anschauen, ob sie ok (=standard-konform) sind. Wenn aber edEIT die Dateien ohne Murren öffnet, dann kannst Du davon ausgehen, dass sie OK sind. -
EMC deinstalliert - Problem behoben
EMC neu installiert - Problem wieder da
Lesen aus .ts.meta in EMC abgeschaltet - Problem behobenGruß Dietmar
-
Freut mich, dass Du die Ursache gefunden hast.
Wenn es an dem Plugin liegt, dann müssten ja andere auch das Problem haben.
Hoffe, es gibt bald 'nen Fix dafür. -
Erstmal ein großes DANKESCHÖN für dieses wundervolle Programm.
Hatte bis jetzt EITitor verwendet, aber wenn ich den als Standard (unter Windows 7) nehme, zeigt er mir beim Öffnen nach Anklicken im Windows-Explorer keine Daten an. Ausserdem wenn ich eine eit händisch über EITitor öffne, komme viele Sonderzeichen.
Das alles funktioniert wunderbar mit Deinem Programm, danke, danke, dankeNachdem EITitor nicht funktionierte, habe ich versucht, in Visual Basic 6 eine eit auszulesen, weil ich einfach nur Titel, Episode und Beschreibung sehen wollte.
Leider bin ich kläglich gescheitert. Was aber relativ egal ist, denn Dein Programm macht eh alles, was ich haben will.
Trotzdem, rein interessenshalber:
Wie liest Du die einzelnen Sachen (Titel, Genre, Beschreibung) aus?
Mir ist schon klar, dass Du jede Menge Zeit dafür investiert hast, aber könntest Du mir diesen einen Code-Schnipsel (nur das Auslesen der 3 Sachen) zukommen lassen? Weil mich hat ein wenig der Ehrgeiz gepackt
Kann es verstehen, wenn Du das nicht möchtest, aber Du würdest mir eine große Freude bereiten, wenn Du mir das per Email zukommen liesest. -
Hi,
ein paar Codezeilen reichen leider nicht. Um alles auszulesen braucht es schon eine ganze Menge Code. Die .eits haben ein (nennen wir es mal) eigenwilliges Format, das noch aus der Zeit stammt, als man sehr sparsam mit Speicher umgegangen ist.
Je nachdem, welche Infos du haben möchtest, musst du unterschiedliche (sog.) descriptors (Infoblöcke; jeweils max. 256 Byte lang) einlesen. Im Aufbau sind die alle ähnlich, haben aber auch jeweils ihre Eigenheiten.
Die vollständige Beschreibung findest du im ETSI Dokument (anbei).
In edEIT sind die Infos in Blöcken unterteilt, wobei im Rahmen immer der jeweilige descriptor -Name steht.
Titel und Beschreibung sind im "short event descriptor", die längere Inhaltsinfo ist in (meist mehreren) "extend event descriptor" enthalten.
Wichtig ist, dass die Texte meist kodiert (z.B. UTF-8) sind, d.h. man muss diese entsprechend konvertieren.Im Anhang als Beispiel der Aufbau des short event descriptors, wobei ich gleich darauf hinweise, dass der auch mehrfach vorkommen kann.
-
Danke für Deine Bemühungen, aber das wußte ich bereits und auch das pdf habe ich schon runtergeladen.
Leider konnte ich auch damit nichts anfangen.
Naja, wenn es so umfangreich ist, kann man nichts machen. Dachte, es sind nur ein paar Zeilen (Position und Länge für die 3 Sachen rausfinden, dann passt das schon), aber wenn es so kompliziert ist.
Ich schau mir mal das Konvertieren von UTF-8 an, vielleicht komme ich noch dahinter (was ich aber bezweifle).
Trotzdem Danke -
Hi,
Position und Länge dieser drei Sachen sind leider nicht absolut. Du müsstest - ausgehend vom Header - die einzelnen descriptors durchgehen, bis der gewünschte descriptor (z.b. SED) gefunden ist, um dort dann die exakten Positionen und Länge der Texte zu finden.
Beim EED ist es sogar noch etwas "unglücklicher", weil dort aufgrund der 256 Byte Begrenzung so ziemlich immer der Text über mehrere Blöcke verteilt ist. Diese sind zwar meist in der richtigen Reihenfolge, eine Garantie dafür gibt es aber nicht. Man muss also alle EED-Texte der einzelnen Blöcke einlesen, anschließend sortieren, zusammenführen und ggf. am Ende noch die CS-Konvertierung durchführen.Grundsätzlich ist es aber schon machbar, wenn du magst. Du wirst aber dafür schon etwas Arbeit reinstecken müssen.
Am Beispiel SED:
1. Du liest die gesamte .eit als ByteArray (Kette von Bytes) ein
2. Bei Byte 12 findest du den ersten descriptor. Dieses Byte sagt dir, was es für ein descriptor es ist, das nächste Byte sagt dir die Länge dieses descriptors
3. Für SED muss es 0x4D (dez 77) sein
4. Ist das Byte also kein 0x4D, dann springt du im Bytearray zum nächsten descriptor in dem du die Länge des descriptors zur aktuellen Position addierst.
5. Dann prüfst du wieder nach 4D
6. usw.Hast du 0x4D gefunden - nehmen wir mal an das wäre gleich der erste descriptor, startet also bei Byte 12 - dann sind die anschließenden Bytes wie folgt zu interpretieren:
Achtung, das ist ein Beispiel mit z.B. Titel = "All is Lost" und Beschreibung = "Drama" (beide CS kodiert)Code12 descriptor_tag | 0x4D / 77 bedeutet SED 13 descriptor_length | Länge des descriptors (in diesem Bsp 23) 14..16 ISO_639_language_code | 3 Bytes = z.B. "D" + "E" + "U", für "DEU" 17 event_name_length | Länge des 'Titels' (in dieses Bsp 12 Zeichen) 18 charset | ggf. CS-Kodierung 19…29 event_name_char | Text des Titel (in diesem Bsp "All is Lost") 30 text_length | Länge der 'Beschreibung' (in diesem Bsp 6) 31 charset | ggf. CS-Kodierung 32..36 text_char | Text der Beschreibung (in diesem Bsp "Drama")
also
Byte 18..29 = Titel (ggf. inkl. CS-Kodierungsbyte am Anfang)
Byte 31..36 = Beschreibung (inkl. CS-Kodierung am Anfang)Du siehst, man muss sich die Positionen und Längen der einzelnen Informationen zusammenrechnen.
Ein simples Suchen nach Byte 0x4D (77) im Array bringt dich nicht weiter, weil 0x4D (77) eine Länge, eine Position oder auch ein "M" in einem Text sein kann. WAS es wirklich ist, hängt davon ab, WO es genau steht.Ich unterstütze dich gerne auf dem Weg, falls du dich daran machen willst
-
Ok, Du hast mir wieder Mut gemacht.
Dafür und für Dein Angebot, mich ein wenig zu unterstützen, ein großes Dankeschön.
Ist heutzutage leider nimmer so oft zu sehen.
Danke. -
Also:
Sprache, Titel und Beschreibung habe ich schon.
Was mir aber jetzt noch fehlt, ist der Inhalt. Somit die Fortsetzung Quellcode von oben
Habe zwar versucht, es selber rauszufinden, aber es gelingt mir nicht ganz.
Kannst Du mir bitte als letztes noch diese Infos zukommen lassen?
sollte sein:
10. 37 inhalt_length | Länge des Inhalts
11. 38 charset | Text des Inhalts
Aber wie gesagt, das habe ich noch nicht ganz behirnt, also wäre ich Dir über eine nochmalige Hilfe sehr dankbar.
lg
Werner -
Vorab: Vorsicht! Auch wenn meist der SED unmittelbar nach dem Header kommt, so gibt es dafür keine Garantie.
Die descriptoren können innerhalb einer .eit in beliebiger Reihenfolge stehen. Du kommst also nicht umhin, die descriptors durchzugehen und nach den gewünschten descriptor_tags zu suchen.Denkt man mein obiges Beispiel weiter, dann wäre der SED mit Byte 36 beendet.
Das bedeutet, dass Byte 37 schon der "descriptor_tag" des nächsten descriptors wäre.
Wäre der descriptor_tag ein 0x4E (= EED), dann wäre das einer der gesuchten descriptors mit dem "Inhalt".
Die EEDs gehören - wirst du ungern hören - zu den komplizierteren descriptors.
Wie gesagt, dadurch dass sie auf 256 Byte begrenzt sind, sind eigentlich immer mehrere davon da.
Zudem können dort auch Werte-Paare (siehe in edEIT den Reiter "Optional" im EED), um z.B. die Schauspieler zu hinterlegen.
Anbei ein Beispiel mit optionalen Werte-Paaren. In der Zip findest du auch einen Dump als Textdatei, der die vielleicht bei der Orientierung hilft.
Bei Byte 217 ist der erste EED.Die Struktur ist dann:
Code
Alles anzeigen217 descriptor_tag | 0x4E 218 descriptor_length | Länge gesamt = 255 bytes 219 descriptor_number & last_descriptor | je 4bit : 2 = 0000 0010 => Nummer 0 von 2 220..222 ISO_639_language_code | "g", "e", "r" 223 length_of_items | Länge der Werte-Paare. Wenn es keine gibt, steht hier eine 0 for ( i=0;i<N;i++){ 224 item_description_length | 6 225..230 item_description_char | 5 + "Actor", wobei die 5 die CS-Kodierung angibt 231 item_length | 17 232..230 item_char | 5 + "Daniel Radcliffe" (wieder CS-Kodiert) ... | usw. jetzt geht es mit dem eigentlichen Inhalt los... 343 text_length | Länge des Texts : 130 344..473 text_char | 5 + "Harry, Ron ... un" nun folgt der nächste EED 474 descriptor_tag | 0x4E 475 descriptor_length | Länge gesamt = 255 bytes 476 descriptor_number & last_descripto | je 4 bit: 18 = 0001 0010 => Nummer 1 von 2 477..479 ISO_639_language_code | "g", "e", "r" 480 length_of_items | 0 = keine Werte-Paare 481 text_length | 249 482..730 text_char | 5 + "d Zerst..." beim "ö" siehst du den Effekt der CS-Kodierung usw.
Wie gesagt: Man sollte alle EED einlesen, sortieren und erst dann die Texte zusammenführen.
Bei der Musterdatei sieht du das "un" am Ende des 1. EED und dann das "d" am Anfang des 2. EED, was später im Text "und" ergibt.
Die CS-Kodierung darf erst erfolgen, wenn die Texte zusammengefügt wurden, weil z.B. ein Sonderzeichen (2 Byte) auf zwei EED aufgeteilt sein könnte. Konvertiert man vorher die einzelnen Teiltexte würde das Sonderzeichen kaputt gehen. -
hier mal als beispiel der emc eit parser in python:
Code
Alles anzeigendef __parse(self, data): EIT_LINKAGE_DESCRIPTOR = 0x4a EIT_SHORT_EVENT_DESCRIPTOR = 0x4d EIT_EXTENDED_EVENT_DESCRIPTOR = 0x4e EIT_COMPONENT_DESCRIPTOR = 0x50 EIT_CONTENT_DESCRIPTOR = 0x54 EIT_PARENTAL_RATING_DESCRIPTOR = 0x55 EIT_PDC_DESCRIPTOR = 0x69 def parse_header(data, pos): e = struct.unpack(">HHBBBBBBH", data[pos:pos + 12]) #event_id = e[0] date = parseMJD(e[1]) # Y, M, D time = unBCD(e[2]), unBCD(e[3]), unBCD(e[4]) # HH, MM, SS duration = unBCD(e[5]), unBCD(e[6]), unBCD(e[7]) # HH, MM, SS running_status = (e[8] & 0xe000) >> 13 #free_CA_mode = e[8] & 0x1000 #descriptors_len = e[8] & 0x0fff if running_status in [1, 2]: self.eit['when'] = "NEXT" elif running_status in [3, 4]: self.eit['when'] = "NOW" self.eit['startdate'] = date self.eit['starttime'] = time self.eit['duration'] = duration return self.eit = {} epglang = config.MVC.epglang.value lang = (language_iso639_2to3(epglang.lower()[:2])).upper() # Parse the data if len(data) >= 12: pos = 0 parse_header(data, pos) pos += 12 name_event_descriptor = [] name_event_descriptor_multi = [] name_event_codepage = None short_event_descriptor = [] short_event_descriptor_multi = [] short_event_codepage = None extended_event_descriptor = [] extended_event_descriptor_multi = [] extended_event_codepage = None component_descriptor = [] content_descriptor = [] linkage_descriptor = [] parental_rating_descriptor = [] pdc_descriptor = [] prev1_ISO_639_language_code = "x" prev2_ISO_639_language_code = "x" while pos < len(data) - 2: rec = ord(data[pos]) length = ord(data[pos + 1]) + 2 if rec == EIT_SHORT_EVENT_DESCRIPTOR: #descriptor_tag = ord(data[pos + 1]) #descriptor_length = ord(data[pos + 2]) ISO_639_language_code = str(data[pos + 2:pos + 5]).upper() event_name_length = ord(data[pos + 5]) name_event_description = "" for i in range(pos + 6, pos + 6 + event_name_length): if str(ord(data[i])) == "10" or int(str(ord(data[i]))) > 31: name_event_description += data[i] if not name_event_codepage: try: byte1 = str(ord(data[pos + 6])) except Exception: byte1 = '' name_event_codepage = self.__determineCodepage(byte1) # if name_event_codepage: # print("MVC: [EIT] Found name_event encoding-type: " + name_event_codepage) short_event_description = "" if not short_event_codepage: try: byte1 = str(ord(data[pos + 7 + event_name_length])) except Exception: byte1 = '' short_event_codepage = self.__determineCodepage(byte1) # if short_event_codepage: # print("MVC: [EIT] Found short_event encoding-type: " + short_event_codepage) for i in range(pos + 7 + event_name_length, pos + length): if ord(data[i]) == EIT_EXTENDED_EVENT_DESCRIPTOR: break if str(ord(data[i])) == "10" or int(str(ord(data[i]))) > 31: short_event_description += data[i] if ISO_639_language_code == lang: short_event_descriptor.append(short_event_description) name_event_descriptor.append(name_event_description) if (ISO_639_language_code == prev1_ISO_639_language_code) or (prev1_ISO_639_language_code == "x"): short_event_descriptor_multi.append(short_event_description) name_event_descriptor_multi.append(name_event_description) else: short_event_descriptor_multi.append("\n\n" + short_event_description) name_event_descriptor_multi.append(" " + name_event_description) prev1_ISO_639_language_code = ISO_639_language_code elif rec == EIT_EXTENDED_EVENT_DESCRIPTOR: ISO_639_language_code = "" for i in range(pos + 3, pos + 6): ISO_639_language_code += data[i] ISO_639_language_code = ISO_639_language_code.upper() extended_event_description = "" if not extended_event_codepage: try: byte1 = str(ord(data[pos + 8])) except Exception: byte1 = '' extended_event_codepage = self.__determineCodepage(byte1) # if extended_event_codepage: # print("MVC: [EIT] Found extended_event encoding-type: " + extended_event_codepage) for i in range(pos + 8, pos + length): if str(ord(data[i])) == "10" or int(str(ord(data[i]))) > 31: extended_event_description += data[i] if ISO_639_language_code == lang: extended_event_descriptor.append(extended_event_description) if (ISO_639_language_code == prev2_ISO_639_language_code) or (prev2_ISO_639_language_code == "x"): extended_event_descriptor_multi.append(extended_event_description) else: extended_event_descriptor_multi.append("\n\n" + extended_event_description) prev2_ISO_639_language_code = ISO_639_language_code elif rec == EIT_COMPONENT_DESCRIPTOR: component_descriptor.append(data[pos + 8:pos + length]) elif rec == EIT_CONTENT_DESCRIPTOR: content_descriptor.append(data[pos + 8:pos + length]) elif rec == EIT_LINKAGE_DESCRIPTOR: linkage_descriptor.append(data[pos + 8:pos + length]) elif rec == EIT_PARENTAL_RATING_DESCRIPTOR: parental_rating_descriptor.append(data[pos + 2:pos + length]) elif rec == EIT_PDC_DESCRIPTOR: pdc_descriptor.append(data[pos + 5:pos + length]) else: print("MVC: EitFile: __parse: unsupported descriptor: %x %x" % (rec, length)) print("MVC: EitFile: __parse: %s" % (data[pos:pos + length])) pass pos += length if name_event_descriptor: name_event_descriptor = "".join(name_event_descriptor) else: name_event_descriptor = ("".join(name_event_descriptor_multi)).strip() self.eit['name'] = convertToUtf8(name_event_descriptor, name_event_codepage) if short_event_descriptor: short_event_descriptor = "".join(short_event_descriptor) else: short_event_descriptor = ("".join(short_event_descriptor_multi)).strip() self.eit['short_description'] = convertToUtf8(short_event_descriptor, short_event_codepage) if extended_event_descriptor: extended_event_descriptor = "".join(extended_event_descriptor) else: extended_event_descriptor = ("".join(extended_event_descriptor_multi)).strip() extended_event_descriptor = convertToUtf8(extended_event_descriptor, extended_event_codepage) if extended_event_descriptor: # This will fix EIT data of RTL group with missing line breaks in extended event description extended_event_descriptor = re.sub('((?:Moderat(?:ion:|or(?:in){0,1})|Vorsitz: |Jur(?:isten|y): |G(?:\xC3\xA4|a)st(?:e){0,1}: |Mit (?:Staatsanwalt|Richter(?:in){0,1}|den Schadenregulierern) |Julia Leisch).*?[a-z]+)(\'{0,1}[0-9A-Z\'])', r'\1\n\n\2', extended_event_descriptor) self.eit['description'] = extended_event_descriptor
-
Vielen lieben Dank an Euch beide, jetzt habe ich ordentlich zu tun.
-
Nur aus Neugierde: In welcher Sprache programmierst du?
-
Visual Basic 6.
Bin ein alter Programmierer (59 Jahre), der leider nie so gut war und dann dort stehengeblieben ist.
Obwohl ich jetzt Zeit habe und ich mir schon überlegt habe, nicht eine neue Version/Sprache zu erlernen.
Was empfiehlst Du bitte (Schwerpunkt Visual Basic)?