Last active
April 2, 2020 17:46
-
-
Save iwalton3/a484879495aad3b81c42b4910fa88b15 to your computer and use it in GitHub Desktop.
Please Go Here: https://github.com/iwalton3/media-scripts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
import sys | |
import subprocess | |
from align_videos_by_soundtrack.align import SyncDetector, cli_common | |
remove = [] | |
remove_specified = False | |
remove_all = False | |
add = [] | |
add_specified = False | |
copy_subtitles = False | |
files = [] | |
print_offset_only = False | |
for argument in sys.argv[1:]: | |
if argument == "-copy-subtitles": | |
copy_subtitles = True | |
elif argument == "-print-offset-only": | |
print_offset_only = True | |
elif argument.startswith("-"): | |
if argument == "-all": | |
remove_all = True | |
else: | |
remove_specified = True | |
remove = argument[1:].split(",") | |
elif argument.startswith("+"): | |
add_specified = True | |
add = argument[1:].split(",") | |
else: | |
files.append(argument) | |
if print_offset_only: | |
main_src, audio_src = files | |
destination = None | |
else: | |
main_src, audio_src, destination = files | |
cli_common.logger_config() | |
with SyncDetector() as det: | |
result = det.align([audio_src, main_src]) | |
offset = 0 | |
if result[0]["trim"] > 0: | |
offset = int(-result[0]["trim"]*1000) | |
else: | |
offset = int(result[0]["pad"]*1000) | |
arguments = ["mkvmerge","-o",destination,"-D","-B","-T"] | |
if not copy_subtitles: | |
arguments.extend(["-S","-M"]) | |
if add_specified: | |
arguments.extend(["-a",",".join(add)]) | |
arguments.extend(["-y", "-1:" + str(offset), audio_src]) | |
if remove_specified: | |
arguments.extend(["-a","!"+(",".join(remove))]) | |
elif remove_all: | |
arguments.append("-A") | |
arguments.append(main_src) | |
if print_offset_only: | |
print(offset) | |
else: | |
print("Sync: {0}".format(offset)) | |
subprocess.check_call(arguments) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
import sys | |
import subprocess | |
import json | |
fname = sys.argv[1] | |
def sign_weight(text): | |
if not text: | |
return 0 | |
lower_text = text.lower() | |
has_songs = "op/ed" in lower_text or "song" in lower_text or "lyric" in lower_text | |
has_signs = "sign" in lower_text | |
custom = "[" in lower_text or "(" in lower_text | |
vendor = "bd" in lower_text or "retail" in lower_text | |
weight = 900 | |
if not (has_songs or has_signs): | |
return 0 | |
if has_songs: | |
weight -= 200 | |
if has_signs: | |
weight -= 300 | |
if custom: | |
weight -= 100 | |
if vendor: | |
weight += 50 | |
return weight | |
metadata = json.loads(subprocess.check_output(["mkvmerge","-J",fname]).decode()) | |
is_english = False | |
sign_track = None | |
sign_track_weight = 1000 | |
forced_uid = None | |
for track in metadata["tracks"]: | |
props = track["properties"] | |
if track["type"] == "audio" and props["language"] == "eng": | |
is_english = True | |
if track["type"] == "subtitles": | |
if props.get("language") == "eng": | |
untagged = False | |
eng_subs = True | |
elif "english" in (props.get("track_name") or "").lower(): | |
untagged = True | |
eng_subs = True | |
else: | |
untagged = False | |
eng_subs = False | |
weight = sign_weight(props.get("track_name")) | |
if weight and eng_subs: | |
if sign_track_weight > weight: | |
sign_track_weight = weight | |
sign_track = props["uid"] | |
if props["forced_track"]: | |
if forced_uid != None: | |
print("Fatal error",fname,"Multiple forced tracks!") | |
sys.exit(1) | |
forced_uid = props["uid"] | |
if not is_english: | |
print("Skipping file",fname,"Not in english!") | |
sys.exit(0) | |
if forced_uid != None and sign_track == forced_uid: | |
print("Skipping file",fname,"Already forced.") | |
sys.exit(0) | |
if sign_track == None: | |
print("Skipping file",fname,"No sign track.") | |
sys.exit(0) | |
if forced_uid != None: | |
print("Remove forced",fname,forced_uid) | |
subprocess.Popen(["mkvpropedit",fname,"--edit","track:="+str(forced_uid),"--set","flag-forced=false"]) | |
print("Set forced",fname,sign_track) | |
subprocess.Popen(["mkvpropedit",fname,"--edit","track:="+str(sign_track),"--set","flag-forced=true"]) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
import sys | |
import subprocess | |
import json | |
import shutil | |
import os.path | |
import os | |
import random | |
fname = sys.argv[1] | |
metadata = json.loads(subprocess.check_output(["mkvmerge","-J",fname]).decode()) | |
permitted_locales = {None, 'und', 'eng', 'jpn', 'mis', 'mul', 'zxx'} | |
saved_audio_tracks = [] | |
saved_subtitle_tracks = [] | |
has_bad_tracks = False | |
for track in metadata["tracks"]: | |
props = track["properties"] | |
if track["type"] == "audio": | |
if props["language"] in permitted_locales: | |
saved_audio_tracks.append(str(track["id"])) | |
else: | |
has_bad_tracks = True | |
print("Discard audio: #{0} {1} ({2})".format(track["id"], props.get("track_name"), props.get("language"))) | |
elif track["type"] == "subtitles": | |
if props["language"] in permitted_locales: | |
saved_subtitle_tracks.append(str(track["id"])) | |
else: | |
has_bad_tracks = True | |
print("Discard subtitle: #{0} {1} ({2})".format(track["id"], props.get("track_name"), props.get("language"))) | |
if has_bad_tracks: | |
if len(saved_audio_tracks) == 0: | |
print("File {0} would have no audio tracks!".format(fname)) | |
sys.exit(1) | |
tempfile = "_temp_{0}.mkv".format(random.randint(0,1000000)) | |
options = ["mkvmerge","-o",tempfile, | |
"-a",",".join(saved_audio_tracks)] | |
if len(saved_subtitle_tracks) == 0: | |
options.append("-S") | |
else: | |
options.extend(["-s", ",".join(saved_subtitle_tracks)]) | |
options.append(fname) | |
subprocess.check_call(options) | |
orig_size = os.path.getsize(fname) | |
new_size = os.path.getsize(tempfile) | |
if orig_size * 0.75 > new_size: | |
print("File {0} is too small after conversion.".format(fname)) | |
os.remove(tempfile) | |
sys.exit(1) | |
print("Moving file {0}...".format(fname)) | |
shutil.move(fname, fname+".bak") | |
try: | |
shutil.move(tempfile, fname) | |
except Exception: | |
print("File {0} could not be moved.".format(fname)) | |
shutil.move(fname+".bak", fname) | |
if os.path.isfile(fname+".bak"): | |
os.remove(fname+".bak") | |
print("Size reduced {0} MiB ({1:n}%)".format((orig_size-new_size)//(1024**2), 100-(new_size*100//orig_size))) | |
else: | |
print("File {0} is already minified!".format(fname)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
from plexapi.myplex import MyPlexAccount | |
import sys | |
account = MyPlexAccount('USERNAME', 'PASSWORD') | |
print("Connecting...") | |
plex = account.resource('SERVERNAME').connect() | |
shows = None | |
for library in plex.library.sections(): | |
if library.type == "show": | |
if shows == None: | |
shows = library | |
else: | |
print("Multiple show libraries. Please hardcode it with plex.library.sectionByID.") | |
sys.exit(1) | |
if len(sys.argv) < 2: | |
print("Usage: [series] [subbed/dubbed]") | |
sys.exit(1) | |
series = sys.argv[1] | |
mode = sys.argv[2] | |
search = shows.search(series) | |
if len(search) == 1: | |
show = search[0] | |
elif len(search) == 0: | |
print("No show found.") | |
sys.exit(1) | |
else: | |
for i, show in enumerate(search): | |
print("%s: %s" % (i, show.title)) | |
index = int(input("# ")) | |
show = search[index] | |
def check_subtitles_full(subtitles, retry_flag=False): | |
for subtitle in subtitles: | |
if subtitle.languageCode != "eng": | |
continue | |
title = (subtitle.title or "").lower() | |
if "sign" in title or "commentary" in title: | |
continue | |
if "Forced" in subtitle._data.get("displayTitle"): | |
continue | |
return subtitle | |
return None | |
def check_subtitles_forced(subtitles): | |
selected_subtitles = None | |
for subtitle in subtitles: | |
if subtitle.languageCode != "eng": | |
continue | |
if not "Forced" in subtitle._data.get("displayTitle"): | |
continue | |
return subtitle | |
return None | |
def process_media(part, debug_name, mode): | |
is_english = False | |
english_audio = None | |
japanese_audio = None | |
for audio in part.audioStreams(): | |
if audio.languageCode == "eng" and english_audio == None: | |
is_english = True | |
english_audio = audio | |
elif audio.languageCode == "jpn" and japanese_audio == None: | |
japanese_audio = audio | |
if not is_english: | |
print("Skipping: %s is not in English." % debug_name) | |
return | |
if mode == "dubbed": | |
subtitles = check_subtitles_forced(part.subtitleStreams()) | |
if subtitles != None: | |
sid = subtitles.id | |
else: | |
sid = 0 | |
print("Set dubbed: %s" % debug_name) | |
plex.query('/library/parts/%s?audioStreamID=%s&allParts=1' % (part.id, english_audio.id),method=plex._session.put) | |
plex.query('/library/parts/%s?subtitleStreamID=%s&allParts=1' % (part.id, sid),method=plex._session.put) | |
elif mode == "subbed": | |
if japanese_audio == None: | |
print("Skipping: %s is English only." % debug_name) | |
return | |
subtitles = check_subtitles_full(part.subtitleStreams()) | |
if subtitles == None: | |
print("Skipping: %s has no subtitles." % debug_name) | |
return | |
sid = subtitles.id | |
print("Set subbed: %s (%s)" % (debug_name,subtitles.title)) | |
plex.query('/library/parts/%s?audioStreamID=%s&allParts=1' % (part.id, japanese_audio.id),method=plex._session.put) | |
plex.query('/library/parts/%s?subtitleStreamID=%s&allParts=1' % (part.id, sid),method=plex._session.put) | |
for season in show.seasons(): | |
for episode in season.episodes(): | |
debug_name = "S%02iE%02i" % (season.index, episode.index) | |
episode = episode.reload() | |
medias = episode.media | |
if len(medias) > 1: | |
print("Warning: %s has multiple media files." % debug_name) | |
for media in medias: | |
parts = media.parts | |
if len(parts) > 1: | |
print("Warning: %s has multiple media parts." % debug_name) | |
for part in parts: | |
process_media(part, debug_name, mode) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
i=0 | |
paste <(ls subtitle) <(ls video) | column -ts $'\t' | |
read -p "Please confirm the numbering is correct. [y/N] " verify | |
if [[ ! "$verify" =~ [yY] ]] | |
then | |
echo "Aborted!" | |
exit 1 | |
fi | |
paste <(ls subtitle) <(ls video) | while IFS=$'\t' read -r s v | |
do | |
((i++)) | |
out="$(sed -e 's/\.[^.]\+$/.mkv/g' <<< "$s")" | |
if [[ ! -e "$out" ]] | |
then | |
if [[ -e "$i.txt" ]] | |
then | |
rm "CHECKME_$out" | |
offset=$(cat "$i.txt") | |
else | |
ffmpeg -loglevel quiet -nostdin -y -i subtitle/"$s" subtmp.srt < /dev/null | |
offset=$(subsync video/"$v" -i subtmp.srt 2>&1 1>/dev/null | grep 'offset seconds' | sed 's/.*: /1000*/g' | bc | sed 's/\..*//g') | |
echo "Sync: $offset" | |
rm subtmp.srt | |
if [[ "${offset#-}" -gt "20000" ]] | |
then | |
echo "Sync using subtitles failed. Trying audio sync..." | |
offset=$(audio-transfer.py -print-offset-only video/"$v" subtitle/"$s") | |
echo "Sync: $offset" | |
if [[ "${offset#-}" -gt "20000" ]] || [[ "$offset" == "" ]] | |
then | |
echo "Sync failure!" | |
echo "Please write $i.txt" | |
echo "$i" >> failed.txt | |
out="CHECKME_$out" | |
offset=0 | |
fi | |
fi | |
fi | |
mkvmerge -o "$out" -A -D -B -T -y "-1:$offset" subtitle/"$s" video/"$v" | |
fi | |
done |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment