Skip to content

Instantly share code, notes, and snippets.

@gazugafan
Last active October 24, 2020 20:31
Show Gist options
  • Save gazugafan/566d7edd767c32d82d5e699a535631a0 to your computer and use it in GitHub Desktop.
Save gazugafan/566d7edd767c32d82d5e699a535631a0 to your computer and use it in GitHub Desktop.
Easily simulcast to a secondary destination from OBS using ffmpeg
echo off
SET search=%1
IF NOT DEFINED search SET search=D:\Streams\*.flv
SET url=%2
IF NOT DEFINED url SET url=rtmp://dallas.restream.io/live/YOUR_STREAM_KEY_HERE
echo Searching for latest file in %search%...
setlocal enabledelayedexpansion
SET ampm[AM]=1
SET ampm[PM]=2
REM Create a list of all files, recursively...
IF EXIST "%temp%\~dir1temp.dat" DEL /Q /F "%temp%\~dir1temp.dat"
FOR /F "TOKENS=*" %%A IN ('Dir /B /S /OD "%search%"') DO ECHO %%~TA, %%~FPNXA>>"%temp%\~dir1temp.dat"
REM Add timestamp to the list of all files...
IF EXIST "%temp%\~dirsorttemp2.dat" DEL /Q /F "%temp%\~dirsorttemp2.dat"
FOR /F "TOKENS=1,2,3,4,5,6,7,8 DELIMS=/:, " %%A IN (%temp%\~dir1temp.dat) DO ECHO %%C%%A%%B!ampm[%%F]!%%D%%E,%%G:%%H>>"%temp%\~dirsorttemp2.dat"
IF EXIST "%temp%\~dir1temp.dat" DEL /Q /F "%temp%\~dir1temp.dat"
REM Sort the file by timestamp...
IF EXIST "%temp%\~dirsorttemp.dat" DEL /Q /F "%temp%\~dirsorttemp.dat"
SORT "%temp%\~dirsorttemp2.dat">>"%temp%\~dirsorttemp.dat"
IF EXIST "%temp%\~dirsorttemp2.dat" DEL /Q /F "%temp%\~dirsorttemp2.dat"
REM Get the file from the last line...
FOR /F "TOKENS=2 DELIMS=," %%A IN (%temp%\~dirsorttemp.dat) DO (SET file=%%~A)
IF EXIST "%temp%\~dirsorttemp.dat" DEL /Q /F "%temp%\~dirsorttemp.dat"
IF NOT EXIST "%file%" GOTO :nofile
ECHO Found %file%
REM Calculate duration of file in progress by counting frames and FPS...
ECHO Calculating duration of file so far...
IF EXIST "%temp%\~durationtemp.dat" DEL /Q /F "%temp%\~durationtemp.dat"
ffprobe -show_entries stream=r_frame_rate,nb_read_frames -select_streams v -count_frames -of compact=p=0:nk=1 -v 0 "%file%" > "%temp%\~durationtemp.dat"
FOR /F "TOKENS=1,2,3 DELIMS=/|" %%A IN (%temp%\~durationtemp.dat) DO (
SET /A "duration=%%C/(%%A/%%B)"
)
IF EXIST "%temp%\~durationtemp.dat" DEL /Q /F "%temp%\~durationtemp.dat"
IF NOT DEFINED duration GOTO :noduration
IF %duration% LEQ 0 GOTO :noduration
ECHO Streaming file starting at %duration% seconds...
ffmpeg -hide_banner -loglevel warning -stats -re -ss %duration% -i "%file%" -acodec copy -vcodec copy -f flv %url%
ECHO Finished streaming
GOTO :exit
:noduration
ECHO Could not determine duration
GOTO :exit
:nofile
ECHO Could not find latest file
GOTO :exit
:exit
@gazugafan
Copy link
Author

Here's a ridiculous Windows batch file to make it easy to start streaming to a secondary destination from OBS using FFMPEG. It's actually surprisingly simple to accomplish. If you're already recording your stream locally, you can use FFMPEG to send the raw recording file to an RTMP server. THAT'S IT! There's no re-encoding necessary, so it's very light on CPU usage. You just need the bandwidth to be sending the same stream to multiple destinations at once.

There are a couple problems that make this annoying to do everytime, though, which this batch file completely automates...

  1. You need to figure out which recording file to stream, and copy/paste the path in the FFMPEG command... Kind've a pain to do everytime. If you're like me, you have your stream recordings organized into sub-folders like D:\Streams\year\month\day\time.flv. This batch file starts by figuring out which file is the newest in the specified folder or sub-folders--a shockingly complex thing to do via a Windows batch file. Phew!

  2. By default, FFMPEG will start streaming the file from the beginning. So, if you start recording, and then it takes you 15 seconds to run the FFMPEG command to start streaming the recording file, there will be a 15 second delay added to the resulting stream. To fix this, you can instruct FFMPEG to start streaming at a certain duration into the video, or even a certain duration from the end of the video. However, because the file is still being actively written, FFMPEG can't easily determine how long the video is. There's actually no way to get FFMPEG to start at the end of a file still being written. The workaround is to use FFPROBE to count how many frames have been written so far, and then calculate the current duration of the video based on the framerate. We can then instruct FFMPEG to start at this duration, which will be very close to the end of the file. The batch file does all of this.

SETUP...
You'll need FFMPEG installed and added to your global PATH... You should be able to run ffmpeg and ffprobe on the command line from any folder. Or, if you really want, add the full path to them on lines 43 and 54. Then, create the batch file above. Either place it wherever is convenient to run it from, or also add it to your global PATH.

You can either fill in the default "search" and "url" variables on lines 4 and 7, or you can specify them as the first and second command line arguments. Search is the location and file pattern to use when searching for the newest recording file, and url is the RTMP destination to stream to. You'll typically add your stream key to the end of the server URL. If you fill them in, you can just double-click the .bat file to run it.

If you haven't already, in OBS, under Settings > Output, specify a recording path. Set the recording quality to "same as stream" to prevent a separate encoding process from happening. FLV recording format works well for me.

USAGE...
Start streaming like normal in OBS. If this doesn't also start recording automatically, then start recording as well. Now just run the batch file to also stream to the secondary destination. DONE! SIMPLE!

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