Page 1 of 1

Strip subtitles when mkv has 30 streams or more

Posted: October 1st, 2022, 3:19 am
by thijsnijhuis
If you have a brand new Samsung with Atmos support and a soundsystem to play it, you might have run into the 'file contains more then 30 streams' issues on Plex. Samsung tv's are not able to directplay files with that many streams and therefore the Plex will transcode the audio. By transcoding, the Atmos data is lost which is very frustrating. The amount of streams the sum of all video, audio and subtitles. Most of releases only have 1 video 1 or two audio streams but it is pretty common for them to have 30 subtitles in a lot of languages. Moest of them you don;t need obviously.
There for I created a script that will:
  • check if the download is a mkv
  • if it is a mkv, chec how many streams it contains using ffprobe
  • if it contains 30 or more streams, create a new mkv and copy all video and audio streams into it (not reencoding) and only the english and dutch subtitles using ffmpeg
  • finish it up by removing the original mkv and replacing it with the new
This runs on a linux backend with SabNzb in a docker container. You would nee to add ffmpeg tot the container image. Credits @sander in this post p98995 (can post link) which helped a lot.

Code: Select all

import sys
import os
import subprocess
from os import listdir
from os.path import isfile, join


try:
    (scriptname, directory, orgnzbname, jobname, reportnumber, category, group, postprocstatus, url) = sys.argv
except:
    print("No commandline parameters found")
    sys.exit(1)



ffprobe = "/usr/bin/ffprobe"
ffmpeg = "/usr/bin/ffmpeg"

def handle_mkv(directory, filename, extension):
    full_path = join(directory, filename)+extension
    
    print("")
    print("######################")
    print("Filename: " + full_path)
  
    
    ffprobe_commands_list = [ffprobe,"-hide_banner","-loglevel", "error", "-show_entries", "stream=index:stream=codec_type:stream_tags=language","-of", "csv=p=0", full_path]
    print("Command list: " + str(ffprobe_commands_list))
   
    #execute process
    ffprobe_result = subprocess.run(ffprobe_commands_list, capture_output=True, text=True, check=True)
    print("")
    print(ffprobe_result.stdout)
        
    nr_of_streams = len(ffprobe_result.stdout.splitlines())
    print("File contains " + str(nr_of_streams) + " streams.")   

    if nr_of_streams >=30:
        print("Stripping subtitles from file...")   

        tmp_filename = filename+"_CLEAN"
        tmp_full_path = join(directory, tmp_filename)+extension
        
        ffmpeg_commands_list = [ffmpeg,"-hide_banner","-i", full_path, "-c", "copy", "-map", "0:v", "-map", "0:a", "-map", "0:s:m:language:eng?", "-map", "0:s:m:language:dut?", tmp_full_path]
        print("Command list: " + str(ffmpeg_commands_list))
       
        ffmpeg_result = subprocess.run(ffmpeg_commands_list, capture_output=True, text=True, check=True)
        print("")
        print(ffmpeg_result.stdout)
        
        print("")        
        print("Swapping old file with cleaned file and setting access rights")
        os.remove(full_path)
        os.rename(tmp_full_path, full_path)
        os.chmod(full_path, 0o664)

print("######################")
print("Searching:" + directory)
onlyfiles = [f for f in listdir(directory) if isfile(join(directory, f))]
for f in onlyfiles:
    print(f)
    if os.path.splitext(f)[1].lower() == '.mkv':
        print ("Found mkv: " + f)
        handle_mkv(directory, os.path.splitext(f)[0], os.path.splitext(f)[1] )  

# Success code
sys.exit(0)