Post not yet marked as solved
Hi,
I'm trying to convert a stream into a PCMBuffer and then use Shazam to match.
Shazam always fails to match.
I have a theory it "listens" to the playback at double speed or more.
Starts from here:
...
let format = audioEngine.outputNode.inputFormat(forBus: 0)
guard let pcmBuffer = format.toPCMBuffer(frame: currentFrame) else {
return
}
session.matchStreamingBuffer(pcmBuffer, at: nil)
Where toPCMBuffer is:
extension AVAudioFormat {
func toPCMBuffer(frame: AudioFrame) -> AVAudioPCMBuffer? {
guard let pcmBuffer = AVAudioPCMBuffer(pcmFormat: self, frameCapacity: UInt32(frame.dataWrap.size[0]) / streamDescription.pointee.mBytesPerFrame) else {
return nil
}
pcmBuffer.frameLength = pcmBuffer.frameCapacity
for i in 0 ..< min(Int(pcmBuffer.format.channelCount), frame.dataWrap.size.count) {
frame.dataWrap.data[i]?.withMemoryRebound(to: Float.self, capacity: Int(pcmBuffer.frameCapacity)) { srcFloatsForChannel in
pcmBuffer.floatChannelData?[i].assign(from: srcFloatsForChannel, count: Int(pcmBuffer.frameCapacity))
}
}
return pcmBuffer
}
}
AudioFrame is:
final class AudioFrame: MEFrame {
var timebase = Timebase.defaultValue
var duration: Int64 = 0
var size: Int64 = 0
var position: Int64 = 0
var numberOfSamples = 0
let dataWrap: ByteDataWrap
public init(bufferSize: Int32, channels: Int32) {
dataWrap = ObjectPool.share.object(class: ByteDataWrap.self, key: "AudioData_\(channels)") { ByteDataWrap() }
if dataWrap.size[0] < bufferSize {
dataWrap.size = Array(repeating: Int(bufferSize), count: Int(channels))
}
}
...
}
and MEFrame is:
extension MEFrame {
public var seconds: TimeInterval { cmtime.seconds }
public var cmtime: CMTime { timebase.cmtime(for: position) }
}
Post not yet marked as solved
Hi,
I have built an app that is based on ShazamKit custom catalog. It works fine when I test it using the simulator. However when I deploy it on my ios 15.5 device, it does not work. It matches the first item and that it. It keeps calling the delegate but match is always equal to the first item.
func session(_ session: SHSession, didFind match: SHMatch) {
if let first = match.mediaItems.first {
if let mediaItemTitle = first.title {
if (title != mediaItemTitle) {
title = mediaItemTitle
}
}
}
}
Post not yet marked as solved
I have the following situation:
I took 3 audio files and generated a Shazam signature for each
I created a custom catalog with these 3 signatures
All 3 audio items have an identical 40 second intro
When I create a SHSession with my custom catalog and try to match audio from that common intro section, the matcher returns on the delegate method session(_ session: SHSession, didFind match: SHMatch) - without exception - only 1 object in the match.mediaItems array.
For example: if didFind is called once per second, for signatures A, B, C, I would get a random sequence like - A, B, A, A, C, C, B, A (it's different every time).
According to the documentation, mediaItems should contain all 3 sounds represented by the signatures as possible matches: mediaItems - An array of the media items in the catalog that match the query signature, in order of the quality of the match.
The catalog was built by loading the signature files from disk:
let signatureData = try Data(contentsOf: sigUrl)
let signature = try SHSignature(dataRepresentation: signatureData)
let mediaItem = SHMediaItem(properties: [.title: sigName])
try customCatalog.addReferenceSignature(signature, representing: [mediaItem])
I tried matching:
with session.matchStreamingBuffer(buffer, at: audioTime) (so sending the audio input directly to the matching session)
by creating a signature of the recorded audio for different durations (from 3 to 15 seconds recording duration) and sending the signature to the matcher to session.match(signature).
I also tried the async/await version, for the small chance of implementation differences between the two
but I always, without exception, only get 1 item in the mediaItems array.
Everything else seems to be working correctly - apart from matching within the common section.
Does anyone have any suggestions about this? Is it expected behaviour or a ShazamKit bug?
Hey there,
I was wondering if it's possible to check how "certain" ShazamKit is with the match.
For example; I'd only change the result when the SHMatch has an accuracy/certainty of at least 80%
I know there's a frequencySkew on the SHMatchedMediaItem but I'm not sure if that could be helpful
Post not yet marked as solved
I am trying to build a "Sing that Tune" game. For example:
The app will tell the user to sing, "Row row your boat."
The user will sing "Row row your boat" into the microphone.
If the user's melody is close enough to the actual melody, the game is won.
My question: Since I'm dealing with live audio that might be "correct" but not "exact," is the best strategy to use ShazamKit and an SHCustomCatalog, or is it better to use Create ML and sound classification? I know Create ML model can learn the difference between a baby and a firetruck, but can it learn the difference between a good guess and a wrong guess of a sung melody?
Thank you,
Eli
Hi There,
Whenever I want to use the microphone for my ShazamKit app while connected to AirPods my app crashes with a "Invalid input sample rate." message.
I've tried multiple formats but keep getting this crash. Any pointers would be really helpful.
func configureAudioEngine() {
do {
try audioSession.setCategory(.playAndRecord, options: [.mixWithOthers, .defaultToSpeaker, .allowAirPlay, .allowBluetoothA2DP ,.allowBluetooth])
try audioSession.setActive(false, options: .notifyOthersOnDeactivation)
} catch {
print(error.localizedDescription)
}
guard let engine = audioEngine else { return }
let inputNode = engine.inputNode
let inputNodeFormat = inputNode.inputFormat(forBus: 0)
let audioFormat = AVAudioFormat(
standardFormatWithSampleRate: inputNodeFormat.sampleRate,
channels: 1
)
// Install a "tap" in the audio engine's input so that we can send buffers from the microphone to the signature generator.
engine.inputNode.installTap(onBus: 0, bufferSize: 1024, format: audioFormat) { buffer, audioTime in
self.addAudio(buffer: buffer, audioTime: audioTime)
}
}
```
Post not yet marked as solved
Hi,
I'm developing an app with ShazamKit and I'd like to check its license agreement in order to know what I can and what I can't do, but I can't find it anywhere.
Is there any link where I can find it?
How to get song title & artist using shazam, i have done with local file & microphone listen but using live Http stream radio url not working.
Please any one have idea please reply.
Post not yet marked as solved
Hi,
I've been asked to develop a software for macOS that monitors daily 24/7 some streamings and logs the aired music.
I'd like to use ShazamKit, by the way I don't know if I have to do something in particular in order to use it in a commercial app and I don't know if with so many requests I can hit some threshold (it could be 10 simultaneous streams, it could be 100 simultaneous streams, I don't know at the moment).
Any info about that?
Post not yet marked as solved
Hi, dear apple developers.
Is there any full example about shazamkit for android developers? I've found that There is no full example about how to use shazamkit to build an android app propertly in WHOLE Internet(eg: github etc.)....
the documentation below is missing a lot of information.
https://developer.apple.com/shazamkit/android/
Especially how to associate MediaItem with signature.
https://developer.apple.com/shazamkit/android/shazamkit/com.shazam.shazamkit/-media-item/index.html
in swift we can use
customCatalog.addReferenceSignature(signature, representing: [mediaItem])
but I can't see anything about it in kotlin
So, is there more information about it?
Post not yet marked as solved
I recently released my first ShazamKit app, but there is one thing that still bothers me.
When I started I followed the steps as documented by Apple right here : https://developer.apple.com/documentation/shazamkit/shsession/matching_audio_using_the_built-in_microphone
however when I was running this on iPad I receive a lot of high pitched feedback noise when I ran my app with this configuration. I got it to work by commenting out the output node and format and only use the input.
But now I want to be able to recognise the song that’s playing from the device that has my app open and was wondering if I need the output nodes for that or if I can do something else to prevent the Mic. Feedback from happening.
In short:
What can I do to prevent feedback from happening
Can I use the output of a device to recognise songs or do I just need to make sure that the microphone can run at the same time as playing music?
Other than that I really love the ShazamKit API and can highly recommend to have a go with it!
This is the code as documented in the above link (I just added the comments of what broke it for me)
func configureAudioEngine() {
// Get the native audio format of the engine's input bus.
let inputFormat = audioEngine.inputNode.inputFormat(forBus: 0)
// THIS CREATES FEEDBACK ON IPAD PRO
let outputFormat = AVAudioFormat(standardFormatWithSampleRate: 48000, channels: 1)
// Create a mixer node to convert the input.
audioEngine.attach(mixerNode)
// Attach the mixer to the microphone input and the output of the audio engine.
audioEngine.connect(audioEngine.inputNode, to: mixerNode, format: inputFormat)
// THIS CREATES FEEDBACK ON IPAD PRO
audioEngine.connect(mixerNode, to: audioEngine.outputNode, format: outputFormat)
// Install a tap on the mixer node to capture the microphone audio.
mixerNode.installTap(onBus: 0,
bufferSize: 8192,
format: outputFormat) { buffer, audioTime in
// Add captured audio to the buffer used for making a match.
self.addAudio(buffer: buffer, audioTime: audioTime)
}
}
Post not yet marked as solved
Hello. I'm a beginner developer trying to release a music app.
My app is,
Use Shazamkit to provide information about music (such as album image of a song, music title and genre, etc.) that the user receives via audio.
Through Apple Music API, provide information about music searched by users (such as artist image, album image, playlist image, title and artist name, genre, etc.).
However, it was rejected by reviewers for the following reasons.
5.2.1(e) Legal: Intellectual Property - General
Of course, I am a member of the Apple Developer Program, and even though I only used APIs and Kits provided by Apple, I was rejected due to copyright issues.
For reference, my app does not have upload/download functions for audio and video, and does not include playback functions.
How do I resolve copyright issues?
Thank you.
Post not yet marked as solved
The resulted matches from a custom catalog on both iOS/ Android are a bit delayed (1-3+ seconds)
How to test? (iOS)
Prepare AVAudioPlayer with recorded audio.
Load custom catalog & listen to recorded audio from an external source.
When a match is found, play recorded audio from the AVAudioPlayer at: predictedCurrentMatchOffset
Result:
1-3+ seconds delayed matches
Question
How to improve or filter the resulting matches to be close if not exact to the external audio source?
Experimental
Filtering results by frequencySkew close to 0, does not minimize delayed matches.
[{
"sh_audioStartDate" = "2021-11-24 12:34:42 +0000";
"sh_frequencySkew" = "2.222024e-05";
"sh_matchOffset" = "388.3738065670163";
"sh_score" = "4302.546";
"sh_speedSkew" = "0.0009712927";
"sh_title" = ItemTitle;
}]
Printing the matchedMediaItems, there is a “sh_score”, maybe we can experiment with?
But it’s not a public property
Best regards.
Post not yet marked as solved
Hi,
I'm developing an android app that uses ShazamKit.
I know that there is an hourly requests rate limit for the Apple Music API, but I can't find anything about ShazamKit.
Is there also a rate limit for ShazamKit?
If yes, how can I find it since I'm using the SDK and not doing direct call API?
Hello, we've encountered issues on Android using Custom Catalogs.
On Android the only possible way to create a custom catalog is using .addFromCatalog() from a .shazamcatalog file, there is no method like iOS SDK provides .addReferenceSignature() to add a signature.
Generating from iOS a .shazamcatalog file and loading in Android returns wrong values for query signature duration:
Android
catalog.minimumQuerySignatureDurationInMs: 3000
catalog.maximumQuerySignatureDurationInMs: 2147483647
iOS
minQuerySignDuration: 1.0 seconds
maxQuerySignDuration: 12.0 seconds
No match resulting for Android but iOS works as expected.
Is it possible to match against a custom catalog on Android?
Any help will be much appreciated.
Post not yet marked as solved
Hi all,
I have an app that is playing music from http live streams using AVPlayer. Have been trying to figure out how to use ShazamKit to recognise the music playing but I just can't figure out how to do it :-( Works well with local files and microphone recordings, but how do I get the data from a stream that is currently playing??? Feels like I tried everything...
Have tried to install an MTAudioProcessingTap but it doesn't seem to work on streaming assets even though I can get hold of the proper AVAssetTrack containing the audio. No callback with data are received? Bug?
I can open the streaming url and just save the bytes to disk and that's fine, but I'm not in sync with what is playing in AVPlayerItem so the recognition isn't working with the same audio data as the user is currently hearing. Hmmm.
Any suggestions and ideas are welcome. It would be such a nice feature for my app so I'm really looking forward to solving this.
Thx in advance / Jörgen, Bitfield
Post not yet marked as solved
This is first time I am developing android app using sdk provided by Apple. I want to integrate Shazamkit in my app but after going through all documents & steps, I got my private key, team id everything except "Public key" for token, as I am not able to create valid access token using jwt, I am not able to use ShazamKit. So if possible please let me know from where I can get this key or am I missing some step?
Thank you in advance.
Post not yet marked as solved
Hey, I wanted to use the ShazamKit API in a web application but it seems like the framework is only for iOS and Android. I came across this resource but it's not very clear how it works as they direct traffic to their own server: https://rapidapi.com/apidojo/api/shazam
Does anyone know if there is an official URL for the Shazam API and how I can use it? Thanks
Post not yet marked as solved
Today, I create a small app to try ShazamKit music detection ability in iOS 15. Follow a tutorial on Youtube, and I have Apple developer membership and have enabled the ShazamKit service for this app identifier.
In short, I want to detect a song metadata with ShazamKit from the audio file inside app.
The problem is that both of delegate method didFind and didNotFindMatchFor didn't fire though I have generated the signature successfully. I think it should give me an error in didNotFindMatchFor delegate method if there is no match found at least, but it doesn't.
It's a pretty new feature, there is not that much related stuff I could find. What am I missing here? Appreciate for any help.
More info: I do find some stuff using audioEngine, however that use output from Microphone, if user listen music with a headphone, that would be not possible. In my case I want to use the file itself since my production app is a music player, which stores a lot audio files in sandbox.
import ShazamKit
import UIKit
class ViewController: UIViewController {
lazy var recoButton: UIButton = {
let button = UIButton(frame: CGRect(x: 0, y: 0, width: 120, height: 60))
button.layer.cornerRadius = 8
button.backgroundColor = .brown
button.setTitle("Recognize", for: .normal)
button.addTarget(self, action: #selector(recognizeSong), for: .touchUpInside)
return button
}()
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(recoButton)
recoButton.center = view.center
}
@objc func recognizeSong(_ sender: UIButton) {
print("reco button tapped")
// ShazamKit is available from iOS 15
if #available(iOS 15, *) {
// session
let session = SHSession()
// delegate
session.delegate = self
do {
// get track
guard let url = Bundle.main.url(forResource: "Baby One More Time", withExtension: "mp3") else {
print("url is NULLLL")
return }
// create audio file
let file = try AVAudioFile(forReading: url)
let frameCapacity = AVAudioFrameCount(file.length / 26)
// Audio -> Buffer
guard let buffer = AVAudioPCMBuffer(pcmFormat: file.processingFormat, frameCapacity: frameCapacity) else {
print("Failed to create a buffer")
return }
// Read file into buffer
try file.read(into: buffer)
// SignatureGenerator
let generator = SHSignatureGenerator()
try generator.append(buffer, at: nil)
// create signature
let signature = generator.signature()
// try to match
session.match(signature)
} catch {
print(error)
}
} else {
// unavailable alert
}
}
}
extension ViewController: SHSessionDelegate {
func session(_ session: SHSession, didFind match: SHMatch) {
print("Match found!")
// get results
let items = match.mediaItems
items.forEach { item in
print(item.title ?? "title")
print(item.artist ?? "artist")
print(item.artworkURL?.absoluteURL ?? "artwork url")
}
}
func session(_ session: SHSession, didNotFindMatchFor signature: SHSignature, error: Error?) {
if let error = error {
print(error)
}
}
}
Post not yet marked as solved
I want to create and publish Android app which uses ShazamKit, but I can't find License Agreement for Android version of ShazamKit, which means I can't publish APK legally.
also I want to include aar file to GitHub repository for build in CI, but I can't include aar file legally without explicit allow from Apple.
Where is the License Agreement for Android version of ShazamKit?