Video Header auslesen ersetzen

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Dami123
User
Beiträge: 225
Registriert: Samstag 23. Februar 2013, 13:01

Ich hab mir pytube geholt und etwas damit gespielt.
Hab dabei eine zweite Download Funktion geschrieben, welche in der Lage ist, nur bestimmte Teile eines Video zu downloaden.
Bei einem 10min. Video z.B. 3:45-4:21.
Der Download funktioniert auch soweit, doch ist das Video nicht abspielbar. Ich schätze das liegt an den Header Informationen des .mp4.
Um nur einen Part vom Video zu downloaden, muss ich Bytes überspringen und somit essentielle Informationen, die das Vid zum abgespielt benötigt.

Meine Frage: Kann ich einfach eine selbstgeschriebene oder kopierte Header-Datei in das Vid reinsetzen?
Ggf. auch den originalen Header.
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

So einfach ist das nicht. Du kannst nicht einfach den header nehmen und so vorn dann klatschen. Der muss aktualisiert werden.
Videos kann man auch nicht einfach byte-weise schneiden. Du must schon den Anfang eines frames bzw. den Anfang eines bestimmten frame Typs treffen. Z.b. auf ein I-Frame.
Kommt auf das container-format und den verwendeten codec an.

Dan beste wird wohl sein eine externes Modul dafür zu nehmen.

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Dami123
User
Beiträge: 225
Registriert: Samstag 23. Februar 2013, 13:01

Hab ich mir schon gedacht.
Die Header und Codecs, die das jeweilige Format benötigt, werden verwendet um dem Abspielmedium zu weisen.
Die jeweiligen Bytes enthalten doch trotzdem die einzelnen Frames. Könnte ich nicht einfach diese lesen und weiterverarbeiten?
BlackJack

@Dami123: Das Wort „einfach” ist in diesem Zusammenhang wahrscheinlich der Stolperstein.
Sirius3
User
Beiträge: 17749
Registriert: Sonntag 21. Oktober 2012, 17:20

@Dami123: um mitten in eine Video zu springen mußt Du trotzdem den Header lesen, um zu wissen, wohin.
Der Aufbau eines mp4-Containers ist relativ simple (QuickTime File Format Specification), um alle Atome richtig zu interpretieren, ist aber etwas Fleiß nötig.
Hier mal ein Anfang:

Code: Alles auswählen

import struct

class MP4Container(object):
    def __init__(self, filename):
        with open(filename,'rb') as fd:
            self.read_tags(fd)

    def skip(self, fd, block_size):
        fd.seek(block_size,1)
        #data = fd.read(block_size)
        #print repr(data[:100])
        
    def read_tags(self, fd, block_size=1e99):
        rd = 0
        while rd<block_size:
            head = fd.read(8)
            if not head: break
            size,tag = struct.unpack('>i4s', head)
            print tag,size
            self.TAGS.get(tag,MP4Container.skip)(self, fd, size-8)
            rd+=size
            
    def time2sample(self, fd, block_size):
        assert block_size>8
        version, entry_count = struct.unpack('>ii',fd.read(8))
        print hex(version), entry_count
        assert block_size-8 == entry_count*8
        entries = zip(*[iter(struct.unpack('>%di'%(entry_count*2), fd.read(entry_count*8)))]*2)
        print entries
        
    TAGS = {
        'moov':read_tags,
        'trak':read_tags,
        'mdia':read_tags,
        'minf':read_tags,
        'stbl':read_tags,
        'stts':time2sample,
    }

MP4Container('beispiel.mp4')
Die eigentlichen Video-Daten stehen in einem oder mehreren großen mdat-Blöcken. Um zu wissen, wo die Frames zu einem bestimmten Zeitpunkt liegen, mußt Du die time-to-sample, sample-to-chunk, chunk-offset Tabellen einlesen.
Um daraus aber wieder ein lesbares mp4-File zu machen, mußt Du aber auch diese ganzen Tabellen entsprechen anpassen.
Dami123
User
Beiträge: 225
Registriert: Samstag 23. Februar 2013, 13:01

Kann mit den Werten leider noch nicht viel Anfangen.
Werde mich mal durch den mp4-Container Aufbau durcharbeiten und schauen, was sich da so machen lässt.

Danke für die Antwort 8)
Antworten