Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support to encode timelapse videos with H.265 / HEVC #226

Open
epheterson opened this issue Jun 10, 2022 · 8 comments
Open

Support to encode timelapse videos with H.265 / HEVC #226

epheterson opened this issue Jun 10, 2022 · 8 comments
Projects

Comments

@epheterson
Copy link

Describe the solution you'd like
To have smaller timelapse video files to share when the print is done, it'd be great if we could start encoding with H.265 / HEVC. This will result in essentially the same quality video, but much smaller file size.

I understand the ffmpeg command line is now editable, but don't believe the Octoprint docker package ships with ffmpeg capable of h.265 encoding, so it would have to be re-compiled. Ideally H.265 could be a simple selection in the drop-down of advanced timelapse settings.

Additional context
Asked on OctoPrint github and was directed to send the request here:
OctoPrint/OctoPrint#4538

@LongLiveCHIEF
Copy link
Member

we're installing ffmpeg from the ubuntu repositories, which winds up being 4.1.9. According to the ffmpeg wiki

fmpeg needs to be built with the --enable-gpl --enable-libx265 configuration flags and requires x265 to be installed on your system

These flags do appear to be part of the ffmpeg configuration in the octoprint image:

docker run -it --rm --entrypoint /bin/sh octoprint/octoprint:latest 
# ffmpeg -version
ffmpeg version 4.1.9-0+deb10u1 Copyright (c) 2000-2022 the FFmpeg developers
built with gcc 8 (Debian 8.3.0-6)
configuration: --prefix=/usr --extra-version=0+deb10u1 --toolchain=hardened --libdir=/usr/lib/x86_64-linux-gnu --incdir=/usr/include/x86_64-linux-gnu --arch=amd64 --enable-gpl --disable-stripping --enable-avresample --disable-filter=resample --enable-avisynth --enable-gnutls --enable-ladspa --enable-libaom --enable-libass --enable-libbluray --enable-libbs2b --enable-libcaca --enable-libcdio --enable-libcodec2 --enable-libflite --enable-libfontconfig --enable-libfreetype --enable-libfribidi --enable-libgme --enable-libgsm --enable-libjack --enable-libmp3lame --enable-libmysofa --enable-libopenjpeg --enable-libopenmpt --enable-libopus --enable-libpulse --enable-librsvg --enable-librubberband --enable-libshine --enable-libsnappy --enable-libsoxr --enable-libspeex --enable-libssh --enable-libtheora --enable-libtwolame --enable-libvidstab --enable-libvorbis --enable-libvpx --enable-libwavpack --enable-libwebp --enable-libx265 --enable-libxml2 --enable-libxvid --enable-libzmq --enable-libzvbi --enable-lv2 --enable-omx --enable-openal --enable-opengl --enable-sdl2 --enable-libdc1394 --enable-libdrm --enable-libiec61883 --enable-chromaprint --enable-frei0r --enable-libx264 --enable-shared
libavutil      56. 22.100 / 56. 22.100
libavcodec     58. 35.100 / 58. 35.100
libavformat    58. 20.100 / 58. 20.100
libavdevice    58.  5.100 / 58.  5.100
libavfilter     7. 40.101 /  7. 40.101
libavresample   4.  0.  0 /  4.  0.  0
libswscale      5.  3.100 /  5.  3.100
libswresample   3.  3.100 /  3.  3.100
libpostproc    55.  3.100 / 55.  3.100

I'm not up to speed on actually running ffmpeg with this output option, but I'm wondering if it requires gpu access? That may mean you'd need additional configuration with docker to enable that capability.

Have you actually tried to run ffmpeg with those encoding options in the image? If so, what errors or output did you get?

I believe the ffmpeg in the image is configured correctly according to ffmpeg documentation, so this may just be more of a documentation isssue once we figure this out. This is the first time this has come up, so we appreciate any information you can provide beyond the feature request, in regards to what you've tried, and what you're results were with those attempts (including error messages or logs when relevant).

@LongLiveCHIEF
Copy link
Member

Actually, i missed the part where it said x265 needs to be installed on the system, and that's easy enough to fix by adding that package to the apt install step of the Dockerfile. I can definitely add that.

@LongLiveCHIEF LongLiveCHIEF added this to In Progress in Roadmap Jun 15, 2022
@LongLiveCHIEF LongLiveCHIEF moved this from In Progress to Ready for Review in Roadmap Jun 15, 2022
@LongLiveCHIEF
Copy link
Member

I've merged and deployed a new image with x265 dependency in the image. That should be all that was mising. Once the new image finishes building and deploying, can you pull it down and give this a shot?

Thanks!

@epheterson
Copy link
Author

epheterson commented Jun 16, 2022

Thanks, giving it a shot. I'm not positive what the best command is to use, some considerations:

  • Setting a constant bitrate will result in not necessarily saving any on the filesize. (To workaround this, I removed bitrate altogether to utilize default crf.)
  • Built-in variables for container format and filters may not be compatible
  • I can only test once per print

Do you know of a way to re-run the timelapse rendering so I can test multiple settings? Also do you know how to add the codec to the drop-down list for easy user selection? (I'd prefer to not have to use a custom ffmpeg command)

Starting with:
{ffmpeg} -framerate {fps} -i "{input}" -vcodec libx265 -threads {threads} -f {containerformat} -y {filters} "{output}"

Think I might want to try something closer to what the docs suggest, though:
ffmpeg -i input -c:v libx265 -crf 26 -preset fast -c:a aac -b:a 128k output.mp4

For us this would be something like:
{ffmpeg} -framerate {fps} -i "{input}" -c:v libx265 -crf 26 -preset fast -threads {threads} -f {containerformat} -y {filters} "{output}"

Unrelated, but to further save on unnecessary filesize I may want to reduce the resolution (no need for 1080p timelapse videos) using something like:
-vf scale=-1:720

@epheterson
Copy link
Author

Well, my first one made a file, and the file size is ~45% of MP4 size, but it doesn't play in Quicktime, though does play in VLC.

ffmpeg -i shows it's HEVC, correct framerate/resolution and 4092 kb/s (vs. default of 10000 kb/s):
Stream #0:0[0x1](und): Video: hevc (Main) (hev1 / 0x31766568), yuv420p(tv, progressive), 1920x1080, 4092 kb/s, 25 fps, 25 tbr, 12800 tbn (default)

Going to see if I can figure out why Quicktime / browser won't play it.

@epheterson
Copy link
Author

Got it! For hevc this must be included: -vtag hvc1

So the full modified line, with bitrate removed and -vtag hvc1 added is:
{ffmpeg} -framerate {fps} -i "{input}" -vcodec libx265 -vtag hvc1 -threads {threads} -f {containerformat} -y {filters} "{output}"

Thanks for adding the codec support! Do you know how we can go about making this an "official" option that's easy to select?

@LongLiveCHIEF
Copy link
Member

Well, if you're interested in doing a PR, then here's what I'd probably do.

  • create an env var for CAMERA_H265
  • modify the mjpg-streamer service script so it tests for this variable, and if set, then uses those args to start instead of the default

This is the basic approach mind you, there might be more logic needed there.

If this isn't something you can contribute, go ahead and open a feature request issue for add CAMERA_H265 env var start option, and link to this video, and I'll try to get to it.

@epheterson
Copy link
Author

Hey @LongLiveCHIEF thanks for the steps though I'm totally sure how to go about it. I've filed a new issue as you suggested: #228

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Roadmap
Ready for Review
Development

No branches or pull requests

2 participants