From 7be5c0993455ca8319e289abea9f6f882cce5399 Mon Sep 17 00:00:00 2001 From: mattmcw Date: Wed, 28 Dec 2022 11:41:42 -0500 Subject: [PATCH] Work in progress. Most of concept fleshed out --- .gitignore | 4 ++++ README.md | 29 +++++++++++++++++++++++++++++ common.sh | 45 +++++++++++++++++++++++++++++++++++++++++++++ default.env | 8 ++++++++ encode.sh | 39 +++++++++++++++++++++++++++++++++++++++ tv.sh | 43 +++++++++++++++++++++++++++++++++++++------ 6 files changed, 162 insertions(+), 6 deletions(-) create mode 100644 .gitignore create mode 100644 README.md create mode 100644 common.sh create mode 100644 default.env create mode 100644 encode.sh diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a3ffb71 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +.env +videos +input +*.sqlite \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..e75ec5d --- /dev/null +++ b/README.md @@ -0,0 +1,29 @@ +# Bash TV + +A simple RTMP streaming TV station in Bash. + +### Dependencies + +* Bash +* ffmpeg +* sqlite3 + +### Scripts + +#### tv.sh + +This script runs the TV station by looping over a collection of files in a directory and playing them randomly until they have all been played one time. + + +#### encode.sh + +This script can be run on a cronjob to detect new video files and re-encode them for playback in the tv station. + + +#### .env + +This configuration file contains the environment variables that are used by the other scripts to operate the streaming station. + +#### common.sh + +Script containing common helper functions and environment configuration scripts used between the `tv.sh` and `encode.sh` scripts. \ No newline at end of file diff --git a/common.sh b/common.sh new file mode 100644 index 0000000..84c9ca7 --- /dev/null +++ b/common.sh @@ -0,0 +1,45 @@ +#!/bin/bash + +if [ ! -f .env ]; then + cp default.env .env +fi + +source .env + +if [ ! -d "${INPUT}" ]; then + mkdir -p "${INPUT}" +fi + +if [ ! -d "${VIDEOS}" ]; then + mkdir -p "${VIDEOS}" +fi + +HISTORY_SETUP="CREATE TABLE IF NOT EXISTS history ( + video VARCHAR PRIMARY KEY, + playcount INT DEFAULT 0, + last INT +)" + +PLAYBACK_SETUP="CREATE TABLE IF NOT EXISTS playback ( + video VARCHAR PRIMARY KEY +)" + +SetupHistory () { + echo "${HISTORY_SETUP}" | sqlite3 "${HISTORY}" +} + +SetupPlayback () { + echo "${PLAYBACK_SETUP}" | sqlite3 "${PLAYBACK}" +} + +WipePlayback () { + rm -f "${PLAYBACK}" +} + +PDB () { + sqlite3 "${PLAYBACK}" "${1}" +} + +HDB () { + sqlite3 "${HISTORY}" "${1}" +} \ No newline at end of file diff --git a/default.env b/default.env new file mode 100644 index 0000000..0a1a19e --- /dev/null +++ b/default.env @@ -0,0 +1,8 @@ +WIDTH=720 +HEIGHT=480 +BUG="" +PLAYBACK="playback.sqlite" +HISTORY="history.sqlite" +VIDEOS="./videos" +INPUT="./input" +DESTINATION="rtmp://localhost/live" \ No newline at end of file diff --git a/encode.sh b/encode.sh new file mode 100644 index 0000000..95be108 --- /dev/null +++ b/encode.sh @@ -0,0 +1,39 @@ +#!/bin/bash + +set -e + +source ./common.sh + +count=$(ls -1 "${INPUT}/" | wc -l) + +if [ ${count} == 0 ]; then + echo "No files to process" + exit 1 +fi + +SCALE="scale=${WIDTH}:${HEIGHT}:force_original_aspect_ratio=decrease,pad=${WIDTH}:${HEIGHT}:(ow-iw)/2:(oh-ih)/2" + +Encode () { + name=$(basename "${1}") + nameNoExt=${name%.*} + now=$(date '+%s') + output="${VIDEOS}/${nameNoExt}_${now}.flv" + if [ -f "${VIDEOS}/${nameNoExt}"*".flv" ]; then + echo "File ${name} already exists" + return + fi + echo "Encoding ${name}..." + ffmpeg -i "${1}" -c:v libx264 -tune zerolatency -pix_fmt yuv420p -vf "${SCALE}" \ + -c:a aac -b:a 190k -ac 2 -ar 44100 \ + -f flv "${output}" +} + +fileList=$(mktemp) + +ls -1 "${INPUT}/" > "${fileList}" + +while read videoIn; do + Encode "${INPUT}/${videoIn}" +done < "${fileList}" + +rm -f "${fileList}" \ No newline at end of file diff --git a/tv.sh b/tv.sh index fe267e1..86c4679 100644 --- a/tv.sh +++ b/tv.sh @@ -1,10 +1,8 @@ #!/bin/bash -WIDTH=720 -HEIGHT=480 -BUG="" -PLAYBACK="playback.sqlite" -HISTORY="history.sqlite" +set -e + +source ./common.sh # Steps : enumerate all files at beginning of every playback decision # Compare to files in folder @@ -16,4 +14,37 @@ HISTORY="history.sqlite" # add to playback database # add to history database # start playback -# \ No newline at end of file +# + +Play () { + ffmpeg -threads 1 -re -i "${1}" -c copy -f flv "${DESTINATION}" +} + +AllFiles () { + fileList=$(mktemp) + ls -1 "${VIDEOS}/"*.flv > "${fileList}" + echo "${fileList}" +} + + + + +SetupHistory +SetupPlayback + +last="" + +while true; do + files=$(AllFiles) + fileCount=$(cat "${files}" | wc -l) + playbackCount=$(PDB "SELECT COUNT(*) FROM playback") + echo $playbackCount + + if [ ${fileCount} -eq 0 ]; then + echo "No files to play :(" + break + fi + break +done + +WipePlayback