charmbracelet / charmbracelet/vhs

empty gif after ffmpeg error "Number of frames to loop is not set"

Open
#581 4 comments 0 reactions 1 assignee Claimed by @raphamorim View on GitHub
bug
Dominant language
Go
Stars
20.9k
Forks
474
Avg merge
4d 1h
Merged PRs (30d)
2

Description

Original issue was made by @TLINDEN in https://github.com/charmbracelet/freeze/issues/168 and it was moved to VHS.

**Describe the bug**
I have made a rather long tape file which worked fine up to a certain point. But I am unable to find the section of the file which causes the issue. If I comment out all sections, only let one section uncommented and then execute vhs, then it works every time. However, if all sections are enabled, then it fails. So I think the tape file has no errors.

When the issue happens, an empty gif will be created and ffmeg shows an error message.

**To Reproduce**
Steps to reproduce the behavior:
1. Clone https://github.com/tlinden/anydb/
2. `git checkout feature/vhs-demo`
3. `go build`
4. `cd demo`
5. `make` (this actually executes `vhs`)

**Expected behavior**
A gif should have been created.

**Screenshots**
```default
[..]
Sleep 4s

Creating demo.gif...
ffmpeg version 7.0.2-3ubuntu1 Copyright (c) 2000-2024 the FFmpeg developers
built with gcc 14 (Ubuntu 14.2.0-2ubuntu1)
configuration: --prefix=/usr --extra-version=3ubuntu1 --toolchain=hardened --libdir=/usr/lib/x86_64-linux-gnu --incdir=/usr/include/x86_64-linux-gnu --arch=amd64 --enable-gpl --disable-stripping --disable-libmfx --disable-omx --enable-gnutls --enable-libaom --enable-libass --enable-libbs2b --enable-libcdio --enable-libcodec2 --enable-libdav1d --enable-libflite --enable-libfontconfig --enable-libfreetype --enable-libfribidi --enable-libglslang --enable-libgme --enable-libgsm --enable-libharfbuzz --enable-libmp3lame --enable-libmysofa --enable-libopenjpeg --enable-libopenmpt --enable-libopus --enable-librubberband --enable-libshine --enable-libsnappy --enable-libsoxr --enable-libspeex --enable-libtheora --enable-libtwolame --enable-libvidstab --enable-libvorbis --enable-libvpx --enable-libwebp --enable-libx265 --enable-libxml2 --enable-libxvid --enable-libzimg --enable-openal --enable-opencl --enable-opengl --disable-sndio --enable-libvpl --enable-libdc1394 --enable-libdrm --enable-libiec61883 --enable-chromaprint --enable-frei0r --enable-ladspa --enable-libbluray --enable-libcaca --enable-libdvdnav --enable-libdvdread --enable-libjack --enable-libpulse --enable-librabbitmq --enable-librist --enable-libsrt --enable-libssh --enable-libsvtav1 --enable-libx264 --enable-libzmq --enable-libzvbi --enable-lv2 --enable-sdl2 --enable-libplacebo --enable-librav1e --enable-pocketsphinx --enable-librsvg --enable-libjxl --enable-shared
libavutil 59. 8.100 / 59. 8.100
libavcodec 61. 3.100 / 61. 3.100
libavformat 61. 1.100 / 61. 1.100
libavdevice 61. 1.100 / 61. 1.100
libavfilter 10. 1.100 / 10. 1.100
libswscale 8. 1.100 / 8. 1.100
libswresample 5. 1.100 / 5. 1.100
libpostproc 58. 1.100 / 58. 1.100
[Parsed_loop_6 @ 0x6058b1b78c40] Number of frames to loop is not set!
[Parsed_loop_8 @ 0x6058b1b79240] Number of frames to loop is not set!
Input #0, image2, from '/tmp/vhs3282649779/frame-text-%05d.png':
Duration: 00:07:01.12, start: 0.000000, bitrate: N/A
Stream #0:0: Video: png, rgba(pc, gbr/bt709/iec61966-2-1), 1044x837, 25 fps, 25 tbr, 25 tbn
Input #1, image2, from '/tmp/vhs3282649779/frame-cursor-%05d.png':
Duration: 00:07:01.12, start: 0.000000, bitrate: N/A
Stream #1:0: Video: png, rgba(pc, gbr/bt709/iec61966-2-1), 1044x837, 25 fps, 25 tbr, 25 tbn
Input #2, lavfi, from 'color=#171717:s=1200x1000':
Duration: N/A, start: 0.000000, bitrate: N/A
Stream #2:0: Video: wrapped_avframe, yuv420p, 1200x1000 [SAR 1:1 DAR 6:5], 25 fps, 25 tbr, 25 tbn
Input #3, png_pipe, from '/tmp/vhs3282649779/bar.png':
Duration: N/A, bitrate: N/A
Stream #3:0: Video: png, rgb24(pc, gbr/unknown/unknown), 1200x1000, 25 fps, 25 tbr, 25 tbn
Input #4, png_pipe, from '/tmp/vhs3282649779/mask.png':
Duration: N/A, bitrate: N/A
Stream #4:0: Video: png, gray(pc, gbr/unknown/unknown), 1200x1000, 25 fps, 25 tbr, 25 tbn
Stream mapping:
Stream #0:0 (png) -> overlay
Stream #1:0 (png) -> overlay
Stream #2:0 (wrapped_avframe) -> scale:default
Stream #3:0 (png) -> loop:default
Stream #4:0 (png) -> loop:default
paletteuse:default -> Stream #0:0 (gif)
Press [q] to stop, [?] for help
[Parsed_loop_6 @ 0x706834019100] Number of frames to loop is not set!
[Parsed_loop_8 @ 0x7068340197c0] Number of frames to loop is not set!

Host your GIF on vhs.charm.sh: vhs publish .gif
```
**Desktop (please complete the following information):**
- OS: Kubuntu 24.10
- Browser: chromium
- `vhs version v0.9.0 (a5f09b2)`

