Streampunk / beamcoder

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

muxerstream and MP4 incompatibility #46

Open ccantill opened 4 years ago

ccantill commented 4 years ago

Sorry to bother you again... So I'm successfully transcoding an MKV file to MP4 (copying the videostream and transcoding the audio), but now I'm unable to get a working MP4 output using muxerstreams. It only works fine if I open the muxer with a file directly. There are some movflags that are required for this to work in ffmpeg; the following works fine from the command line: ffmpeg -loglevel trace -i media/DTS_HD_OUT_OF_THE_BOX_60-thedigitaltheater.mkv -f mp4 -c:v copy -movflags +empty_moov - | vlc

FFMPEG writes to a pipe and VLC immediately starts playing it (doesn't wait for the encoding to finish).

With beamcoder, it doesn't work with those flags (I've also tried various combinations of +empty_moov, +faststart, +frag_keyframe and even +dash). Without empty_moov and frag_keyframe, I get the expected error of the muxer not supporting a non-seekable output. Adding those flags removes that error (so it's correctly picking them up), but the resulting file is not playable. FFprobe displays the following error: [mov,mp4,m4a,3gp,3g2,mj2 @ 0x555f94a37f00] Could not find codec parameters for stream 0 (Video: h264 (avc1 / 0x31637661), none, 1920x1080): unspecified pixel format The pixelformat is set correctly in the videostream object (outputVideoStream.codecpar.format === 'yuv420p').

Comparing the two files (only difference being one uses muxerstream and the other is written directly to file, movflags kept the same), I see quite a few offsets are 0 in the muxerstream result vs the direct file, and somewhere along the line the contents are shifted a couple of bytes (the muxerstream file is 24 bytes longer).

I've enabled trace logging in ffmpeg in the hopes to glean some insight into what it does differently, but I couldn't find anything. Any ideas as to what might be different?

scriptorian commented 4 years ago

Do you think this could be caused by the missing bitstream filter as mentioned in #35?

ccantill commented 4 years ago

I don't think so; according to the trace output from ffmpeg, bitstream filters are disabled anyway when using empty_moov: [mp4 @ 0x56177b989200] Empty MOOV enabled; disabling automatic bitstream filtering

ccantill commented 4 years ago

I'm not sure if this is relevant, but I did just notice that muxer.ctx_flags.UNSEEKABLE is false. I can't seem to set this from the javascript code though.

scriptorian commented 4 years ago

There is currently no 'setter' for muxer.ctx_flags. Reading the flag description it seems unlikely this is causing your trouble though?

Bahlinc-Dev commented 2 years ago

Something is still not right, and i'm getting the same thing described above. Outputting from a plain muxer to file works, but from muxerstream to file produces a non-playable file. At least if you are muxing video into mp4. Anyone figure out what is going on here?

Bahlinc-Dev commented 2 years ago

Ok, revisited this today. I managed to fix the muxerstream, but I'm not exactly sure of the root cause. I fixed by changing the buffer length in adapter.h. Looks like it is set to low. If i increase this to say, 4096, I get playable output and muxerstream seems to work correctly. There must be some kind of padding that gets added to the avio_context (in libav) when write() fills the buffer? I'm not sure, but with the default value of 1024 you WILL get garbled output. I would like to add some logging to announce when new data arrives from libav with no buffer space left to store it since that will break any streamed output as we have seen here.