0

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

1 Answers1

0

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'
Mike Anthony
  • 429
  • 3
  • 9
  • how do I covert the audio to raw before converting to base64 – Alec McCutcheon Apr 18 '22 at 05:16
  • RAW 500 kb, 16 pcm, mono – Alec McCutcheon Apr 18 '22 at 05:42
  • I figured it out, Thx a Bunch – Alec McCutcheon Apr 18 '22 at 07:57
  • I highly recommend sox - http://sox.sourceforge.net/sox.html I believe the command would be as simple as "sox infile.ext outfile.raw" – Mike Anthony Apr 18 '22 at 11:02
  • Is it faster then what I'm currently using? And or does something better? I'll check it out regardless but it is currently working so unless it improves the speed or track recognition, not sure why I'd swap it – Alec McCutcheon Apr 19 '22 at 18:47
  • Just much easier for future ref e.g. ///// "sox infile -b 16 -s -c 1 -t raw outfile.raw" ///// instead of ///// "$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" – Mike Anthony Apr 19 '22 at 22:22