Skip to content

Instantly share code, notes, and snippets.

@anotherjesse
Created September 25, 2021 13:35
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save anotherjesse/71d7f2615c3f46792a28dc76d6fbf9b5 to your computer and use it in GitHub Desktop.
Save anotherjesse/71d7f2615c3f46792a28dc76d6fbf9b5 to your computer and use it in GitHub Desktop.
golang ffmpeg imagepipe streaming

using golang to create image pipe for ffmpeg

If you want to stream a slideshow using ffmpeg, it seems like one easy way to do it is to create an imagepipe of the files.

This can then be streamed to twitch.tv or youtube ... https://trac.ffmpeg.org/wiki/StreamingGuide

This sample cycles between images on disk

usage

go run main.go -duration 1.5 -fps 25 *.png | ./stream.sh twitch_streaming_key_goes_here

thoughts

  • if the FPS is too low, it won't actually send enough data to cause images to be read often enough (it seems)
  • ffmpeg will rescale the images to the resolution specified in stream.sh
  • ffmpeg seems want the imagepipe (all the images) to be the same format (although it will scale each independantly)
package main
import (
"bufio"
"flag"
"os"
"time"
)
func main() {
fps := flag.Float64("fps", 10, "frames to send per second")
duration := flag.Float64("duration", 2, "seconds to display an image")
flag.Parse()
frames := int(*fps * *duration)
delay := time.Second / time.Duration(*fps)
out := bufio.NewWriterSize(os.Stdout, 4096)
for {
for _, f := range flag.Args() {
data, err := os.ReadFile(f)
if err == nil {
for i := 0; i < frames; i++ {
out.Write(data)
out.Flush()
time.Sleep(delay)
}
}
}
}
}
#!/bin/bash
stream_key="$1" # key will be passed as an agument from the command line
stream_server="iad05.contribute.live-video.net" # see https://stream.twitch.tv/ingests for list
threads="2" # max 6
cbr="3000k" # constant bitrate (should be between 1000k–3000k)
quality="medium" # one of the many FFmpeg presets
loglevel="warning" # supress unecessary information from printing
ffmpeg \
-f image2pipe -i - \
-loglevel "${loglevel}" \
-f flv \
-vcodec libx264 -b:v ${cbr} \
-minrate ${cbr} -maxrate ${cbr} -pix_fmt yuv420p \
-preset "${quality}" -tune film \
-strict normal \
-bufsize ${cbr} \
"rtmp://${stream_server}/app/${stream_key}"
@anotherjesse
Copy link
Author

https://stackoverflow.com/questions/46397240/ffmpeg-image2pipe-producing-broken-video is interesting

cat 2017*.png | ./ffmpeg -f image2pipe -framerate 1 -i - -c:v libx264 -vf format=yuv420p -r 25 -movflags +faststart out.mp4
  • Use the -framerate input option instead of -r for image2pipe demuxer.
  • Many players have trouble with such low frame rate MP4. Add the -r output option to give it a more normal output rate. ffmpeg will duplicate frames to match but it will still look as if it is 1 fps.
  • Add -vf format=yuv420p (or the alias -pix_fmt yuv420p) to make the output use a widely compatible pixel format.
  • Use -movflags +faststart to enable faster starting playback.

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