Streampunk / beamcoder

Node.js native bindings to FFmpeg.
GNU General Public License v3.0
397 stars 76 forks source link

muxer.writeFrame not working with Audio Frames. Only working with Audio Packets #62

Open Rock-N-Troll opened 3 years ago

Rock-N-Troll commented 3 years ago

I have been trying to get the muxer.writeFrame function to accept uncompressed audio Frames instead of compressed audio Packets.

Performing await muxer.writeFrame(packet); works. No errors. Performing await muxer.writeFrame({frame: dec_result.frames[0]}); does not work. It leads to a segfault.

https://github.com/Streampunk/beamcoder/blob/20e28d29d3bf7933b8a250005c7f43fc6c73cc9d/types/Muxer.d.ts

     * Write media data to the file by sending a packet containing data for a media stream.
     * @param options Object containing a stream index property and a frame property of an
     * uncompressed Frame, which must contain the timestamps measured in the `time_base` of the stream.
     * @returns Promise that resolves to _undefined_ on success
     */
    writeFrame(options: { frame: Frame, stream_index: number }) : Promise<undefined>

The documentation suggests muxer.writeFrame should work with frames unless I'm missing something. Maybe it actually means video frames? Any input or sample code for using muxer.writeFrame with an audio frame object would be much appreciated.

    let audioDemuxer = await beamcoder.demuxer('file:input.mp3');

    let muxer = beamcoder.muxer({ filename: 'file:output.mp3' });

    let stream = muxer.newStream({
      name: 'mp3',
      time_base: [1, 44100 ],
      interleaved: true });
    Object.assign(stream.codecpar, {
      channels: 2,
      sample_rate: 44100,
      frame_size:1,
      format: 's16p',
      channel_layout: 'stereo',
      bit_rate: 128000
    });

    await muxer.openIO();
    await muxer.writeHeader();

    let packet = {};
    let decoder = beamcoder.decoder({ demuxer: audioDemuxer, stream_index: 0 });
    while (true) {
        packet = await audioDemuxer.read();
        if(packet == null){
            break;
        }
        let dec_result = await decoder.decode(packet);
         if (dec_result.frames.length === 0){ // Frame may be buffered, so flush it out
            dec_result = await decoder.flush();
         }

        //Frame Option: does not work even with variation on frame object/frame array passed
        for(var i=0; i < dec_result.frames.length; i++){
            //await muxer.writeFrame({frame: dec_result.frames[0], stream_index: 0 });
        }
        //Packet Option:works
        //await muxer.writeFrame(packet);
    }
Bahlinc-Dev commented 2 years ago

writeFrame is a little misleading. I think the muxer needs compressed data. After your "decode" operation, the data is uncompressed. If you run through an encoder again, it will be compressed again, and can then send to the muxer. The "packet" you are using is still compressed straight out of the demuxer, so it works.