Reworked some of the scripts
This commit is contained in:
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
git-honney333-work-cred
|
||||
git-tub
|
||||
@@ -1,5 +1,4 @@
|
||||
import os
|
||||
import ffmpeg
|
||||
import subprocess
|
||||
import re
|
||||
import json
|
||||
|
||||
@@ -358,168 +358,3 @@ 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
|
||||
|
||||
130
video-audio
Executable file
130
video-audio
Executable file
@@ -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 <video_dir> [audio_out_dir]")
|
||||
print(" script include <video_dir> [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()
|
||||
Reference in New Issue
Block a user