Skip to content

Transcode server for remote - #611

Draft
whyboris wants to merge 10 commits into
mainfrom
transcode
Draft

Transcode server for remote#611
whyboris wants to merge 10 commits into
mainfrom
transcode

Conversation

@whyboris

@whyboris whyboris commented Dec 18, 2020

Copy link
Copy Markdown
Owner

Huge thank you to @cal2195 for his code 🙇

This code comes from his transcoding-video branch 🥇

This is meant to be released in tandem with whyboris/Video-Hub-App-remote#9 🤝

Help wanted

update: Thank you @cal2195 for the on-finished suggestion -- I think it fixed the below problem

When running this branch in tandem with the Remote - after a little bit (playing the video 10-20 times) the server fails:

x264 [error]: malloc of size 2840448 failed
Video encoding failed

I messed on my PC with the pagefile settings, so it could be me. But I also wonder if, since for every HTTP request that comes to this server, we're spawning a new ffmpeg process, and perhaps never killing it, something goes wrong? 😅

Help still wanted:

Also, I set '-frag_duration', '15' to test a different value, but originally it was 3600 ... I'm unsure about what it's meant to do - the unit is seconds, and 3600 is 1 hour which seems awfully long (though I still don't understand what the flag does) 😅

Documentation is conflicting (see comment in discussion below).

@cal2195

cal2195 commented Dec 18, 2020

Copy link
Copy Markdown
Collaborator

Sounds like you're correct - we need something like this to catch the connection closed event, and then .kill() the ffmpeg process, possibly with the correct signal: ⚠️

https://github.com/jshttp/on-finished

@cal2195

cal2195 commented Dec 18, 2020

Copy link
Copy Markdown
Collaborator

Also note, for MOV/MP4/ISMV (Smooth Streaming) muxer, -frag_duration is in _micro_seconds, not seconds! 😄

https://ffmpeg.org/ffmpeg-formats.html#Options-9

@whyboris

whyboris commented Dec 19, 2020

Copy link
Copy Markdown
Owner Author

@cal2195 the FFmpeg documentation seems confusing 😅

frag_duration duration
Set the length in seconds of fragments within segments (fractional value can be set).

-frag_duration duration
Create fragments that are duration microseconds long.

:trollface:

Also, microseconds !?!! 😱 that's 1,000,000 microseconds in 1 second ... that's a million :trollface: ... they must have messed up in the documentation, right? Especially that they allow fractional value ... right? 😖

@whyboris

whyboris commented Dec 19, 2020

Copy link
Copy Markdown
Owner Author

Thanks @cal2195 -- I think the on-finished did the trick: the server no longer crashes (no malloc error) 🤞 44ead95

@cal2195

cal2195 commented Dec 21, 2020

Copy link
Copy Markdown
Collaborator

@cal2195 the FFmpeg documentation seems confusing 😅

frag_duration duration
Set the length in seconds of fragments within segments (fractional value can be set).

-frag_duration duration
Create fragments that are duration microseconds long.

:trollface:

Also, microseconds !?!! 😱 that's 1,000,000 microseconds in 1 second ... that's a million :trollface: ... they must have messed up in the documentation, right? Especially that they allow fractional value ... right? 😖

The one that is in seconds is for the dash muxer, each muxer had it's own options. :) Only the one in seconds allows fractional values.

We want the mp4 muxer, which is in microseconds! 😄

@whyboris

Copy link
Copy Markdown
Owner Author

I don't know what's a sensible values (as measured in seconds is). Is there a way to tell whether the value affects anything?

I can't see any difference whether it was 3600 as originally, or when it's 15 :trollface: - what would I expect to happen when I change it? Perhaps it gets ignored if it's too short to matter, and any effect is only noticeable at values above 1 million (1second)?

Sorry to ask about questions that I should be able to research on my own -- but the documentation is so terse 😕 I glanced around online (not too long, just a quick search) and found nothing of value to explain.

Or if it's easier, please let me know how you figured this stuff out 🙇

@whyboris whyboris added the ⛑️ WIP Work in progress label Dec 23, 2020
Comment thread node/server.ts
'-crf', '17',
'-preset', 'ultrafast',
'-movflags', 'frag_keyframe+empty_moov+faststart',
'-frag_duration', '15',

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can probably remove this - I think it might have a sensible default anyway. We can change it later.

The idea with fragmenting, is that you can seek and stream much easier, without having to download the entire mp4 file before playback can begin. Each fragment contains metadata about the video, rather than all the metadata being store at the end of the file!

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can look into finding the best options, but if the code works as is, may as well use that for now!

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks Cal for looking at this again. I've paused this feature for a while because I had at least two days of trying hard with no success: getting the video to play in Chrome ✅ no problem 👌 but getting Safari on iOS (on my phone) to play anything was a no-go 😓 which is the sole purpose of this feature.

I'll come back to this with renewed energy once I move in to the new house (these few months have been busy).

😅 also I've been working on an image-centric analogous-to-VHA app this past month -- I want to finish it first before returning to this headache :trollface:

Comment thread node/server.ts
Comment on lines +106 to +133
app.get('/video', (req, res) => {
const seekTime = req.query.seek || 0;
const file = req.query.file || '';
// see https://trac.ffmpeg.org/wiki/Encode/H.264#a2.Chooseapreset for more options
const ffmpeg = spawn(ffmpegPath, [
'-ss', seekTime,
'-i', file,
'-f', 'mp4',
'-crf', '17',
'-preset', 'ultrafast',
'-movflags', 'frag_keyframe+empty_moov+faststart',
'-frag_duration', '15',
'pipe:1'
]);
res.writeHead(200, {
'Content-Type': 'video/mp4'
});
ffmpeg.stdout.pipe(res);
// error logging
ffmpeg.stderr.setEncoding('utf8');
ffmpeg.stderr.on('data', (data) => {
console.log(data);
});
onFinished(res, () => {
console.log('about to kill!');
ffmpeg.kill();
});
});

Check failure

Code scanning / CodeQL

Missing rate limiting High

This route handler performs
a system command
, but is not rate-limited.
@whyboris

Copy link
Copy Markdown
Owner Author

I intend to glance around to see whether sending video to the phone is easier in 2026 - after release of VHA 3.3.0 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

help wanted Extra attention is needed server ⛑️ WIP Work in progress

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants