Search code examples
powershellshazam

Assistance/tutorial with Shazam API in PowerShell


I'm trying to use PowerShell to interact with the Shazam API but their documentation is mainly in PHP. I found this snippet from another forum on here in Python that supposedly works:

from pydub import AudioSegment
import base64
import requests
import json


file_path="./test.raw"
url = "https://rapidapi.p.rapidapi.com/songs/detect"
encode_string = base64.b64encode(open(file_path, "rb").read())
payload=encode_string
print(type(payload))

headers = {
    'content-type': "text/plain",
    'x-rapidapi-key': "<<<your key>>>",
    'x-rapidapi-host': "shazam.p.rapidapi.com"
    }

response = requests.request("POST", url, data=payload, headers=headers)
 
print(json.dumps(json.loads(response.text)))

The only thing PowerShell related from the documentation that I found was this little snippet but it doesn't seem to be very helpful:

$headers=@{}
$headers.Add("content-type", "multipart/form-data; boundary=---011000010111000001101001")
$headers.Add("X-RapidAPI-Host", "shazam-core.p.rapidapi.com")
$headers.Add("X-RapidAPI-Key", "<<<your key>>>")
$response = Invoke-WebRequest -Uri 'https://shazam-core.p.rapidapi.com/v1/tracks/recognize' -Method POST -Headers $headers -ContentType 'multipart/form-data; boundary=---011000010111000001101001' -Body '-----011000010111000001101001
Content-Disposition: form-data; name="file"


-----011000010111000001101001--

'

I would like to do it the way that the other person did it in Python but I just need help translating it to PowerShell. I already found a way to convert the audio file into base 64 and shorten it to 500kb similar to how they did:

 $Bytes = [System.IO.File]::ReadAllBytes("file.mp3") | select -First 500000

 $EncodedText = [Convert]::ToBase64String($Bytes)

I just need to know how to format the request using Invoke-WebRequest.

For anyone interested I'm planning on making a song tagger that uses purely Shazam it may end up getting a GUI at some point but I haven't decided that far yet, once I can get this road block out of the way everything else should be pretty smooth.

EDIT:

After getting help, this is how I ended up going from audio file to shazam api output:

$Track = "Thru the 7th with My Woadies.mp3"

$RAWTemp = $PSScriptRoot + "\Temp.pcm"
$SampleRateExpression = "(($PSScriptRoot\ffmpeg\bin\ffprobe.exe -loglevel 0 -print_format json -show_format -show_streams '$Track' | ConvertFrom-Json).streams).sample_rate"
$SampleRate = Invoke-expression $SampleRateExpression
$ConvertToRawExpression = "$PSScriptRoot\ffmpeg\bin\ffmpeg.exe -nostats -loglevel 0 -y  -i '$Track' -acodec pcm_s16le -f s16le -ac 1 -ar $SampleRate '$RAWTemp'"
Invoke-expression $ConvertToRawExpression
$RawBytes = [System.IO.File]::ReadAllBytes($RAWTemp) | select -First 780000
$EncodedTracKSnippet = [Convert]::ToBase64String($RawBytes)
Remove-Item $RAWTemp
$url = 'https://shazam.p.rapidapi.com/songs/v2/detect'
$headers = @{
    'X-RapidAPI-Host'='shazam.p.rapidapi.com';
    'X-RapidAPI-Key'='<<<your key>>>'
}
$r = Invoke-WebRequest -Uri $url -UseBasicParsing -Method Post -Body $EncodedTrackSnippet -Headers $headers -ContentType 'text/plain'

$TrackBase = ($r.Content | ConvertFrom-Json).track

$ShazamTrackMetaData = New-Object -TypeName psobject

if (($TrackBase.title) -ne $null) { $ShazamTrackMetaData | Add-Member -MemberType NoteProperty -Name Title -Value $TrackBase.title; }
if (($TrackBase.subtitle) -ne $null) { $ShazamTrackMetaData | Add-Member -MemberType NoteProperty -Name Artist -Value $TrackBase.subtitle; }
if ((((($TrackBase).sections).metadata | Where-Object title -eq "Label").text) -ne $null) { $ShazamTrackMetaData | Add-Member -MemberType NoteProperty -Name Label -Value ((($TrackBase).sections).metadata | Where-Object title -eq "Label").text; }
if ((((($TrackBase).sections).metadata | Where-Object title -eq "Album").text) -ne $null) { $ShazamTrackMetaData | Add-Member -MemberType NoteProperty -Name Album -Value ((($TrackBase).sections).metadata | Where-Object title -eq "Album").text; }
if ((((($TrackBase).sections).metadata | Where-Object title -eq "Released").text) -ne $null) { $ShazamTrackMetaData | Add-Member -MemberType NoteProperty -Name Year -Value ((($TrackBase).sections).metadata | Where-Object title -eq "Released").text; }
if ((($TrackBase.genres).primary) -ne $null) { $ShazamTrackMetaData | Add-Member -MemberType NoteProperty -Name Genre -Value ($TrackBase.genres).primary; }
if (((($TrackBase).sections).text) -ne $null) { $ShazamTrackMetaData | Add-Member -MemberType NoteProperty -Name Lyrics -Value ((($TrackBase).sections).text); }
if ((($TrackBase.images).coverart) -ne $null) { $ShazamTrackMetaData | Add-Member -MemberType NoteProperty -Name CoverArt -Value ($TrackBase.images).coverart; }

$ShazamTrackMetaData | Format-list

Output:

Title    : Runnin' Thru The 7th With My Woadies
Artist   : $UicideBoy$ & Pouya
Label    : G59 Records
Album    : $Outh $Ide $Uicide - EP
Year     : 2015
Genre    : Hip-Hop/Rap
Lyrics   : {$null, View from a balcony, Pool lit up blue, Lawn chairs next to the ice chest...}
CoverArt : https://is3-ssl.mzstatic.com/image/thumb/Music115/v4/aa/87/11/aa871103-dba3-4797-4ccd-38e0a811bfe6/195497822997.jpg/400x400cc.jpg

Solution

  • They do have powershell examples for that in their API Documentation, click Songs > Detectv2 on the left, then select powershell from the dropdown on the right

    $Bytes = [System.IO.File]::ReadAllBytes("C:\Users\User\Downloads\clinteastwood_portion_mono.raw") #| select -First 500000
    $EncodedText = [Convert]::ToBase64String($Bytes)
    $url = 'https://shazam.p.rapidapi.com/songs/v2/detect'
    $headers = @{
        'X-RapidAPI-Host'='shazam.p.rapidapi.com';
        'X-RapidAPI-Key'='<<<your key>>'
    }
    $r = Invoke-WebRequest -Uri $url -UseBasicParsing -Method Post -Body $EncodedText -Headers $headers -ContentType 'text/plain'