Jellyfin direct play cheatsheet
The ultimate goal for any media server is to achieve “Direct Play,” where the server simply sends the file to the client without modifying it. When this fails, the server must transcode the media on the fly, which consumes significant CPU resources, causes buffering, and often results in 5.1 surround sound being downmixed to stereo. This guide covers two common FFmpeg workflows to resolve these incompatibilities permanently.
Scenario 1: Fixing DTS audio incompatibility
If a video plays but the server logs indicate “Audio Transcoding,” the issue is likely the audio codec. Many televisions, soundbars using optical connections, and streaming sticks cannot decode DTS audio natively. This forces Jellyfin to convert the audio, which strains the hardware. The most reliable solution is to convert the audio track to AC3 (Dolby Digital)—the industry standard for surround sound compatibility—while copying the video stream exactly as it is.
Finding the files
You can use the following command to recursively scan your library and identify
any files using the dts codec.
find . -type f \( -name "*.mkv" -o -name "*.mp4" -o -name "*.avi" -o -name "*.webm" \) \
-exec sh -c 'codec=$(ffprobe -v error -select_streams a:0 -show_entries stream=codec_name -of default=noprint_wrappers=1:nokey=1 "$0"); if [ "$codec" = "dts" ]; then echo "$0"; fi' {} \;
The conversion command
This command remuxes the video instantly and converts the audio to AC3 at
maximum quality. Note the use of -map 0, which ensures that all
tracks—including commentary audio and secondary subtitles—are preserved in the
new file.
ffmpeg -i "video.mkv" \
-map 0 \
-c:v copy \
-c:a ac3 -b:a 640k \
-c:s copy \
"video.ac3.mkv"
Scenario 2: Modernizing obsolete video formats
Some files, often from the early internet era, may fail to play or cause heavy
transcoding because their internal codecs are obsolete. Containers like .flv,
.wmv, or old .avi files often contain video streams like Sorenson Spark
(flv1), VP6, or early DivX that have no hardware decoding support on
modern devices. In these cases, simply changing the container is not enough;
the video stream itself must be re-encoded to a modern standard like H.264.
Finding the files
The following command scans for common legacy container types and then uses
ffprobe to check if the video codec is a known-obsolete format.
find . -type f \( -name "*.flv" -o -name "*.wmv" -o -name "*.avi" \) \
-exec sh -c 'vcodec=$(ffprobe -v error -select_streams v:0 -show_entries stream=codec_name -of default=noprint_wrappers=1:nokey=1 "$0"); case "$vcodec" in flv1|vp6f|msmpeg4*) echo "$0";; esac' {} \;
The modernization command
This command re-encodes the legacy video stream into the universally compatible H.264 format and the audio into AAC. This creates a completely modern file that will Direct Play on virtually any client.
ffmpeg -i "input.flv" \
-c:v libx264 -crf 23 -preset fast -pix_fmt yuv420p \
-c:a aac -b:a 128k -ar 48000 \
"output.mp4"
-c:v libx264: Re-encodes video to H.264, the most widely supported codec.-crf 23: A standard quality setting for a good balance of size and fidelity.-preset fast: A balance between encoding speed and file size.-pix_fmt yuv420p: Ensures maximum compatibility for the color space.-c:a aac -b:a 128k: Re-encodes audio to AAC, the standard for MP4 containers.-ar 48000: Standardizes the audio sample rate for better compatibility.
Combined Find and Convert Command
for f in *.flv; do
ffmpeg -i "$f" \
-c:v libx264 -crf 23 -preset fast -pix_fmt yuv420p \
-c:a aac -b:a 128k -ar 48000 \
"${f%.flv}.mp4"
done