dmrschmidt / DSWaveformImage

Generate waveform images from audio files on iOS, macOS & visionOS in Swift. Native SwiftUI & UIKit views.
MIT License
1.07k stars 114 forks source link

-11800 Error code when generation samples on iOS 17 beta #75

Closed ogrodowski-tomasz closed 1 year ago

ogrodowski-tomasz commented 1 year ago

Hello, i have a problem with iOS 17 beta.

When generating samples in waveformSamples method, status of assetReader changes to .failed with error description:

(String) "Error Domain=AVFoundationErrorDomain Code=-11800 \"The operation could not be completed\" UserInfo={NSLocalizedFailureReason=An unknown error occurred (-12849), NSLocalizedDescription=The operation could not be completed, NSUnderlyingError=0x2804dee20 {Error Domain=NSOSStatusErrorDomain Code=-12849 \"(null)\"}}"

When i'm on device that runs iOS 16, everything works fine. Above error is very informative as -11800 is "unknown" error. When i try to play this audio file it works fine. There is only problem with audiowave generator.

In my app i have to generate audiowaves for a couple of audiofiles. There are no differences between AVAssetReader etc. objects when i generate those waves and yet, some of them works fine, some of them does not.

I can provide you with more information. Just tell me what do you want me to provide. I don't even know where to look for source of problem anymore.

dmrschmidt commented 1 year ago

Hmm... So one thing that could be helpful here, is trying to set a breakpoint and catch the original NSUnderlyingError. I've googled for code -12849 but didn't find anything. If you could see where this originates from, that might give some hint.

One common theme that came up when googling for the outer error, -11800, though is that it may be that the file is not readily available yet, because it is offloaded to iCloud and has not yet been downloaded to the device. Can you make sure that this 100% not the case in your instance? I've seen people run into this trap all the time.

So one thing to try out whether this is something relating to downloading etc would be to bundle the file when compiling the app and the loading it from the bundle. If it also fails in that case, it must be sth with the library / the file format. If it works, then the error sits somewhere else. Which is what I am expecting atm.

dmrschmidt commented 1 year ago

@ogrodowski-tomasz is this still an issue?

itcmarcinrabieko commented 1 year ago

@dmrschmidt yes, we still facing the same issue. We can't do anything on our side to change the result on iOS17.

I created example project to let you debug it on your own. It's very simple, one view controller with base64 that's converting to .mp3 and then we are using the file to create waveform image.

Here you are ViewController implementation. You just need to create empty project in Xcode and overwrite default ViewController.

https://gist.github.com/itcmarcinrabieko/1e36f9ba3e379d854bd339e9e3ca37ea

This code behaves completely differently on iOS 15/16 and on iOS17. On iOS 15/16 we are getting proper image:

Player item:<AVPlayerItem: 0x281604d30, asset = <AVURLAsset: 0x281422f20, URL = file:///var/mobile/Containers/Data/Application/FC2D1277-EDE2-4D0F-9771-E4CE4740BA64/Documents/voicemail.mp3>>
Ready to play
Image:Optional(<UIImage:0x28260d950 anonymous {200, 50} renderingMode=automatic>)

On iOS17 it's:

Player item:<AVPlayerItem: 0x282fa1000, asset = <AVURLAsset: 0x282d964c0, URL = file:///var/mobile/Containers/Data/Application/C1F4597D-D7BF-4C58-955E-78AD87DC4D1D/Documents/voicemail.mp3>>
Ready to play
ERROR: reading waveform audio data has failed AVAssetReaderStatus(rawValue: 3)
Image:nil

I'm sure there is an issue in your implementation around

guard let nextSampleBuffer = trackOutput.copyNextSampleBuffer(),

because in case there is no more samples to buffer asset reader throw an error and became .failed.

dmrschmidt commented 1 year ago

Hey @ogrodowski-tomasz,

thanks a lot for providing the sample code. I have tried it out now on Xcode 15.0 beta 8 (15A5229m), running on an iPhone 14 Simulator with iOS 17. I've also experimented changing the Deployment target to iOS 17 (and ran it on iOS 14).

I still cannot reproduce the issue. My output looks like your working output:

Screenshot 2023-09-13 at 12 07 02

And the waveform is being rendered:

Simulator Screenshot - iPhone 14 - 2023-09-13 at 12 06 11

