ShazamKit

RSS for tag

Get exact audio matching for any audio source using the Shazam catalog or a custom catalog in an app.

Posts under ShazamKit tag

75 Posts

Post

Replies

Boosts

Views

Activity

ShazamKit Cost
We're looking to integrate ShazamKit, but can't find any details of associated costs. Is there a fee or rate limits for matching? And is attribution required to the matched song on Apple Music? Thank you
0
0
732
Oct ’23
ShazamKit SDK crash on Android
We are using ShazamKit SDK for Android and our application sometimes crashes when performing an audio recognition. We get the following logs: Cause: null pointer dereference backtrace: #00 pc 000000000000806c /data/app/lib/arm64/libsigx.so (SHAZAM_SIGX::reset()) (BuildId: 40e0b3c4250b21f23f7c4ec7d7b88f954606d914) #01 pc 00000000000dc324 /data/app//oat/arm64/base.odex at libsigx.SHAZAM_SIGX::reset()(reset:0) at base.0xdc324(Native Method)
1
2
1.7k
Oct ’23
Shazamkit's SHManagedSession() doesn't work on macOS 14 RC 23A339
Shazamkit's SHManagedSession() doesn't work on macOS 14 RC 23A339 Error code: AddInstanceForFactory: No factory registered for id <CFUUID 0x600000540340> F8BB1C28-BAE8-11D6-9C31-00039315CD46 HALC_ShellDevice.cpp:2,609 HALC_ShellDevice::RebuildControlList: couldn't find the control object Prepare call ignored, the caller does not have record permission Error The operation couldn’t be completed. (com.apple.ShazamKit error 202.)
1
0
811
Sep ’23
SHLibrary.default.items always return empty list
I want use SHLibrary.default.items to show the music i recognized by Shazam. but SHLibrary.default.items always return empty list. I did an experiment and I called SHLibrary.default.items as soon as I entered on a page and it returned an empty list, but after use SHManagedSession to identify songs and then call SHLibrary.default.items it returned the result I wanted. Below is the test code private func bindEvent() { // call when View was create the items return empty if #available(iOS 17, *) { let items = SHLibrary.default.items print("-------->>>>>>>>\(items)") } self.addToMediaLibray.onTap { [weak self] in guard let `self` = self, let result = self.result, let appleMusicID = result.appleMusicID else { return } if #available(iOS 17, *) { // call when music was recognized the item is not empty. let items = SHLibrary.default.items print("1111-------->>>>>>>>\(items)") } } } The attach file is the part of result log My iOS Verion is iOS 17 (21A5326a) XCode Version is 15.0 beta 8 (15A5229m) The result log
1
0
893
Sep ’23
ShazamKit failing to get matches
I'm trying to get ShazamKit for Android to work. I have a catalog that I am downloading from an external service, caching in internal app storage and reading from internal app storage. Doing so I'm getting no matches. However if I manually download the file from internal app storage to my computer and put it in the assets folder and read it from there I'm getting matches. So the issue must be in the reading of the file. See comments in the code below. Here's the code: private const val BUFFER_SIZE = 3840 class ShazamService(private val app: Application) { private val coroutineScope = CoroutineScope(Dispatchers.IO + Job()) private val repository = ShazamRepository(...) private val catalog = ShazamKit.createCustomCatalog() private val recorder by lazy { AudioRecording(app) } private var session: StreamingSession? = null suspend fun initialize(source: Source) { // This method does not work addCatalog(source) // This works when used // loadCustomCatalog() session = (ShazamKit.createStreamingSession( catalog, AudioSampleRateInHz.SAMPLE_RATE_48000, BUFFER_SIZE ) as ShazamKitResult.Success).data session?.recognitionResults()?.onEach { matchResult -> onMatch(matchResult) }?.flowOn(Dispatchers.Main)?.launchIn(coroutineScope) } // This works private suspend fun loadCustomCatalog() { val assetManager = app.assets val inputStream: InputStream = assetManager.open("catalog.shazamcatalog") catalog.addFromCatalog(inputStream) } // This does not work private suspend fun addCatalog(source: Source) { repository.loadFile(app.applicationContext, source)?.use { data -> val result = this.catalog.addFromCatalog(data) Timber.d("Catalog added: $result") } } fun start() { recorder.startRecording { data -> session?.matchStream(data, data.size, 0) } } fun stop() { recorder.stopRecording() } private fun onMatch(result: com.shazam.shazamkit.MatchResult) { Timber.d("Received MatchResult: $result") } fun destroy() { coroutineScope.cancel() } } Here's the repository responsible for providing the catalog file. Source contains an id and a url from which a catalog can be downloaded. It downloads the catalog and saves it as a file in internal app storage and returns a FileInputStream. class ShazamRepository( private val shazamClient: ShazamClient ) { suspend fun loadFile(context: Context, source: Source): FileInputStream? { val file = File(context.filesDir, source.id + ".shazamcatalog") val catalog = loadFile(file) if (catalog == null) { val response = shazamClient.getCatalog(source.url) if (response.isSuccessful) { response.body()?.let { data -> saveResponseData(data, file) } } } else { return catalog } return loadFile(file) } private fun saveResponseData(data: ResponseBody, file: File) { data.byteStream().use { inputStream -> FileOutputStream(file).use { outputStream -> val buffer = ByteArray(4 * 1024) var read: Int while (inputStream.read(buffer).also { read = it } != -1) { outputStream.write(buffer, 0, read) } outputStream.flush() } inputStream.close() } } private fun loadFile(file: File): FileInputStream? { return if (file.exists()) { FileInputStream(file) } else { return null } } } To summarise: The catalog is downloaded and saved correctly. If the catalog file is opened with assetManager.open I'm getting matches. When using FileInputStream(file) no matches are received. What could be wrong with the File-API approach? Why does it work when using the AssetManager but not when using it as a File?
0
0
736
Aug ’23
matchStreamingBuffer causes an NSException
Hi, I am using ShazamKit to detect songs from a live stream. I am using matchStreamingBuffer with a PCMBuffer. It looks like it works for the most part, but sometimes it throws an NSException. Here's the code calling the match: engine.mainMixerNode.installTap(onBus: 0, bufferSize: 4096, format: options.audioFormat) { buffer, time in do { self.session.matchStreamingBuffer(buffer, at: time) } catch { } } The exception: Supplied audio format is not supported <CMAudioFormatDescription 0x2828a29e0 [0x20f7863a0]> { mediaType:'soun' mediaSubType:'lpcm' mediaSpecific: { ASBD: { mSampleRate: 44100.000000 mFormatID: 'lpcm' mFormatFlags: 0x29 mBytesPerPacket: 4 mFramesPerPacket: 1 mBytesPerFrame: 4 mChannelsPerFrame: 2 mBitsPerChannel: 32 } cookie: {(null)} ACL: {Stereo (L R)} FormatList Array: { Index: 0 ChannelLayoutTag: 0x650002 ASBD: { mSampleRate: 44100.000000 mFormatID: 'lpcm' mFormatFlags: 0x29 mBytesPerPacket: 4 mFramesPerPacket: 1 mBytesPerFrame: 4 mChannelsPerFrame: 2 mBitsPerChannel: 32 }} } extensions: {(null)} } This is the stack stack: 0 CoreFoundation 0xa248 __exceptionPreprocess 1 libobjc.A.dylib 0x17a68 objc_exception_throw 2 ShazamKit 0x159d0 -[SHMutableSignature appendBuffer:atTime:error:] 3 ShazamKit 0x6d7c -[SHSignatureGenerator appendBuffer:atTime:error:] 4 ShazamKit 0x3968 -[SHSessionDriverSignatureSlot appendBuffer:atTime:error:] 5 ShazamKit 0x10430 -[SHSignatureBuffer flow:time:] 6 ShazamKit 0x2490 -[SHStreamingSessionDriver flow:time:] 7 ShazamKit 0xf784 -[SHSession matchStreamingBuffer:atTime:] 8 MyApp 0x17f69c thunk for @escaping @callee_guaranteed (@guaranteed AVAudioPCMBuffer, @guaranteed AVAudioTime) -> () (<compiler-generated>) 9 AVFAudio 0x482ac AVAudioNodeTap::TapMessage::RealtimeMessenger_Perform() 10 AVFAudio 0x71c4 CADeprecated::RealtimeMessenger::_PerformPendingMessages() 11 AVFAudio 0x471e4 invocation function for block in CADeprecated::RealtimeMessenger::RealtimeMessenger(applesauce::dispatch::v1::queue) I don't mind failing if the format is not good, but how can I avoid crashing?
3
0
963
Jun ’23
Shazam fails to find match
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) } }
3
1
1.7k
Apr ’23
Help with Shazam
am trying to identify songs using shazamkit. every time it runs, this is the output: 2023-04-26 04:39:28.947059-0400 shazoom[38003:3098314] [AQ] AudioQueueObject.cpp:2364 Error (-4) getting reporterIDs Processing chunk 1 from 0.0 to 60.0: 4316113920 Chunk saved at: file:///Users/youssefhemimy/Downloads/beyoncee.mp3 No match found 2023-04-26 04:39:29.483659-0400 shazoom[38003:3098339] [AQ] AudioQueueObject.cpp:2364 Error (-4) getting reporterIDs Processing chunk 2 from 60.0 to 120.0: 4317271680 Chunk saved at: file:///Users/youssefhemimy/Downloads/beyoncee.mp3 No match found 2023-04-26 04:39:29.965718-0400 shazoom[38003:3098343] [AQ] AudioQueueObject.cpp:2364 Error (-4) getting reporterIDs Processing chunk 3 from 120.0 to 180.0: 4317324608 Chunk saved at: file:///Users/youssefhemimy/Downloads/beyoncee.mp3 No match found Note: all songs I have used have been identified by shazam the app. I have tried to use different songs, re-exported them from logic pro x but no luck. It also takes less than 2 seconds to generate this output which is way faster than the app. I have tried to use: var minimumQuerySignatureDuration: TimeInterval { get } but no luck. Below is the full code: import Foundation import AVFoundation import ShazamKit class ShazamAnalyzer: NSObject, SHSessionDelegate { let session = SHSession() func analyzeAudioFile(url: URL) { let asset = AVAsset(url: url) let assetDuration = asset.duration.seconds let chunkDuration = 30.0 let numberOfChunks = Int(ceil(assetDuration / chunkDuration)) session.delegate = self for i in 0..<numberOfChunks { let startTime = Double(i) * chunkDuration let start = CMTime(seconds: startTime, preferredTimescale: asset.duration.timescale) let end = CMTime(seconds: min(startTime + chunkDuration, assetDuration), preferredTimescale: asset.duration.timescale) let range = CMTimeRange(start: start, end: end) if let signature = generateSignature(from: asset, for: range) { print("Processing chunk &bsol;(i + 1) from &bsol;(start.seconds) to &bsol;(end.seconds): &bsol;(signature.hash)") print("Chunk saved at: &bsol;(url.absoluteString)") session.match(signature) } else { print("Error generating signature for chunk &bsol;(i + 1)") } } } func generateSignature(from asset: AVAsset, for timeRange: CMTimeRange) -> SHSignature? { let audioFormat = AVAudioFormat(standardFormatWithSampleRate: 44100, channels: 1) let signatureGenerator = SHSignatureGenerator() let exportSession = AVAssetExportSession(asset: asset, presetName: AVAssetExportPresetPassthrough)! exportSession.timeRange = timeRange let reader = try? AVAssetReader(asset: exportSession.asset) let audioOutput = AVAssetReaderAudioMixOutput(audioTracks: exportSession.asset.tracks(withMediaType: .audio), audioSettings: nil) audioOutput.alwaysCopiesSampleData = false reader?.add(audioOutput) reader?.startReading() while let sampleBuffer = audioOutput.copyNextSampleBuffer() { if let blockBuffer = CMSampleBufferGetDataBuffer(sampleBuffer) { let length = CMBlockBufferGetDataLength(blockBuffer) var data = Data(count: length) _ = data.withUnsafeMutableBytes {(bytes: UnsafeMutableRawBufferPointer) in CMBlockBufferCopyDataBytes(blockBuffer, atOffset: 0, dataLength: length, destination: bytes.baseAddress!) } let audioBuffer = AVAudioPCMBuffer(pcmFormat: audioFormat!, frameCapacity: AVAudioFrameCount(length) / audioFormat!.streamDescription.pointee.mBytesPerFrame)! guard let channelData = audioBuffer.floatChannelData else { print("Error: Channel data is nil") return nil } let channels = UnsafeBufferPointer(start: channelData, count: Int(audioFormat!.channelCount)) let destinationBuffer = UnsafeMutableBufferPointer(start: channels[0], count: length) _ = data.copyBytes(to: destinationBuffer) do { try signatureGenerator.append(audioBuffer, at: nil) } catch { print( "Error appending buffer to signature generator: &bsol;(error)") return nil } } } return signatureGenerator.signature() } func session(_ session: SHSession, didFind match: SHMatch) { if let matchedItem = match.mediaItems.first { print("Match found: &bsol;(matchedItem.title ?? "Unknown Title") by &bsol;(matchedItem.artist ?? "Unknown Artist")") } else { print("Match found, but unable to retrieve media item details.") } } func session(_ session: SHSession, didNotFindMatchFor signature: SHSignature, error: Error?) { print("No match found") } } let filePath = "/Users/youssefhemimy/Downloads/beyoncee.mp3" // Replace this with the actual path to your audio file if let fileURL = URL(string: "file://" + filePath) { let analyzer = ShazamAnalyzer() analyzer.analyzeAudioFile(url: fileURL) } else { print("Invalid file path") }
1
0
898
Apr ’23
API Call limitations to ShazamKit
Hi, Is there an app limit or user limit for song matches with ShazamKit? I need to know if I need to limit access or not on my app. If there is a limit, is it per user or per the entire calls made by the app? I am using the matchStreamingBuffer continiously, so it is called every few seconds (with the same match).
0
0
908
Apr ’23
ShazamKit match(SHSignature) not working on IOS 16
I am trying to use ShazamKit to detect the song in a local audio file. When I call match(SHSignature), nothing happens. Neither delegate function ever gets called, and nothing is printed to the console. I don't know what went wrong, how to fix it or even how to debug this further. Here is some sample code where the issue is occurring. You will need to place a song.m4a audio file in your xcode project for this to work. Your song.m4a file must be 3-12 seconds in length. The code will fail if the audio file exceeds 12 seconds for reasons discussed here. import SwiftUI import ShazamKit @main struct ShazamKitTestExApp: App { var body: some Scene { WindowGroup { ContentViewTrio() } } } struct ContentViewTrio: View { @StateObject private var detectSong: DetectSongEx = DetectSongEx() var body: some View { VStack { Text("ShazamKitTestEx") Button { print("Detecting Song") Task { if let url = Bundle.main.url(forResource: "song", withExtension: "m4a") { print(url.absoluteString) await detectSong.matchSong(from: url) } } } label: { Text("Detect Song from Audio File") } } } } class DetectSongEx: NSObject, ObservableObject, SHSessionDelegate { func matchSong(from url: URL) async { let session = SHSession() session.delegate = self let asset = AVURLAsset(url: url) do { let signature = try await SHSignatureGenerator.signature(from: asset) print("Calling session match method") session.match(signature) } catch { print("Failed to generate signature") } } func session(_ session: SHSession, didFind match: SHMatch) { print("session delegate - DidFindMatch") } func session(_ session: SHSession, didNotFindMatchFor signature: SHSignature, error: Error?) { print("session delegate called - DidNotFindMatch") if let shError = error as? SHError { print(shError.localizedDescription) } } } Notes Yes, I have added ShazamKit to my App ID using the instructions here. Device Test Results I tried this on a Mac (macOS 13.0.1), on a physical iPhone (iOS 16.4.1) and a physical iPad (iPadOS 16.1.1). Unfortunately, I don't have any hardware running iOS 15 or macOS 12. When I use an audio file with a length of 6 seconds with the sample code (on all devices), neither delegate ever gets called and match(SHSignature) just silently fails. If I use an audio file of length > 12s then the DidNotFindMatch delegate does get called with the error "The operation couldn’t be completed. (com.apple.ShazamKit error 201.)" as expected. iOS 15 I have used ShazamKit before prior to iOS 16 being released. Back then, I used the the code found here to match a song from a local audio file, since the new iOS 16 simple api didn't exist. I was able to successfully use match(SHSignature) back then and the DidFindMatch delegate was called as expected giving me a match. When I tried this old code now on iOS 16, without any changes, it didn't work. Everything complied fine but the same thing happened as described at the beginning of this post, match(SHSignature) would silently fail and neither delegate is ever called. Simulator Test Results I am aware that ShazamKit does not work from within the simulator. However, since I have no access to iOS 15 hardware, this is my only option to compare the code on iOS 15.5 vs iOS 16.4. The results were odd. When I tried my old code in the simulator running iOS 15.5, the DidNotFindMatch delegate does get called with the error "The operation couldn’t be completed. (com.apple.ShazamKit error 202.)". Based on other forum posts, I believe this is the expected error when trying to run ShazamKit from the simulator. However, when I tried my old code in the simulator running iOS 16.4, the DidNotFindMatch delegate does not get called, match(SHSignature) would silently fail and neither delegate is ever called. This is strange, I expected the result to be the same as when I ran the old code in the 15.5 simulator. Conclusion If anyone has an ideas what is going on or how to test this further, I am all ears. It seems kind of crazy to me that this was broken in iOS 16.0 and has never been fixed. Has anyone run into anything similar? Or is the sample code working on your iOS 16 device?
1
0
1.1k
Apr ’23
Cannot set desired duration when using generateSignature(from:completionHandler:)
A new API was added to ShazamKit is iOS 16 that lets you generate a signature from an AVAsset. https://developer.apple.com/documentation/shazamkit/shsignaturegenerator/3991425-generatesignature This new API is great, it cuts down on a lot of custom code, but is there a way to make the duration of the signature generated a desired length? Currently the API creates a signature for the entire duration of the AVAsset. If you give it a 60 second long audio file, the signature is 60 seconds. This makes sense when creating signatures for a custom catalog BUT this is not useful when trying to match a song using the Shazam Music Catalog from an audio file. When matching a song, the match API enforces limits on the signature length (minimumQuerySignatureDuration of 3s, maximumQuerySignatureDuration or 12s). Unless the audio file is between 3 and 12 seconds, the signature from generateSignature will always fail to find a match because it is too short/long.
0
0
691
Apr ’23
Shazam vs. ShazamKit
Hi, We included the Shazam API to record snippets and sent it to the API for track recognition and it works fine, the only problem is that way less tracks are recognized as in the Shazam app. So my questions is: does ShazamKit use the same track database as Shazam? In this case we should be able to optimize the recognition process to achieve the level of Shazam, right? Best regards
3
0
1.6k
Apr ’23
Advice on Implementing Continuous Music Recognition in the Background on iOS
I'm developing an iOS application that involves continuous music recognition in the background. I understand that iOS imposes limitations on background tasks, and I want to ensure that my app complies with Apple's guidelines and best practices. Specifically, I'm interested in implementing a feature similar to Shazam's Auto mode, which listens in the background for music and recognizes it automatically. However, I'm not sure if this is feasible or recommended on iOS, given the battery life, privacy, and app review implications. I would appreciate any advice or guidance on how to implement this feature in a way that is efficient, secure, and compliant with Apple's guidelines. Are there any recommended APIs or frameworks for background audio processing and music recognition? What are the best practices for handling battery life and privacy concerns? Thank you in advance for your help.
0
0
697
Apr ’23
ShazamKit Cost
We're looking to integrate ShazamKit, but can't find any details of associated costs. Is there a fee or rate limits for matching? And is attribution required to the matched song on Apple Music? Thank you
Replies
0
Boosts
0
Views
732
Activity
Oct ’23
ShazamKit SDK crash on Android
We are using ShazamKit SDK for Android and our application sometimes crashes when performing an audio recognition. We get the following logs: Cause: null pointer dereference backtrace: #00 pc 000000000000806c /data/app/lib/arm64/libsigx.so (SHAZAM_SIGX::reset()) (BuildId: 40e0b3c4250b21f23f7c4ec7d7b88f954606d914) #01 pc 00000000000dc324 /data/app//oat/arm64/base.odex at libsigx.SHAZAM_SIGX::reset()(reset:0) at base.0xdc324(Native Method)
Replies
1
Boosts
2
Views
1.7k
Activity
Oct ’23
Shazamkit's SHManagedSession() doesn't work on macOS 14 RC 23A339
Shazamkit's SHManagedSession() doesn't work on macOS 14 RC 23A339 Error code: AddInstanceForFactory: No factory registered for id <CFUUID 0x600000540340> F8BB1C28-BAE8-11D6-9C31-00039315CD46 HALC_ShellDevice.cpp:2,609 HALC_ShellDevice::RebuildControlList: couldn't find the control object Prepare call ignored, the caller does not have record permission Error The operation couldn’t be completed. (com.apple.ShazamKit error 202.)
Replies
1
Boosts
0
Views
811
Activity
Sep ’23
SHLibrary.default.items always return empty list
I want use SHLibrary.default.items to show the music i recognized by Shazam. but SHLibrary.default.items always return empty list. I did an experiment and I called SHLibrary.default.items as soon as I entered on a page and it returned an empty list, but after use SHManagedSession to identify songs and then call SHLibrary.default.items it returned the result I wanted. Below is the test code private func bindEvent() { // call when View was create the items return empty if #available(iOS 17, *) { let items = SHLibrary.default.items print("-------->>>>>>>>\(items)") } self.addToMediaLibray.onTap { [weak self] in guard let `self` = self, let result = self.result, let appleMusicID = result.appleMusicID else { return } if #available(iOS 17, *) { // call when music was recognized the item is not empty. let items = SHLibrary.default.items print("1111-------->>>>>>>>\(items)") } } } The attach file is the part of result log My iOS Verion is iOS 17 (21A5326a) XCode Version is 15.0 beta 8 (15A5229m) The result log
Replies
1
Boosts
0
Views
893
Activity
Sep ’23
Shazam CLI download
In the video, there is a demonstration of shazam tool. Where do I download it from? What is the process of getting it on mac os.
Replies
2
Boosts
0
Views
1.5k
Activity
Sep ’23
On the example project SHLibrary doesn't display any previously played songs
https://developer.apple.com/documentation/shazamkit/shazamkit_dance_finder_with_managed_session The song detection is successful however with new APIs, I can't find this demo working with SHLibrary, it expect to display the RecentDanceRowView. I wonder if I missed any steps or the SHLibrary is not ready yet.
Replies
3
Boosts
0
Views
1.2k
Activity
Sep ’23
ShazamKit Integration in an app question.
Looking to fill up a budget line for an iOs application we are trying to build. By adding ShazamKit to our app, how much cost the use of it per stream ? My research indicates that it is 0,00065$, correct ?
Replies
0
Boosts
0
Views
710
Activity
Sep ’23
ShazamKit failing to get matches
I'm trying to get ShazamKit for Android to work. I have a catalog that I am downloading from an external service, caching in internal app storage and reading from internal app storage. Doing so I'm getting no matches. However if I manually download the file from internal app storage to my computer and put it in the assets folder and read it from there I'm getting matches. So the issue must be in the reading of the file. See comments in the code below. Here's the code: private const val BUFFER_SIZE = 3840 class ShazamService(private val app: Application) { private val coroutineScope = CoroutineScope(Dispatchers.IO + Job()) private val repository = ShazamRepository(...) private val catalog = ShazamKit.createCustomCatalog() private val recorder by lazy { AudioRecording(app) } private var session: StreamingSession? = null suspend fun initialize(source: Source) { // This method does not work addCatalog(source) // This works when used // loadCustomCatalog() session = (ShazamKit.createStreamingSession( catalog, AudioSampleRateInHz.SAMPLE_RATE_48000, BUFFER_SIZE ) as ShazamKitResult.Success).data session?.recognitionResults()?.onEach { matchResult -> onMatch(matchResult) }?.flowOn(Dispatchers.Main)?.launchIn(coroutineScope) } // This works private suspend fun loadCustomCatalog() { val assetManager = app.assets val inputStream: InputStream = assetManager.open("catalog.shazamcatalog") catalog.addFromCatalog(inputStream) } // This does not work private suspend fun addCatalog(source: Source) { repository.loadFile(app.applicationContext, source)?.use { data -> val result = this.catalog.addFromCatalog(data) Timber.d("Catalog added: $result") } } fun start() { recorder.startRecording { data -> session?.matchStream(data, data.size, 0) } } fun stop() { recorder.stopRecording() } private fun onMatch(result: com.shazam.shazamkit.MatchResult) { Timber.d("Received MatchResult: $result") } fun destroy() { coroutineScope.cancel() } } Here's the repository responsible for providing the catalog file. Source contains an id and a url from which a catalog can be downloaded. It downloads the catalog and saves it as a file in internal app storage and returns a FileInputStream. class ShazamRepository( private val shazamClient: ShazamClient ) { suspend fun loadFile(context: Context, source: Source): FileInputStream? { val file = File(context.filesDir, source.id + ".shazamcatalog") val catalog = loadFile(file) if (catalog == null) { val response = shazamClient.getCatalog(source.url) if (response.isSuccessful) { response.body()?.let { data -> saveResponseData(data, file) } } } else { return catalog } return loadFile(file) } private fun saveResponseData(data: ResponseBody, file: File) { data.byteStream().use { inputStream -> FileOutputStream(file).use { outputStream -> val buffer = ByteArray(4 * 1024) var read: Int while (inputStream.read(buffer).also { read = it } != -1) { outputStream.write(buffer, 0, read) } outputStream.flush() } inputStream.close() } } private fun loadFile(file: File): FileInputStream? { return if (file.exists()) { FileInputStream(file) } else { return null } } } To summarise: The catalog is downloaded and saved correctly. If the catalog file is opened with assetManager.open I'm getting matches. When using FileInputStream(file) no matches are received. What could be wrong with the File-API approach? Why does it work when using the AssetManager but not when using it as a File?
Replies
0
Boosts
0
Views
736
Activity
Aug ’23
ShazamKit Music Recognition Issue in Specific Countries/Regions
ShazamKit is integrated into my music app, but some users have reported issues with the music recognition function not working for them. I am wondering if ShazamKit's functionality could be limited in certain countries or regions. Any insights on this matter would be greatly appreciated.
Replies
0
Boosts
0
Views
636
Activity
Jul ’23
Displaying "matchedMediaItem.artist" on the screen of iPhone
I try to match a microphone audio with a custom catalog which I created via ShazamKit. What is the code for extracting and displaying "matchedMediaItem.artist" information on my iPhone screen after finding a song match with an entry of my custom-built catalog? I am a beginner.
Replies
1
Boosts
0
Views
769
Activity
Jul ’23
matchStreamingBuffer causes an NSException
Hi, I am using ShazamKit to detect songs from a live stream. I am using matchStreamingBuffer with a PCMBuffer. It looks like it works for the most part, but sometimes it throws an NSException. Here's the code calling the match: engine.mainMixerNode.installTap(onBus: 0, bufferSize: 4096, format: options.audioFormat) { buffer, time in do { self.session.matchStreamingBuffer(buffer, at: time) } catch { } } The exception: Supplied audio format is not supported <CMAudioFormatDescription 0x2828a29e0 [0x20f7863a0]> { mediaType:'soun' mediaSubType:'lpcm' mediaSpecific: { ASBD: { mSampleRate: 44100.000000 mFormatID: 'lpcm' mFormatFlags: 0x29 mBytesPerPacket: 4 mFramesPerPacket: 1 mBytesPerFrame: 4 mChannelsPerFrame: 2 mBitsPerChannel: 32 } cookie: {(null)} ACL: {Stereo (L R)} FormatList Array: { Index: 0 ChannelLayoutTag: 0x650002 ASBD: { mSampleRate: 44100.000000 mFormatID: 'lpcm' mFormatFlags: 0x29 mBytesPerPacket: 4 mFramesPerPacket: 1 mBytesPerFrame: 4 mChannelsPerFrame: 2 mBitsPerChannel: 32 }} } extensions: {(null)} } This is the stack stack: 0 CoreFoundation 0xa248 __exceptionPreprocess 1 libobjc.A.dylib 0x17a68 objc_exception_throw 2 ShazamKit 0x159d0 -[SHMutableSignature appendBuffer:atTime:error:] 3 ShazamKit 0x6d7c -[SHSignatureGenerator appendBuffer:atTime:error:] 4 ShazamKit 0x3968 -[SHSessionDriverSignatureSlot appendBuffer:atTime:error:] 5 ShazamKit 0x10430 -[SHSignatureBuffer flow:time:] 6 ShazamKit 0x2490 -[SHStreamingSessionDriver flow:time:] 7 ShazamKit 0xf784 -[SHSession matchStreamingBuffer:atTime:] 8 MyApp 0x17f69c thunk for @escaping @callee_guaranteed (@guaranteed AVAudioPCMBuffer, @guaranteed AVAudioTime) -> () (<compiler-generated>) 9 AVFAudio 0x482ac AVAudioNodeTap::TapMessage::RealtimeMessenger_Perform() 10 AVFAudio 0x71c4 CADeprecated::RealtimeMessenger::_PerformPendingMessages() 11 AVFAudio 0x471e4 invocation function for block in CADeprecated::RealtimeMessenger::RealtimeMessenger(applesauce::dispatch::v1::queue) I don't mind failing if the format is not good, but how can I avoid crashing?
Replies
3
Boosts
0
Views
963
Activity
Jun ’23
Shazam fails to find match
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) } }
Replies
3
Boosts
1
Views
1.7k
Activity
Apr ’23
Help with Shazam
am trying to identify songs using shazamkit. every time it runs, this is the output: 2023-04-26 04:39:28.947059-0400 shazoom[38003:3098314] [AQ] AudioQueueObject.cpp:2364 Error (-4) getting reporterIDs Processing chunk 1 from 0.0 to 60.0: 4316113920 Chunk saved at: file:///Users/youssefhemimy/Downloads/beyoncee.mp3 No match found 2023-04-26 04:39:29.483659-0400 shazoom[38003:3098339] [AQ] AudioQueueObject.cpp:2364 Error (-4) getting reporterIDs Processing chunk 2 from 60.0 to 120.0: 4317271680 Chunk saved at: file:///Users/youssefhemimy/Downloads/beyoncee.mp3 No match found 2023-04-26 04:39:29.965718-0400 shazoom[38003:3098343] [AQ] AudioQueueObject.cpp:2364 Error (-4) getting reporterIDs Processing chunk 3 from 120.0 to 180.0: 4317324608 Chunk saved at: file:///Users/youssefhemimy/Downloads/beyoncee.mp3 No match found Note: all songs I have used have been identified by shazam the app. I have tried to use different songs, re-exported them from logic pro x but no luck. It also takes less than 2 seconds to generate this output which is way faster than the app. I have tried to use: var minimumQuerySignatureDuration: TimeInterval { get } but no luck. Below is the full code: import Foundation import AVFoundation import ShazamKit class ShazamAnalyzer: NSObject, SHSessionDelegate { let session = SHSession() func analyzeAudioFile(url: URL) { let asset = AVAsset(url: url) let assetDuration = asset.duration.seconds let chunkDuration = 30.0 let numberOfChunks = Int(ceil(assetDuration / chunkDuration)) session.delegate = self for i in 0..<numberOfChunks { let startTime = Double(i) * chunkDuration let start = CMTime(seconds: startTime, preferredTimescale: asset.duration.timescale) let end = CMTime(seconds: min(startTime + chunkDuration, assetDuration), preferredTimescale: asset.duration.timescale) let range = CMTimeRange(start: start, end: end) if let signature = generateSignature(from: asset, for: range) { print("Processing chunk &bsol;(i + 1) from &bsol;(start.seconds) to &bsol;(end.seconds): &bsol;(signature.hash)") print("Chunk saved at: &bsol;(url.absoluteString)") session.match(signature) } else { print("Error generating signature for chunk &bsol;(i + 1)") } } } func generateSignature(from asset: AVAsset, for timeRange: CMTimeRange) -> SHSignature? { let audioFormat = AVAudioFormat(standardFormatWithSampleRate: 44100, channels: 1) let signatureGenerator = SHSignatureGenerator() let exportSession = AVAssetExportSession(asset: asset, presetName: AVAssetExportPresetPassthrough)! exportSession.timeRange = timeRange let reader = try? AVAssetReader(asset: exportSession.asset) let audioOutput = AVAssetReaderAudioMixOutput(audioTracks: exportSession.asset.tracks(withMediaType: .audio), audioSettings: nil) audioOutput.alwaysCopiesSampleData = false reader?.add(audioOutput) reader?.startReading() while let sampleBuffer = audioOutput.copyNextSampleBuffer() { if let blockBuffer = CMSampleBufferGetDataBuffer(sampleBuffer) { let length = CMBlockBufferGetDataLength(blockBuffer) var data = Data(count: length) _ = data.withUnsafeMutableBytes {(bytes: UnsafeMutableRawBufferPointer) in CMBlockBufferCopyDataBytes(blockBuffer, atOffset: 0, dataLength: length, destination: bytes.baseAddress!) } let audioBuffer = AVAudioPCMBuffer(pcmFormat: audioFormat!, frameCapacity: AVAudioFrameCount(length) / audioFormat!.streamDescription.pointee.mBytesPerFrame)! guard let channelData = audioBuffer.floatChannelData else { print("Error: Channel data is nil") return nil } let channels = UnsafeBufferPointer(start: channelData, count: Int(audioFormat!.channelCount)) let destinationBuffer = UnsafeMutableBufferPointer(start: channels[0], count: length) _ = data.copyBytes(to: destinationBuffer) do { try signatureGenerator.append(audioBuffer, at: nil) } catch { print( "Error appending buffer to signature generator: &bsol;(error)") return nil } } } return signatureGenerator.signature() } func session(_ session: SHSession, didFind match: SHMatch) { if let matchedItem = match.mediaItems.first { print("Match found: &bsol;(matchedItem.title ?? "Unknown Title") by &bsol;(matchedItem.artist ?? "Unknown Artist")") } else { print("Match found, but unable to retrieve media item details.") } } func session(_ session: SHSession, didNotFindMatchFor signature: SHSignature, error: Error?) { print("No match found") } } let filePath = "/Users/youssefhemimy/Downloads/beyoncee.mp3" // Replace this with the actual path to your audio file if let fileURL = URL(string: "file://" + filePath) { let analyzer = ShazamAnalyzer() analyzer.analyzeAudioFile(url: fileURL) } else { print("Invalid file path") }
Replies
1
Boosts
0
Views
898
Activity
Apr ’23
API Call limitations to ShazamKit
Hi, Is there an app limit or user limit for song matches with ShazamKit? I need to know if I need to limit access or not on my app. If there is a limit, is it per user or per the entire calls made by the app? I am using the matchStreamingBuffer continiously, so it is called every few seconds (with the same match).
Replies
0
Boosts
0
Views
908
Activity
Apr ’23
ShazamKit match(SHSignature) not working on IOS 16
I am trying to use ShazamKit to detect the song in a local audio file. When I call match(SHSignature), nothing happens. Neither delegate function ever gets called, and nothing is printed to the console. I don't know what went wrong, how to fix it or even how to debug this further. Here is some sample code where the issue is occurring. You will need to place a song.m4a audio file in your xcode project for this to work. Your song.m4a file must be 3-12 seconds in length. The code will fail if the audio file exceeds 12 seconds for reasons discussed here. import SwiftUI import ShazamKit @main struct ShazamKitTestExApp: App { var body: some Scene { WindowGroup { ContentViewTrio() } } } struct ContentViewTrio: View { @StateObject private var detectSong: DetectSongEx = DetectSongEx() var body: some View { VStack { Text("ShazamKitTestEx") Button { print("Detecting Song") Task { if let url = Bundle.main.url(forResource: "song", withExtension: "m4a") { print(url.absoluteString) await detectSong.matchSong(from: url) } } } label: { Text("Detect Song from Audio File") } } } } class DetectSongEx: NSObject, ObservableObject, SHSessionDelegate { func matchSong(from url: URL) async { let session = SHSession() session.delegate = self let asset = AVURLAsset(url: url) do { let signature = try await SHSignatureGenerator.signature(from: asset) print("Calling session match method") session.match(signature) } catch { print("Failed to generate signature") } } func session(_ session: SHSession, didFind match: SHMatch) { print("session delegate - DidFindMatch") } func session(_ session: SHSession, didNotFindMatchFor signature: SHSignature, error: Error?) { print("session delegate called - DidNotFindMatch") if let shError = error as? SHError { print(shError.localizedDescription) } } } Notes Yes, I have added ShazamKit to my App ID using the instructions here. Device Test Results I tried this on a Mac (macOS 13.0.1), on a physical iPhone (iOS 16.4.1) and a physical iPad (iPadOS 16.1.1). Unfortunately, I don't have any hardware running iOS 15 or macOS 12. When I use an audio file with a length of 6 seconds with the sample code (on all devices), neither delegate ever gets called and match(SHSignature) just silently fails. If I use an audio file of length > 12s then the DidNotFindMatch delegate does get called with the error "The operation couldn’t be completed. (com.apple.ShazamKit error 201.)" as expected. iOS 15 I have used ShazamKit before prior to iOS 16 being released. Back then, I used the the code found here to match a song from a local audio file, since the new iOS 16 simple api didn't exist. I was able to successfully use match(SHSignature) back then and the DidFindMatch delegate was called as expected giving me a match. When I tried this old code now on iOS 16, without any changes, it didn't work. Everything complied fine but the same thing happened as described at the beginning of this post, match(SHSignature) would silently fail and neither delegate is ever called. Simulator Test Results I am aware that ShazamKit does not work from within the simulator. However, since I have no access to iOS 15 hardware, this is my only option to compare the code on iOS 15.5 vs iOS 16.4. The results were odd. When I tried my old code in the simulator running iOS 15.5, the DidNotFindMatch delegate does get called with the error "The operation couldn’t be completed. (com.apple.ShazamKit error 202.)". Based on other forum posts, I believe this is the expected error when trying to run ShazamKit from the simulator. However, when I tried my old code in the simulator running iOS 16.4, the DidNotFindMatch delegate does not get called, match(SHSignature) would silently fail and neither delegate is ever called. This is strange, I expected the result to be the same as when I ran the old code in the 15.5 simulator. Conclusion If anyone has an ideas what is going on or how to test this further, I am all ears. It seems kind of crazy to me that this was broken in iOS 16.0 and has never been fixed. Has anyone run into anything similar? Or is the sample code working on your iOS 16 device?
Replies
1
Boosts
0
Views
1.1k
Activity
Apr ’23
Cannot set desired duration when using generateSignature(from:completionHandler:)
A new API was added to ShazamKit is iOS 16 that lets you generate a signature from an AVAsset. https://developer.apple.com/documentation/shazamkit/shsignaturegenerator/3991425-generatesignature This new API is great, it cuts down on a lot of custom code, but is there a way to make the duration of the signature generated a desired length? Currently the API creates a signature for the entire duration of the AVAsset. If you give it a 60 second long audio file, the signature is 60 seconds. This makes sense when creating signatures for a custom catalog BUT this is not useful when trying to match a song using the Shazam Music Catalog from an audio file. When matching a song, the match API enforces limits on the signature length (minimumQuerySignatureDuration of 3s, maximumQuerySignatureDuration or 12s). Unless the audio file is between 3 and 12 seconds, the signature from generateSignature will always fail to find a match because it is too short/long.
Replies
0
Boosts
0
Views
691
Activity
Apr ’23
Shazam vs. ShazamKit
Hi, We included the Shazam API to record snippets and sent it to the API for track recognition and it works fine, the only problem is that way less tracks are recognized as in the Shazam app. So my questions is: does ShazamKit use the same track database as Shazam? In this case we should be able to optimize the recognition process to achieve the level of Shazam, right? Best regards
Replies
3
Boosts
0
Views
1.6k
Activity
Apr ’23
Advice on Implementing Continuous Music Recognition in the Background on iOS
I'm developing an iOS application that involves continuous music recognition in the background. I understand that iOS imposes limitations on background tasks, and I want to ensure that my app complies with Apple's guidelines and best practices. Specifically, I'm interested in implementing a feature similar to Shazam's Auto mode, which listens in the background for music and recognizes it automatically. However, I'm not sure if this is feasible or recommended on iOS, given the battery life, privacy, and app review implications. I would appreciate any advice or guidance on how to implement this feature in a way that is efficient, secure, and compliant with Apple's guidelines. Are there any recommended APIs or frameworks for background audio processing and music recognition? What are the best practices for handling battery life and privacy concerns? Thank you in advance for your help.
Replies
0
Boosts
0
Views
697
Activity
Apr ’23
Shazam API
We would like to know what are the terms & conditions of using Shazam API for commercial use (calling it from our webservers)?
Replies
0
Boosts
0
Views
770
Activity
Mar ’23
Is there a minimum length of a sound sample for matching?
I haven't found this mentioned anywhere in the documentation: is there a minimum length of sound that can be matched by ShazamKit with a custom catalog? Is it possible to have it match a single spoken word?
Replies
2
Boosts
0
Views
896
Activity
Mar ’23