**Additional context**
Many thanks for this awesome program, I love it! :)

## Commentary

Ok, I have extracted the precise ffmpeg commandline executed by vhs:

```shell
ffmpeg -y -r 50 -start_number 1 -i /tmp/vhs3763011057/frame-text-%05d.png -r 50 \
-start_number 1 -i /tmp/vhs3763011057/frame-cursor-%05d.png -f lavfi -i \
color=#171717:s=1200x1000 -i /tmp/vhs3763011057/bar.png -i /tmp/vhs3763011057/mask.png \
-filter_complex "[0][1]overlay[merged]; [merged]scale=1080:850:force_original_aspect_ratio=1[scaled];
[scaled]fps=50,setpts=PTS/1.000000[speed];
[speed]pad=1200:970:(ow-iw)/2:(oh-ih)/2:#29283b[padded];
[padded]fillborders=left=60:right=60:top=60:bottom=60:mode=fixed:color=#29283b[padded] ;
[3]loop=-1[loopbar]; [loopbar][padded]overlay=0:30[withbar] ;
[4]loop=-1[loopmask]; [withbar][loopmask]alphamerge[rounded] ;
[2]scale=1200:1000[bg]; [bg][rounded]overlay=(W-w)/2:(H-h)/2:shortest=1[withbg] ;
[withbg]split[plt_a][plt_b]; [plt_a]palettegen=max_colors=256[plt];
[plt_b][plt]paletteuse[palette]" -map "[palette]" demo.gif
```

I also saved the dir `/tmp/vhs3763011057/` containing the png frame images away. Then I run the ffmpeg command myself which leads to the same error as above.

I also looked if the provided frame and cursor images matched - they did, that is, no image was missing. There were 14514 text and 14514 cursor frames.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.