Search code examples
iosobjective-cfilepathnsurlavassetreader

AVAsset not recognising NSURL - Crashing - iOS


I am making an iOS app. One of its features is that it can save record and save audio files.

In order to save the URL's of the recorded audio files, I storing them in NSUserDefaults as filePaths like so:

file:///var/mobile/Containers/Data/Application/17F8E799-D7E1-4B3C-9DFE-7BA48E346314/Documents/recordName.aif

I am using a library called "FVSoundWaveDemo" to try and display a sound wave for the recorded file. But I have a problem with URL's...

The example in "FVSoundWaveDemo" loads a locally imported file like so:

NSString* filename = [NSString stringWithFormat:@"song1.m4a"];
NSURL* url = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:filename ofType:nil]];
_soundWaveView.soundURL = url;

You see the bit with "song1.m4a", well I want to replace that and get the app to use a filePath URL instead. Like the filePath URL I displayed above in my question.

I have tried all sort of things like trying to "convert" the filePath into a normal URL and trying to use AVAssets and so on. But everything I try just comes up with this error:

Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArrayM objectAtIndex:]: index 0 beyond bounds for empty array'

And this is because the library I am using, uses AVAssets like so:

AVAssetReader* reader = [[AVAssetReader alloc] initWithAsset:songAsset error:&error];

AVAssetTrack* songTrack = [songAsset.tracks objectAtIndex:0];

NSDictionary* outputSettingsDict = [[NSDictionary alloc] initWithObjectsAndKeys:
                                    [NSNumber numberWithInt:kAudioFormatLinearPCM],AVFormatIDKey,
                                    [NSNumber numberWithInt:1],AVNumberOfChannelsKey,
                                    [NSNumber numberWithInt:8],AVLinearPCMBitDepthKey,
                                    [NSNumber numberWithBool:NO],AVLinearPCMIsBigEndianKey,
                                    [NSNumber numberWithBool:NO],AVLinearPCMIsFloatKey,
                                    [NSNumber numberWithBool:NO],AVLinearPCMIsNonInterleaved,
                                    nil];

So how an earth do I get an AVAsset to just work with a filePath URL?

Remember I am trying to get it to view a recorded audio file saved by the app, NOT a locally imported audio file which a developer can add into the Xcode project.

I have been stuck on this for days now, if you can help me, that would be much appreciated, thanks.

Thanks for your time, Dan.


Solution

  • Figured it out in the end. I made the following changes to get it to work:

    1) I used fileURLWithPath instead of URLWithString like so:

    NSURL *assetURL = [NSURL fileURLWithPath:passURL];
    AVURLAsset *asset = [AVURLAsset assetWithURL:assetURL];
    

    2) Before when I was saving the audio file URL, I got it to save as a NSString like so:

    file:///var/mobile/Containers/Data/Application/17F8E799-D7E1-4B3C-9DFE-7BA48E346314/Documents/recordName.aif

    This doesn't work when you want to use something like AVPlayer. Instead you have to make sure you save the URL so that it does NOT include "file:///" bit at the start of the string. In order to do this, make sure you save the string path value and not an NSURL of the string path like so:

        NSArray *searchPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
        NSString *documentPath_ = [searchPaths objectAtIndex:0];
        NSString *pathToSave = [documentPath_ stringByAppendingPathComponent:@"audioName.aif"];
    

    Now save "pathToSave" NSString to wherever you want and use that when you want to load the file. Doing this will result in the audio file URL being saved like so:

    /var/mobile/Containers/Data/Application/45ABF4BD-FA0E-43F7-B936-7DE29D8F28ED/Documents/23Feb2015_074118pm.aif

    You see it doesn't have the "file:///" bit at the start. This string will now work with part 1 of this answer.

    Hope this helps anyone having similar issues to me.