diff --git a/README.md b/README.md index 1d278b4..94615a9 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,29 @@ # stream-scripts -Scripts to help automate my cursed streaming setup \ No newline at end of file +This is a set of scripts to help automate my cursed streaming setup. It's divided into two parts: + +- The "client" side, ie my desktop. This part spews video and audio minimally compressed over the LAN to the server side. +- The "server" side, which does all the heavy lifting to reduce the load on my desktop. + +## Requiremens + +- ffmpeg +- pulseaudio +- bash +- Lua (optional) + +## Client side. + +Included are two scripts, `recordscreen.sh`, and `paremap.lua`. + +`recordscreen.sh` is fairly self-explanatory, it records the screen, pulls audio from pulseaudio, and spews it over the LAN. Doesn't take any arguments, but you'll need to modify it for your needs if you're going to use it yourself. + +`paremap.lua` is less obvious. I listen to music when I stream games, and I want to be able to keep that separate for any actual recordings, for both legal reasons potential future technical reasons. This script will automatically shift over any matching applications to the third, not-included part of the client setup, detailed below. + +In order to keep game audio (or whatever else) separate from the rest of my system, I'm using the pulseaudio `module-combine-sink` module, which just creates a secondary sink that also outputs to my speakers/headphones, but can be recorded from separately. To set one up, use `load-module module-combine-sink` in your default.pa. + +## Server side. + +`record.sh` is a straightforward recording program that won't waste tonnes of space. It takes input over the LAN and records it to disk, with all the audio streams intact. Takes the prefix as an argument, so it can label the file. + +`stream.sh` is more ... interesting. It does everything that record.sh does, but also spews the video and one audio track to a stream URL of your choice. Takes the file prefix, and a stream URL, as arguments. diff --git a/client/paremap.lua b/client/paremap.lua new file mode 100755 index 0000000..f6c6b2f --- /dev/null +++ b/client/paremap.lua @@ -0,0 +1,25 @@ +#!/usr/bin/env lua +local games = {"mpv Media Player"} +for k,v in pairs(games) do + games[v] = true +end + +local sinkname = "combined" + +local running = {} +local input +for line in io.popen("pactl list sink-inputs 2>&1","r"):read("*a"):gmatch("[^\n]+") do + if line:match("Sink Input #(%d+)") then + input = line:match("Sink Input #(%d+)") + elseif line:match('application.name = "([^"]+)') then + running[line:match('application.name = "([^"]+)')] = input + end +end + +for k,v in pairs(running) do + if games[k] then + print("Match",k) + print(string.format("pacmd move-sink-input '%d' '%s'",v,sinkname)) + os.execute(string.format("pacmd move-sink-input '%d' '%s'",v,sinkname)) + end +end diff --git a/client/recordscreen.sh b/client/recordscreen.sh new file mode 100755 index 0000000..900aff7 --- /dev/null +++ b/client/recordscreen.sh @@ -0,0 +1,34 @@ +#!/bin/bash +monitor=$(pactl list short sources | grep output | grep monitor | cut -d ' ' -f 2) +mic=$(pactl list short sources | grep input | cut -d ' ' -f 2) +combined=$(pactl list short sources | grep combined | cut -d ' ' -f 2) +echo $monitor $mic $combined +ffmpeg \ +-hide_banner \ +-thread_queue_size 512 \ +-video_size 1920x1200 \ +-framerate 30 \ +-f x11grab \ +-i :0.0+1050+0 \ +-thread_queue_size 512 \ +-f pulse \ +-channel_layout stereo \ +-i "$monitor" \ +-thread_queue_size 512 \ +-f pulse \ +-channel_layout stereo \ +-i "$mic" \ +-thread_queue_size 512 \ +-f pulse \ +-channel_layout stereo \ +-i "$combined" \ +-c:a aac \ +-b:a 256k \ +-c:v libx264rgb \ +-crf 0 \ +-preset ultrafast \ +-f mpegts \ +-map 0 \ +-map 1 \ +-map 2 \ +-map 3 tcp://10.0.1.22:9999 diff --git a/server/record.sh b/server/record.sh new file mode 100755 index 0000000..2acc621 --- /dev/null +++ b/server/record.sh @@ -0,0 +1,18 @@ +#!/bin/bash +ofile="$1-$(date +%Y-%m-%dT%H-%M-%S).mkv" +ffmpeg \ +-hide_banner \ +-protocol_whitelist rtp,file,udp,crypto,tcp \ +-listen 1 \ +-i tcp://10.0.1.22:9999?listen,overrun_nonfatal \ +-c:v libx264 -pix_fmt yuv420p -threads 0 \ +-map 0 \ +-c:a copy \ +-crf 18 \ +-tune zerolatency \ +-preset slow \ +-maxrate 7.5M \ +-bufsize 35M \ +-max_muxing_queue_size 9999 \ +"$ofile" +echo "$ofile" diff --git a/server/stream.sh b/server/stream.sh new file mode 100755 index 0000000..dbd369a --- /dev/null +++ b/server/stream.sh @@ -0,0 +1,33 @@ +#!/bin/bash +ofile="$1-$(date +%Y-%m-%dT%H-%M-%S).mkv" +ffmpeg \ +-hide_banner \ +-protocol_whitelist rtp,file,udp,crypto,tcp \ +-listen 1 \ +-i tcp://10.0.1.22:9999?listen,overrun_nonfatal \ +-filter_complex '[0:v]split=2[v1][v2];[0:a:0]asplit=2[a1][a2];[v2]scale=w=1280:h=-1[v3]' \ +-map '[v1]' \ +-map '[a1]' \ +-map '0:a:1' \ +-map '0:a:2' \ +-c:v libx264 -pix_fmt yuv420p -threads 0 \ +-c:a libopus -b:a 128k \ +-crf 18 \ +-tune zerolatency \ +-preset slow \ +-maxrate 7.5M \ +-bufsize 35M \ +-max_muxing_queue_size 9999 \ +"$ofile" \ +-map '[v3]' \ +-map '[a2]' \ +-c:v libx264 -pix_fmt yuv420p -threads 0 \ +-c:a aac -b:a 128k \ +-crf 18 \ +-tune zerolatency \ +-preset slow \ +-maxrate 3.5M \ +-bufsize 35M \ +-f flv \ +"$2" +echo "$ofile"