kokarare1212 / librespot-python

Open Source Spotify Client
http://librespot-python.rtfd.io
Apache License 2.0
235 stars 45 forks source link

[FEATURE REQUEST] Add support for streaming podcasts please :) #82

Closed MrBruz closed 3 years ago

MrBruz commented 3 years ago

Not much more to this feature request than specified in the title ^ :+1:

kokarare1212 commented 3 years ago

Thank you for your inquiry. Some podcasts are already supported (Episode), but they are still incomplete, so we will add additional features.

kokarare1212 commented 3 years ago

Full podcast support should now be implemented with the following commit. 62feb08f4ea6a21b3a91d7d53ef96b6078074c80

MrBruz commented 3 years ago

Awesome thanks! Is this exactly the same code as if im streaming tracks or should I chnage stuff?

kokarare1212 commented 3 years ago

You can get the stream by writing the following.

from librespot.audio.decoders import AudioQuality, VorbisOnlyAudioQuality
from librespot.metadata import EpisodeId

# e.g. NHK Radio News (https://open.spotify.com/episode/2KAW1GCHpOsxPBuZ0v59S4) 
episode_id = EpisodeId.from_base62("2KAW1GCHpOsxPBuZ0v59S4")
stream = session.content_feeder().load(episode_id, VorbisOnlyAudioQuality(AudioQuality.VERY_HIGH), False, None)

The TrackId and EpisodeId have changed, but nothing else.

