Засунуть h264 в mp4 на python с gstreamer

Создаю пайп:

def encoder(name):
    pipeline = Gst.Pipeline()

    audioin = Gst.ElementFactory.make("appsrc", "audioin")
    videoin = Gst.ElementFactory.make("appsrc", "videoin")
    h264parse = Gst.ElementFactory.make("h264parse", "h264")
    alaw = Gst.ElementFactory.make("rawaudioparse", "alaw")

    faac = Gst.ElementFactory.make("faac", "faac")
    mux = Gst.ElementFactory.make("mp4mux", "mux")
    filesink = Gst.ElementFactory.make("filesink", "fsink")
    filesink.set_property("location", name + ".mp4")

    videoin.set_property("caps", Gst.caps_from_string('video/x-h264,width=1920,height=1080,framerate=9/1,stream-format=(string)avc'))

    audioin.set_property("caps", Gst.caps_from_string('audio/x-alaw,channels=1,rate=8000'))

    pipeline.add(videoin)
    pipeline.add(audioin)
    pipeline.add(alaw)
    pipeline.add(faac)
    pipeline.add(h264parse)
    pipeline.add(mux)
    pipeline.add(filesink)

    audioin.link(alaw)
    videoin.link(h264parse)
    h264parse.link(mux)
    alaw.link(faac)
    faac.link(mux)
    mux.link(filesink)

    return pipeline, audioin, videoin


    pipeline, audioin, videoin = encoder('filename')

Вот тут из reader.video, reader.audio получаю данные и пихаю в буфер

async def convert(reader):
    async def readforever(stream, cb):
        while not stream.at_eof():
            cb(await stream.read(2048))

    def push(src):
        def pushbuffer(data):
            print(rotating(), len(data), '      ', end="\r", flush=True)
            buf = Gst.Buffer.new_allocate(None, len(data), None)
            buf.fill(0, data)
            src.emit('push-buffer', buf)
            return True
        return pushbuffer

    pipeline.set_state(Gst.State.PLAYING)
    print('started')
    await asyncio.gather(readforever(reader.video, push(videoin)), readforever(reader.audio, push(audioin)))

    videoin.emit("end-of-stream")
    audioin.emit("end-of-stream")
    print(pipeline)
    bus = pipeline.get_bus()

    print(await reader.picture.read())
    print(await reader.bort.read())
    print('eos')
    #bus.timed_pop_filtered(Gst.CLOCK_TIME_NONE, Gst.MessageType.EOS) # зависает
    pipeline.set_state(Gst.State.NULL)

Лог gstreamer говорит что данные пришли, но в файле нет ничего.


Ответы (1 шт):

Автор решения: eri

Нужно сделать ворэраунд на баг https://bugzilla.gnome.org/show_bug.cgi?id=659489

h264parse = Gst.ElementFactory.make("h264parse", "h264")
GstBase.BaseParse.set_infer_ts(h264parse, True)
GstBase.BaseParse.set_pts_interpolation(h264parse, True)

И пропустить входящий поток через queue

pipeline = Gst.Pipeline()
audioin = Gst.ElementFactory.make("appsrc", "audioin")
videoin = Gst.ElementFactory.make("appsrc", "videoin")
h264parse = Gst.ElementFactory.make("h264parse", "h264")
GstBase.BaseParse.set_infer_ts(h264parse, True)
GstBase.BaseParse.set_pts_interpolation(h264parse, True)
alaw = Gst.ElementFactory.make("alawdec", "alaw")
faac = Gst.ElementFactory.make("faac", "faac")
mux = Gst.ElementFactory.make("mp4mux", "mux")
filesink = Gst.ElementFactory.make("filesink", "fsink")
filesink.set_property("location", name + ".mp4")
vq = Gst.ElementFactory.make('queue', 'vq')
aq = Gst.ElementFactory.make('queue', 'aq')
vf = Gst.ElementFactory.make("capsfilter", 'vf')
af = Gst.ElementFactory.make("capsfilter", 'af')
vf.set_property("caps", Gst.caps_from_string('video/x-h264,width=1920,height=1080,framerate=9/1,stream-format=(string)avc'))
af.set_property("caps", Gst.caps_from_string('audio/x-alaw,channels=1,rate=8000'))
pipeline.add(videoin)
pipeline.add(vq)
pipeline.add(vf)
pipeline.add(aq)
pipeline.add(af)
pipeline.add(audioin)
pipeline.add(alaw)
pipeline.add(faac)
pipeline.add(h264parse)
pipeline.add(mux)
pipeline.add(filesink)
audioin.link(aq)
aq.link(af)
af.link(alaw)
videoin.link(vq)
vq.link(h264parse)
h264parse.link(mux)
alaw.link(faac)
faac.link(mux)
mux.link(filesink)
return pipeline, audioin, videoin
→ Ссылка