UIImagepickercontroller: converting to low quality video error - iphone

I am getting inputurl [info objectForKey:UIImagePickerControllerMediaURL] from UIImagepickercontroller's didFinishPickingMediaWithInfo's method.
NSURL *inputURL = [NSURL URLWithString:inputurlstring];
I am giving outputurl from this code
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *videoPath = [NSString stringWithFormat:#"%#/%#", documentsDirectory,#"capturedvideo.MOV"];
NSURL *outputURL = [NSURL fileURLWithPath:videoPath];
I used the following code to get low quality video
- (void)convertVideoToLowQuailtyWithInputURL:(NSURL*)inputURL
outputURL:(NSURL*)outputURL
handler:(void (^)(AVAssetExportSession*))handler
{
[[NSFileManager defaultManager] removeItemAtURL:outputURL error:nil];
AVURLAsset *asset = [AVURLAsset URLAssetWithURL:inputURL options:nil];
AVAssetExportSession *exportSession = [[AVAssetExportSession alloc] initWithAsset:asset presetName:AVAssetExportPresetLowQuality];
exportSession.outputURL = outputURL;
exportSession.outputFileType = AVFileTypeQuickTimeMovie;
[exportSession exportAsynchronouslyWithCompletionHandler:^(void)
{
if (exportSession.status == AVAssetExportSessionStatusCompleted)
{
printf("completed\n");
}
else
{
printf("error\n");
NSLog(#"error is %#",exportSession.error);
}
}];
}
I am getting following error when I use large files only. Because when I use small size video file I did not get any error.
Error Domain=NSURLErrorDomain Code=-1 "unknown error" UserInfo=0x616d890
{NSErrorFailingURLStringKey=/private/var/mobile/Applications/EE1E6701-EED0-4830-BD1D-7366680713C0/tmp//trim.7mL7VS.MOV, NSErrorFailingURLKey=/private/var/mobile/Applications/EE1E6701-EED0-4830-BD1D-7366680713C0/tmp//trim.7mL7VS.MOV, NSLocalizedDescription=unknown error, NSUnderlyingError=0x2d1460 "The operation couldn’t be completed. (OSStatus error -12935.)", NSURL=/private/var/mobile/Applications/EE1E6701-EED0-4830-BD1D-7366680713C0/tmp//trim.7mL7VS.MOV}

the above code is perfectly works. the only change is inputURL.
after I changed the inputURL to fileURLWithPath:
NSURL *inputURL = [NSURL fileURLWithPath:inputurlstring];
Now its perfectly works.

Instead of this
[info objectForKey:UIImagePickerControllerMediaURL];
use
NSURL *imageURL = [info valueForKey:UIImagePickerControllerReferenceURL];
AVAssetLibrary can access your video through its reference url only.

Related

AVAssetExportSession outputfile

How should the AVAssetExportSession output file look like? I'm trying to compress a video from an ALAsset item and it doesn't work. I'm guessing the output file has something to do with it.
Here's the code i'm using:
NSString *destinationPath = [NSHomeDirectory() stringByAppendingPathComponent:#"Documents/Movie"];
[self convertVideoToLowQualityWithInputURL:asset.defaultRepresentation.url outputURL:[NSURL URLWithString:destinationPath]];
- (void)convertVideoToLowQualityWithInputURL:(NSURL*)inputURL outputURL:(NSURL*)outputURL {
if([[NSFileManager defaultManager] fileExistsAtPath:[NSString stringWithContentsOfURL:outputURL encoding: 0 error:Nil]]) [[NSFileManager defaultManager] removeItemAtURL:outputURL error:nil];
AVURLAsset *assetAV = [AVURLAsset URLAssetWithURL:inputURL options:nil];
NSLog(#"url string from asset: %#", assetAV.URL);
NSLog(#"output url: %#", [outputURL absoluteString]);
[[NSFileManager defaultManager] createFileAtPath:[outputURL path] contents:nil attributes:nil];
NSLog(#"duration: %lld", assetAV.duration.value); //it logs a valid value, so it's all good so far
AVAssetExportSession *exportSession = [[AVAssetExportSession alloc] initWithAsset:assetAV presetName:AVAssetExportPresetLowQuality];
exportSession.outputURL = outputURL;
exportSession.outputFileType = AVFileTypeQuickTimeMovie;
[exportSession exportAsynchronouslyWithCompletionHandler:^(void) {
if (exportSession.status == AVAssetExportSessionStatusCompleted) {
NSLog(#"success");
} else {
NSLog(#"error: %#", [exportSession error]);
//error: Error Domain=AVFoundationErrorDomain Code=-11800 "The operation could not be completed" UserInfo=0x2023b720 {NSLocalizedDescription=The operation could not be completed, NSUnderlyingError=0x2023bb70 "The operation couldn’t be completed. (OSStatus error -12780.)", NSLocalizedFailureReason=An unknown error occurred (-12780)}
}
}];
}
Can someone please help me?
UPDATE:
Found the solution. As I thought the problem was the output file so here is the code for generating a valid one:
NSUInteger count = 0;
NSString *filePath = nil;
do {
NSString *extension = ( NSString *)UTTypeCopyPreferredTagWithClass(( CFStringRef)AVFileTypeQuickTimeMovie, kUTTagClassFilenameExtension);
NSString *fileNameNoExtension = [[asset.defaultRepresentation.url URLByDeletingPathExtension] lastPathComponent];
NSString *fileName = [NSString stringWithFormat:#"%#-%#-%u",fileNameNoExtension , AVAssetExportPresetLowQuality, count];
filePath = NSTemporaryDirectory();
filePath = [filePath stringByAppendingPathComponent:fileName];
filePath = [filePath stringByAppendingPathExtension:extension];
count++;
} while ([[NSFileManager defaultManager] fileExistsAtPath:filePath]);
NSURL *outputURL = [NSURL fileURLWithPath:filePath];
Your issue is [NSURL URLWithString:destinationPath] and only that. You need to use [NSURL fileURLWithPath:xxx] like you did in your solution. Posting this just to clarify that that is the only problem.

Not getting resulted movie in PhotoLibrary iPad

i am creating a movie with an array of images and a audio file and saving that created movie to photo library, in simulator i am getting correct movie with my array of image and audio file but while running in device i am not getting my resulted movie instead i am getting the video what i added(OutPut.mov i used in my code) to write my output file (mixed audio and array of images file).
here is my code to save my mixed audio and array of images file to photo lib:
AVMutableComposition* mixComposition = [AVMutableComposition composition];
NSString* audio_inputFilePath = [[NSBundle mainBundle] pathForResource:#"Ruler" ofType:#"caf"];
NSURL* audio_inputFileUrl = [NSURL fileURLWithPath:audio_inputFilePath];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = ([paths count] > 0) ? [paths objectAtIndex:0] : nil;
NSString *video_inputFilePath = [documentsDirectory stringByAppendingPathComponent:#"videoOutput1234videoOutput1234.mp4"];
NSLog(#"output url %#",video_inputFilePath);
NSURL* video_inputFileUrl = [NSURL fileURLWithPath:video_inputFilePath];
NSString* outputFilePath = [[NSBundle mainBundle] pathForResource:#"OutPut" ofType:#"mov"];
NSURL* outputFileUrl = [NSURL fileURLWithPath:outputFilePath];
if ([[NSFileManager defaultManager] fileExistsAtPath:outputFilePath])
[[NSFileManager defaultManager] removeItemAtPath:outputFilePath error:nil];
if ([[NSFileManager defaultManager] fileExistsAtPath:outputFilePath])
[[NSFileManager defaultManager] removeItemAtPath:outputFilePath error:nil];
CMTime nextClipStartTime = kCMTimeZero;
AVURLAsset* videoAsset = [[AVURLAsset alloc]initWithURL:video_inputFileUrl options:nil];
CMTimeRange video_timeRange = CMTimeRangeMake(kCMTimeZero,videoAsset.duration);
AVMutableCompositionTrack *a_compositionVideoTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid];
[a_compositionVideoTrack insertTimeRange:video_timeRange ofTrack:[[videoAsset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0] atTime:nextClipStartTime error:nil];
AVURLAsset* audioAsset = [[AVURLAsset alloc]initWithURL:audio_inputFileUrl options:nil];
CMTimeRange audio_timeRange = CMTimeRangeMake(kCMTimeZero, audioAsset.duration);
AVMutableCompositionTrack *b_compositionAudioTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];
[b_compositionAudioTrack insertTimeRange:audio_timeRange ofTrack:[[audioAsset tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0] atTime:nextClipStartTime error:nil];
AVAssetExportSession* _assetExport = [[AVAssetExportSession alloc] initWithAsset:mixComposition presetName:AVAssetExportPresetHighestQuality];
_assetExport.outputFileType = #"com.apple.quicktime-movie";
_assetExport.outputURL = outputFileUrl;
[_assetExport exportAsynchronouslyWithCompletionHandler:^(void ) {[self saveVideoToAlbum:outputFilePath]; } ];
You have to write the video file into the photolibrary path like..
- (void)writeVideoToPhotoLibrary:(NSURL *)url
{
ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
[library writeVideoAtPathToSavedPhotosAlbum:url completionBlock:^(NSURL *assetURL, NSError *error){
if (error) {
NSLog(#"Video could not be saved");
}
}];
[library release];
}
- (void)video:(NSString *)videoPath didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo {
// Let's see what happened
NSLog(#"finished");
NSLog(#":error : %#", error);
}

iOS 5.0 AVAudioPlayer Error loading audio clip: The operation couldn’t be completed. (OSStatus error -50.)

So I'm trying to test out the audio player on the iPhone, and I went off Troy Brant's iOS book. I have the Core Audio, Core Foundation, AudioToolbox, and AVFoundation frameworks added to my project. The error message I get is in the subject field. I read like 20 pages of Google search results before resorting to asking here! /sigh. Thanks if you can help. Here's my code, pretty much verbatim out of his book:
NSString *soundFilePath = [[NSBundle mainBundle] pathForResource:#"Yonah" ofType:#"caf"];
NSLog(#"%#", soundFilePath);
NSURL *fileURL = [NSURL URLWithString:soundFilePath];
NSError *error;
audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:fileURL error:&error];
if (!error)
{
audioPlayer.delegate = self;
//audioPlayer.numberOfLoops = -1;
[audioPlayer play];
}
else
{
NSLog(#"Error loading audio clip: %#", [error localizedDescription]);
}
EDIT: Holy Shinto. I figured out what it was. I changed
NSURL *fileURL = [NSURL URLWithString:soundFilePath];
to
NSURL *fileURL = [NSURL fileURLWithPath:soundFilePath];
to the latter and I was getting a weird error, weirder than the one in the subject BUT I googled that and I changed my OS input device from my webcam to my internal microphone and guess what, it worked under the fileURLWithPath method. I'll be. Damned.
try this one- convert your url into NSdata
NSString* resourcePath = self.audioStr; //your url
NSData *_objectData = [NSData dataWithContentsOfURL:[NSURL URLWithString:resourcePath]];
NSError *error = [[NSError alloc] init];
NSLog(#"url is %#",resourcePath);
audioPlayer = [[AVAudioPlayer alloc] initWithData:_objectData error:&error];
audioPlayer.numberOfLoops = 0;
if (error)
{
NSLog(#"Error in audioPlayer: %#",
[error localizedDescription]);
} else {
audioPlayer.delegate = self;
[audioPlayer prepareToPlay];
}`
Try to read the audio file with something like this:
audioPlayer_ = [[AVAudioPlayer alloc] initWithContentsOfURL:
[NSURL fileURLWithPath:[NSString stringWithString:soundFilePath_]]
error:&error];

How to concatenate 2 or 3 audio files in iOS?

I am newcomer in Objective-C and have experience only 5 months in iPhone development.
What I need:
I need to concatenate 2 or more audio files into one, and export result as aiff, mp3, caf or m4a format.
For example:
First audio file containing "You need", second "download" and third "document".
Every audio part depends on actions from user.
I spent 2 days without luck. That place is my last frontier.
I will very appreciate for a piece of code.
Code below can be used to merge audio files.
Input files: Ids of the files to be supplied in array audioIds.
Eg. audio1.mp3, audio2.mp3 … audioN.mp3 to be available in documents folder
Output file: combined.m4a
- (BOOL) combineVoices {
NSError *error = nil;
BOOL ok = NO;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
CMTime nextClipStartTime = kCMTimeZero;
//Create AVMutableComposition Object.This object will hold our multiple AVMutableCompositionTrack.
AVMutableComposition *composition = [[AVMutableComposition alloc] init];
AVMutableCompositionTrack *compositionAudioTrack = [composition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];
for (int i = 0; i< [self.audioIds count]; i++) {
int key = [[self.audioIds objectAtIndex:i] intValue];
NSString *audioFileName = [NSString stringWithFormat:#"audio%d", key];
//Build the filename with path
NSString *soundOne = [documentsDirectory stringByAppendingPathComponent:[NSString stringWithFormat:#"%#.mp3", audioFileName]];
//NSLog(#"voice file - %#",soundOne);
NSURL *url = [NSURL fileURLWithPath:soundOne];
AVAsset *avAsset = [AVURLAsset URLAssetWithURL:url options:nil];
NSArray *tracks = [avAsset tracksWithMediaType:AVMediaTypeAudio];
if ([tracks count] == 0)
return NO;
CMTimeRange timeRangeInAsset = CMTimeRangeMake(kCMTimeZero, [avAsset duration]);
AVAssetTrack *clipAudioTrack = [[avAsset tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0];
ok = [compositionAudioTrack insertTimeRange:timeRangeInAsset ofTrack:clipAudioTrack atTime:nextClipStartTime error:&error];
if (!ok) {
NSLog(#"Current Video Track Error: %#",error);
}
nextClipStartTime = CMTimeAdd(nextClipStartTime, timeRangeInAsset.duration);
}
// create the export session
// no need for a retain here, the session will be retained by the
// completion handler since it is referenced there
AVAssetExportSession *exportSession = [AVAssetExportSession
exportSessionWithAsset:composition
presetName:AVAssetExportPresetAppleM4A];
if (nil == exportSession) return NO;
NSString *soundOneNew = [documentsDirectory stringByAppendingPathComponent:#"combined.m4a"];
//NSLog(#"Output file path - %#",soundOneNew);
// configure export session output with all our parameters
exportSession.outputURL = [NSURL fileURLWithPath:soundOneNew]; // output path
exportSession.outputFileType = AVFileTypeAppleM4A; // output file type
// perform the export
[exportSession exportAsynchronouslyWithCompletionHandler:^{
if (AVAssetExportSessionStatusCompleted == exportSession.status) {
NSLog(#"AVAssetExportSessionStatusCompleted");
} else if (AVAssetExportSessionStatusFailed == exportSession.status) {
// a failure may happen because of an event out of your control
// for example, an interruption like a phone call comming in
// make sure and handle this case appropriately
NSLog(#"AVAssetExportSessionStatusFailed");
} else {
NSLog(#"Export Session Status: %d", exportSession.status);
}
}];
return YES;
}
You can use this method to merge 3 sounds together.
- (BOOL) combineVoices1
{
NSError *error = nil;
BOOL ok = NO;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
CMTime nextClipStartTime = kCMTimeZero;
//Create AVMutableComposition Object.This object will hold our multiple AVMutableCompositionTrack.
AVMutableComposition *composition = [[AVMutableComposition alloc] init];
AVMutableCompositionTrack *compositionAudioTrack = [composition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];
[compositionAudioTrack setPreferredVolume:0.8];
NSString *soundOne =[[NSBundle mainBundle]pathForResource:#"test1" ofType:#"caf"];
NSURL *url = [NSURL fileURLWithPath:soundOne];
AVAsset *avAsset = [AVURLAsset URLAssetWithURL:url options:nil];
NSArray *tracks = [avAsset tracksWithMediaType:AVMediaTypeAudio];
AVAssetTrack *clipAudioTrack = [[avAsset tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0];
[compositionAudioTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, avAsset.duration) ofTrack:clipAudioTrack atTime:kCMTimeZero error:nil];
AVMutableCompositionTrack *compositionAudioTrack1 = [composition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];
[compositionAudioTrack setPreferredVolume:0.3];
NSString *soundOne1 =[[NSBundle mainBundle]pathForResource:#"test" ofType:#"caf"];
NSURL *url1 = [NSURL fileURLWithPath:soundOne1];
AVAsset *avAsset1 = [AVURLAsset URLAssetWithURL:url1 options:nil];
NSArray *tracks1 = [avAsset1 tracksWithMediaType:AVMediaTypeAudio];
AVAssetTrack *clipAudioTrack1 = [[avAsset1 tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0];
[compositionAudioTrack1 insertTimeRange:CMTimeRangeMake(kCMTimeZero, avAsset.duration) ofTrack:clipAudioTrack1 atTime:kCMTimeZero error:nil];
AVMutableCompositionTrack *compositionAudioTrack2 = [composition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];
[compositionAudioTrack2 setPreferredVolume:1.0];
NSString *soundOne2 =[[NSBundle mainBundle]pathForResource:#"song" ofType:#"caf"];
NSURL *url2 = [NSURL fileURLWithPath:soundOne2];
AVAsset *avAsset2 = [AVURLAsset URLAssetWithURL:url2 options:nil];
NSArray *tracks2 = [avAsset2 tracksWithMediaType:AVMediaTypeAudio];
AVAssetTrack *clipAudioTrack2 = [[avAsset2 tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0];
[compositionAudioTrack1 insertTimeRange:CMTimeRangeMake(kCMTimeZero, avAsset2.duration) ofTrack:clipAudioTrack2 atTime:kCMTimeZero error:nil];
AVAssetExportSession *exportSession = [AVAssetExportSession
exportSessionWithAsset:composition
presetName:AVAssetExportPresetAppleM4A];
if (nil == exportSession) return NO;
NSString *soundOneNew = [documentsDirectory stringByAppendingPathComponent:#"combined10.m4a"];
//NSLog(#"Output file path - %#",soundOneNew);
// configure export session output with all our parameters
exportSession.outputURL = [NSURL fileURLWithPath:soundOneNew]; // output path
exportSession.outputFileType = AVFileTypeAppleM4A; // output file type
// perform the export
[exportSession exportAsynchronouslyWithCompletionHandler:^{
if (AVAssetExportSessionStatusCompleted == exportSession.status) {
NSLog(#"AVAssetExportSessionStatusCompleted");
} else if (AVAssetExportSessionStatusFailed == exportSession.status) {
// a failure may happen because of an event out of your control
// for example, an interruption like a phone call comming in
// make sure and handle this case appropriately
NSLog(#"AVAssetExportSessionStatusFailed");
} else {
NSLog(#"Export Session Status: %d", exportSession.status);
}
}];
return YES;
}
You should probably look into this post for doing the same:
Combine two audio files into one in objective c
The answer is similar to what Dimitar has suggested. But 2 important things that you have to keep in mind are that, first - it works only for mp3 format and second the bit-rate of all the files that you are trying to concatenate should be same, or else only parts of your file would play in the final output. It would stop playing where the bit rate changes.
SSteve- Files like Wav files have their own headers and if you just write one file after another, It would play just the first file and would then stop playing, inspite that the file info showing a greater file size. this is because we do not have information updated into the header of the first file.
I have taken two diffrent mp3 files from AVMutableCompositionTrack. and these two mp3 files are stored in same AVMutableComposition.
when i will press the button the path of new mp3 will be shown by console.
-(IBAction)play
{
[self mixAudio];
}
-(void)mixAudio
{
CFAbsoluteTime currentTime=CFAbsoluteTimeGetCurrent();
AVMutableComposition *composition = [[AVMutableComposition alloc] init];
AVMutableCompositionTrack *compositionAudioTrack = [composition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];
[compositionAudioTrack setPreferredVolume:0.8];
NSString *soundOne =[[NSBundle mainBundle]pathForResource:#"KICK1" ofType:#"mp3"];
NSURL *url = [NSURL fileURLWithPath:soundOne];
AVAsset *avAsset = [AVURLAsset URLAssetWithURL:url options:nil];
NSArray *tracks = [avAsset tracksWithMediaType:AVMediaTypeAudio];
AVAssetTrack *clipAudioTrack = [tracks objectAtIndex:0];
[compositionAudioTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, avAsset.duration) ofTrack:clipAudioTrack atTime:kCMTimeZero error:nil];
AVMutableCompositionTrack *compositionAudioTrack1 = [composition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];
[compositionAudioTrack setPreferredVolume:0.8];
NSString *soundOne1 =[[NSBundle mainBundle]pathForResource:#"KICK2" ofType:#"mp3"];
NSURL *url1 = [NSURL fileURLWithPath:soundOne1];
AVAsset *avAsset1 = [AVURLAsset URLAssetWithURL:url1 options:nil];
NSArray *tracks1 = [avAsset1 tracksWithMediaType:AVMediaTypeAudio];
AVAssetTrack *clipAudioTrack1 = [tracks1 objectAtIndex:0];
[compositionAudioTrack1 insertTimeRange:CMTimeRangeMake(kCMTimeZero, avAsset1.duration) ofTrack:clipAudioTrack1 atTime: kCMTimeZero error:nil];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES);
NSString *libraryCachesDirectory = [paths objectAtIndex:0];
NSString *strOutputFilePath = [libraryCachesDirectory stringByAppendingPathComponent:#"output.mov"];
NSString *requiredOutputPath = [libraryCachesDirectory stringByAppendingPathComponent:#"output.m4a"];
NSURL *audioFileOutput = [NSURL fileURLWithPath:requiredOutputPath];
[[NSFileManager defaultManager] removeItemAtURL:audioFileOutput error:NULL];
AVAssetExportSession *exporter=[[AVAssetExportSession alloc] initWithAsset:composition presetName:AVAssetExportPresetAppleM4A];
exporter.outputURL=audioFileOutput;
exporter.outputFileType=AVFileTypeAppleM4A;
[exporter exportAsynchronouslyWithCompletionHandler:^{
NSLog(#" OUtput path is \n %#", requiredOutputPath);
NSFileManager * fm = [[NSFileManager alloc] init];
[fm moveItemAtPath:strOutputFilePath toPath:requiredOutputPath error:nil];
NSLog(#" OUtput path is \n %#", requiredOutputPath);
NSLog(#"export complete: %lf",CFAbsoluteTimeGetCurrent()-currentTime);
NSError *error;
audioPlayer=[[AVAudioPlayer alloc]initWithContentsOfURL:audioFileOutput error:&error];
audioPlayer.numberOfLoops=0;
[audioPlayer play];
}];
}
Have you tried something like this:
AudioFileCreateWithURL //to create the output file
For each input file:
AudioFileOpenURL //open file
repeat
AudioFileReadBytes //read from input file
AudioFileWriteBytes //write to output file
until eof(input file)
AudioFileClose //close input file
AudioFileClose //close output file
This would probably require that the input files are all the same format and would create the output file in that same format. If you need to convert the format, that might be better done after creating the output file.
The easiest way to implement multiple combinations of aac:
- (NSString *)concatenatedAACVoicesPath{
NSMutableData *concatenatedData = [[NSMutableData alloc] init];
NSArray *aacPathArr = [self queryAAC];
for (NSString *path in aacPathArr) {
NSData *data = [[NSData alloc] initWithContentsOfFile:path];
[concatenatedData appendData: data];
}
NSString *fileNamePath = [NSString stringWithFormat:#"%#/%#.aac",[NSString createPath:currRecordDocName],currRecordDocName];
[concatenatedData writeToFile:fileNamePath atomically:YES];
return fileNamePath;
}
I have an idea, not sure it will work. Try to get NSData from these 3 files, append the data into another NSData and then write it. Something like:
NSMutableData *concatenatedData = [NSMutableData alloc] init];
NSData *data1 = [[NSData alloc] initWithContentsOfFile:(NSString *)path];
NSData *data2 = [[NSData alloc] initWithContentsOfFile:(NSString *)path];
NSData *data3 = [[NSData alloc] initWithContentsOfFile:(NSString *)path];
[concatenatedData appendData: data1];
[concatenatedData appendData: data2];
[concatenatedData appendData: data3];
[concatenatedData writeToFile:#"/path/to/concatenatedData.mp3" atomically:YES];
It's a theory I'm not sure it will work :), it actually works if i open an mp3 with hex editor - copy everything and paste it in the end - then I have the same sound twice. Please try it and let us know if it works.

AVAudioPlayer with external URL to *.m4p

My Problem is the following. I got this code and i guess a corrupt NSURL since the AVAudioPlayer is nil after initializing:
NSString *dummyURLString = #"http://a825.phobos.apple.com/us/r2000/005/Music/d8/a8/d2/mzi.jelhjoev.aac.p.m4p";
NSError *error;
NSURL *url = [NSURL URLWithString:dummyURLString];
AVAudioPlayer *player = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:&error];
[player play];
Any suggestions what is going wrong here?
The &error shows this:
Error Domain=NSOSStatusErrorDomain Code=-43 "Operation could not be completed. (OSStatus error -43.)"
AVAudioPlayer only works with local URL's. It must be a File URL (file://)
See Apple's Technical Q&A QA1634
I tried this first but got error 2003334207:
NSData *soundData = [NSData dataWithContentsOfURL:URL];
AVAudioPlayer *player = [[AVAudioPlayer alloc] initWithData:soundData error:&error];
Seems that AVAudioPlayer really wants a file. So I put the data into a file first:
NSURL *url = [NSURL URLWithString:#"http://a825.phobos.apple.com/us/r2000/005/Music/d8/a8/d2/mzi.jelhjoev.aac.p.m4p"];
NSData *soundData = [NSData dataWithContentsOfURL:url];
NSString *filePath = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
NSUserDomainMask, YES) objectAtIndex:0]
stringByAppendingPathComponent:#"sound.caf"];
[soundData writeToFile:filePath atomically:YES];
player = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL
fileURLWithPath:filePath] error:NULL];
NSLog(#"error %#", error);
Instead of using the AVAudioPlayer you can use the AVPlayer. The AVPlayer works as well with remote URLs