Encoding Video for Plex Direct Play

How to encode video files to ensure Direct Play from Plex running on pretty much anything, but in this example a Raspberry Pi 3B+.

This focuses on h264 and selecting the right Profile and Level both for your server and your playback device, but h265/HEVC works the same way.

tldr: The FFmpeg Command

The full ffmpeg command
1
ffmpeg -i input.mkv -c:s copy -c:a copy -c:v libx264 -profile:v high -level:v 4.1 -pix_fmt yuv420p output.mkv
libx264 parameters
1
libx264 -profile:v high -level:v 4.1 -pix_fmt yuv420p

Copy subtitles, copy audio, convert video to H.264 with the profile High level 4.1 and set the colour space to yuv420p.

These settings give you a video file with the widest range of hardware encode/decode support.

Explanation

The H.264 codec has capabilities with various degrees of support by hardware out in the world. These are defined as profiles. Within each profile there are further constraints that indicate required decoder performance, and these are defined as levels.

According to that profile link and my own limited research, the High profile appears to be the most widely supported and most older devices support level 4.1.

I don’t understand the technical details of the colour space part, but when I tried to run ffmpeg with without the -pix_fmt parameter I got x264 [error]: high profile doesn't support a bit depth of 10. The optimised file that Plex generates has yuv420p in the output so I added -pix_fmt yuv420p and everything worked.

Inspecting Files with ffmpeg

Plex has an Optimise function that converts the selected file to a format that it can handle. Plex doesn’t tell you exactly what it’s doing but ffmpeg can tell you details about a file.

I had some videos that were struggling to stream to my Gen 2 Chromecast from my Pi 3B+ Plex server so I compared the original video and the Plex optimised file.

The command ffmpeg -i original.mkv gave me this information (a lot of other information removed for brevity):

Original file
1
2
3
Stream #0:0: Video: h264 (High 10), yuv420p10le(progressive), 
1920x1080 [SAR 1:1 DAR 16:9], 23.98 fps, 23.98 tbr,
1k tbn, 47.95 tbc (default)

Then the same for optimised.mkv:

Optimised for TV by Plex
1
2
3
Stream #0:0(und): Video: h264 (Main) (avc1 / 0x31637661), yuv420p, 
1920x1080 [SAR 1:1 DAR 16:9], 1731 kb/s, 23.98 fps, 23.98 tbr,
11988 tbn, 47.95 tbc (default)

Which lead me to look into how to match the optimised file with ffmpeg.

Device Support Considerations For Ensuring Direct Play

In order to get Direct Play from Plex, the video needs to be in a format that is supported by both the server and the playback device.

Playback Devices

Looking at the specifications for some devices we get the following information:

DeviceProfileLevel
Chromecast 1st and 2nd Gen.High4.1
Chromecast 3rd GenHigh4.2
Chromecast UltraHigh4.2
Apple TV HDBaseline3.0
Apple TV HDMain, High4.2
Apple TV 4KBaseline3.0
Apple TV 4KMain, High4.2
RokuMain, High4.2

Encoding Devices

I’m moving my Plex server from a Raspberry Pi 3B+ to an HTPC with an i5 9600K so let’s see what those can handle:

DeviceEncoding ProfileEncoding Level
Raspberry Pi 3BHigh4.1
Intel i5 9600K (UHD 630)Main, High5.1

Note: I can’t find anything that explicitly states the profile and level supported by the VideoCore 4 GPU used by the Raspberry Pi 3B+ but the 3B product brief lists encode and decode support of “1080p30” which maps to level 4.1 support so that matches my experience of a video encoded to High 4.1 getting Direct Play.

Using This Information

By checking the codec support for your hardware you can determine the correct codec profile and level to encode your video to, and again this applies to h265 as well as h264.

My new HTPC can encode at High 5.1 but my Gen 2 Chromecast can’t play higher than High 4.1 so if I encode everything to High 4.1 then everything will be happy and the HTPC won’t have to do any work to stream the video.

Plex allows you to encode files in different formats and so long as they have the same name, it will understand that you have multiple versions of the same video and will pick the most appropriate file for the target playback device. This means you could encode a video once for your 4k TV and again for your iPad and Plex will Direct Play the most appropriate file.

Final Notes

This article covers handling video, but there are similar considerations for the audio and subtitle streams.

The Direct Play support page lists a variety of caveats and edge cases around audio stream, resolution support and container support.