forked from platypush/platypush
Better termination logic for the ffmpeg audio converter.
This commit is contained in:
parent
a6351dddd4
commit
9aa8e4538a
4 changed files with 17 additions and 18 deletions
|
@ -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>
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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,7 +60,9 @@ class AudioRecorder(AudioThread):
|
||||||
|
|
||||||
@override
|
@override
|
||||||
def notify_stop(self):
|
def notify_stop(self):
|
||||||
|
prev_state = self.state
|
||||||
super().notify_stop()
|
super().notify_stop()
|
||||||
|
if prev_state != AudioState.STOPPED:
|
||||||
get_bus().post(SoundRecordingStoppedEvent())
|
get_bus().post(SoundRecordingStoppedEvent())
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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,20 +159,20 @@ 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()
|
||||||
|
try:
|
||||||
self._loop.run_until_complete(self._audio_proxy(timeout=1))
|
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
|
||||||
|
|
||||||
if self._loop:
|
|
||||||
self._loop = None
|
self._loop = None
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
|
Loading…
Reference in a new issue