charmbracelet / vhs

Your CLI home video recorder 📼
MIT License
14.8k stars 249 forks source link

serve mode not working #439

Closed t-chab closed 6 months ago

t-chab commented 7 months ago

When I try to use vhs "serve" mode from the docker container, it fails with an ffmpeg error :

Starting SSH server on 0.0.0.0:1976
Starting server with GID: 1976, UID: 1976
Creating /tmp/vhs-882877197...
ffmpeg version 5.1.4-0+deb12u1 Copyright (c) 2000-2023 the FFmpeg developers
  built with gcc 12 (Debian 12.2.0-14)
  configuration: --prefix=/usr --extra-version=0+deb12u1 --toolchain=hardened --libdir=/usr/lib/x86_64-linux-gnu --incdir=/usr/include/x86_64-linux-gnu --arch=amd64 --enable-gpl --disable-stripping --enable-gnutls --enable-ladspa --enable-libaom --enable-libass --enable-libbluray --enable-libbs2b --enable-libcaca --enable-libcdio --enable-libcodec2 --enable-libdav1d --enable-libflite --enable-libfontconfig --enable-libfreetype --enable-libfribidi --enable-libglslang --enable-libgme --enable-libgsm --enable-libjack --enable-libmp3lame --enable-libmysofa --enable-libopenjpeg --enable-libopenmpt --enable-libopus --enable-libpulse --enable-librabbitmq --enable-librist --enable-librubberband --enable-libshine --enable-libsnappy --enable-libsoxr --enable-libspeex --enable-libsrt --enable-libssh --enable-libsvtav1 --enable-libtheora --enable-libtwolame --enable-libvidstab --enable-libvorbis --enable-libvpx --enable-libwebp --enable-libx265 --enable-libxml2 --enable-libxvid --enable-libzimg --enable-libzmq --enable-libzvbi --enable-lv2 --enable-omx --enable-openal --enable-opencl --enable-opengl --enable-sdl2 --disable-sndio --enable-libjxl --enable-pocketsphinx --enable-librsvg --enable-libmfx --enable-libdc1394 --enable-libdrm --enable-libiec61883 --enable-chromaprint --enable-frei0r --enable-libx264 --enable-libplacebo --enable-librav1e --enable-shared
  libavutil      57. 28.100 / 57. 28.100
  libavcodec     59. 37.100 / 59. 37.100
  libavformat    59. 27.100 / 59. 27.100
  libavdevice    59.  7.100 / 59.  7.100
  libavfilter     8. 44.100 /  8. 44.100
  libswscale      6.  7.100 /  6.  7.100
  libswresample   4.  7.100 /  4.  7.100
  libpostproc    56.  6.100 / 56.  6.100
Input #0, image2, from '/tmp/vhs1308650082/frame-text-%05d.png':
  Duration: 00:00:12.52, start: 0.000000, bitrate: N/A
  Stream #0:0: Video: png, rgba(pc), 1036x427, 25 fps, 25 tbr, 25 tbn
Input #1, image2, from '/tmp/vhs1308650082/frame-cursor-%05d.png':
  Duration: 00:00:12.52, start: 0.000000, bitrate: N/A
  Stream #1:0: Video: png, rgba(pc), 1036x427, 25 fps, 25 tbr, 25 tbn
Input #2, lavfi, from 'color=#171717:s=1200x600':
  Duration: N/A, start: 0.000000, bitrate: N/A
  Stream #2:0: Video: rawvideo (I420 / 0x30323449), yuv420p, 1200x600 [SAR 1:1 DAR 2:1], 25 tbr, 25 tbn
[NULL @ 0x55837b4a69c0] Unable to find a suitable output format for '/tmp/vhs-882877197'
/tmp/vhs-882877197: Invalid argument

Setup

To Reproduce Steps to reproduce the behavior:

#!/usr/bin/env bash

set -eEuxo pipefail

tape_file="/tmp/demo.tape"

# create a simple tape file
cat << EOF > "${tape_file}"
# Where should we write the GIF?
Output demo.gif

# Set up a 1200x600 terminal with 46px font.
Set FontSize 46
Set Width 1200
Set Height 600

# Type a command in the terminal.
Type "echo 'Welcome to VHS!'"

# Pause for dramatic effect...
Sleep 500ms

# Run the command by pressing enter.
Enter

# Admire the output for a bit.
Sleep 5s
EOF

# launch vhs docker container in background
docker run \
    -d \
    -p 1976:1976 \
    --rm \
    --name vhs \
    ghcr.io/ghcr.io/charmbracelet/vhs \
    serve

