Better termination logic for the ffmpeg audio converter.

This commit is contained in:
Fabio Manganiello 2023-06-16 11:47:37 +02:00
parent a6351dddd4
commit 9aa8e4538a
Signed by: blacklight
GPG Key ID: D90FBA7F76362774
4 changed files with 17 additions and 18 deletions

View File

@ -40,8 +40,7 @@
<div class="audio-container"> <div class="audio-container">
<audio autoplay preload="none" ref="player" v-if="audioOn"> <audio autoplay preload="none" ref="player" v-if="audioOn">
<!--suppress HtmlUnknownTarget --> <source :src="`/sound/stream.aac?t=${(new Date()).getTime()}`">
<source :src="`/sound/stream?t=${(new Date()).getTime()}`" type="audio/x-wav;codec=pcm">
Your browser does not support audio elements Your browser does not support audio elements
</audio> </audio>
</div> </div>

View File

@ -2,8 +2,7 @@
<div class="sound"> <div class="sound">
<div class="sound-container"> <div class="sound-container">
<audio autoplay preload="none" ref="player" v-if="recording"> <audio autoplay preload="none" ref="player" v-if="recording">
<!--suppress HtmlUnknownTarget --> <source :src="`/sound/stream.aac?t=${(new Date()).getTime()}`">
<source :src="`/sound/stream?t=${(new Date()).getTime()}`" type="audio/x-wav;codec=pcm">
Your browser does not support audio elements Your browser does not support audio elements
</audio> </audio>
</div> </div>

View File

@ -1,5 +1,3 @@
from dataclasses import dataclass
from typing import IO from typing import IO
from typing_extensions import override from typing_extensions import override
@ -16,7 +14,6 @@ from .._model import AudioState
from ._base import AudioThread from ._base import AudioThread
@dataclass
class AudioRecorder(AudioThread): class AudioRecorder(AudioThread):
""" """
The ``AudioRecorder`` thread is responsible for recording audio from the The ``AudioRecorder`` thread is responsible for recording audio from the
@ -32,7 +29,7 @@ class AudioRecorder(AudioThread):
# _ = frames # _ = frames
# __ = time # __ = time
def callback(indata, outdata, _, __, status): def callback(indata, outdata, _, __, status):
if self.state == AudioState.PAUSED: if self.state != AudioState.RUNNING:
return return
if status: if status:
@ -41,7 +38,7 @@ class AudioRecorder(AudioThread):
try: try:
audio_converter.write(indata.tobytes()) audio_converter.write(indata.tobytes())
except AssertionError as e: except AssertionError as e:
self.logger.warning('Audio recorder callback error: %s', e) self.logger.warning('Audio converter callback error: %s', e)
self.state = AudioState.STOPPED self.state = AudioState.STOPPED
return return
@ -63,8 +60,10 @@ class AudioRecorder(AudioThread):
@override @override
def notify_stop(self): def notify_stop(self):
prev_state = self.state
super().notify_stop() super().notify_stop()
get_bus().post(SoundRecordingStoppedEvent()) if prev_state != AudioState.STOPPED:
get_bus().post(SoundRecordingStoppedEvent())
# vim:sw=4:ts=4:et: # vim:sw=4:ts=4:et:

View File

@ -1,5 +1,6 @@
import asyncio import asyncio
from asyncio.subprocess import PIPE from asyncio.subprocess import PIPE
from logging import getLogger
from queue import Empty from queue import Empty
from queue import Queue from queue import Queue
@ -74,6 +75,7 @@ class ConverterProcess(Thread):
self._closed = False self._closed = False
self._out_queue = Queue() self._out_queue = Queue()
self.ffmpeg = None self.ffmpeg = None
self.logger = getLogger(__name__)
self._loop = None self._loop = None
self._should_stop = Event() self._should_stop = Event()
self._stop_lock = RLock() self._stop_lock = RLock()
@ -157,21 +159,21 @@ class ConverterProcess(Thread):
def run(self): def run(self):
super().run() super().run()
self._loop = get_or_create_event_loop() self._loop = get_or_create_event_loop()
self._loop.run_until_complete(self._audio_proxy(timeout=1)) try:
self._loop.run_until_complete(self._audio_proxy(timeout=1))
except RuntimeError as e:
self.logger.warning(e)
finally:
self.stop()
def stop(self): def stop(self):
with self._stop_lock: with self._stop_lock:
self._should_stop.set() self._should_stop.set()
if self.ffmpeg: if self.ffmpeg:
try: self.ffmpeg.kill()
self.ffmpeg.kill()
except ProcessLookupError:
pass
self.ffmpeg = None self.ffmpeg = None
self._loop = None
if self._loop:
self._loop = None
@property @property
def should_stop(self) -> bool: def should_stop(self) -> bool: