This caused some issues with ffprobe if the remote command ever sends something to stderr (which then gets sent to stdout locally, causing format issues). However, from some testing, this was original though needed to ensure the 'q' sent to FFmpeg was sent directly over the pipe, but this seems to not be required (any longer?). |
||
|---|---|---|
| README.md | ||
| rffmpeg.py | ||
| rffmpeg.yml.sample | ||
rffmpeg
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 to better handle the load.
Usage
-
Install the required Python 3 dependencies:
yamlandsubprocess. -
Create the directory
/etc/rffmpeg. -
Copy the
rffmpeg.yml.samplefile to/etc/rffmpeg/rffmpeg.ymland edit it to suit your needs. -
Install
rffmpeg.pysomewhere useful, for instance at/usr/local/bin/rffmpeg.py. -
Create symlinks for the command names
ffmpegandffprobetorffmpeg.py, for instance/usr/local/bin/ffmpeg -> /usr/local/bin/rffmpeg.pyand/usr/local/bin/ffprobe -> /usr/local/bin/rffmpeg.py. -
Edit your media program to use the
rffmpeg.pybinary (via the symlink names) instead of the standardffmpegbinary. -
Profit!
rffmpeg options
Remote hosts
rffmpeg supports setting multiple hosts. It keeps state in /run/shm/rffmpeg, of all running processes. These state files are used during rffmpeg's initialization in order to determine the optimal target host. rffmpeg will run through these hosts sequentially, choosing the one with the fewest running rffmpeg jobs. This helps distribute the transcoding load across multiple servers.
Full setup guide
This example setup is the one I use for rffmpeg, involving a media server (jf1) and a remote transcode server (gpu1). Both systems run Debian GNU/Linux, though the commands below should also work on Ubuntu.
-
Prepare the media server (
jf1) with Jellyfin. Make note of the "Transcode path" in the Playback settings menu (e.g./var/lib/jellyfin/transcoding-temp). -
On the media server, create an SSH keypair owned by the Jellyfin service user; save this SSH key somewhere readable to the service user:
sudo -u jellyfin mkdir -p /var/lib/jellyfin/.ssh && sudo -u jellyfin ssh-keygen -t rsa -f /var/lib/jellyfin/.ssh/id_rsa -
Install the rffmpeg program as detailed in the above section, including creating the
/etc/rffmpeg/rffmpeg.ymlconfiguration file and symlinks. -
Install the NFS kernel server:
sudo apt -y install nfs-kernel-server -
Export the "Transcode path" directory found in step 1 with NFS; you will need to know the local IP address of the transcode server(s) (e.g.
10.0.0.100) to lock this down; alternatively, use your entire local network range (e.g.10.0.0.0/24):echo '/var/lib/jellyfin/transcoding-temp 10.0.0.100/32(rw,sync,no_subtree_check)' | sudo tee -a /etc/exports && sudo systemctl restart nfs-kernel-server -
On the transcode server, install any required tools or programs to make use of hardware transcoding; this is optional if you only use software (i.e. CPU) transcoding.
-
Install the
jellyfin-ffmpegpackage to provide an FFmpeg binary; follow the Jellyfin installation instructions for details on setting up the Jellyfin repository, though install onlyjellyfin-ffmpeg. -
Install the NFS client utilities:
sudo apt install -y nfs-common -
Create a user for rffmpeg to SSH into the server as. This user should match the
jellyfinuser on the media server in every way, including UID (id jellyfinon the media server), home path, and groups. -
Install the SSH public key created in step 2 into the new user's home directory:
sudo -u jellyfin mkdir -p /var/lib/jellyfin/.ssh && echo 'ssh-rsa MyJellyfinUserPublicKey' | sudo -u jellyfin tee /var/lib/jellyfin/.ssh/authorized_keys -
Ensure that the "Transcode path" directory exists at the same location as on the media server; create it if required:
sudo mkdir -p /var/lib/jellyfin/transcoding-temp -
Mount the media server NFS transcode share at the transcode directory:
echo 'jf1:/var/lib/jellyfin/transcoding-temp /var/lib/jellyfin/transcoding-temp nfs defaults,vers=3,sync 0 0' | sudo tee -a /etc/fstab && sudo mount -a -
Mount your media directory on the transcode server at the same location as on the media server and using the same method; if your media is local to the media server, export it with NFS similarly to the transcode directory.
-
On the media server, attempt to SSH to the transcode server as the
jellyfinuser using the key from step 2; this both tests the connection as well as saves the transcode server SSH host key locally:sudo -u jellyfin ssh -i /var/lib/jellyfin/.ssh/id_rsa jellyfin@gpu1 -
Verify that rffmpeg itself works by calling its
ffmpegalias with the-versionoption:sudo -u jellyfin /usr/local/bin/ffmpeg -version -
In Jellyfin, set the rffmpeg binary, via its
ffmpegsymlink, as your "FFmpeg path" in the Playback settings; optionally, enable any hardware encoding you configured in step 6. -
Try running a transcode and verifying that the
rffmpegprogram works as expected. The flow should be:-
Jellyfin calls rffmpeg with the expected arguments.
-
FFmpeg begins running on the transcode server.
-
The FFmpeg process writes the output files to the NFS-mounted temporary transcoding directory.
-
Jellyfin reads the output files from the NFS-exported temporary transcoding directory and plays back normally.
-