{"id":6617,"date":"2023-08-07T18:55:13","date_gmt":"2023-08-07T18:55:13","guid":{"rendered":"https:\/\/dgen.net\/0\/?p=6617"},"modified":"2024-12-30T15:33:39","modified_gmt":"2024-12-30T15:33:39","slug":"how-to-get-now-playing-album-art-from-spotify-api","status":"publish","type":"post","link":"https:\/\/dgen.net\/0\/2023\/08\/07\/how-to-get-now-playing-album-art-from-spotify-api\/","title":{"rendered":"How to get now playing album art from Spotify API"},"content":{"rendered":"\n<p>In a <a href=\"https:\/\/dgen.net\/0\/2023\/07\/05\/bringing-album-art-back-to-life\/\">previous post<\/a>, I hacked this by getting the album artwork jpg from my amplifier.  Unfortunately, upgrading to a new amp &#8216;improved&#8217; its operating system and the artwork vanished, so I had to bite the bullet to get it straight from Spotify. This is far more painful than it needs to be and Spotify could do better (see footnote).<\/p>\n\n\n\n<p>So, with a bit of help (actually a lot of help) from ChatGPT-4* and many rabbit holes explored, I&#8217;ve now got a call directly to the Spotify API of &#8220;now playing&#8221;.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/dgen.net\/0\/wp-content\/uploads\/2023\/07\/AlbumArt-BinaryDust.jpg\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"568\" src=\"https:\/\/dgen.net\/0\/wp-content\/uploads\/2023\/07\/AlbumArt-BinaryDust-1024x568.jpg\" alt=\"\" class=\"wp-image-6382\" srcset=\"https:\/\/dgen.net\/0\/wp-content\/uploads\/2023\/07\/AlbumArt-BinaryDust-1024x568.jpg 1024w, https:\/\/dgen.net\/0\/wp-content\/uploads\/2023\/07\/AlbumArt-BinaryDust-300x166.jpg 300w, https:\/\/dgen.net\/0\/wp-content\/uploads\/2023\/07\/AlbumArt-BinaryDust-768x426.jpg 768w, https:\/\/dgen.net\/0\/wp-content\/uploads\/2023\/07\/AlbumArt-BinaryDust-1536x852.jpg 1536w, https:\/\/dgen.net\/0\/wp-content\/uploads\/2023\/07\/AlbumArt-BinaryDust-830x460.jpg 830w, https:\/\/dgen.net\/0\/wp-content\/uploads\/2023\/07\/AlbumArt-BinaryDust-230x128.jpg 230w, https:\/\/dgen.net\/0\/wp-content\/uploads\/2023\/07\/AlbumArt-BinaryDust-350x194.jpg 350w, https:\/\/dgen.net\/0\/wp-content\/uploads\/2023\/07\/AlbumArt-BinaryDust-480x266.jpg 480w, https:\/\/dgen.net\/0\/wp-content\/uploads\/2023\/07\/AlbumArt-BinaryDust.jpg 1706w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><\/figure>\n\n\n\n<p>To get going, set up a <a href=\"https:\/\/developer.spotify.com\/\">developer account<\/a> in Spotify, create a new app and then get hold of <\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Client ID<\/strong><\/li>\n\n\n\n<li><strong>Client secret<\/strong><\/li>\n<\/ul>\n\n\n\n<p>You <strong>must<\/strong> also set a <strong>Redirect URIs<\/strong> because Spotify <strong>requires you<\/strong> to use a web browser to authenticate: it&#8217;s not possible to do entirely on the command line (no, you can&#8217;t use CURL either, apparently). <\/p>\n\n\n\n<figure class=\"wp-block-gallery has-nested-images columns-default is-cropped wp-block-gallery-1 is-layout-flex wp-block-gallery-is-layout-flex\">\n<figure class=\"wp-block-image size-large is-style-default\"><a href=\"https:\/\/dgen.net\/0\/wp-content\/uploads\/2023\/08\/Screenshot-2023-08-06-at-21.57.37.png\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"884\" data-id=\"6620\" src=\"https:\/\/dgen.net\/0\/wp-content\/uploads\/2023\/08\/Screenshot-2023-08-06-at-21.57.37-1024x884.png\" alt=\"\" class=\"wp-image-6620\" srcset=\"https:\/\/dgen.net\/0\/wp-content\/uploads\/2023\/08\/Screenshot-2023-08-06-at-21.57.37-1024x884.png 1024w, https:\/\/dgen.net\/0\/wp-content\/uploads\/2023\/08\/Screenshot-2023-08-06-at-21.57.37-300x259.png 300w, https:\/\/dgen.net\/0\/wp-content\/uploads\/2023\/08\/Screenshot-2023-08-06-at-21.57.37-768x663.png 768w, https:\/\/dgen.net\/0\/wp-content\/uploads\/2023\/08\/Screenshot-2023-08-06-at-21.57.37-1536x1327.png 1536w, https:\/\/dgen.net\/0\/wp-content\/uploads\/2023\/08\/Screenshot-2023-08-06-at-21.57.37-2048x1769.png 2048w, https:\/\/dgen.net\/0\/wp-content\/uploads\/2023\/08\/Screenshot-2023-08-06-at-21.57.37-830x717.png 830w, https:\/\/dgen.net\/0\/wp-content\/uploads\/2023\/08\/Screenshot-2023-08-06-at-21.57.37-230x199.png 230w, https:\/\/dgen.net\/0\/wp-content\/uploads\/2023\/08\/Screenshot-2023-08-06-at-21.57.37-350x302.png 350w, https:\/\/dgen.net\/0\/wp-content\/uploads\/2023\/08\/Screenshot-2023-08-06-at-21.57.37-480x415.png 480w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><\/figure>\n<\/figure>\n\n\n\n<p>This means you need to be able to put a web page <em>somewhere<\/em> that you can access. I decided to use one of my public web servers, so I can get the image from anywhere, not just at home, but you can use <em>localhost<\/em>. <\/p>\n\n\n\n<p>Luckily there&#8217;s a <strong>Python<\/strong> library that does things. So, install python <\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">apt-get install python3<\/pre>\n\n\n\n<p>Also, to use a custom env we also need to add it to a <strong>Python<\/strong> virtual environment using this:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">python3 -m venv myenv<br>source myenv\/bin\/activate  <br>pip install virtualenv<br>pip freeze > requirements.txt<br>pip install spotipy<\/pre>\n\n\n\n<p>And using <strong><em>source myenv\/bin\/activate<\/em><\/strong> to recall.  <\/p>\n\n\n\n<p>After many iterations (thanks ai), we get to a script:<\/p>\n\n\n\n<p><strong><em>get_spot.py<\/em><\/strong><\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">import spotipy\nfrom spotipy.oauth2 import SpotifyOAuth\n\n# Add your credentials here\nSPOTIPY_CLIENT_ID = 'your_spotify_client_id'\nSPOTIPY_CLIENT_SECRET = 'your_spotify_client_secret'\nSPOTIPY_REDIRECT_URI = 'your_redirect_uri'\nUSERNAME = 'your_username'\nSCOPE = \"user-read-currently-playing\"\n\n# Create Spotify object with permissions\noauth = SpotifyOAuth(client_id=SPOTIPY_CLIENT_ID,\n                     client_secret=SPOTIPY_CLIENT_SECRET,\n                     redirect_uri=SPOTIPY_REDIRECT_URI,\n                     username=USERNAME,\n                     scope=SCOPE,\n                     open_browser=False)\n\ntoken_info = oauth.get_cached_token()\n\n# Check if token needs to be refreshed\nif token_info and oauth.is_token_expired(token_info):\n    token_info = oauth.refresh_access_token(token_info['refresh_token'])\n\nsp = spotipy.Spotify(auth_manager=oauth)\n\n# Get current playing\ncurrent_playing = sp.current_user_playing_track()\n\n# Ensure that a track is playing\nif current_playing is not None:\n    # Get the album art\n    album_art = current_playing['item']['album']['images'][0]['url']\n    print(album_art)\nelse:\n    print(\"No track is currently playing.\")\n<\/pre>\n\n\n\n<p>When you first run this, using<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">python get_spot.py<\/pre>\n\n\n\n<p>it&#8217;ll give you a URL to copy\/paste into a browser so you can authenticate.  <\/p>\n\n\n\n<p>You need to have this as a web page at the <strong>RedirectURI<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">&lt;div id=\"authorizationCode\"&gt;&lt;\/div&gt;\n  &lt;script&gt;\n    function handleAuthorizationCode() {\n      const queryString = window.location.search;\n      const urlParams = new URLSearchParams(queryString);\n      const authorizationCode = urlParams.get('code');\n\n      const authorizationCodeDiv = document.getElementById('authorizationCode');\n      if (authorizationCode) {\n        authorizationCodeDiv.innerHTML = `${authorizationCode}`;\n        \/\/ Do something with the code (e.g., store it for later use)\n        \/\/ You can also make a POST request to your server to exchange it for an access token\n      } else {\n        authorizationCodeDiv.innerHTML = 'No authorization code found in the URL.';\n        \/\/ Handle the case when the user denies permission or other errors\n      }\n    }\n\n    handleAuthorizationCode();\n  &lt;\/script&gt;<\/pre>\n\n\n\n<p>Then access it, via <em>&lt;your URL&gt;\/&lt;file&gt;?code=&lt;your_ClientID&gt;<\/em><\/p>\n\n\n\n<p>You need to copy the &#8216;return <strong>URL<\/strong>&#8216; (not the code it renders) that it generates and paste it back onto the command line prompt.<\/p>\n\n\n\n<p>After you&#8217;ve done that, you can run it again and it&#8217;ll (hopefully) give you a URL directly to the artwork on Spotify&#8217;s CDN, for example:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"><a href=\"https:\/\/i.scdn.co\/image\/ab67616d0000b2737a9230e1ede602936d5056c8\">https:\/\/i.scdn.co\/image\/ab67616d0000b2737a9230e1ede602936d5056c8<\/a><\/pre>\n\n\n\n<p>We can then use <strong>THAT<\/strong> URL instead of the one I was getting from the amplifier in the previous post. <\/p>\n\n\n\n<p>And, finally, we want to cron this as we did with the local example from last time. <\/p>\n\n\n\n<p><strong>spot.sh<\/strong> (this time, on the server)<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">#!\/bin\/bash\n\nfolder='\/<em>{path}<\/em>\/spotify'\ncd $folder\n\n# Activate the virtual environment and get the album art URL\nsource $folder\/myenv\/bin\/activate\nalbumart=$(python $folder\/get.py)\n\n# Check if the Python script executed successfully\nif [ $? -ne 0 ]; then\n  echo \"Error: Failed to execute the Python script.\"\n  echo \"empty\" &gt; status.flag\n  exit 1\nfi\n\n# Download the album art, or exit with an error message if curl fails\nif ! curl -o nowtmp.jpg $albumart; then\n  echo \"Failed to download album art\"\n  echo \"empty\" &gt; status.flag\n  exit 1 \nfi\n\n# Move the temporary image to 'now.jpg'\nmv nowtmp.jpg now.jpg\n\nfile now.jpg | awk '{print $2}' &gt; status.flag\n\n# Compute the MD5 checksums of the current and live images\ncurrent_checksum=$(md5sum now.jpg  | awk '{print $1}')\nlive_checksum=$(md5sum live.jpg | awk '{print $1}')\n\n# If the checksums differ, update the live image\nif [ \"$current_checksum\"  != \"$live_checksum\" ]; then\n  cp now.jpg live.jpg\nfi <\/pre>\n\n\n\n<p>Then, on the pi, we can do this:<\/p>\n\n\n\n<p><strong>up-spot.sh<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">#!\/bin\/bash\ncd \/<em>{path}<\/em>\/hcm\n\nserver=`curl -k https:\/\/{server}\/{folder}\/status.flag`\necho server $server\n\nif [  \"$server\" = \"JPEG\" ]; then\n if [ `cat status.flag` = \"no\" ]; then \n\t echo \"yes\" &gt; status.flag\n  \t cp album-cover-live-safe.html album-cover.html\n\t .\/refresh.sh\n fi\t \n else \n if [ `cat status.flag` = \"yes\" ]; then\t \n\t echo \"no\" &gt; status.flag\n \t cp clock-analogue.html album-cover.html\n\t .\/refresh.sh\n fi\nfi<\/pre>\n\n\n\n<p>and put that into cron on the pi with:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">*       *       *       *       *       \/{path}\/up-spot.sh &gt; \/dev\/null 2&gt;&amp;1<\/pre>\n\n\n\n<p>and then<\/p>\n\n\n\n<p><strong>test-refresh.sh<\/strong> becomes<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">#!\/bin\/bash\ncd \/{local path}\nhifi=`cat hifi.ip`\nalbumart=\"https:\/\/{server}\/{path}\/live.jpg\"\n\nnowtmp=\"nowtmp.jpg\"\ncurl -k $albumart &gt; $nowtmp\nwait \n\nif [ -f \"$nowtmp\" ]; then \n# echo `date` \"file exists: \" `du -sk $nowtmp` \"and\" `md5sum $nowtmp` &gt;&gt; log\n mv nowtmp.jpg now.jpg # do as a step in case latency leads to partial download tests\n x=`md5sum now.jpg  | awk '{print $1}'`\n y=`md5sum live.jpg | awk '{print $1}'`\n\n\n if [ \"$x\" != \"$y\" ] ; then\n#   echo \"updating\" `date`  $x $y &gt;&gt; log\n  cp now.jpg live.jpg\n   .\/refresh.sh\n fi\n\nfi\n<\/pre>\n\n\n\n<p>See the <a href=\"https:\/\/dgen.net\/0\/2023\/07\/05\/bringing-album-art-back-to-life\/\">previous post<\/a> for more on other bits of script and cron.<\/p>\n\n\n\n<p>* I started with &#8220;write a shell script to get the &#8216;now playing&#8217; album art from my spotify account&#8221;<\/p>\n\n\n\n<p><strong>Footnote<\/strong><\/p>\n\n\n\n<p>As an aside, I found that <a href=\"https:\/\/spotify.aidenwallis.co.uk\/\">this nice chap<\/a> has done a *really simple* integration where you just authorise his app and it tells you what&#8217;s playing. Unfortunately, it&#8217;s not generating the images (just the titles) and I didn&#8217;t want to rely on a 3rd party service [hint: Spotify, just make it this easy, good grief!]<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In a previous post, I hacked this by getting the album artwork jpg from my amplifier. Unfortunately, upgrading to a new amp &#8216;improved&#8217; its operating [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":6383,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[3],"tags":[],"class_list":["post-6617","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-stuff"],"jetpack_featured_media_url":"https:\/\/dgen.net\/0\/wp-content\/uploads\/2023\/07\/AlbumArt-clock.jpg","jetpack_shortlink":"https:\/\/wp.me\/pfJFK3-1IJ","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/dgen.net\/0\/wp-json\/wp\/v2\/posts\/6617","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/dgen.net\/0\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/dgen.net\/0\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/dgen.net\/0\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/dgen.net\/0\/wp-json\/wp\/v2\/comments?post=6617"}],"version-history":[{"count":16,"href":"https:\/\/dgen.net\/0\/wp-json\/wp\/v2\/posts\/6617\/revisions"}],"predecessor-version":[{"id":7316,"href":"https:\/\/dgen.net\/0\/wp-json\/wp\/v2\/posts\/6617\/revisions\/7316"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/dgen.net\/0\/wp-json\/wp\/v2\/media\/6383"}],"wp:attachment":[{"href":"https:\/\/dgen.net\/0\/wp-json\/wp\/v2\/media?parent=6617"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/dgen.net\/0\/wp-json\/wp\/v2\/categories?post=6617"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/dgen.net\/0\/wp-json\/wp\/v2\/tags?post=6617"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}