dmrschmidt / DSWaveformImage

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

Wavefrom form Data in SwiftUI #66

Closed activcoding closed 1 year ago

activcoding commented 1 year ago

Hey,

Maybe I'm just stupid but is there a way to draw a Wave, from a AudioFile that is saved in a Data variable?

var data: Data
WaveformView(audioData: data)

I tried to write the data to a file that's on the device via data.write(to: ...). But that didn't work for me... I hope I didn't do something wrong🫣, thanks in advance.

dmrschmidt commented 1 year ago

Hey @activcoding,

so the short answer is: currently this isn't something that's available as a SwiftUI view directly. It is generally somewhat possible with this WaveformImageDrawer method to draw an image from a an array of Float samples.

But unfortunately that's also not directly usable for you, since what you currently have is "random audio data", that would first need to be unpacked into an actual stream of samples. This is done internally using AVAssetReader which does all the heavy lifting of the different audio encodings etc.

I've just done a quick & dirty SO search on how to get an AVAsset from Data and it seems the best way is to go through writing it to Disk.

That's what I'd have probably recommended in your case and that also seems to be the most direct way in general.

You mentioned you tried that but it didn't work. It definitely will work once the data has been written properly, as long as the audio data is something iOS can read out of the box. Generally speaking, once you wrote the data to disk and an AVPlayer can play it back, WaveformImage will be able to render it.

So long story short, I'd suggest your best way forward is to figure out why the writing to disk doesn't work. Is the format correct? Is the file maybe written with some important header information missing, so that AVFoundation doesn't know what format it is?

activcoding commented 1 year ago

Thank you @DMrschmidt, I'll try my best. I very much appreciate your detailed answer, you are a true gem for this community.

dmrschmidt commented 1 year ago

Appreciated :) Please free to re-open this or open another issue if there's something else I can help with in the library.

activcoding commented 1 year ago

Found the bug 🎉! In one of the examples in the readME an m4a file is used:

@State var audioURL = Bundle.main.url(forResource: "example_sound", withExtension: "m4a")!
WaveformView(audioURL: audioURL)

Yesterday I always tried it with a m4a file, but the app keep crashing... Today I just tried justing a mp3 file, it worked like magic.

dmrschmidt commented 1 year ago

Great to hear you’ve found the issue.

I’d be really curious to see what the issue with the file may have been. m4a should typically just work. Would it be possible for you to share the file that cause the crash here?

activcoding commented 1 year ago

Sure. The audio is from a pet project of me: AI-Voices with ElevenLabs Here are two audio files, the m4a is not playable and the mp3 is: But is seems the problem is on the server-side of ElevenLabs 🤦‍♂️, looks like they are sending broken m4a files...

dmrschmidt commented 1 year ago

Thanks for sharing! Just tried playing it and macOS definitely can't. Tried VLC and it played it. So I opened it in a hex editor, and checked the header bytes to see what format those say it is. Turns out its also just an mp3. If you rename it to mp3, that one also plays on macOS. VLC does a better job at trying to figure put what format files are in. AVFoundation seems to just look at the file ending. So that's that riddle solved :) Sounds like a bug on their end for sure then.