ffmpeg-over-ip

repository·main·Indexed 22 days ago

https://github.com/steelbrain/ffmpeg-over-ip

A client-server system that allows remote machines, such as Docker containers or VMs, to use a host's GPU for transcoding without GPU passthrough or shared filesystems. It works by intercepting ffmpeg commands via a client and tunneling file I/O over TCP to a server running a patched, GPU-enabled ffmpeg. The system supports HMAC-SHA256 authentication, real-time stdout/stderr forwarding, and an optional fallback to local ffmpeg/ffprobe binaries if the server is unreachable.

Tokens
8.3K
Snippets
23
Records
33
Agent score
77%

What's inside ffmpeg-over-ip

  1. How fallback to local ffmpeg works

    main

    When fallbackToLocal is enabled, the client attempts to run the host's local ffmpeg (or ffprobe) if the initial TCP connection to the server fails. This ensures transcoding continues even if the remote GPU machine is offline.

    Key Behaviors

    • Trigger: Only triggered on initial TCP connection failure. Mid-stream errors are fatal and do not trigger a local restart.
    • Binary Selection: The client selects ffmpeg or ffprobe based on its own argv[0] basename. A binary named ffprobe (or containing it) looks for ffprobe on $PATH; otherwise, it looks for ffmpeg.
    • Environment Security: FFMPEG_OVER_IP_* environment variables are stripped from the local process to prevent the authSecret from leaking into /proc/<pid>/environ.
    • Path Searching: The client searches $PATH for the local binary. On Windows, it tries the bare name first, then follows %PATHEXT% order.

    Security Considerations

    • Path Hijacking: Only enable this on hosts where you trust the $PATH. A user with write access to a directory earlier in $PATH than the real binary could hijack transcodes.
    • Windows %PATHEXT%: A malicious ffmpeg.com could be picked up before ffmpeg.exe depending on the declared order.
    • Root Users: Audit $PATH directory permissions if running the client as root to prevent non-root users from hijacking transcodes.
  2. Understand the configuration resolution order

    main

    The ffmpeg-over-ip configuration is resolved using a 'first match wins' strategy. The order of precedence is:

    1. Explicit path: Using the --config <path> flag (Server only).
    2. Config file environment variable: FFMPEG_OVER_IP_SERVER_CONFIG or FFMPEG_OVER_IP_CLIENT_CONFIG pointing to a specific file.
    3. Individual environment variables: If both ADDRESS and AUTH_SECRET are set (and no _CONFIG variable is present), the system reads configuration entirely from environment variables.
    4. File search: The system searches standard system paths (see Config File Search Paths).
  3. Use Rewrites to substitute ffmpeg arguments

    main

    Rewrites allow the server (via rewrites) or the client (via fallbackRewrites) to substitute elements in the argv array before execution. This is useful for mapping requested codecs to available hardware (e.g., requesting h264_nvenc but using h264_qsv on the server).

    Rules

    • Exact Matches: Each [find, replace] pair matches whole argv elements, not substrings. h264_nvenc will match, but h264_nvenc_extra will not.
    • Whitespace Handling: find and replace strings are split on whitespace. This allows a single rewrite to match a run of elements and replace them with a run of a different length.
    • Order of Operations: Rewrites are applied in the order they are declared. A later rewrite can match tokens produced by an earlier one.
    • Global Application: The same rewrite is applied to every matching run in the argv array.

    Examples

    {
      "rewrites": [
        // Swap a two-element run for a different two-element run
        ["-hwaccel qsv", "-hwaccel cuda"],
    
        // Expand a two-element run into a four-element run
        ["-hwaccel qsv", "-hwaccel cuda -hwaccel_output_format cuda"],
    
        // Remove a one-element argv entry entirely
        ["-nostdin", ""],
    
        // Remove a two-element run
        ["-preset veryfast", ""]
      ]
    }
    {
      "rewrites": [
        // Swap a two-element run (-hwaccel qsv) for a different two-element run.
        ["-hwaccel qsv", "-hwaccel cuda"],
    
        // Expand a two-element run into a four-element run.
        ["-hwaccel qsv", "-hwaccel cuda -hwaccel_output_format cuda"],
    
        // Remove a one-element argv entry entirely (empty replacement).
        ["-nostdin", ""],
    
        // Remove a two-element run.
        ["-preset veryfast", ""],
      ],
    }
  4. How ffmpeg-over-ip works

    main

    ffmpeg-over-ip enables GPU-accelerated transcoding on a remote machine without requiring GPU passthrough, shared filesystems (NFS/SMB), or complex driver alignment. It uses a client-server model where the client acts as a drop-in replacement for the ffmpeg binary.

    The Workflow:

    1. Invocation: Your media server calls the ffmpeg-over-ip-client using standard ffmpeg arguments.
    2. Connection: The client establishes a TCP connection to the server and sends the command using HMAC authentication.
    3. Execution: The server launches a patched ffmpeg process. This patched version tunnels all file I/O (reads and writes) back through the TCP connection to the client's local filesystem.
    4. Streaming: stdout and stderr are forwarded in real-time. When the server-side ffmpeg exits, the client exits with the same exit code.

    Key Benefits:

    • No GPU Passthrough: The server handles the hardware acceleration (NVENC, QSV, VAAPI, AMF, VideoToolbox, etc.).
    • No Shared Filesystems: Files stay on the client; the server only receives the I/O stream.
    • Concurrency: Multiple clients can connect to a single server simultaneously, with each session spawning its own ffmpeg process.
  5. Security and Authentication

    main

    ffmpeg-over-ip uses HMAC-SHA256 with a shared secret to secure the connection. Every command sent from the client to the server is signed to prevent unauthorized execution.

    From a network perspective, the architecture is secure because only the server listens on a port; the client only makes outbound connections.

  6. Configure via environment variables

    main

    You can configure the client or server entirely via environment variables without a config file, provided you set both the ADDRESS and AUTH_SECRET variables. Note that rewrites (server) and fallbackRewrites (client) cannot be configured via environment variables; they require a JSONC config file.

    Client Environment Variables

    VariableRequiredDescription
    FFMPEG_OVER_IP_CLIENT_ADDRESSYesServer address (host:port or unix:/path)
    FFMPEG_OVER_IP_CLIENT_AUTH_SECRETYesHMAC auth secret (must match server)
    FFMPEG_OVER_IP_CLIENT_LOGNoLog destination: stdout, stderr, or file path
    FFMPEG_OVER_IP_CLIENT_FALLBACK_TO_LOCALNoRun local ffmpeg if the server is unreachable (true, 1, yes, y — case-insensitive)
    FFMPEG_OVER_IP_CLIENT_DEBUGNoLog original/rewritten args when fallback runs (true, 1, yes, y — case-insensitive)

    Server Environment Variables

    VariableRequiredDescription
    FFMPEG_OVER_IP_SERVER_ADDRESSYesListen address (host:port or unix:/path)
    FFMPEG_OVER_IP_SERVER_AUTH_SECRETYesHMAC auth secret (must match client)
    FFMPEG_OVER_IP_SERVER_LOGNoLog destination: stdout, stderr, or file path
    FFMPEG_OVER_IP_SERVER_DEBUGNoLog original/rewritten args (true, 1, yes, y — case-insensitive)

    Docker Example

    docker run \
      -e FFMPEG_OVER_IP_CLIENT_ADDRESS=192.168.1.100:5050 \
      -e FFMPEG_OVER_IP_CLIENT_AUTH_SECRET=my-secret \
      -v ./ffmpeg-over-ip-client:/usr/bin/ffmpeg \
      your-image
  7. Set up the ffmpeg-over-ip client

    main

    To set up the client (typically on a media server):

    1. Extract ffmpeg-over-ip-client to a convenient location.
    2. Create a configuration file named ffmpeg-over-ip.client.jsonc next to the binary or in your home directory.
    3. To allow your media server to probe files, you must provide an ffprobe binary. You can do this by symlinking or copying the client binary to a file named ffprobe.
    4. Configure your media server to use the client binary. For example, in Jellyfin, set the FFmpeg path in Dashboard > Playback to the path of ffmpeg-over-ip-client.
    {
      "address": "192.168.1.100:5050",  // your server's IP
      "authSecret": "pick-a-strong-secret"
    }
  8. Install ffmpeg-over-ip on Windows

    main

    On Windows, use the .exe binaries provided in the release.

    1. Place ffmpeg-over-ip.client.jsonc next to the .exe binary or in your user directory (C:\Users\<you>\).
    2. To provide ffprobe functionality, copy and rename the client binary to ffprobe.exe.
    copy ffmpeg-over-ip-client.exe ffprobe.exe
  9. Migrate from v4 to v5

    main

    Upgrading from v4 to v5 involves significant architectural changes. v5 eliminates the requirement for a shared filesystem (NFS, SMB, or Docker mounts) by using a patched ffmpeg that tunnels all file I/O over TCP.

    Follow this checklist to complete the migration:

    1. Download the v5 release (includes ffmpeg-over-ip-server, ffmpeg, and ffprobe).
    2. Place all three server binaries in the same directory.
    3. Remove ffmpegPath from your server config.
    4. If using Unix sockets, add the unix: prefix to your address.
    5. Remove path rewrites from your server config (no longer needed).
    6. Remove any shared filesystem mounts that were only needed for ffmpeg-over-ip.
    7. If using --config on the client, switch to the FFMPEG_OVER_IP_CLIENT_CONFIG environment variable.
  10. Enable ffprobe mode via symlinks

    main

    The client determines if it should operate in ffprobe mode based on its binary name. To enable this, create a symlink or copy of the client binary where the filename contains the string "ffprobe".

    Linux / macOS:

    ln -s ffmpeg-over-ip-client ffprobe

    Windows:

    mklink ffprobe.exe ffmpeg-over-ip-client.exe

    Any name containing "ffprobe" is valid (e.g., my-ffprobe, ffprobe-remote).

    # Linux / macOS
    ln -s ffmpeg-over-ip-client ffprobe
    
    # Windows
    mklink ffprobe.exe ffmpeg-over-ip-client.exe
  11. Run the ffmpeg-over-ip client in Docker

    main

    To use ffmpeg-over-ip in a Docker container without needing local GPU access or complex setups, mount the ffmpeg-over-ip-client binary as /usr/bin/ffmpeg and provide connection details via environment variables.

    If your application requires ffprobe, you must also mount the client binary to /usr/bin/ffprobe.

    # Basic client setup
    docker run \
      -e FFMPEG_OVER_IP_CLIENT_ADDRESS=192.168.1.100:5050 \
      -e FFMPEG_OVER_IP_CLIENT_AUTH_SECRET=your-secret \
      -v ./ffmpeg-over-ip-client:/usr/bin/ffmpeg \
      your-image
    
    # Client setup with ffprobe support
    docker run \
      -e FFMPEG_OVER_IP_CLIENT_ADDRESS=192.168.1.100:5050 \
      -e FFMPEG_OVER_IP_CLIENT_AUTH_SECRET=your-secret \
      -v ./ffmpeg-over-ip-client:/usr/bin/ffmpeg \
      -v ./ffmpeg-over-ip-client:/usr/bin/ffprobe \
      your-image
  12. Install the ffmpeg-over-ip server

    main

    Run this command on the machine that has the GPU. The installation script downloads the latest release, prompts you for the host, port, and an authentication secret, and creates a starter configuration file in the current directory. The installation is idempotent; re-running it will not overwrite existing configurations or binaries.

    # Linux/macOS
    curl -fsSL https://ffmpeg-over-ip.com/install-server.sh | sh
    
    # Windows (PowerShell)
    irm https://ffmpeg-over-ip.com/install-server.ps1 | iex