"""Collect all args to send to the sox (or ffmpeg) process."""
stream_path = streamdetails.path
stream_type = StreamType(streamdetails.type)
- content_type = streamdetails.content_type
+ input_format = streamdetails.content_type
if output_format is None:
- output_format = streamdetails.content_type
+ output_format = input_format
sox_present, ffmpeg_present = await check_audio_support()
# use ffmpeg if content not supported by SoX (e.g. AAC radio streams)
- if not sox_present or not streamdetails.content_type.sox_supported():
+ if not sox_present or not input_format.sox_supported():
if not ffmpeg_present:
raise AudioError(
"FFmpeg binary is missing from system."
"-loglevel",
"error",
"-f",
- content_type.value,
+ input_format.value,
"-i",
"-",
]
filter_args = []
if streamdetails.gain_correct:
filter_args += ["-filter:a", f"volume={streamdetails.gain_correct}dB"]
- if resample:
+ if resample or input_format.is_pcm():
filter_args += ["-ar", str(resample)]
return input_args + filter_args + output_args
"|",
"sox",
"-t",
- content_type.sox_format(),
- "-",
+ input_format.sox_format(),
]
+ if input_format.is_pcm():
+ input_args += [
+ "-r",
+ str(streamdetails.sample_rate),
+ "-c",
+ str(streamdetails.channels),
+ ]
+ input_args.append("-")
else:
- input_args = ["sox", "-t", content_type.sox_format(), stream_path]
+ input_args = ["sox", "-t", input_format.sox_format(), stream_path]
# collect output args
if output_format.is_pcm():
output_args = ["-t", output_format.sox_format(), "-c", "2", "-"]
# make sure that the token is still valid by just requesting it
await self.get_token()
spotty = await self.get_spotty_binary()
- spotty_exec = f'{spotty} -n temp -c "/tmp" -b 320 --pass-through --single-track spotify://track:{track.item_id}'
+ spotty_exec = f'{spotty} -n temp -c "/tmp" -b 320 --single-track spotify://track:{track.item_id}'
return StreamDetails(
type=StreamType.EXECUTABLE,
item_id=track.item_id,
provider=self.id,
path=spotty_exec,
- content_type=ContentType.OGG,
+ content_type=ContentType.PCM_S16LE,
sample_rate=44100,
bit_depth=16,
)
) as response:
return await response.text()
- async def get_spotty_binary(self):
+ @staticmethod
+ async def get_spotty_binary():
"""Find the correct spotty binary belonging to the platform."""
if platform.system() == "Windows":
return os.path.join(
return os.path.join(
os.path.dirname(__file__), "spotty", "linux", "spotty-i386"
)
- if "aarch64" in architecture or "armv8" in architecture:
- # try arm64 linux binary, fallback to 32 bits
+ # arm architecture... try all options one by one...
+ for arch in ["aarch64", "armhf", "muslhf", "armv6"]:
spotty_path = os.path.join(
- os.path.dirname(__file__), "spotty", "linux", "spotty-aarch64"
+ os.path.dirname(__file__), "spotty", "linux", f"spotty-{arch}"
)
try:
spotty = await asyncio.create_subprocess_exec(
stdout, _ = await spotty.communicate()
if spotty.returncode == 0 and b"librespot" in stdout:
return spotty_path
- except OSError as err:
- self.logger.exception(
- "failed to start arm64 spotty binary, fallback to 32 bits",
- exc_info=err,
- )
- # assume armv7
- return os.path.join(
- os.path.dirname(__file__), "spotty", "linux", "spotty-armhf"
- )
+ except OSError:
+ pass
return None