FFmpeg Interactive Commands via Local Socket
This article explains how to dynamically control FFmpeg filters
during runtime using interactive commands sent through a local Unix
socket. You will learn how to configure FFmpeg with the ZeroMQ
(zmq) filter, set up a local IPC socket, and send real-time
commands to modify video and audio filter parameters on the fly without
restarting your processing pipeline.
Prerequisites
To send interactive commands to FFmpeg via a local socket, your FFmpeg build must be compiled with ZeroMQ support. You can verify this by running the following command in your terminal:
ffmpeg -filters | grep zmqIf you see zmq (video) and azmq (audio) in
the output, your installation is ready.
Step 1: Start FFmpeg with the ZMQ Filter
The zmq filter acts as a local socket server inside
FFmpeg. It listens for incoming commands and dispatches them to target
filters in your filtergraph.
To bind FFmpeg to a local Unix domain socket (IPC), use the following syntax:
ffmpeg -i input.mp4 -vf "zmq=bind_address='ipc:///tmp/ffmpeg.sock',drawtext=fontfile=Arial.ttf:text='Initial Text':x=10:y=10" output.mp4In this command: *
zmq=bind_address='ipc:///tmp/ffmpeg.sock' creates a local
socket file at /tmp/ffmpeg.sock. * drawtext is
the target filter we want to control interactively. By default, FFmpeg
assigns it the identifier Parsed_drawtext_1.
Step 2: Write a Client to Send Interactive Commands
Because the zmq filter utilizes ZeroMQ’s
REP (Reply) socket pattern, you cannot use standard utility
tools like netcat (nc) to write raw text
directly to the socket. Instead, you must use a ZeroMQ-compatible
client.
Below is a simple Python script using the pyzmq library
to send interactive commands to the FFmpeg local socket.
Install the Dependency
pip install pyzmqThe Python
Command Sender Script (send_command.py)
import zmq
import sys
# Define the local socket address
socket_address = "ipc:///tmp/ffmpeg.sock"
# Initialize ZeroMQ context and REQ (Request) socket
context = zmq.Context()
socket = context.socket(zmq.REQ)
socket.connect(socket_address)
# Command format: [Target Filter] [Command] [Arguments]
# Example: Parsed_drawtext_1 reinit text='Dynamic Text Update'
command = "Parsed_drawtext_1 reinit text='Dynamic Text Update'"
print(f"Sending command: {command}")
socket.send_string(command)
# Wait for FFmpeg's response
reply = socket.recv_string()
print(f"FFmpeg Reply: {reply}")Run this script while FFmpeg is running, and the text overlay on your output video will instantly change to “Dynamic Text Update”.
Step 3: Using the
sendcmd Filter via Socket
If you prefer to use the sendcmd (or
asendcmd) filter to queue up multiple timed commands
interactively, you can target the sendcmd filter directly
through the ZMQ socket.
Run FFmpeg with
sendcmd and zmq:
ffmpeg -i input.mp4 -vf "zmq=bind_address='ipc:///tmp/ffmpeg.sock',sendcmd=f=NULL,drawtext=text='Static'" output.mp4Send Commands to
sendcmd:
The sendcmd filter accepts a reinit command
followed by a timeline-based command string. You can send this block
over the ZMQ socket using your Python script:
command = "Parsed_sendcmd_0 reinit 2.0 drawtext reinit text='Updated after 2 seconds'"When FFmpeg receives this command via the local socket, it passes the
instruction to sendcmd, which schedules the text change to
execute exactly at the 2.0-second mark of the video playback
timeline.