Update torchlight_changes_unloze/torchlight3/Torchlight/FFmpegAudioPlayer.py

This commit is contained in:
Metroid_Skittles 2026-02-06 19:40:29 +01:00
parent 67529b652f
commit 3e44425df9

View File

@ -43,6 +43,7 @@ class FFmpegAudioPlayer():
self.Torchlight().Config["VoiceServer"]["Port"] self.Torchlight().Config["VoiceServer"]["Port"]
) )
self.SampleRate = float(self.Torchlight().Config["VoiceServer"]["SampleRate"]) self.SampleRate = float(self.Torchlight().Config["VoiceServer"]["SampleRate"])
self.Channels = int(self.Torchlight().Config["VoiceServer"].get("Channels", 2))
self.StartedPlaying = None self.StartedPlaying = None
self.StoppedPlaying = None self.StoppedPlaying = None
@ -62,35 +63,51 @@ class FFmpegAudioPlayer():
if position: if position:
PosStr = str(datetime.timedelta(seconds = position)) PosStr = str(datetime.timedelta(seconds = position))
#Command = ["/usr/bin/ffmpeg", "-ss", PosStr, "-i", uri, "-acodec", "pcm_s16le", "-ac", "1", "-ar", str(int(self.SampleRate)), "-f", "s16le", "-vn", *args] #Command = ["/usr/bin/ffmpeg", "-ss", PosStr, "-i", uri, "-acodec", "pcm_s16le", "-ac", "1", "-ar", str(int(self.SampleRate)), "-f", "s16le", "-vn", *args]
Command = ["/usr/bin/ffmpeg", "-ss", PosStr, "-i", uri, "-af", "highpass=f=20", "-acodec", "pcm_s16le", "-ac", "2", "-ar", str(int(self.SampleRate)), "-f", "s16le", "-vn", *args] Command = ["/usr/bin/ffmpeg", "-ss", PosStr, "-i", uri, "-acodec", "pcm_s16le", "-ac", str(self.Channels), "-ar", str(int(self.SampleRate)), "-f", "s16le", "-vn"]
else: else:
#Command = ["/usr/bin/ffmpeg", "-i", uri, "-acodec", "pcm_s16le", "-ac", "1", "-ar", str(int(self.SampleRate)), "-f", "s16le", "-vn", *args] #Command = ["/usr/bin/ffmpeg", "-i", uri, "-acodec", "pcm_s16le", "-ac", "1", "-ar", str(int(self.SampleRate)), "-f", "s16le", "-vn", *args]
Command = ["/usr/bin/ffmpeg", "-i", uri, "-af", "highpass=f=20", "-acodec", "pcm_s16le", "-ac", "2", "-ar", str(int(self.SampleRate)),"-f", "s16le", "-vn"] Command = ["/usr/bin/ffmpeg", "-i", uri, "-acodec", "pcm_s16le", "-ac", str(self.Channels), "-ar", str(int(self.SampleRate)), "-f", "s16le", "-vn"]
if args:
Command += list(args)
self.Playing = True self.Playing = True
if dec_params: if dec_params:
Command += dec_params Command += dec_params
if rubberband and backwards: filter_chain = ["highpass=f=20"]
Command += ["-filter:a"]
rubberCommand = ""
for rubber in rubberband:
rubberCommand += rubber + ", "
rubberCommand = rubberCommand[:-2]
Command += [rubberCommand + "[reversed];[reversed]areverse"] #[reversed] is intermediate stream label so reverse knows what stream label to reverse
else:
if rubberband: if rubberband:
Command += ["-filter:a"] # Treat rubberband as either a single pre-built filtergraph string
rubberCommand = "" # or an iterable of simple, comma-safe filters. Validate to avoid
for rubber in rubberband: # generating invalid ffmpeg filter syntax.
rubberCommand += rubber + ", " rubberband_filters = []
rubberCommand = rubberCommand[:-2] if isinstance(rubberband, str):
Command += [rubberCommand] rubberband_filters = [rubberband]
else:
try:
iterator = iter(rubberband)
except TypeError:
# Not iterable: coerce to string and treat as single element.
rubberband_filters = [str(rubberband)]
else:
for f in iterator:
if not isinstance(f, str):
f = str(f)
# Reject potentially complex/unsafe filter fragments that
# could break the filtergraph when joined with commas.
if any(ch in f for ch in [",", ";", "[", "]"]):
self.Master.Logger.error(
"Skipping unsafe rubberband filter fragment %r: "
"contains ',', ';', '[' or ']'", f
)
continue
rubberband_filters.append(f)
filter_chain.extend(rubberband_filters)
if backwards: if backwards:
Command += ["-af"] filter_chain.append("areverse")
Command += ["areverse"] Command += ["-filter:a", ",".join(filter_chain)]
if bitrate: if bitrate:
Command += ["-ab ", str(bitrate), "k"] Command += ["-b:a", f"{bitrate}k"]
self.Master.Logger.debug(f"command: {Command}") self.Master.Logger.debug(f"command: {Command}")
Command += ["-"] Command += ["-"]
#self.Master.Logger.debug(f"command: {Command}") #self.Master.Logger.debug(f"command: {Command}")
@ -123,7 +140,7 @@ class FFmpegAudioPlayer():
self.Playing = False self.Playing = False
self.Callback("Stop") self.Callback("Stop")
del self.Callbacks self.Callbacks = []
return True return True
@ -159,8 +176,6 @@ class FFmpegAudioPlayer():
self.Stop(False) self.Stop(False)
return return
LastSecondsElapsed = SecondsElapsed
await asyncio.sleep(0.1) await asyncio.sleep(0.1)
async def _read_stream(self, stream, writer): async def _read_stream(self, stream, writer):
@ -174,9 +189,21 @@ class FFmpegAudioPlayer():
await writer.drain() await writer.drain()
Bytes = len(Data) Bytes = len(Data)
Samples = Bytes / SAMPLEBYTES frame_size = SAMPLEBYTES * self.Channels
Seconds = Samples / self.SampleRate
# Guard against invalid configuration and use integral frame counting
if frame_size <= 0 or self.SampleRate <= 0:
self.Master.Logger.error(
"Invalid audio configuration: Channels=%r, SampleRate=%r",
self.Channels,
self.SampleRate,
)
else:
# Accumulate remainder bytes to avoid systematic undercounting
total_bytes = getattr(self, "_byte_remainder", 0) + Bytes
Frames = total_bytes // frame_size
self._byte_remainder = total_bytes % frame_size
Seconds = Frames / self.SampleRate
self.Seconds += Seconds self.Seconds += Seconds
if not Started: if not Started: