A lot of bug fixes and edge cases

This commit is contained in:
Hannes committed 2026-03-22 03:20:45 +01:00
1 parent 58e66996cc
commit 004556c4a7
5 files changed
+237 -106

No files matched your search

+148 -65
View File
@@ -35,8 +35,9 @@ def extract_audio_segment_file(video: Path, start_time: float, end_time: float,
"-i", video,
"-ss", str(start_time),
"-to", str(end_time),
"-map", "0:a:0", # first audio track
"-c:a", "copy", # no re-encode
"-map", "0:a:0",
"-ac", "2", # force stereo
"-c:a", "aac", # re-encode
out_audio
])
@@ -152,32 +153,55 @@ def get_audio_duration(file_path: Path):
res += float(result[i])*(60**i)
return res
def stick_together_audio(left_audio: Path, right_audio: Path, output_audio: Path) -> None:
"""
Concatenate two audio files so that left_audio plays directly
before right_audio in the output file.
"""
### V1
# def stick_together_audio(left_audio: Path, right_audio: Path, output_audio: Path) -> None:
# """
# Concatenate two audio files so that left_audio plays directly
# before right_audio in the output file.
# """
# left_audio = Path(left_audio)
# right_audio = Path(right_audio)
# output_audio = Path(output_audio)
# # Use stem instead of prefix to create a temporary file
# output_audio_tmp = output_audio.parent / (output_audio.stem + "_temp" + output_audio.suffix)
# run([
# "ffmpeg",
# "-y",
# "-i", str(left_audio),
# "-i", str(right_audio),
# "-filter_complex", "[0:a][1:a]concat=n=2:v=0:a=1[a]",
# "-map", "[a]",
# "-c:a", "opus", # or "aac" if you prefer
# "-strict", "-2",
# str(output_audio_tmp)
# ])
# shutil.move(output_audio_tmp, output_audio)
def stick_together_audio(left_audio: Path, right_audio: Path, output_audio: Path) -> None:
left_audio = Path(left_audio)
right_audio = Path(right_audio)
output_audio = Path(output_audio)
# Use stem instead of prefix to create a temporary file
output_audio_tmp = output_audio.parent / (output_audio.stem + "_temp" + output_audio.suffix)
run([
"ffmpeg",
"-y",
"-i", str(left_audio),
"-i", str(right_audio),
"-filter_complex", "[0:a][1:a]concat=n=2:v=0:a=1[a]",
"-map", "[a]",
"-c:a", "opus", # or "aac" if you prefer
"-strict", "-2",
str(output_audio_tmp)
])
shutil.move(output_audio_tmp, output_audio)
with tempfile.NamedTemporaryFile("w", delete=False, suffix=".txt") as f:
f.write(f"file '{left_audio.resolve()}'\n")
f.write(f"file '{right_audio.resolve()}'\n")
list_file = f.name
try:
run([
"ffmpeg",
"-y",
"-f", "concat",
"-safe", "0",
"-i", list_file,
"-c", "copy", # no re-encode
str(output_audio)
])
except Exception as e:
raise BrokenPipeError(f"{e}\n{f.readlines(-1)}")
def get_audio_streams(file: Path) -> List[int]:
"""
@@ -224,6 +248,9 @@ def get_track_info(file: Path, audioline: int):
return {"codec": "aac", "bitrate": "192k", "lang": "eng", "title": "Audio"}
def shift_audio(file: Path, audioline: int, offset: float):
"""
Shifts audio by offset sekonds to the right.
"""
if not file.is_file(): return
info = get_track_info(file, audioline)
@@ -258,7 +285,7 @@ def shift_audio(file: Path, audioline: int, offset: float):
"-b:a", str(info['bitrate']),
str(temp_mka)
]
subprocess.run(process_cmd, check=True)
run(process_cmd)
# --- STEP 2: Replace in MKV via mkvmerge ---
# --audio-tracks !ID excludes the old track
@@ -271,13 +298,71 @@ def shift_audio(file: Path, audioline: int, offset: float):
str(temp_mka)
]
subprocess.run(merge_cmd, check=True)
run(merge_cmd)
# Cleanup and Replace
shutil.move(str(output_mkv), str(file))
temp_mka.unlink()
print(f"Done: {file.name} updated physically.")
def add_silence(file: Path, offset: float) -> None:
"""
Hard-edits an MKA file by adding silence.
Positive offset: Adds silence at the beginning.
Negative offset: Adds silence at the end.
"""
if not file.is_file():
print(f"File not found: {file}")
return
if offset == 0:
print("Offset is 0, no silence to add.")
return
# Create a normal file path right next to the original file
new_file = file.parent / f"silenced_{file.name}"
# 1. Determine the filter
if offset > 0:
# Silence at the beginning: delay all channels
ms = int(offset * 1000)
audio_filter = f"adelay={ms}:all=1"
action_text = "beginning"
else:
# Silence at the end: pad with specific duration in seconds
sec = abs(offset)
audio_filter = f"apad=pad_dur={sec}"
action_text = "end"
# 2. Execute FFmpeg
cmd = [
"ffmpeg", "-y",
"-i", str(file),
"-af", audio_filter,
"-c:a", "libopus",
str(new_file)
]
# print(f"Adding {abs(offset)}s of silence to the {action_text} of {file.name}...")
result = subprocess.run(cmd, capture_output=True, text=True)
# 3. Verify and replace
if result.returncode == 0:
# Quick safety check to ensure FFmpeg didn't output an empty file
if new_file.exists() and new_file.stat().st_size > 0:
shutil.move(str(new_file), str(file))
# print(f"Successfully updated: {file.name}")
else:
print("Error: FFmpeg succeeded, but the output file is empty.")
if new_file.exists():
new_file.unlink()
else:
print(f"FFmpeg Error:\n{result.stderr}")
# Clean up the leftover file if the process failed
if new_file.exists():
new_file.unlink()
def replace_with_shifted_mka(mkv_file: Path, mka_source: Path, audioline: int, offset: float):
"""
Physically shifts an existing MKA and replaces a track in the MKV.
@@ -289,45 +374,43 @@ def replace_with_shifted_mka(mkv_file: Path, mka_source: Path, audioline: int, o
return
# mkvmerge IDs: 0 is usually video, so audioline 0 is track 1, etc.
mkv_track_id = audioline + 1
mkv_track_id = audioline + 1
shifted_mka = mkv_file.parent / "shifted.mka"
output_mkv = mkv_file.parent / "final_output.mkv"
# --- STEP 1: Physical Shift ---
# Positive offset: adelay (adds real silence packets)
# Negative offset: atrim (removes packets) + asetpts (resets timestamps)
ms = int(abs(offset) * 1000)
if offset > 0:
filter_chain = f"adelay={ms}:all=1"
else:
filter_chain = f"atrim=start={abs(offset)},asetpts=PTS-STARTPTS"
print(f"Physically shifting {mka_source.name}...")
process_cmd = [
"ffmpeg", "-y", "-i", str(mka_source),
"-af", filter_chain,
"-c:a", "libopus", # Set to Opus as per your track name
"-b:a", "160k", # Standard high-quality bitrate for stereo Opus
str(shifted_mka)
]
subprocess.run(process_cmd, check=True, capture_output=True)
# --- STEP 2: Replace track in MKV ---
# --audio-tracks !ID excludes the old line from the original MKV
print(f"Replacing track {audioline} in {mkv_file.name}...")
merge_cmd = [
"mkvmerge", "-o", str(output_mkv),
"--audio-tracks", f"!{mkv_track_id}", str(mkv_file),
"--language", "0:ger",
"--track-name", "0:German (Opus Stereo)",
str(shifted_mka)
]
with tempfile.TemporaryDirectory() as temp_dir:
temp_path = Path(temp_dir)
shifted_mka = temp_path / "shifted.mka"
output_mkv = temp_path / "final_output.mkv"
subprocess.run(merge_cmd, check=True, capture_output=True)
# --- STEP 1: Physical Shift ---
# Positive offset: adelay (adds real silence packets)
# Negative offset: atrim (removes packets) + asetpts (resets timestamps)
ms = int(abs(offset) * 1000)
if offset > 0:
filter_chain = f"adelay={ms}:all=1"
else:
filter_chain = f"atrim=start={abs(offset)},asetpts=PTS-STARTPTS"
print(f"Physically shifting {mka_source.name}...")
process_cmd = [
"ffmpeg", "-y", "-i", str(mka_source),
"-af", filter_chain,
"-c:a", "libopus", # Set to Opus as per your track name
"-b:a", "160k", # Standard high-quality bitrate for stereo Opus
str(shifted_mka)
]
subprocess.run(process_cmd, check=True, capture_output=True)
# --- STEP 2: Replace track in MKV ---
# --audio-tracks !ID excludes the old line from the original MKV
print(f"Replacing track {audioline} in {mkv_file.name}...")
merge_cmd = [
"mkvmerge", "-o", str(output_mkv),
"--audio-tracks", f"!{mkv_track_id}", str(mkv_file),
"--language", "0:ger",
"--track-name", "0:German (Opus Stereo)",
str(shifted_mka)
]
subprocess.run(merge_cmd, check=True, capture_output=True)
# --- STEP 3: Cleanup and Overwrite ---
shutil.move(str(output_mkv), str(mkv_file))
print(f"Success: Updated {mkv_file.name}")
# --- STEP 3: Cleanup and Overwrite ---
shutil.move(str(output_mkv), str(mkv_file))
# print(f"Success: Updated {mkv_file.name}")