MrBruz commented 3 years ago
  File "/home/james/Documents/programs/python/spotify_testing/spotify_testing.py", line 169, in client
    stream = SESSION.content_feeder().load(episode_id, VorbisOnlyAudioQuality(QUALITY), False, None)
  File "/home/james/.local/lib/python3.9/site-packages/librespot/audio/__init__.py", line 722, in load
    return self.load_episode(playable_id, audio_quality_picker,
  File "/home/james/.local/lib/python3.9/site-packages/librespot/audio/__init__.py", line 754, in load_episode
    return CdnFeedHelper.load_episode_external(self.__session, episode,
  File "/home/james/.local/lib/python3.9/site-packages/librespot/audio/__init__.py", line 366, in load_episode_external
    streamer = session.cdn().stream_external_episode(
  File "/home/james/.local/lib/python3.9/site-packages/librespot/audio/__init__.py", line 429, in stream_external_episode
    StreamId(episode),
  File "/home/james/.local/lib/python3.9/site-packages/librespot/audio/__init__.py", line 879, in __init__
    self.file_id = None if file is None else file.file_id
AttributeError: 'Episode' object has no attribute 'file_id'

I get this error while trying to load the following episode: https://open.spotify.com/episode/3u0krXMhLcdGZUZkDVmMSt

kokarare1212 commented 3 years ago

It was caused by a faulty keyword argument. I've fixed it in the commit below, can you please try again? 459c02ec99117756c022d8417fa5592518cc52c6

MrBruz commented 3 years ago
Traceback (most recent call last):
  File "/home/james/Documents/programs/python/spotify_testing/spotify_testing.py", line 529, in <module>
    main()
  File "/home/james/Documents/programs/python/spotify_testing/spotify_testing.py", line 525, in main
    client()
  File "/home/james/Documents/programs/python/spotify_testing/spotify_testing.py", line 169, in client
    stream = SESSION.content_feeder().load(episode_id, VorbisOnlyAudioQuality(QUALITY), False, None)
  File "/home/james/.local/lib/python3.9/site-packages/librespot/audio/__init__.py", line 722, in load
    return self.load_episode(playable_id, audio_quality_picker,
  File "/home/james/.local/lib/python3.9/site-packages/librespot/audio/__init__.py", line 754, in load_episode
    return CdnFeedHelper.load_episode_external(self.__session, episode,
  File "/home/james/.local/lib/python3.9/site-packages/librespot/audio/__init__.py", line 366, in load_episode_external
    streamer = session.cdn().stream_external_episode(
  File "/home/james/.local/lib/python3.9/site-packages/librespot/audio/__init__.py", line 427, in stream_external_episode
    return CdnManager.Streamer(
  File "/home/james/.local/lib/python3.9/site-packages/librespot/audio/__init__.py", line 577, in __init__
    self.write_chunk(first_chunk, 0, False)
  File "/home/james/.local/lib/python3.9/site-packages/librespot/audio/__init__.py", line 586, in write_chunk
    self.buffer[chunk_index] = self.__audio_decrypt.decrypt_chunk(
  File "/home/james/.local/lib/python3.9/site-packages/librespot/structure.py", line 67, in decrypt_chunk
    raise NotImplementedError
NotImplementedError
kokarare1212 commented 3 years ago

It seems that the NoopAudioDecrypt class was not implemented. It was fixed in the following commit. c5db0a84a825f97da38d405653e0dae4b4e04850

MrBruz commented 3 years ago

Nice job! It now works with https://open.spotify.com/episode/3u0krXMhLcdGZUZkDVmMSt but it unfortunately fails on the url you provided. https://open.spotify.com/episode/2KAW1GCHpOsxPBuZ0v59S4

Using 0 because preferred AudioQuality.HIGH couldn't be found.
Audio key error, code: 1
Audio key error, code: 1
Traceback (most recent call last):
  File "/home/james/Documents/programs/python/spotify_testing/spotify_testing.py", line 530, in <module>
    main()
  File "/home/james/Documents/programs/python/spotify_testing/spotify_testing.py", line 526, in main
    client()
  File "/home/james/Documents/programs/python/spotify_testing/spotify_testing.py", line 169, in client
    stream = SESSION.content_feeder().load(episode_id, VorbisOnlyAudioQuality(QUALITY), False, None)
  File "/home/james/.local/lib/python3.9/site-packages/librespot/audio/__init__.py", line 722, in load
    return self.load_episode(playable_id, audio_quality_picker,
  File "/home/james/.local/lib/python3.9/site-packages/librespot/audio/__init__.py", line 762, in load_episode
    return self.load_stream(file, None, episode, preload,
  File "/home/james/.local/lib/python3.9/site-packages/librespot/audio/__init__.py", line 737, in load_stream
    return CdnFeedHelper.load_episode(self.__session, episode, file,
  File "/home/james/.local/lib/python3.9/site-packages/librespot/audio/__init__.py", line 389, in load_episode
    key = session.audio_key().get_audio_key(episode.gid, file.file_id)
  File "/home/james/.local/lib/python3.9/site-packages/librespot/audio/__init__.py", line 279, in get_audio_key
    return self.get_audio_key(gid, file_id, False)
  File "/home/james/.local/lib/python3.9/site-packages/librespot/audio/__init__.py", line 280, in get_audio_key
    raise RuntimeError(
RuntimeError: Failed fetching audio key! gid: 5a6837196f0851b78d9a7b26ad00e044, fileId: ea90811b5f1a8631786631cd8bb9ffbbf591d70f
kokarare1212 commented 3 years ago

It turns out that an unintended default value by Protobuf caused an unintended AudioFile to be selected. This has been fixed in the following commit. 9c35e6362bdc901d5ed72367de6c32353f7ab406

MrBruz commented 3 years ago
Traceback (most recent call last):
  File "/home/james/Documents/programs/python/spotify_testing/./spotify_testing.py", line 544, in <module>
    main()
  File "/home/james/Documents/programs/python/spotify_testing/./spotify_testing.py", line 540, in main
    client()
  File "/home/james/Documents/programs/python/spotify_testing/./spotify_testing.py", line 169, in client
    stream = SESSION.content_feeder().load(
  File "/home/james/.local/lib/python3.9/site-packages/librespot/audio/__init__.py", line 722, in load
    return self.load_episode(playable_id, audio_quality_picker,
  File "/home/james/.local/lib/python3.9/site-packages/librespot/audio/__init__.py", line 752, in load_episode
    episode = self.__session.api().get_metadata_4_episode(episode_id)
  File "/home/james/.local/lib/python3.9/site-packages/librespot/core.py", line 105, in get_metadata_4_episode
    ApiClient.StatusCodeException.check_status(response)
  File "/home/james/.local/lib/python3.9/site-packages/librespot/core.py", line 160, in check_status
    raise ApiClient.StatusCodeException(response)
librespot.core.StatusCodeException: 451
kokarare1212 commented 3 years ago

This may be prohibited by censorship. https://developer.mozilla.org/ja/docs/Web/HTTP/Status/451

MrBruz commented 3 years ago

Ah I see! Turns out doing a api request about that episode before attempting to stream will return a 404 error so I can use that to check before trying to stream :)

Thanks for all the help as always!!