Skip to content

GUACAMOLE-1370: guacenc output to stdout. - #687

Open
grintor wants to merge 3 commits into
apache:mainfrom
grintor:main
Open

grintor wants to merge 3 commits into
apache:mainfrom
grintor:main

Conversation

@grintor

@grintor grintor commented Jul 6, 2026

Copy link
Copy Markdown

Added a -o option to guacenc allowing the output path to be specified explicitly. It defaults to FILE.m4v as before when unspecified for backwards compatibility. Specifying "-" as the output path streams the encoded video to stdout. Normal MP4 (which is what's being used for file output still) doesn't support streaming, so we use fragmented MP4 here when outputting to stdout. This paves the way to streaming that stdout to a video player or even the browser in real time as it's being encoded.

Comment thread src/guacenc/guacenc.c
Comment thread src/guacenc/video.c Outdated
Comment on lines +59 to +65
/* The container format cannot be guessed from a pipe URL and must be
* specified explicitly. The "ipod" container is used, matching the
* container that would be guessed from the ".m4v" extension of the output
* files normally produced */
bool is_pipe = (strncmp(path, "pipe:", 5) == 0);
const char* format_name = is_pipe ? "ipod" : NULL;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Is this an appropriate assumption to make universally, or should this be configurable, as well? Are there situations where users may want to stream in a format different than iPod?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

"ipod" was already an assumption being made universally before, just not explicitly. When writing to a file, the third argument to avformat_alloc_output_context2() is NULL so libavformat guesses the container from the extension of the output path. Since that was hardcoded to "FILE.m4v" it was always making the same guess based on ".m4v" -- 'ipod'. This is a pretty universally supported format, even in web browsers, so I think it's a good default. Maybe someone will want it to be configurable in the future, but we can just wait for that feature request.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I agree that it was assumed by virtue of the fact that all files were necessarily m4v files. Now we're giving folks an option on what to name the files, which implicitly allows them to also adjust the format - and we're giving them an option to pipe everything to stdout, but forcing them to use the ipod format when going to stdout.

I'm not going to block this PR from going through if you don't want to do this, it's just something that seems to be in the same spirit as the ability to send it to stdout, and change the filename.

[It's also worth noting that simply having the ability to send to stdout means that you could also pipe it back into ffmpeg and reformat it that way, but you may start to lose the fidelity of the video that way due to lossy encodings, etc.]

@necouchman

Copy link
Copy Markdown
Contributor

@grintor You may need to rebase this on top of the current main branch - there were some issues with the main branch there for a while, and the build check is currently failing.

@grintor

grintor commented Sep 15, 2026

Copy link
Copy Markdown
Author

Ok this latest commit closes GUACAMOLE-974 in addition to the GUACAMOLE-1370 the original pull request by adding your requested feature. I also noticed that my original pull request closes GUACAMOLE-973 as well.

Added a -o option to guacenc allowing the output path to be specified explicitly.
It defaults to FILE.m4v as before when unspecified for backwards compatibility.
Specifying "-" as the output path streams the encoded video to stdout.
Added a -c option selecting the libavcodec encoder (default "mpeg4") and a -F
option selecting the libavformat container, mirroring ffmpeg's -c:v and -f.
The container is otherwise guessed from the output filename's extension, or
defaults to "ipod" when streaming to a pipe, which has no extension. Generated
output filenames use the chosen container's conventional extension, and
unknown format names are rejected before any encoding begins.

Restored the refusal to overwrite existing output files, which was lost in the
migration to libavformat but is still documented in the man page.
@grintor

grintor commented Sep 15, 2026

Copy link
Copy Markdown
Author

Ok the commits are on top of the current main branch now.

@vlouvet

vlouvet commented Sep 15, 2026

Copy link
Copy Markdown

I built b248d24 on Ubuntu 24.04 (FFmpeg 6.1.1, libvpx 1.14.0) and ran it against a small synthetic recording and a 1280x720 one. Everything below was checked with ffprobe:

Command Result
guacenc -s 320x240 in.guac mpeg4 in in.guac.m4v, same as before
-c libvpx-vp9 -F webm VP9 in in.guac.webm
-c libvpx -F webm VP8 in in.guac.webm
-c libaom-av1 -F webm AV1 in in.guac.webm
-c libx264 -F mp4 H.264 in in.guac.mp4
-c libvpx-vp9 -o out.webm WebM, guessed from the extension
-c libvpx-vp9 -F webm -o - valid WebM on stdout
-o - (defaults) fragmented MP4 on stdout
-F notaformat rejected before encoding, exit 1
-c not_a_codec "Failed to locate codec", no file written
second run into an existing file refused, original left untouched

One thing I ran into: guacenc -c libvpx-vp9 in.guac with no -F still names the output in.guac.m4v, so the ipod muxer is picked and the header write fails:

[ipod @ ...] Could not find tag for codec vp9 in stream #0, codec not currently supported in container
guacenc: ERROR: Error occurred while writing output file header.

The man page does say the codec has to fit the container, so I don't think this needs to hold up the PR. Once it's merged I'd be glad to send a small follow-up under GUACAMOLE-2298 that picks the default extension from the codec when neither -F nor -o is given (VP8/VP9/AV1 to .webm), with unit tests.

Separately, and the same in 1.6.0: guacenc exits 0 even when every file fails (bad codec, codec/container mismatch, refusing to overwrite). That matters a bit more now that output can go to a pipe. I can open an issue for it if it's worth changing.

Thanks for adding the format option. It covers most of what I filed GUACAMOLE-2298 for.

@grintor

grintor commented Sep 15, 2026

Copy link
Copy Markdown
Author

Good call on the exit code @vlouvet
I added a fix here for it.

Sorry to duplicate your work on GUACAMOLE-2298 I hadn't seen that.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants