2025-12-27, 05:57 PM
Hi, not sure if this should go into Server Development. I wanted to livestream my desktop PC to my Roku TV. Every client was transcoding unnecessarily (web client & roku)
I think the script will explain pretty how it was set up:
Don't mind the long ass ffmpeg command, I was throwing pretty much everything at the wall trying to fix this.
So here was the problem. Every time a client would try to open the Live TV, it kept thinking it was High 4:4:4 Predictive, even though it was clearly yuv420p
I tried lots of different things, I grabbed one of these logs from a few days ago that kind of illustrates the problem. I got to the point where it was saying "stream 0:0 COPY and stream 0:1 COPY" but still no luck.
The solution was to disable transcoding for that user which is just unacceptable.
I think the script will explain pretty how it was set up:
Code:
#!/usr/bin/env bash
cd "/home/REDACTED/Jellyfin Server Media/.stream"
MYIP=$(hostname -I | awk '{print $1}')
echo "#EXTM3U" >live.m3u
echo "#EXTINF:-1,My OBS Live Stream" >>live.m3u
echo "http://$MYIP:8080/stream.m3u8" >>live.m3u
python3 -m http.server 8080 &
AUDIO_SOURCE="alsa_output.pci-0000_03_00.1.hdmi-stereo-extra4.monitor"
rm *.ts
rm *.mp4
rm *.m3u8
ffmpeg -f x11grab -framerate 30 -video_size 1920x1080 -i :0.0 \
-f pulse -i "$AUDIO_SOURCE" \
-vaapi_device /dev/dri/renderD129 \
-vf 'format=nv12,hwupload' \
-c:v h264_vaapi -b:v 500k -minrate 500k -maxrate 500k -bufsize 1000k \
-compression_level 1 \
-c:a aac -b:a 192k \
-bsf:v h264_mp4toannexb \
-flags +global_header \
-movflags frag_keyframe+empty_moov+default_base_moof+separate_moof+global_sidx \
-f hls \
-hls_time 1 \
-hls_list_size 10 \
-hls_flags append_list+delete_segments+independent_segments \
-hls_segment_type mpegts \
-hls_segment_filename "/home/REDACTED/Jellyfin Server Media/.stream/seg%d.ts" \
"/home/REDACTED/Jellyfin Server Media/.stream/stream.m3u8"Don't mind the long ass ffmpeg command, I was throwing pretty much everything at the wall trying to fix this.
So here was the problem. Every time a client would try to open the Live TV, it kept thinking it was High 4:4:4 Predictive, even though it was clearly yuv420p
Code:
{"Protocol":1,"Id":"0f06faf5049ef8c988b8d5031582a8f5","Path":"http://192.168.12.172:8080/stream.m3u8","EncoderPath":null,"EncoderProtocol":null,"Type":0,"Container":"hls","Size":264,"Name":null,"IsRemote":false,"ETag":null,"RunTimeTicks":null,"ReadAtNativeFramerate":true,"IgnoreDts":true,"IgnoreIndex":false,"GenPtsInput":false,"SupportsTranscoding":true,"SupportsDirectStream":false,"SupportsDirectPlay":true,"IsInfiniteStream":true,"UseMostCompatibleTranscodingProfile":false,"RequiresOpening":true,"OpenToken":null,"RequiresClosing":true,"LiveStreamId":"e2329f4997b378e64ccf8fa396deb76e_af999c25a00715699361240d4c6c7a53_0f06faf5049ef8c988b8d5031582a8f5","BufferMs":null,"RequiresLooping":false,"SupportsProbing":true,"VideoType":null,"IsoType":null,"Video3DFormat":null,"MediaStreams":[{"Codec":"h264","CodecTag":null,"Language":null,"ColorRange":null,"ColorSpace":null,"ColorTransfer":null,"ColorPrimaries":null,"DvVersionMajor":null,"DvVersionMinor":null,"DvProfile":null,"DvLevel":null,"RpuPresentFlag":null,"ElPresentFlag":null,"BlPresentFlag":null,"DvBlSignalCompatibilityId":null,"Rotation":null,"Comment":null,"TimeBase":"1/90000","CodecTimeBase":null,"Title":null,"Hdr10PlusPresentFlag":null,"VideoRange":1,"VideoRangeType":1,"VideoDoViTitle":null,"AudioSpatialFormat":0,"LocalizedUndefined":null,"LocalizedDefault":null,"LocalizedForced":null,"LocalizedExternal":null,"LocalizedHearingImpaired":null,"DisplayTitle":"1080p H264 SDR","NalLengthSize":"0","IsInterlaced":false,"IsAVC":null,"ChannelLayout":null,"BitRate":185,"BitDepth":8,"RefFrames":1,"PacketLength":null,"Channels":null,"SampleRate":null,"IsDefault":false,"IsForced":false,"IsHearingImpaired":false,"Height":1080,"Width":1920,"AverageFrameRate":29.97003,"RealFrameRate":29.97003,"ReferenceFrameRate":29.97003,"Profile":"High 4:4:4 Predictive","Type":1,"AspectRatio":"16:9","Index":-1,"Score":null,"IsExternal":false,"DeliveryMethod":null,"DeliveryUrl":null,"IsExternalUrl":null,"IsTextSubtitleStream":false,"SupportsExternalStream":false,"Path":null,"PixelFormat":"yuv444p","Level":40,"IsAnamorphic":true},{"Codec":"aac","CodecTag":null,"Language":null,"ColorRange":null,"ColorSpace":null,"ColorTransfer":null,"ColorPrimaries":null,"DvVersionMajor":null,"DvVersionMinor":null,"DvProfile":null,"DvLevel":null,"RpuPresentFlag":null,"ElPresentFlag":null,"BlPresentFlag":null,"DvBlSignalCompatibilityId":null,"Rotation":null,"Comment":null,"TimeBase":"1/90000","CodecTimeBase":null,"Title":null,"Hdr10PlusPresentFlag":null,"VideoRange":0,"VideoRangeType":0,"VideoDoViTitle":null,"AudioSpatialFormat":0,"LocalizedUndefined":null,"LocalizedDefault":"Default","LocalizedForced":null,"LocalizedExternal":"External","LocalizedHearingImpaired":null,"DisplayTitle":"AAC - Stereo","NalLengthSize":null,"IsInterlaced":false,"IsAVC":false,"ChannelLayout":"stereo","BitRate":192000,"BitDepth":null,"RefFrames":null,"PacketLength":null,"Channels":2,"SampleRate":48000,"IsDefault":false,"IsForced":false,"IsHearingImpaired":false,"Height":null,"Width":null,"AverageFrameRate":null,"RealFrameRate":null,"ReferenceFrameRate":null,"Profile":"LC","Type":0,"AspectRatio":null,"Index":-1,"Score":null,"IsExternal":false,"DeliveryMethod":null,"DeliveryUrl":null,"IsExternalUrl":null,"IsTextSubtitleStream":false,"SupportsExternalStream":false,"Path":null,"PixelFormat":null,"Level":0,"IsAnamorphic":null}],"MediaAttachments":[],"Formats":[],"Bitrate":192185,"FallbackMaxStreamingBitrate":30000000,"Timestamp":null,"RequiredHttpHeaders":{"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36"},"TranscodingUrl":null,"TranscodingSubProtocol":0,"TranscodingContainer":null,"AnalyzeDurationMs":3000,"DefaultAudioStreamIndex":null,"DefaultSubtitleStreamIndex":null,"HasSegments":false}
ffmpeg -analyzeduration 3000000 -probesize 1G -user_agent "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36" -re -fflags +igndts -f hls -init_hw_device drm=dr:/dev/dri/renderD128 -init_hw_device vaapi=va@dr -init_hw_device vulkan=vk@dr -filter_hw_device vk -i "http://192.168.12.172:8080/stream.m3u8" -map_metadata -1 -map_chapters -1 -threads 0 -sn -codec:v:0 hevc_vaapi -tag:v:0 hvc1 -rc_mode VBR -b:v 1848 -maxrate 1848 -bufsize 3696 -profile:v:0 main -sei -a53_cc -force_key_frames:0 "expr:gte(t,n_forced*3)" -flags:v -global_header -vf "setparams=color_primaries=bt709:color_trc=bt709:colorspace=bt709,scale=trunc(min(max(iw\,ih*a)\,min(1920\,1080*a))/2)*2:trunc(min(max(iw/a\,ih)\,min(1920/a\,1080))/2)*2,format=nv12,hwupload_vaapi" -codec:a:0 copy -bsf:a aac_adtstoasc -copyts -avoid_negative_ts disabled -max_muxing_queue_size 2048 -f hls -max_delay 5000000 -hls_time 3 -hls_segment_type fmp4 -hls_fmp4_init_filename "73e3e90974c01b514ec0e6c3a2846bd6-1.mp4" -start_number 0 -hls_base_url "hls/73e3e90974c01b514ec0e6c3a2846bd6/" -hls_segment_filename "/home/REDACTED/.var/app/org.jellyfin.JellyfinServer/cache/jellyfin/transcodes/73e3e90974c01b514ec0e6c3a2846bd6%d.mp4" -hls_playlist_type event -hls_list_size 0 -hls_segment_options movflags=+frag_discont -y "/home/REDACTED/.var/app/org.jellyfin.JellyfinServer/cache/jellyfin/transcodes/73e3e90974c01b514ec0e6c3a2846bd6.m3u8"
ffmpeg version 7.1.3-Jellyfin Copyright (c) 2000-2025 the FFmpeg developers
built with gcc 14.3.0 (GCC)
configuration: --prefix=/app --disable-doc --disable-ffplay --disable-libxcb --disable-ptx-compression --disable-sdl2 --disable-static --disable-xlib --enable-chromaprint --enable-gmp --enable-gnutls --enable-gpl --enable-libass --enable-libbluray --enable-libdav1d --enable-libdrm --enable-libfdk-aac --enable-libfontconfig --enable-libfreetype --enable-libfribidi --enable-libharfbuzz --enable-libmp3lame --enable-libopenmpt --enable-libopus --enable-libsvtav1 --enable-libtheora --enable-libvorbis --enable-libvpx --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxml2 --enable-libzimg --enable-libzvbi --enable-lto=auto --enable-opencl --enable-shared --enable-version3 --extra-libs=-lfftw3f --extra-version=Jellyfin --target-os=linux --enable-libvpl --enable-amf --enable-cuda --enable-cuda-llvm --enable-cuvid --enable-ffnvcodec --enable-libplacebo --enable-libshaderc --enable-nvdec --enable-nvenc --enable-vaapi --enable-vulkan
libavutil 59. 39.100 / 59. 39.100
libavcodec 61. 19.101 / 61. 19.101
libavformat 61. 7.100 / 61. 7.100
libavdevice 61. 3.100 / 61. 3.100
libavfilter 10. 4.100 / 10. 4.100
libswscale 8. 3.100 / 8. 3.100
libswresample 5. 3.100 / 5. 3.100
libpostproc 58. 3.100 / 58. 3.100
[hls @ 0x55e1668d8d40] Skip ('#EXT-X-VERSION:3')
[hls @ 0x55e1668d8d40] Opening 'http://192.168.12.172:8080/stream4.ts' for reading
Input #0, hls, from 'http://192.168.12.172:8080/stream.m3u8':
Duration: N/A, start: 25.944000, bitrate: N/A
Program 0
Metadata:
variant_bitrate : 0
Stream #0:0: Video: h264 (High) ([27][0][0][0] / 0x001B), yuv420p(tv, bt709), 1280x720, 30 fps, 30 tbr, 90k tbn
Metadata:
variant_bitrate : 0
Stream #0:1: Audio: aac (LC) ([15][0][0][0] / 0x000F), 48000 Hz, stereo, fltp
Metadata:
variant_bitrate : 0
Stream mapping:
Stream #0:0 -> #0:0 (h264 (native) -> hevc (hevc_vaapi))
Stream #0:1 -> #0:1 (copy)
Press [q] to stop, [?] for help
[hls @ 0x55e166944f40] Opening '/home/REDACTED/.var/app/org.jellyfin.JellyfinServer/cache/jellyfin/transcodes/73e3e90974c01b514ec0e6c3a2846bd6-1.mp4' for writing
Output #0, hls, to '/home/REDACTED/.var/app/org.jellyfin.JellyfinServer/cache/jellyfin/transcodes/73e3e90974c01b514ec0e6c3a2846bd6.m3u8':
Metadata:
encoder : Lavf61.7.100
Stream #0:0: Video: hevc (Main) (hvc1 / 0x31637668), vaapi(tv, bt709, progressive), 1280x720, q=2-31, 1 kb/s, 30 fps, 15360 tbn
Metadata:
encoder : Lavc61.19.101 hevc_vaapi
Stream #0:1: Audio: aac (LC) ([15][0][0][0] / 0x000F), 48000 Hz, stereo, fltp
frame= 10 fps=0.0 q=-0.0 size=N/A time=00:00:00.00 bitrate=N/A speed= 0x
frame= 25 fps= 25 q=-0.0 size=N/A time=00:00:00.50 bitrate=N/A speed= 0.5x
frame= 40 fps= 27 q=-0.0 size=N/A time=00:00:01.00 bitrate=N/A speed=0.667x
[hls @ 0x55e1668d8d40] Opening 'http://192.168.12.172:8080/stream5.ts' for reading
frame= 55 fps= 27 q=-0.0 size=N/A time=00:00:01.50 bitrate=N/A speed=0.75x
frame= 70 fps= 28 q=-0.0 size=N/A time=00:00:02.00 bitrate=N/A speed= 0.8x
frame= 85 fps= 28 q=-0.0 size=N/A time=00:00:02.50 bitrate=N/A speed=0.833x
[hls @ 0x55e166944f40] Opening '/home/REDACTED/.var/app/org.jellyfin.JellyfinServer/cache/jellyfin/transcodes/73e3e90974c01b514ec0e6c3a2846bd60.mp4' for writing
[hls @ 0x55e166944f40] Opening '/home/REDACTED/.var/app/org.jellyfin.JellyfinServer/cache/jellyfin/transcodes/73e3e90974c01b514ec0e6c3a2846bd6.m3u8.tmp' for writing
[hls @ 0x55e1668d8d40] Opening 'http://192.168.12.172:8080/stream6.ts' for reading
frame= 100 fps= 29 q=-0.0 size=N/A time=00:00:03.00 bitrate=N/A speed=0.857x
frame= 115 fps= 29 q=-0.0 size=N/A time=00:00:03.50 bitrate=N/A speed=0.875x
frame= 130 fps= 29 q=-0.0 size=N/A time=00:00:04.00 bitrate=N/A speed=0.889xI tried lots of different things, I grabbed one of these logs from a few days ago that kind of illustrates the problem. I got to the point where it was saying "stream 0:0 COPY and stream 0:1 COPY" but still no luck.
The solution was to disable transcoding for that user which is just unacceptable.
