diff --git a/episode_numbers b/.broken_episode_numbers similarity index 100% rename from episode_numbers rename to .broken_episode_numbers diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..8a0ca77 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +git-honney333-work-cred +git-tub \ No newline at end of file diff --git a/extract_audio.py b/extract_audio.py index 61abfc5..8413b4b 100644 --- a/extract_audio.py +++ b/extract_audio.py @@ -1,5 +1,4 @@ import os -import ffmpeg import subprocess import re import json diff --git a/simple_ffprobe_script b/simple_ffprobe_script index dc5aba8..85e5240 100755 --- a/simple_ffprobe_script +++ b/simple_ffprobe_script @@ -357,169 +357,4 @@ elif [ -f "$1" ]; then else echo "Error: $1 is not a valid file or directory." exit 1 -fi - - -# #!/bin/bash - -# # Choose which Extensions are acceptable - - -# extensions=("mp4" "mkv" "avi" "mov" "m4v" "flv" "lrv") - -# # Language code translation associative array -# declare -A LANG_CODES=( -# ["eng"]="English" -# ["en"]="English" -# ["spa"]="Spanish" -# ["es"]="Spanish" -# ["fra"]="French" -# ["fr"]="French" -# ["deu"]="German" -# ["ger"]="German" -# ["de"]="German" -# ["jpn"]="Japanese" -# ["ja"]="Japanese" -# ["ita"]="Italian" -# ["it"]="Italian" -# ["por"]="Portuguese" -# ["pt"]="Portuguese" -# ["rus"]="Russian" -# ["ru"]="Russian" -# ["chi"]="Chinese" -# ["zh"]="Chinese" -# ["kor"]="Korean" -# ["ko"]="Korean" -# ["dut"]="Dutch" -# ["nl"]="Dutch" -# ["swe"]="Swedish" -# ["sv"]="Swedish" -# ["fin"]="Finnish" -# ["fi"]="Finnish" -# ["pol"]="Polish" -# ["pl"]="Polish" -# ["ara"]="Arabic" -# ["ar"]="Arabic" -# ["hin"]="Hindi" -# ["hi"]="Hindi" -# ["tur"]="Turkish" -# ["tr"]="Turkish" -# ["und"]="Undefined" -# [" "]="Undefined" -# ) - -# # Function to translate language codes -# translate_language() { -# local code="$1" -# # Sanitize input: remove spaces and convert to lowercase -# code=$(echo "$code" | tr -d '[:space:]' | tr '[:upper:]' '[:lower:]') - -# # Debugging output -# # echo "DEBUG: Translating code: '$code'" >&2 - -# # Check for valid subscript and handle fallback -# if [[ -z "$code" || ! ${LANG_CODES[$code]+_} ]]; then -# echo "Undefined" -# else -# echo "${LANG_CODES[$code]}" -# fi -# } - -# # Function to format file size in human-readable form -# format_file_size() { -# local size_bytes="$1" -# if [ "$size_bytes" -lt 1024 ]; then -# echo "${size_bytes}B" -# elif [ "$size_bytes" -lt 1048576 ]; then -# echo "$((size_bytes / 1024))KB" -# elif [ "$size_bytes" -lt 1073741824 ]; then -# echo "$((size_bytes / 1048576))MB" -# else -# echo "$((size_bytes / 1073741824))GB" -# fi -# } - -# # Function to extract video, audio, and subtitle details for a single file -# process_file() { -# local file="$1" -# local file_size -# file_size=$(stat --printf="%s" "$file") -# formatted_size=$(format_file_size "$file_size") - -# # Extract video codec, width, height, and pixel format (like yuv420p(tv, bt709)) -# video_info=$(ffprobe -v quiet -select_streams v:0 -show_entries stream=codec_name,width,height,pix_fmt,color_space \ -# -of default=noprint_wrappers=1:nokey=1 "$file") -# codec=$(echo "$video_info" | sed -n '1p') -# width=$(echo "$video_info" | sed -n '2p') -# height=$(echo "$video_info" | sed -n '3p') -# pix_fmt=$(echo "$video_info" | sed -n '4p') -# color_space=$(echo "$video_info" | sed -n '5p') - -# # Extract audio information (language, codec, and channel layout) -# audio_info=$(ffprobe -v quiet -select_streams a -show_entries stream=codec_name,channel_layout:stream_tags=language \ -# -of default=noprint_wrappers=1:nokey=1 "$file" | paste -sd "," -) - -# # Extract subtitle information (language) -# subtitle_info=$(ffprobe -v quiet -select_streams s -show_entries stream_tags=language \ -# -of default=noprint_wrappers=1:nokey=1 "$file" | paste -sd "," -) - -# # Format video output -# video_output="Video: ${codec} (${width}x${height}), ${pix_fmt} (${color_space})" - -# # Format audio output -# audio_output="Audio: " -# IFS=',' read -r -a audio_streams <<< "$audio_info" -# for (( i=0; i<${#audio_streams[@]}; i+=3 )); do -# audio_codec="${audio_streams[i]}" -# channel_layout="${audio_streams[i+1]}" -# lang_code="${audio_streams[i+2]}" -# lang=$(translate_language "${lang_code:-" "}") -# audio_output+="${lang} ${audio_codec} ${channel_layout}" -# if (( i+3 < ${#audio_streams[@]} )); then -# audio_output+=", " -# fi -# done - -# # Format subtitle output -# subtitle_output="Subtitles: " -# if [ -n "$subtitle_info" ]; then -# IFS=',' read -r -a subtitle_streams <<< "$subtitle_info" -# for lang in "${subtitle_streams[@]}"; do -# subtitle_output+=$(translate_language "$lang") -# subtitle_output+=", " -# done -# # Remove the last comma -# subtitle_output=${subtitle_output%, } -# else -# subtitle_output="Subtitles: None" -# fi - -# # Output the result for the file -# echo "$file ($formatted_size):" -# echo -e "\t$video_output" -# echo -e "\t$audio_output" -# echo -e "\t$subtitle_output" -# } - -# # Main script logic -# if [ -z "$1" ]; then -# for ext in "${extensions[@]}"; do -# # No argument provided, process all video files in the current directory -# for file in *."$ext"; do -# [ -e "$file" ] || continue # Skip if no matching files -# process_file "$file" -# done -# done -# elif [ -d "$1" ]; then -# # Argument is a directory, process all video files in that directory -# for file in "$1"/*.{mp4,mkv,avi,mov}; do -# [ -e "$file" ] || continue # Skip if no matching files -# process_file "$file" -# done -# elif [ -f "$1" ]; then -# # Argument is a single file, process only that file -# process_file "$1" -# else -# echo "Error: $1 is not a valid file or directory." -# exit 1 -# fi +fi \ No newline at end of file diff --git a/video-audio b/video-audio new file mode 100755 index 0000000..3a01ec8 --- /dev/null +++ b/video-audio @@ -0,0 +1,130 @@ +#!/usr/bin/env python3 + +import json +import subprocess +import sys +from pathlib import Path +import shutil + +def run(cmd): + print(f"[*] Running: {' '.join(map(str, cmd))}") + subprocess.run(cmd, check=True) + +def get_tracks(video): + result = subprocess.run( + ["mkvmerge", "-J", str(video)], + capture_output=True, + text=True, + check=True, + ) + data = json.loads(result.stdout) + return [t for t in data["tracks"] if t["type"] == "audio"] + +def codec_to_ext(codec): + codec = codec.lower() + if "aac" in codec: return "aac" + if "ac-3" in codec or "ac3" in codec: return "ac3" + if "dts" in codec: return "dts" + if "flac" in codec: return "flac" + if "opus" in codec: return "opus" + return "mka" + +def clean(text): + return "".join(c if c.isalnum() or c in "-_." else "_" for c in text) + +def extract(vdir, outdir): + outdir.mkdir(parents=True, exist_ok=True) + + for video in vdir.iterdir(): + if not video.is_file(): + continue + + name = video.stem + print(f"\n=== Scanning {video.name} ===") + + for track in get_tracks(video): + tid = track["id"] + props = track.get("properties", {}) + lang = props.get("language", "und") + tname = props.get("track_name", "") + codec = track.get("codec", "") + + ext = codec_to_ext(codec) + + suffix = lang + if tname: + suffix += "-" + clean(tname) + + outfile = outdir / f"{name}-{suffix}.{ext}" + + print(f"Extracting track {tid}: lang={lang}, name={tname}, codec={codec}") + run(["mkvextract", "tracks", str(video), f"{tid}:{outfile}"]) + +def include(vdir, adir): + for video in vdir.iterdir(): + if not video.is_file(): + continue + + name = video.stem + tmp = video.with_name(name + "-tmp.mkv") + + print(f"\n=== Processing {video.name} ===") + + audios = list(adir.glob(f"{name}-*")) + if not audios: + print("No matching audio found.") + continue + + unknown = [] + known = [] + + for a in audios: + meta = a.stem[len(name)+1:] # remove "name-" + parts = meta.split("-", 1) + lang = parts[0] + tname = parts[1] if len(parts) > 1 else "" + + entry = (a, lang, tname) + if lang in ("und", "unknown", ""): + unknown.append(entry) + else: + known.append(entry) + + cmd = ["mkvmerge", "-o", str(tmp), str(video)] + + for file, lang, tname in unknown + known: + print(f"Adding {file.name} lang={lang} name={tname}") + cmd += ["--language", f"0:{lang}"] + if tname: + cmd += ["--track-name", f"0:{tname}"] + cmd.append(str(file)) + + run(cmd) + shutil.move(tmp, video) + print(f"Finished {video.name}") + +def main(): + if len(sys.argv) < 3: + print("Usage:") + print(" script extract [audio_out_dir]") + print(" script include [audio_dir]") + sys.exit(1) + + action = sys.argv[1] + vdir = Path(sys.argv[2]).resolve() + adir = Path(sys.argv[3]).resolve() if len(sys.argv) > 3 else vdir + + if not vdir.is_dir(): + print("Video directory not found.") + sys.exit(1) + + if action == "extract": + extract(vdir, adir) + elif action == "include": + include(vdir, adir) + else: + print("Unknown action.") + sys.exit(1) + +if __name__ == "__main__": + main()