(it's distored because I just did minimal effort integration, to not change you sample code in any way, other than using the generated image).

You can run the sample code in the branch https://github.com/dmrschmidt/DSWaveformImage/tree/issue-75

It would be very helpful if you could run it there and let me know if you still experience the same issue.

itcmarcinrabieko commented 1 year ago

Hi, @dmrschmidt

thanks for your response and the effort to replicate it on your end.

I downloaded your project with my applied changes but unfortunately it doesn't work for me.

objc[54563]: Class NEDiagnosticReport is implemented in both /Library/Developer/CoreSimulator/Volumes/iOS_21A5291g/Library/Developer/CoreSimulator/Profiles/Runtimes/iOS 17.0.simruntime/Contents/Resources/RuntimeRoot/usr/lib/libnetworkextension.dylib (0x1229cd030) and /Library/Developer/CoreSimulator/Volumes/iOS_21A5291g/Library/Developer/CoreSimulator/Profiles/Runtimes/iOS 17.0.simruntime/Contents/Resources/RuntimeRoot/System/Library/Frameworks/NetworkExtension.framework/NetworkExtension (0x127d17228). One of the two will be used. Which one is undefined.
Player item:<AVPlayerItem: 0x600003cfcf90, asset = <AVURLAsset: 0x600003eb4820, URL = file:///Users/marcinrabieko/Library/Developer/CoreSimulator/Devices/71338935-6246-488A-B6B9-1C66FB813595/data/Containers/Data/Application/1A03F370-1E64-469D-8F4A-E894A1315BB0/Documents/voicemail.mp3>>
<<<< AVAsset >>>> +[AVURLAsset _getFigAssetCreationOptionsFromURLAssetInitializationOptions:assetLoggingIdentifier:figAssetCreationFlags:error:]: AVURLAssetHTTPHeaderFieldsKey must be a dictionary
<<<< Async >>>> playerasync_runAsynchronousCommandOnQueue: Command 26 returned -12 784; this async error will be discarded
<<< FFR_Common >>> FigFormatReaderCreateForStreamReturningResults signalled err=-12 873 (instantiation.firstFailedAttempt.error) (Error creating FormatReader) at FigFormatReader_Common.c:3 616
<<<< AVError >>>> AVLocalizedErrorWithUnderlyingOSStatus: Returning error (AVFoundationErrorDomain / -11 849) status (-12 873)
2
<<<< AVError >>>> AVLocalizedErrorWithUnderlyingOSStatus: Returning error (AVFoundationErrorDomain / -11 849) status (-12 873)
<<<< Async >>>> playerasync_runAsynchronousCommandOnQueue: Command 26 returned -12 784; this async error will be discarded
<<<< AVError >>>> AVLocalizedErrorWithUnderlyingOSStatus: Returning error (AVFoundationErrorDomain / -11 849) status (-12 873)

AVPlayerItem.Status is .failed when I want to observe status. It's not possible to have two different results on the same code. I suppose it's issue with beta configurations.

I installed it on my iPhone, too but I got previous result:

Player item:<AVPlayerItem: 0x281b7d730, asset = <AVURLAsset: 0x28192ca00, URL = file:///var/mobile/Containers/Data/Application/30D105AB-B8C2-45DA-8B35-4AC63A4D5EDB/Documents/voicemail.mp3>>
Ready to play
ERROR: reading waveform audio data has failed AVAssetReaderStatus(rawValue: 3)
Image:nil

It's interesting the same code working for you. Couple of times I was experiencing unexplained issues during beta/new versions of macOS especially.

I want to ask what simulator iOS, Xcode and macOS version did you use?

Mine:

Xcode 15.0 beta 5 (15A5209g) macOS Ventura 13.5. Simulator Zrzut ekranu 2023-09-13 o 12 49 15 Command Line Tools Zrzut ekranu 2023-09-13 o 12 55 02

Do you find any differences?

dmrschmidt commented 1 year ago

I have been testing it on Xcode 15.0 beta 8 (15A5229m), so a newer version than you. So given the beta status, at this point I'd assume it may be an issue with the older beta 5 that you're using.

I just checked https://xcodereleases.com/ and the RC 1 is already out now. So I'll download that one now and check with this one. I'd suggest you try the same.

FWIW I'm on Ventura 13.5.2, so also a slightly newer version. And I could only try on the iOS 17 Simulator, as I don't currently have iOS 17 installed on my phone. If the issue persists for you even on the latest Xcode RC 1, I can get the iOS 17 RC installed on my phone and test there. But I'd want to wait installing a pre-release iOS on my phone otherwise and wait till the 18th. (I've been burned in the past by iOS beta versions on my personal device)

itcmarcinrabieko commented 1 year ago

Hi @dmrschmidt,

I updated Xcode to release candidates, the same as command line tools and simulators. Also, I updated macOS to the newest. On simulator iOS17 it's working very well, the same as on iOS 15 and 16. Unfortunately, it doesn't work on iPhone 12 and iPhone 11, both iOS17 (21A329).

I wonder what is the issue. Maybe you will meet the same results on your iPhone.

dmrschmidt commented 1 year ago

So I've checked this now on my iPhone 13 mini after installing the iOS 17 RC. Cannot replicate the error either. Neither can I replicate it on a simulator for iPhone 11 or 12.

I've done a bit of googling on the 2 errors in the log you provided. There's one that I'm not sure where it would even be coming from, the first one, AVURLAssetHTTPHeaderFieldsKey must be a dictionary. Coincidentally however, I did stumble across this forum thread here https://developer.apple.com/forums/thread/734743 which talks about iOS 17 and being reproducible on device. So while that thread is talking about something slightly different, it might indicate an issue with AVFoundation in some cases.

The other, part of the error message, FigFormatReaderCreateForStreamReturningResults may indicate that something with the file's format may be an issue. Can you confirm whether this happens with all files, or only this one in particular? It could also be an issue with a specific application used to encode the mp3 for instance.

Looking at the resulting waveform, the file looks like it is just silence. Where is it from?

itcmarcinrabieko commented 1 year ago

@dmrschmidt thanks for your work, we appreciate it so much.

The issue on our side was related with saving audio file in wrong way. Previously, we were saving .wav file directly from Data based on base64 String what was not acceptable by Apple.

We decided to do that more properly. We used FFmpegKit (https://github.com/arthenica/ffmpeg-kit) with following command:

let command = String(format: "-y -i \(wavFileURL) -c:a libmp3lame -q:a 2 \(mp3FileURL)")

And it started to work, finally. File with .mp3 extension was properly saved in document path:

var documentsPath: URL? { try? FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false) }

Anyway, it was quite confusing it was not working on our devices and it was working on your devices. Strange, but.. it's Apple :D

dmrschmidt commented 1 year ago

I'm happy to hear you've found the issue. And thanks for reporting back on this. Appreciate it :)