From b56655b1870ff51ce3466f0b68ef565f6cb299a6 Mon Sep 17 00:00:00 2001 From: marcelveldt Date: Sun, 19 May 2019 20:34:04 +0200 Subject: [PATCH] fixes for streaming --- music_assistant/modules/player.py | 35 ++++++++++--------- .../modules/playerproviders/chromecast.py | 8 +++-- .../modules/playerproviders/lms.py | 8 +++-- music_assistant/modules/web.py | 2 +- 4 files changed, 30 insertions(+), 23 deletions(-) diff --git a/music_assistant/modules/player.py b/music_assistant/modules/player.py index 79fcaef1..11b4b39c 100755 --- a/music_assistant/modules/player.py +++ b/music_assistant/modules/player.py @@ -20,6 +20,7 @@ import xml.etree.ElementTree as ET import concurrent import aiohttp import random +import urllib BASE_DIR = os.path.dirname(os.path.abspath(__file__)) MODULES_PATH = os.path.join(BASE_DIR, "playerproviders" ) @@ -60,9 +61,9 @@ class Player(): ] # config for the http streamer config_entries = [ - ('volume_normalisation', '', 'enable_r128_volume_normalisation'), - ('target_volume', '-12', 'target_volume_lufs'), - ('fallback_gain_correct', '', 'fallback_gain_correct'), + ('volume_normalisation', True, 'enable_r128_volume_normalisation'), + ('target_volume', '-23', 'target_volume_lufs'), + ('fallback_gain_correct', '-12', 'fallback_gain_correct'), ('enable_cache', True, 'enable_audio_cache'), ('trim_silence', True, 'trim_silence') ] @@ -325,12 +326,12 @@ class Player(): player_supported_provs = player_prov.supported_musicproviders if media_provider in player_supported_provs and not self.mass.config['player_settings'][player_id]['force_http_streamer']: # the provider can handle this media_type directly ! - track.uri = await self.get_track_uri(media_item_id, media_provider) + track.uri = await self.get_track_uri(media_item_id, media_provider, player_id) playable_tracks.append(track) match_found = True elif 'http' in player_prov.supported_musicproviders: # fallback to http streaming if supported - track.uri = await self.get_track_uri(media_item_id, media_provider, True) + track.uri = await self.get_track_uri(media_item_id, media_provider, player_id, True) playable_tracks.append(track) match_found = True if match_found: @@ -344,11 +345,13 @@ class Player(): else: raise Exception("Musicprovider and/or media not supported by player %s !" % (player_id) ) - async def get_track_uri(self, item_id, provider, http_stream=False): + async def get_track_uri(self, item_id, provider, player_id, http_stream=False): ''' generate the URL/URI for a media item ''' uri = "" if http_stream: - uri = 'http://%s:8095/stream/%s/%s'% (self.local_ip, provider, item_id) + params = {"provider": provider, "track_id": str(item_id), "player_id": str(player_id)} + params_str = urllib.parse.urlencode(params) + uri = 'http://%s:8095/stream?%s'% (self.local_ip, params_str) elif provider == "spotify": uri = 'spotify://spotify:track:%s' % item_id elif provider == "qobuz": @@ -367,22 +370,22 @@ class Player(): ''' get audio stream from provider and apply additional effects/processing where/if needed''' input_content_type = await self.mass.music.providers[provider].get_stream_content_type(track_id) cachefile = self.__get_track_cache_filename(track_id, provider) - sox_effects = '' + sox_effects = [] if self.mass.config['base']['http_streamer']['volume_normalisation']: gain_correct = await self.__get_track_gain_correct(track_id, provider) LOGGER.info("apply gain correction of %s" % gain_correct) - sox_effects='vol %s dB' % gain_correct + sox_effects += ['vol', '%s dB' % gain_correct] if player_id and self.mass.config['player_settings'][player_id]['sox_effects']: - sox_effects += ' ' + self.mass.config['player_settings'][player_id]['sox_effects'] + sox_effects += self.mass.config['player_settings'][player_id]['sox_effects'].split('/') if os.path.isfile(cachefile): # we have a cache file for this track which we can use - args = ['-t', 'flac', cachefile, '-t', 'flac', '-C', '0', '-', *sox_effects.split(' ')] + args = ['-t', 'flac', cachefile, '-t', 'flac', '-', *sox_effects] process = await asyncio.create_subprocess_exec('sox', *args, stdout=asyncio.subprocess.PIPE) buffer_task = None else: # stream from provider - args = ['-t', input_content_type, '-', '-t', 'flac', '-C', '0', '-', *sox_effects.split(' ')] + args = ['-t', input_content_type, '-', '-t', 'flac', '-', *sox_effects] process = await asyncio.create_subprocess_exec('sox', *args, stdout=asyncio.subprocess.PIPE, stdin=asyncio.subprocess.PIPE) buffer_task = asyncio.create_task( @@ -415,10 +418,10 @@ class Player(): if self.mass.config['base']['http_streamer']['enable_cache']: # use sox to store cache file (optionally strip silence from start and end) if self.mass.config['base']['http_streamer']['trim_silence']: - cmd = 'sox -t %s %s -t flac -C 5 %s silence 1 0.1 1%% reverse silence 1 0.1 1%% reverse' %(content_type, tmpfile, cachefile) + cmd = 'sox -t %s %s -t flac -C5 %s silence 1 0.1 1%% reverse silence 1 0.1 1%% reverse' %(content_type, tmpfile, cachefile) else: # cachefile is always stored as flac - cmd = 'sox -t %s %s -t flac -C 5 %s' %(content_type, tmpfile, cachefile) + cmd = 'sox -t %s %s -t flac -C5 %s' %(content_type, tmpfile, cachefile) process = await asyncio.create_subprocess_shell(cmd) await process.wait() # always clean up temp file @@ -429,8 +432,8 @@ class Player(): async def __get_track_gain_correct(self, track_id, provider): ''' get the gain correction that should be applied to a track ''' - target_gain = -23 - fallback_gain = -14 # fallback if no analyse info is available + target_gain = int(self.mass.config['base']['http_streamer']['target_volume']) + fallback_gain = int(self.mass.config['base']['http_streamer']['fallback_gain_correct']) analysis_file = os.path.join(self.mass.datapath, 'analyse_info', "%s_%s.xml" %(provider, track_id.split(os.sep)[-1])) if not os.path.isfile(analysis_file): return fallback_gain diff --git a/music_assistant/modules/playerproviders/chromecast.py b/music_assistant/modules/playerproviders/chromecast.py index 4423e683..10a9e12b 100644 --- a/music_assistant/modules/playerproviders/chromecast.py +++ b/music_assistant/modules/playerproviders/chromecast.py @@ -24,6 +24,7 @@ from pychromecast.controllers import BaseController from pychromecast.controllers.spotify import SpotifyController from pychromecast.controllers.media import MediaController import types +import urllib def setup(mass): ''' setup the provider''' @@ -281,9 +282,10 @@ class ChromecastProvider(PlayerProvider): track_id = uri.replace('qobuz://','').replace('.flac','') track = await self.mass.music.providers['qobuz'].track(track_id) elif uri.startswith('http') and '/stream' in uri: - item_id = uri.split('/')[-1] - provider = uri.split('/')[-2] - track = await self.mass.music.providers[provider].track(item_id) + params = urllib.parse.parse_qs(uri.split('?')[1]) + track_id = params['track_id'] + provider = params['provider'] + track = await self.mass.music.providers[provider].track(track_id) return track async def __handle_group_members_update(self, mz, added_player=None, removed_player=None): diff --git a/music_assistant/modules/playerproviders/lms.py b/music_assistant/modules/playerproviders/lms.py index 988637fd..2b2200b0 100644 --- a/music_assistant/modules/playerproviders/lms.py +++ b/music_assistant/modules/playerproviders/lms.py @@ -18,6 +18,7 @@ from asyncio_throttle import Throttler from aiocometd import Client, ConnectionType, Extension from modules.cache import use_cache import copy +import urllib def setup(mass): ''' setup the provider''' @@ -217,9 +218,10 @@ class LMSProvider(PlayerProvider): except Exception as exc: LOGGER.error(exc) elif track_url.startswith('http') and '/stream' in track_url: - item_id = track_url.split('/')[-1] - provider = track_url.split('/')[-2] - return await self.mass.music.providers[provider].track(item_id) + params = urllib.parse.parse_qs(track_url.split('?')[1]) + track_id = params['track_id'] + provider = params['provider'] + return await self.mass.music.providers[provider].track(track_id) # fallback to a generic track track = Track() track.name = track_details['title'] diff --git a/music_assistant/modules/web.py b/music_assistant/modules/web.py index 50d52d9a..7e18a63c 100755 --- a/music_assistant/modules/web.py +++ b/music_assistant/modules/web.py @@ -60,7 +60,7 @@ class Web(): async def setup_web(self): app = web.Application() app.add_routes([web.get('/ws', self.websocket_handler)]) - app.add_routes([web.get('/stream/{provider}/{track_id}', self.stream)]) + app.add_routes([web.get('/stream', self.stream)]) app.add_routes([web.get('/api/search', self.search)]) app.add_routes([web.get('/api/config', self.get_config)]) app.add_routes([web.post('/api/config', self.save_config)]) -- 2.34.1