Update torchlight_changes_unloze/torchlight3/Torchlight/FFmpegAudioPlayer.py
This commit is contained in:
parent
ff3dff14a6
commit
6715d2a07c
@ -60,6 +60,9 @@ class FFmpegAudioPlayer():
|
|||||||
|
|
||||||
def PlayURI(self, uri, position, rubberband = None, dec_params = None, bitrate = None,
|
def PlayURI(self, uri, position, rubberband = None, dec_params = None, bitrate = None,
|
||||||
backwards = None, *args):
|
backwards = None, *args):
|
||||||
|
if self.Playing:
|
||||||
|
self.Stop()
|
||||||
|
|
||||||
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]
|
||||||
@ -71,7 +74,13 @@ class FFmpegAudioPlayer():
|
|||||||
if args:
|
if args:
|
||||||
Command += list(args)
|
Command += list(args)
|
||||||
|
|
||||||
|
# Reset per-play counters/state in case this instance is reused.
|
||||||
|
self.Seconds = 0.0
|
||||||
|
self.StartedPlaying = None
|
||||||
|
self.StoppedPlaying = None
|
||||||
|
self._byte_remainder = 0
|
||||||
self.Playing = True
|
self.Playing = True
|
||||||
|
|
||||||
if dec_params:
|
if dec_params:
|
||||||
Command += dec_params
|
Command += dec_params
|
||||||
|
|
||||||
@ -172,7 +181,7 @@ class FFmpegAudioPlayer():
|
|||||||
|
|
||||||
if SecondsElapsed >= self.Seconds:
|
if SecondsElapsed >= self.Seconds:
|
||||||
if not self.StoppedPlaying:
|
if not self.StoppedPlaying:
|
||||||
print("BUFFER UNDERRUN!")
|
self.Master.Logger.warning("BUFFER UNDERRUN")
|
||||||
self.Stop(False)
|
self.Stop(False)
|
||||||
return
|
return
|
||||||
|
|
||||||
@ -180,55 +189,65 @@ class FFmpegAudioPlayer():
|
|||||||
|
|
||||||
async def _read_stream(self, stream, writer):
|
async def _read_stream(self, stream, writer):
|
||||||
Started = False
|
Started = False
|
||||||
|
try:
|
||||||
|
while stream and self.Playing:
|
||||||
|
Data = await stream.read(65536)
|
||||||
|
|
||||||
while stream and self.Playing:
|
if Data:
|
||||||
Data = await stream.read(65536)
|
try:
|
||||||
|
writer.write(Data)
|
||||||
|
await writer.drain()
|
||||||
|
except (ConnectionError, BrokenPipeError, OSError) as ex:
|
||||||
|
self.Master.Logger.warning("Voice socket write failed: %s", ex)
|
||||||
|
break
|
||||||
|
|
||||||
if Data:
|
Bytes = len(Data)
|
||||||
writer.write(Data)
|
frame_size = SAMPLEBYTES * self.Channels
|
||||||
await writer.drain()
|
|
||||||
|
|
||||||
Bytes = len(Data)
|
# Guard against invalid configuration and use integral frame counting
|
||||||
frame_size = SAMPLEBYTES * self.Channels
|
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
|
||||||
|
|
||||||
# Guard against invalid configuration and use integral frame counting
|
if not Started:
|
||||||
if frame_size <= 0 or self.SampleRate <= 0:
|
Started = True
|
||||||
self.Master.Logger.error(
|
self.Callback("Play")
|
||||||
"Invalid audio configuration: Channels=%r, SampleRate=%r",
|
self.StartedPlaying = time.time()
|
||||||
self.Channels,
|
asyncio.ensure_future(self._updater())
|
||||||
self.SampleRate,
|
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
# Accumulate remainder bytes to avoid systematic undercounting
|
self.Process = None
|
||||||
total_bytes = getattr(self, "_byte_remainder", 0) + Bytes
|
break
|
||||||
Frames = total_bytes // frame_size
|
finally:
|
||||||
self._byte_remainder = total_bytes % frame_size
|
self.StoppedPlaying = time.time()
|
||||||
Seconds = Frames / self.SampleRate
|
|
||||||
self.Seconds += Seconds
|
|
||||||
|
|
||||||
if not Started:
|
|
||||||
Started = True
|
|
||||||
self.Callback("Play")
|
|
||||||
self.StartedPlaying = time.time()
|
|
||||||
asyncio.ensure_future(self._updater())
|
|
||||||
else:
|
|
||||||
self.Process = None
|
|
||||||
break
|
|
||||||
|
|
||||||
self.StoppedPlaying = time.time()
|
|
||||||
|
|
||||||
async def _stream_subprocess(self, cmd):
|
async def _stream_subprocess(self, cmd):
|
||||||
if not self.Playing:
|
if not self.Playing:
|
||||||
return
|
return
|
||||||
|
try:
|
||||||
|
_, self.Writer = await asyncio.open_connection(self.Host[0], self.Host[1])
|
||||||
|
|
||||||
_, self.Writer = await asyncio.open_connection(self.Host[0], self.Host[1])
|
Process = await asyncio.create_subprocess_exec(*cmd,
|
||||||
|
stdout = asyncio.subprocess.PIPE, stderr = asyncio.subprocess.DEVNULL)
|
||||||
|
self.Process = Process
|
||||||
|
|
||||||
Process = await asyncio.create_subprocess_exec(*cmd,
|
await self._read_stream(Process.stdout, self.Writer)
|
||||||
stdout = asyncio.subprocess.PIPE, stderr = asyncio.subprocess.DEVNULL)
|
await Process.wait()
|
||||||
self.Process = Process
|
|
||||||
|
|
||||||
await self._read_stream(Process.stdout, self.Writer)
|
if self.Playing:
|
||||||
await Process.wait()
|
self.Stop(False)
|
||||||
|
except asyncio.CancelledError:
|
||||||
if self.Seconds == 0.0:
|
raise
|
||||||
self.Stop()
|
except Exception:
|
||||||
|
self.Master.Logger.error(traceback.format_exc())
|
||||||
|
if self.Playing:
|
||||||
|
self.Stop()
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user