# send the tape file with ssh and expect a GIF result
ssh \
    -T \
    -p 1976 \
    localhost < "${tape_file}" > /tmp/demo.gif

Expected behavior

I was expecting to get a usable /tmp/demo.gif file instead of an empty file (because ffmpeg command failed as explained)

jimbobmcgee commented 6 months ago
Creating /tmp/vhs-882877197...

I think the attempt to use these constants for .gif, .mp4 and .webm here conflicts with the variable declaration here, so the tempfile value never actually gets the .gif extension.

As such, ffmpeg cannot infer the output type from the filename and would need the additional -f gif option passed to it (which serve does not give the option to do).

If the tmpfile manipulation in this switch is changed to use the string literals ".gif", ".mp4" and/or ".webm", then these would be included in the tempfile, and ffmpeg would infer the output type without needing the additional -f gif argument.

(Just a drive-by analysis, I don't know enough about the project to PR...)

t-chab commented 6 months ago

@jimbobmcgee : thanks a lot for the explanation. I tried to submit a PR, let's see what happens.

maaslalani commented 6 months ago

Great catch @jimbobmcgee and thank you for the PR @t-chab, I will merge.

nwithan8 commented 5 months ago

The Docker container is still broken since a new image hasn't been cut since this PR was merged.

t-chab commented 5 months ago

@nwithan8 : you can build an image from main branch as a workaround (this Dockerfile is a quick hack over the official one) :

FROM tsl0922/ttyd:alpine as ttyd
FROM alpine:latest as fontcollector

# Install Fonts
RUN apk add --no-cache \
    --repository=http://dl-cdn.alpinelinux.org/alpine/edge/main \
    --repository=http://dl-cdn.alpinelinux.org/alpine/edge/community \
    --repository=http://dl-cdn.alpinelinux.org/alpine/edge/testing \
    font-adobe-source-code-pro font-source-code-pro-nerd \
    font-dejavu font-dejavu-sans-mono-nerd \
    font-fira-code font-fira-code-nerd \
    font-hack font-hack-nerd \
    font-ibm-plex-mono-nerd \
    font-inconsolata font-inconsolata-nerd \
    font-jetbrains-mono font-jetbrains-mono-nerd \
    font-liberation font-liberation-mono-nerd \
    font-noto \
    font-roboto-mono \
    font-ubuntu font-ubuntu-mono-nerd \
    font-noto-emoji

FROM golang:1.22.2 as builder

RUN git clone https://github.com/charmbracelet/vhs \
    && cd vhs \
    && go build -o /tmp/vhs .

FROM debian:stable-slim

RUN apt-get update

# Add fonts
COPY --from=fontcollector /usr/share/fonts/ /usr/share/fonts

# Install latest ttyd
COPY --from=ttyd /usr/bin/ttyd /usr/bin/ttyd

# Expose port
EXPOSE 1976

# Create volume
VOLUME /vhs
WORKDIR /vhs

# Install Dependencies
RUN apt-get -y install ffmpeg chromium bash

# Create user
RUN useradd -u 1976 -U -s /bin/false vhs
# Mimic alpine default color option
RUN echo 'alias ls="ls --color"' >> ~/.bashrc
# Install
COPY --from=builder /tmp/vhs /usr/bin/

ENV VHS_PORT "1976"
ENV VHS_HOST "0.0.0.0"
ENV VHS_GID "1976"
ENV VHS_UID "1976"
ENV VHS_KEY_PATH "/vhs/vhs"
ENV VHS_AUTHORIZED_KEYS_PATH ""
ENV VHS_NO_SANDBOX "true"

ENTRYPOINT ["/usr/bin/vhs"]
nwithan8 commented 5 months ago

@t-chab No dice, need an prebuilt image, can't build it manually. Trying to set up an Unraid app template.

t-chab commented 5 months ago

@nwithan8 : Meanwhile you can fork this repo, and replace the Dockerfile with the one in previous comment. Then set up a Github Action, and you'll have a working image available on a public docker registry.

nwithan8 commented 5 months ago

Eh, I'd rather not have to maintain a fork of this project. Just wanted to make the maintainers aware that this patch (and I'm sure others) hasn't made its way into production yet because a new release hasn't been cut in a while.

maaslalani commented 5 months ago

Hey @t-chab @nwithan8! Thanks for the comments, just cut a new release of VHS with all the bug fixes.

nwithan8 commented 5 months ago

@maaslalani Thanks for putting out the new release. As a result, I was able to build an app template so Unraid users can easily run a VHS server on their Unraid machines: https://unraid.net/community/apps?q=vhs#r