mirror of
https://git.srhtnin.garden/sarah/SaraView.git
synced 2026-10-15 02:43:17 +02:00
Fixed audio embed videos running longer than the audio in AudioEmbed.py
This commit is contained in:
1 parent
72ebe6186b
commit
5f47a4a9da
1 file changed
+21
-3
+21
-3
@@ -25,6 +25,9 @@ ApplicationDirectory = Path(__file__).resolve().parent
|
||||
# The browser-tab icon (Frontend/public/Icons), when the audio has no cover art.
|
||||
IconPath = ApplicationDirectory.parent / "Frontend" / "dist" / "Icons" / "Icon.png"
|
||||
FrameSize = 480
|
||||
# Part of every cache key: bump it when the videos change, so old ones
|
||||
# aren't served (2: cut to the audio's exact length).
|
||||
EncodingVersion = 2
|
||||
EncodeTimeout = 600 # seconds
|
||||
|
||||
_Locks: dict[str, threading.Lock] = {}
|
||||
@@ -65,10 +68,19 @@ def _BackgroundColour() -> str:
|
||||
|
||||
def _CachePath(AudioPath: Path) -> Path:
|
||||
Stat = AudioPath.stat()
|
||||
Key = hashlib.sha256(f"{AudioPath}|{Stat.st_size}|{Stat.st_mtime_ns}".encode()).hexdigest()[:32]
|
||||
Key = hashlib.sha256(f"{EncodingVersion}|{AudioPath}|{Stat.st_size}|{Stat.st_mtime_ns}".encode()).hexdigest()[:32]
|
||||
return GetDataDirectory() / "EmbedCache" / f"{Key}.mp4"
|
||||
|
||||
|
||||
def _AudioDuration(AudioPath: Path) -> float | None:
|
||||
try:
|
||||
Result = subprocess.run(["ffprobe", "-v", "error", "-show_entries", "format=duration", "-of", "csv=p=0",
|
||||
str(AudioPath)], capture_output=True, text=True, timeout=60)
|
||||
return float(Result.stdout.strip())
|
||||
except (OSError, subprocess.SubprocessError, ValueError):
|
||||
return None
|
||||
|
||||
|
||||
def _ExtractCoverArt(AudioPath: Path, Target: Path) -> bool:
|
||||
"""Writes the file's own cover art (if it has any) to Target as a PNG."""
|
||||
try:
|
||||
@@ -95,11 +107,17 @@ def _Encode(AudioPath: Path, Target: Path) -> None:
|
||||
# A non-square cover gets bars in the theme's background colour.
|
||||
Fit = (f"scale={FrameSize}:{FrameSize}:force_original_aspect_ratio=decrease:flags={Scaling},"
|
||||
f"pad={FrameSize}:{FrameSize}:(ow-iw)/2:(oh-ih)/2:color=0x{Background},format=yuv420p")
|
||||
# The picture loops forever, so the video is cut to the audio's length.
|
||||
# -shortest alone overshoots: libx264 buffers ~40 frames ahead, which at
|
||||
# one frame a second left the picture running 40+ seconds past the
|
||||
# audio, and Discord wouldn't play that.
|
||||
Duration = _AudioDuration(AudioPath)
|
||||
Length = ["-t", f"{Duration:.3f}"] if Duration else []
|
||||
Command = [
|
||||
"ffmpeg", "-y", "-loglevel", "error", *Picture, "-i", str(AudioPath),
|
||||
"-map", "0:v:0", "-map", "1:a:0", "-vf", Fit, "-r", "1",
|
||||
"-map", "0:v:0", "-map", "1:a:0", "-vf", Fit, "-r", "1", "-g", "10",
|
||||
*_VideoEncoder(),
|
||||
"-c:a", "aac", "-b:a", "192k", "-shortest", "-movflags", "+faststart", str(Partial),
|
||||
"-c:a", "aac", "-b:a", "192k", "-shortest", *Length, "-movflags", "+faststart", str(Partial),
|
||||
]
|
||||
try:
|
||||
subprocess.run(Command, check=True, capture_output=True, timeout=EncodeTimeout)
|
||||
|
||||
Reference in new issue
Block a user