Merge pull request #451 from junkman690/jellyfin-rffmpeg

jellyfin:rffmpeg initial release
This commit is contained in:
aptalca
2022-08-30 08:49:00 -04:00
committed by GitHub
27 changed files with 331 additions and 73 deletions
+2 -2
View File
@@ -4,8 +4,8 @@ on: [push, pull_request, workflow_dispatch]
env:
ENDPOINT: "linuxserver/mods" #don't modify
BASEIMAGE: "replace_baseimage" #replace
MODNAME: "replace_modname" #replace
BASEIMAGE: "jellyfin" #replace
MODNAME: "rffmpeg" #replace
jobs:
build:
+1 -1
View File
@@ -1,6 +1,6 @@
FROM scratch
LABEL maintainer="username"
LABEL maintainer="junkman690"
# copy local files
COPY root/ /
-23
View File
@@ -1,23 +0,0 @@
## Buildstage ##
FROM ghcr.io/linuxserver/baseimage-alpine:3.12 as buildstage
RUN \
echo "**** install packages ****" && \
apk add --no-cache \
curl && \
echo "**** grab rclone ****" && \
mkdir -p /root-layer && \
curl -o \
/root-layer/rclone.deb -L \
"https://downloads.rclone.org/v1.47.0/rclone-v1.47.0-linux-amd64.deb"
# copy local files
COPY root/ /root-layer/
## Single layer deployed image ##
FROM scratch
LABEL maintainer="username"
# Add files from buildstage
COPY --from=buildstage /root-layer/ /
+80 -17
View File
@@ -1,25 +1,88 @@
# Rsync - Docker mod for openssh-server
# rffmpeg - Docker mod for Jellyfin
This mod adds rsync to openssh-server, to be installed/updated during container start.
This mod adds rffmpeg to Linuxserver.io's Jellyfin https://github.com/linuxserver/docker-jellyfin.
In openssh-server docker arguments, set an environment variable `DOCKER_MODS=linuxserver/mods:openssh-server-rsync`
rffmpeg is a remote FFmpeg wrapper used to execute FFmpeg commands on a remote server via SSH. It is most useful in situations involving media servers such as Jellyfin (our reference user), where one might want to perform transcoding actions with FFmpeg on a remote machine or set of machines which can better handle transcoding, take advantage of hardware acceleration, or distribute transcodes across multiple servers for load balancing.
If adding multiple mods, enter them in an array separated by `|`, such as `DOCKER_MODS=linuxserver/mods:openssh-server-rsync|linuxserver/mods:openssh-server-mod2`
See https://github.com/joshuaboniface/rffmpeg for more details about rffmpeg
# Mod creation instructions
In Jellyfin docker arguments, set an environment variable `DOCKER_MODS=linuxserver/mods:jellyfin-rffmpeg`
* Fork the repo, create a new branch based on the branch `template`.
* Edit the `Dockerfile` for the mod. `Dockerfile.complex` is only an example and included for reference; it should be deleted when done.
* Inspect the `root` folder contents. Edit, add and remove as necessary.
* Edit this readme with pertinent info, delete these instructions.
* Finally edit the `.github/workflows/BuildImage.yml`. Customize the build branch, and the vars for `BASEIMAGE` and `MODNAME`.
* Ask the team to create a new branch named `<baseimagename>-<modname>`. Baseimage should be the name of the image the mod will be applied to. The new branch will be based on the `template` branch.
* Submit PR against the branch created by the team.
If adding multiple mods, enter them in an array separated by `|`, such as `DOCKER_MODS=linuxserver/mods:jellyfin-rffmpeg|linuxserver/mods:jellyfin-mod2`
This mod requires you to update the rffmpeg.yml located in "Your jellyfin config dir"/rffmpeg/rffmpeg.yml with your remote SSH username. You also need to add your authorized SSH file to "Your jellyfin config dir"/rffmpeg/.ssh/id_rsa"
## Tips and tricks
You can specify the remote SSH username and host using ENV, note currently only supports 1 host and doesn't overwrite values other than defaults:
* RFFMPEG_USER= remote SSH username
* RFFMPEG_HOST= remote server name or IP
* To decrease startup times when multiple mods are used, we have consolidated `apt-get update` down to one file. As seen in the [nodejs mod](https://github.com/linuxserver/docker-mods/tree/code-server-nodejs/root/etc/cont-init.d)
* Some images has helpers built in, these images are currently:
* [Openvscode-server](https://github.com/linuxserver/docker-openvscode-server/pull/10/files)
* [Code-server](https://github.com/linuxserver/docker-code-server/pull/95)
You also need to ensure that /cache inside the container is exported on the host so it can be mapped on the remote host. Eg for docker compose.
```yaml
volumes:
- "Your jellyfin config dir":/config
- "Your jellyfin config dir"/cache:/cache
```
See https://github.com/joshuaboniface/rffmpeg/blob/master/SETUP.md NFS setup for more details
EXAMPLE Docker-Compose file with WOL support via API:
```yaml
---
version: "2.1"
services:
jellyfin:
image: lscr.io/linuxserver/jellyfin:latest
container_name: jellyfin
environment:
- PUID=1000
- PGID=1000
- TZ=Europe/London
- RFFMPEG_USER=jellyfin
- RFFMPEG_WOL=api
- RFFMPEG_HOST=transcode
- RFFMPEG_HOST_MAC="12:ab:34:cd:ef:56"
- WOL_API=192.168.1.5 #docker host IP
- WOL_API_PORT=8431
- WOL_WAIT=10 #time transcode host takes to start
volumes:
- /path/to/jellyfin/config:/config
- /path/to/jellyfin/config/cache:/cache
- /path/to/data:/data/
ports:
- 8096:8096
- 8920:8920 #optional
- 7359:7359/udp #optional
- 1900:1900/udp #optional
restart: unless-stopped
depends_on:
- wol_api
wol_api:
image: rix1337/docker-wol_api
container_name: wol_api
environment:
- PORT=8431
network_mode: host
restart: unless-stopped
```
If you want to run rffmpeg commands they must be run as ABC inside the container eg:
* To add new host ``` docker exec -it jellyfin s6-setuidgid abc /usr/local/bin/rffmpeg add --weight 1 remotehost ```
* To view status ``` docker exec -it jellyfin s6-setuidgid abc /usr/local/bin/rffmpeg status ```
* To test connection ``` docker exec -it jellyfin s6-setuidgid abc /usr/local/bin/ffmpeg -version ```
* To test connection ``` docker exec -it jellyfin s6-setuidgid abc /usr/local/bin/ffprobe -version ```
* To view all commands ``` docker exec -it jellyfin s6-setuidgid abc /usr/local/bin/rffmpeg -h ```
You then need to set your FFMPEG binary in Jellyfin to:
* /usr/local/bin/ffmpeg - Normal rffmpeg without WOL support
* /usr/local/bin/wol_rffmpeg/ffmpeg - rffmpeg with WOL support
WOL Support
Native WOL support is available if you are running in host network mode. If not you can use the WOL_API container https://hub.docker.com/r/rix1337/docker-wol_api. Note the image name is rix1337/docker-wol_api
WOL ENV:
* RFFMPEG_WOL= native or api
* RFFMPEG_HOST= remote host to wake
* RFFMPEG_HOST_MAC= remote host to wake mac enclosed in " " eg "aa:12:34:bb:cc:56"
* WOL_API = IP of docker host
* WOL_API_PORT= port wol_api is running on
* WOL_WAIT= time in seconds to wait for host to wake
+70
View File
@@ -0,0 +1,70 @@
---
# Configuration file for rffmpeg
#
# Copy this sample to /etc/rffmpeg/rffmpeg.yml and replace the various attributes
# with the values for your environment. For more details please see the README.
#
# Any commented value represents the default. Uncomment and alter as required.
rffmpeg:
# Logging configuration
logging:
# Enable or disable file logging.
#log_to_file: true
# Log messages to this file.
# Ensure the user running rffmpeg can write to this directory.
#logfile: "/var/log/jellyfin/rffmpeg.log"
# Show debugging messages
#debug: false
# Directory configuration
directories:
# Persistent directory to store state database.
#state: "/var/lib/rffmpeg"
# Temporary directory to store SSH persistence sockets.
#persist: "/run/shm"
# The user who should own the state directory and database.
# This should normally be the user who normally runs rffmpeg commands (i.e. the media
# server service user).
#owner: jellyfin
# The group who should own the state directory and database (an administrative group).
# Use this group to control who is able to run "rffmpeg" management commands; users in
# this group will have unlimited access to the tool to add/remove hosts, view status, etc.
#group: sudo
# Remote (SSH) configuration
remote:
# The remote SSH user to connect as.
#user: jellyfin
# How long to persist SSH sessions; 0 to disable SSH persistence.
#persist: 300
# A YAML list of additional SSH arguments (e.g. private keys).
# One entry line per space-separated argument element.
#args:
# - "-i"
# - "/var/lib/jellyfin/id_rsa"
# Remote command configuration
commands:
# The path (either full or in $PATH) to the default SSH binary.
#ssh: "/usr/bin/ssh"
# A YAML list of prefixes to the ffmpeg command (e.g. sudo, nice, etc.).
# One entry line per space-separated command element.
#pre:
# - ""
# The (remote) ffmpeg and ffprobe command binary paths.
#ffmpeg: "/usr/lib/jellyfin-ffmpeg/ffmpeg"
#ffprobe: "/usr/lib/jellyfin-ffmpeg/ffprobe"
# Optional local fallback ffmpeg and ffprobe binary paths, if different from the above.
#fallback_ffmpeg: "/usr/lib/jellyfin-ffmpeg/ffmpeg"
#fallback_ffprobe: "/usr/lib/jellyfin-ffmpeg/ffprobe"
+3
View File
@@ -0,0 +1,3 @@
#!/usr/bin/with-contenv bash
apt-get update
+58
View File
@@ -0,0 +1,58 @@
#!/usr/bin/with-contenv bash
#Install dependancies
apt-get install -y --no-install-recommends \
iputils-ping \
openssh-client \
python3-click \
python3-yaml \
wakeonlan
#Grab Config
mkdir -p \
/etc/rffmpeg \
/config/rffmpeg/.ssh
touch /config/rffmpeg/.ssh/id_rsa
chmod 600 /config/rffmpeg/.ssh/id_rsa
if [ -f /config/rffmpeg/rffmpeg.yml ]; then
echo "**** rffmpeg.yml already present ****"
else
echo "**** Creating rffmpeg.yml from sample ****"
cp /defaults/rffmpeg.yml.sample /config/rffmpeg/rffmpeg.yml
fi
#Grab rffmpeg
mkdir -p /usr/local/bin/
echo "**** Grabbing rffmpeg from upstream ****"
rm -rf /usr/local/bin/rffmpeg
curl -L -o /usr/local/bin/rffmpeg https://raw.githubusercontent.com/joshuaboniface/rffmpeg/master/rffmpeg
chmod +x /usr/local/bin/rffmpeg
##Update rffmpeg.yml
sed -i 's~#persist: "/run/shm"~persist: "/dev/shm"~' /config/rffmpeg/rffmpeg.yml
sed -i 's~#state: "/var/lib/rffmpeg"~state: "/config/rffmpeg"~' /config/rffmpeg/rffmpeg.yml
sed -i 's~#logfile: "/var/log/jellyfin/rffmpeg.log"~logfile: "/config/rffmpeg/rffmpeg.log"~' /config/rffmpeg/rffmpeg.yml
sed -i 's~#log_to_file: true~log_to_file: true~' /config/rffmpeg/rffmpeg.yml
sed -i 's~#owner: jellyfin~owner: abc~' /config/rffmpeg/rffmpeg.yml
sed -i 's~#group: sudo~group: abc~' /config/rffmpeg/rffmpeg.yml
sed -i 's~#args:~args:~' /config/rffmpeg/rffmpeg.yml
sed -i 's~# - "-i"~ - "-i"~' /config/rffmpeg/rffmpeg.yml
sed -i 's~# - "/var/lib/jellyfin/id_rsa"~ - "/config/rffmpeg/.ssh/id_rsa"~' /config/rffmpeg/rffmpeg.yml
if [ ! -z "$RFFMPEG_USER" ]; then
sed -i "s~#user: jellyfin~user: $RFFMPEG_USER~" /config/rffmpeg/rffmpeg.yml
fi
#Fix permissions
chown abc:abc -R /config/rffmpeg
#Initialize database
if [ -f /config/rffmpeg/rffmpeg.db ]; then
echo "**** DB already inialized ****"
else
echo "**** Initialize database ****"
/usr/local/bin/rffmpeg init --yes
#Add host
if [ ! -z "$RFFMPEG_HOST" ]; then
s6-setuidgid abc /usr/local/bin/rffmpeg add --weight 1 $RFFMPEG_HOST
fi
fi
-27
View File
@@ -1,27 +0,0 @@
#!/usr/bin/with-contenv bash
# Determine if setup is needed
if [ ! -f /usr/local/lib/python***/dist-packages/sshuttle ] && \
[ -f /usr/bin/apt ]; then
## Ubuntu
apt-get update
apt-get install --no-install-recommends -y \
iptables \
openssh-client \
python3 \
python3-pip
pip3 install sshuttle
fi
if [ ! -f /usr/lib/python***/site-packages/sshuttle ] && \
[ -f /sbin/apk ]; then
# Alpine
apk add --no-cache \
iptables \
openssh \
py3-pip \
python3
pip3 install sshuttle
fi
chown -R root:root /root
chmod -R 600 /root/.ssh
+1
View File
@@ -0,0 +1 @@
/config/rffmpeg/rffmpeg.yml
@@ -0,0 +1,14 @@
#!/usr/bin/with-contenv bash
for package in iputils-ping openssh-client python3-click python3-yaml wakeonlan; do
if ! dpkg -s "${package}" >/dev/null 2>&1; then
PACKAGES="${package} ${PACKAGES}"
fi
done
if [ -n "${PACKAGES}" ]; then
echo "${PACKAGES}" >> /mod-repo-packages-to-install.list
echo "**** Adding rffmpeg dependencies to package install list ****"
else
echo "**** rffmpeg dependencies already installed, skipping ****"
fi
@@ -0,0 +1 @@
oneshot
@@ -0,0 +1 @@
/etc/s6-overlay/s6-rc.d/init-mod-jellyfin-rffmpeg-add-package/run
@@ -0,0 +1,50 @@
#!/usr/bin/with-contenv bash
#Grab Config
mkdir -p \
/etc/rffmpeg \
/config/rffmpeg/.ssh
touch /config/rffmpeg/.ssh/id_rsa
chmod 600 /config/rffmpeg/.ssh/id_rsa
if [ -f /config/rffmpeg/rffmpeg.yml ]; then
echo "**** rffmpeg.yml already present ****"
else
echo "**** Creating rffmpeg.yml from sample ****"
cp /defaults/rffmpeg.yml.sample /config/rffmpeg/rffmpeg.yml
fi
#Grab rffmpeg
mkdir -p /usr/local/bin/
echo "**** Grabbing rffmpeg from upstream ****"
rm -rf /usr/local/bin/rffmpeg
curl -L -o /usr/local/bin/rffmpeg https://raw.githubusercontent.com/joshuaboniface/rffmpeg/master/rffmpeg
chmod +x /usr/local/bin/rffmpeg
##Update rffmpeg.yml
sed -i 's~#persist: "/run/shm"~persist: "/dev/shm"~' /config/rffmpeg/rffmpeg.yml
sed -i 's~#state: "/var/lib/rffmpeg"~state: "/config/rffmpeg"~' /config/rffmpeg/rffmpeg.yml
sed -i 's~#logfile: "/var/log/jellyfin/rffmpeg.log"~logfile: "/config/rffmpeg/rffmpeg.log"~' /config/rffmpeg/rffmpeg.yml
sed -i 's~#log_to_file: true~log_to_file: true~' /config/rffmpeg/rffmpeg.yml
sed -i 's~#owner: jellyfin~owner: abc~' /config/rffmpeg/rffmpeg.yml
sed -i 's~#group: sudo~group: abc~' /config/rffmpeg/rffmpeg.yml
sed -i 's~#args:~args:~' /config/rffmpeg/rffmpeg.yml
sed -i 's~# - "-i"~ - "-i"~' /config/rffmpeg/rffmpeg.yml
sed -i 's~# - "/var/lib/jellyfin/id_rsa"~ - "/config/rffmpeg/.ssh/id_rsa"~' /config/rffmpeg/rffmpeg.yml
if [ ! -z "$RFFMPEG_USER" ]; then
sed -i "s~#user: jellyfin~user: $RFFMPEG_USER~" /config/rffmpeg/rffmpeg.yml
fi
#Fix permissions
chown abc:abc -R /config/rffmpeg
#Initialize database
if [ -f /config/rffmpeg/rffmpeg.db ]; then
echo "**** rffmpeg DB already inialized ****"
else
echo "**** Initialize rffmpeg database ****"
/usr/local/bin/rffmpeg init --yes
#Add host
if [ ! -z "$RFFMPEG_HOST" ]; then
s6-setuidgid abc /usr/local/bin/rffmpeg add --weight 1 $RFFMPEG_HOST
fi
fi
@@ -0,0 +1 @@
oneshot
@@ -0,0 +1 @@
/etc/s6-overlay/s6-rc.d/init-mod-jellyfin-rffmpeg-setup/run
-3
View File
@@ -1,3 +0,0 @@
#!/usr/bin/with-contenv bash
sshuttle --dns --remote root@${HOST}:${PORT} 0/0 -x 172.17.0.0/16
+1
View File
@@ -0,0 +1 @@
rffmpeg
+1
View File
@@ -0,0 +1 @@
rffmpeg
+1
View File
@@ -0,0 +1 @@
wol
+1
View File
@@ -0,0 +1 @@
wol
+44
View File
@@ -0,0 +1,44 @@
#!/usr/bin/bash
mac="${RFFMPEG_HOST_MAC%\"}"
mac="${mac#\"}"
if [ -z $WOL_WAIT ]
then
WOL_WAIT=30
fi
ping -c1 -W1 $RFFMPEG_HOST >/dev/null 2>&1 && host=up || host=down
if [ $RFFMPEG_WOL == "native" ] && [ ! -z $RFFMPEG_HOST ] && [ ! -z $RFFMPEG_HOST_MAC ] && [ ! -z $WOL_WAIT ] && [ $host == "down" ];
then
echo WOL enabled
echo "$RFFMPEG_HOST" is down, sending wakeup to "$mac"
wakeonlan $mac
#wakeonlan -i $RFFMPEG_HOST $mac
echo "waiting $WOL_WAIT seconds for $RFFMPEG_HOST to wake"
sleep $WOL_WAIT
fi
if [ $RFFMPEG_WOL == "api" ] && [ ! -z $RFFMPEG_HOST ] && [ ! -z $RFFMPEG_HOST_MAC ] && [ $host == "down" ] && [ ! -z $WOL_WAIT ] && [ ! -z $WOL_API ] && [ ! -z $WOL_API_PORT ];
then
echo WOL enabled
echo "$RFFMPEG_HOST" is down, sending wakeup via WOL_API: curl -X POST $WOL_API:$WOL_API_PORT/wol/"$mac"
curl -X POST $WOL_API:$WOL_API_PORT/wol/$mac
echo "waiting $WOL_WAIT seconds for $RFFMPEG_HOST to wake"
sleep $WOL_WAIT
fi
if [ ${0##*/} == "ffmpeg" ]
then
#echo ${0##*/}
/usr/local/bin/ffmpeg "$@"
fi
if [ ${0##*/} == "ffprobe" ];
then
#echo ${0##*/}
/usr/local/bin/ffprobe "$@"
fi
exit