xat / castnow

commandline chromecast player
MIT License
3.81k stars 243 forks source link

'--tomp4' on mp4 files fails to load. #226

Closed mhertz closed 6 years ago

mhertz commented 6 years ago

I don't know if this is only a problem with some files or all mp4 files, but I cannot run mp4 files with '--tomp4' when i've tried it, and it fails with an error. Note, the files work on chromecast without '--tomp4', but I wanted to transcode because I wanted to add a ffmpeg audio normalization filter; dynaudnorm.

I tested with converting first the mp4 file to mkv with:

'ffmpeg -i test.mp4 -c:v copy -c:a copy out.mkv'

And this mkv works fine through castnow's '--tomp4'.

Also, side-question, the option "--ffmpeg-*" only is considered when using "--tomp4" right? Thanks in advance.

martin@arch ~/testing % DEBUG=castnow* ~/.castnow/lib/node_modules/castnow/index.js --tomp4 test.mp4
castnow volume step: 0.05 +0ms castnow launching... +0ms castnow:stdin [ { path: 'test.mp4' } ] +1ms castnow:localfile started webserver on address 192.168.0.2 using port 4100 +4ms castnow:transcode started webserver on address 192.168.0.2 using port 4103 +1ms castnow player status: loading plugins +0ms castnow player status: scanning +0ms castnow player status: connecting +14ms castnow player status: launching +60ms castnow player status: loading +2s castnow:transcode incoming request for path http://192.168.0.2:4100/0 +422ms castnow:transcode spawning ffmpeg -i - -vcodec h264 -f mp4 -movflags frag_keyframe+faststart -strict experimental pipe:1 +5ms castnow:localfile incoming request serving test.mp4 +9ms castnow:transcode finished transcoding +1s castnow player error: Error: Load failed at /home/martin/.castnow/lib/node_modules/castnow/node_modules/chromecast-player/api.js:104:19 at fn.onmessage (/home/martin/.castnow/lib/node_modules/castnow/node_modules/castv2-client/lib/controllers/request-response.js:27:7) at fn.emit (events.js:187:15) at Channel.onmessage (/home/martin/.castnow/lib/node_modules/castnow/node_modules/castv2-client/lib/controllers/controller.js:16:10) at Channel.emit (events.js:182:13) at Client.onmessage (/home/martin/.castnow/lib/node_modules/castnow/node_modules/castv2/lib/channel.js:23:10) at Client.emit (events.js:187:15) at PacketStreamWrapper.onpacket (/home/martin/.castnow/lib/node_modules/castnow/node_modules/castv2/lib/client.js:81:10) at PacketStreamWrapper.emit (events.js:182:13) at TLSSocket. (/home/martin/.castnow/lib/node_modules/castnow/node_modules/castv2/lib/packet-stream-wrapper.js:28:16) +960ms Error: Load failed

smblott-github commented 6 years ago

(I'm not an expert on this, but...)

What happens if you execute the ffmpeg command manually, does it work? It seems to be:

ffmpeg -i - -vcodec h264 -f mp4 -movflags frag_keyframe+faststart -strict experimental pipe:1
mhertz commented 6 years ago

Thanks for your reply smblott-github, and indeed that is the command that fails! Thank you! :)

I didn't thought it was this, because before i posted the issue-report, then I had tried that command, but I had changed the piped input to ffmpeg, to instead the direct file i.e. changed '-' to 'test.mp4', and then adding ' | mpv -' and that worked, but now I actually tried the unchanged line, like you suggested with ' | mpv -' after it, to check it plays, and added 'cat test.mp4 | ' infront, and indeed it fails now, though e.g. works with the mkv muxed version.

martin@arch ~ % cat test.mp4 | ffmpeg -i - -vcodec h264 -f mp4 -movflags frag_keyframe+faststart -strict experimental pipe:1 | mpv -

Now that I know that it's specifically the mp4 piping to ffmpeg that fails, then I searched for a solution(since it works with mp4 without the piping but directly), and I found this reply from the ffmpeg mailing-list:

kolychev <kolychev speechpro.com> writes:

I need to read video from pipe, cut into frames and send them to pipe. I have a video file video.mp4.

You generally cannot pipe mov (or mp4) files unless you used -movflags +faststart when encoding or if run tools/qt-faststart on the input file before piping it.

Carl Eugen

I'll have to make a shell-function/script which runs qt-faststart on the mp4 files first, before the castnow command then.

Thanks again! :)

Edit:

martin@arch ~ % qt-faststart -h                        
Usage: qt-faststart <infile.mov> <outfile.mov>
Note: alternatively you can use -movflags +faststart in ffmpeg

I tried changing the '-movflags' command castnow uses to only '+faststart', but it didn't work, and e.g. states:

[mov,mp4,m4a,3gp,3g2,mj2 @ 0x55ae5f182b40] stream 0, offset 0x30: partial file
[mov,mp4,m4a,3gp,3g2,mj2 @ 0x55ae5f182b40] Could not find codec parameters for stream 0 (Video: h264 (avc1 / 0x31637661), none, 832x468, 1401 kb/s): unspecified pixel format
Consider increasing the value for the 'analyzeduration' and 'probesize' options

I then tried adding: '-analyzeduration 2147483647 -probesize 2147483647' to my test command-line, which should be max values, but to no avail.

Finally I tested with the tip from the ffmpeg-list i.e. 'qt-faststart test.mp4 out.mp4' and the resulting file worked with my test command-line(piping mp4 with cat to ffmpeg and piping output to mpv) + it works with castnow's '--tomp4' also, so I just use that command first in a shell-function/script.

Thanks! :)

Btw, here's my updated shell-function(.bashrc/.zshrc) for least CPU intensive transcoding for files that don't work with castnow without transcoding(--tomp4). I use mkv because I tested it previously to help with something, either seeking or pausing, can't remember which. If no sub available it's just omitted - '--tomp4' doesn't make castnow autoload subs by default. Also, I have omitted the ffmpeg dynamic volume normalization filter I have added for myself for evening out highs and lows i.e. '--ffmpeg-af dynaudnorm':

castnow2() {
    if [ ${1: -4} == ".mp4" ]; then
        qt-faststart "$1" ~/video/out.mp4 >/dev/null
        castnow --tomp4 --ffmpeg-f matroska --ffmpeg-preset ultrafast --ffmpeg-tune fastdecode -subtitles "$(echo $1 | sed -e 's/\.[^.]*$//').srt" ~/video/out.mp4
        rm ~/video/out.mp4
    else
        castnow --tomp4 --ffmpeg-f matroska --ffmpeg-preset ultrafast --ffmpeg-tune fastdecode --subtitles "$(echo $1 | sed -e 's/\.[^.]*$//').srt" $1
    fi
}
mhertz commented 6 years ago

I'm closing this report, because it's not a bug but an issue with mp4 fileformat and piping, though maybe an option could be added to auto-run qt-faststart on the file first if possible. I just found an issue with normal use and this report, i.e. mp4 files encoded with hevc(x265) which would need --tomp4 to play, but doesn't work without running qt-faststart on it first. qt-faststart is included as a binary with ffmpeg btw and is very fast to run and can be fully automated. Thanks again!