# like https hosts and it also offers the pre-announce 'bell'
return f"{self.base_url}/announcement/{player_id}.{content_type.value}"
- @use_buffer(30, 4)
+ @use_buffer(30, 2)
async def get_queue_flow_stream(
self,
queue: PlayerQueue,
"Starting queue item stream for %s (%s)"
" - using buffer: %s"
" - using fade-in: %s"
- " - volume normalization: %s",
+ " - using volume normalization: %s",
queue_item.name,
- queue_item.uri,
+ queue_item.streamdetails.uri,
allow_buffer,
streamdetails.fade_in,
streamdetails.volume_normalization_mode,
fade_in_buffer = b""
bytes_received = 0
aborted = False
+ stream_started_at = asyncio.get_event_loop().time()
try:
async for chunk in media_stream_gen:
bytes_received += len(chunk)
self.mass.player_queues.track_loaded_in_buffer(
queue_item.queue_id, queue_item.queue_item_id
)
+ self.logger.debug(
+ "First audio chunk received for %s (%s) after %.2f seconds",
+ queue_item.name,
+ queue_item.streamdetails.uri,
+ asyncio.get_event_loop().time() - stream_started_at,
+ )
# handle optional fade-in
if streamdetails.fade_in:
if len(fade_in_buffer) < pcm_format.pcm_sample_size * 4:
seconds_streamed = bytes_received / pcm_format.pcm_sample_size
streamdetails.seconds_streamed = seconds_streamed
self.logger.debug(
- "stream %s for %s - seconds streamed: %s",
+ "stream %s for %s in %.2f seconds - seconds streamed: %s",
"aborted" if aborted else "finished",
streamdetails.uri,
+ asyncio.get_event_loop().time() - stream_started_at,
seconds_streamed,
)
# report stream to provider
loop = asyncio.get_running_loop()
await loop.run_in_executor(None, gc.collect)
- @use_buffer(30, 4)
+ @use_buffer(30, 2)
async def get_queue_item_stream_with_smartfade(
self,
queue_item: QueueItem,
filter_params: list[str] | None = None,
) -> AsyncGenerator[bytes, None]:
"""Get audio stream for given media details as raw PCM with buffering."""
- LOGGER.debug(
- "get_media_stream_with_buffer: Starting for %s (seek: %s)",
+ LOGGER.log(
+ VERBOSE_LOG_LEVEL,
+ "buffered_media_stream: Starting for %s (seek: %s)",
streamdetails.uri,
seek_position,
)
if not existing_buffer.is_valid(checksum, seek_position):
LOGGER.log(
VERBOSE_LOG_LEVEL,
- "get_media_stream_with_buffer: Existing buffer invalid for %s "
- "(seek: %s, discarded: %s)",
+ "buffered_media_stream: Existing buffer invalid for %s (seek: %s, discarded: %s)",
streamdetails.uri,
seek_position,
existing_buffer._discarded_chunks,
existing_buffer = None
else:
LOGGER.debug(
- "get_media_stream_with_buffer: Reusing existing buffer for %s - "
+ "buffered_media_stream: Reusing existing buffer for %s - "
"available: %ss, seek: %s, discarded: %s",
streamdetails.uri,
existing_buffer.seconds_available,
# otherwise we would need to fill the buffer up to the seek position first
# which is not efficient.
LOGGER.debug(
- "get_media_stream_with_buffer: No existing buffer and seek >60s for %s, "
- "starting normal stream",
+ "buffered_media_stream: No existing buffer and seek >60s for %s, "
+ "starting normal (unbuffered) stream",
streamdetails.uri,
)
async for chunk in get_media_stream(
if not existing_buffer:
# create new audio buffer and start fill task
LOGGER.debug(
- "get_media_stream_with_buffer: Creating new buffer for %s",
+ "buffered_media_stream: Creating new buffer for %s",
streamdetails.uri,
)
audio_buffer = AudioBuffer(pcm_format, checksum)
finally:
LOGGER.log(
VERBOSE_LOG_LEVEL,
- "get_media_stream_with_buffer: Completed, yielded %s chunks",
+ "buffered_media_stream: Completed, yielded %s chunks",
chunk_count,
)