diff --git a/src/croaker/streamer.py b/src/croaker/streamer.py index 93b118f..9467730 100644 --- a/src/croaker/streamer.py +++ b/src/croaker/streamer.py @@ -80,12 +80,10 @@ class AudioStreamer(threading.Thread): return self.silence, "[NOTHING PLAYING]" def stream_queued_audio(self): - stream = None title = None next_stream = None next_title = None - buffer = b'' while True: stream, title = (next_stream, next_title) if next_stream else self.queued_audio_source() diff --git a/src/croaker/transcoder.py b/src/croaker/transcoder.py index f806583..d563ae8 100644 --- a/src/croaker/transcoder.py +++ b/src/croaker/transcoder.py @@ -1,8 +1,8 @@ import logging import subprocess +from dataclasses import dataclass from io import BufferedReader from pathlib import Path -from dataclasses import dataclass import ffmpeg @@ -24,8 +24,9 @@ class FrameAlignedStream: >>> for segment in stream: ... """ + source: BufferedReader - chunk_size: int = 1024 + chunk_size: int = 1024 bit_rate: int = 192000 sample_rate: int = 44100 @@ -44,7 +45,7 @@ class FrameAlignedStream: # step through the source a byte at a time and look for the frame sync. header = None - buffer = b'' + buffer = b"" while not header: buffer += self.source.read(4 - len(buffer)) if len(buffer) != 4: @@ -84,11 +85,11 @@ class FrameAlignedStream: Generate approximately chunk_size segments of audio data by iterating over the frames, buffering them, and then yielding several as a single bytes object. """ - buf = b'' + buf = b"" for frame in self.frames: if len(buf) >= self.chunk_size: yield buf - buf = b'' + buf = b"" if not frame: break buf += frame @@ -102,28 +103,27 @@ class FrameAlignedStream: """ ffmpeg_args = ( ffmpeg.input(str(infile)) - .output("pipe:", - map='a', - format="mp3", - - # no ID3 headers -- saves having to decode them later - write_xing=0, - id3v2_version=0, - - # force sasmple and bit rates - **{ - 'b:a': kwargs.get('bit_rate', cls.bit_rate), - 'ar': kwargs.get('sample_rate', cls.sample_rate), - }) + .output( + "pipe:", + map="a", + format="mp3", + # no ID3 headers -- saves having to decode them later + write_xing=0, + id3v2_version=0, + # force sasmple and bit rates + **{ + "b:a": kwargs.get("bit_rate", cls.bit_rate), + "ar": kwargs.get("sample_rate", cls.sample_rate), + }, + ) .global_args("-hide_banner", "-vn") .compile() ) # Force close STDIN to prevent ffmpeg from trying to read from it. silly ffmpeg. - proc = subprocess.Popen(ffmpeg_args, - bufsize=kwargs.get('chunk_size', cls.chunk_size), - stdout=subprocess.PIPE, - stdin=subprocess.PIPE) + proc = subprocess.Popen( + ffmpeg_args, bufsize=kwargs.get("chunk_size", cls.chunk_size), stdout=subprocess.PIPE, stdin=subprocess.PIPE + ) proc.stdin.close() logger.debug(f"Spawned ffmpeg (PID {proc.pid}) with args {ffmpeg_args = }") return cls(proc.stdout, **kwargs) diff --git a/test/test_transcoder.py b/test/test_transcoder.py index a090d17..3e8bc2c 100644 --- a/test/test_transcoder.py +++ b/test/test_transcoder.py @@ -10,9 +10,8 @@ from croaker import playlist, transcoder def mock_mp3decoder(monkeypatch): def read(stream): return stream.read() - monkeypatch.setattr(transcoder, 'MP3Decoder', MagicMock(**{ - '__enter__.return_value.read': read - })) + + monkeypatch.setattr(transcoder, "MP3Decoder", MagicMock(**{"__enter__.return_value.read": read})) @pytest.mark.xfail