Can't play AVMutableComposition with sound - audio

I'm currently working on an iPhone App, that only plays the Audio Track of an .mp4. The Player starts playing, but I can't hear any sound.
Here is the Code:
NSURL *videoUrl = [NSURL URLWithString:#"http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4"];
AVMutableComposition* composition = [AVMutableComposition composition];
AVMutableCompositionTrack *track = [composition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];
AVURLAsset* videoAsset = [AVURLAsset URLAssetWithURL:videoUrl options:nil];
AVAssetTrack *audioTrack = [[videoAsset tracksWithMediaType:AVMediaTypeAudio]objectAtIndex:0];
NSError *error = nil;
BOOL success = [track insertTimeRange:CMTimeRangeMake(kCMTimeZero, videoAsset.duration) ofTrack:audioTrack atTime:kCMTimeZero error:&error];
if (!success)
{
NSLog(#"error: %#", error);
}
AVPlayerItem *playerItem = [AVPlayerItem playerItemWithAsset:composition];
self.player = [[AVPlayer alloc] initWithPlayerItem:playerItem];
[self.player play];

I had a similar problem and just found that AVFoundation is very unforgiving in how you format your composition. I eventually answered my own question - which was the same as your's here.
Check out my post:
iOS AVFoundation Export Session is missing audio

Related

iOS8 & xcode6 no longer plays sound

I'm having a problem that appeared after the big update to iOS 8 and XCode6.
When I try to play sound with AudioToolBox nothing comes out the speakers. I am using the simulator.
I have two variants of the function that plays the sound.
-(void)playSound:(NSString *)fileName
{
SystemSoundID soundEffet = [self soundEffect];
NSURL *soundURL = [[NSBundle mainBundle] URLForResource:fileName withExtension:#"mp3"];
NSString *URLString = [soundURL absoluteString];
if ([[NSFileManager defaultManager] fileExistsAtPath:URLString])
{
AudioServicesCreateSystemSoundID((__bridge CFURLRef)soundURL, &soundEffet);
AudioServicesPlaySystemSound(soundEffet);
} else {
NSLog(#"error, file not found: %#", fileName);
}
}
This fails the file exists at path check.
-(void)playSound:(NSString *)fileName
{
SystemSoundID soundEffet = [self soundEffect];
NSString *path = [[NSBundle mainBundle] pathForResource:fileName ofType:#"mp3"];
if ([[NSFileManager defaultManager] fileExistsAtPath:URLString])
{
NSURL *pathURL = [NSURL fileURLWithPath:path];
AudioServicesCreateSystemSoundID((__bridge CFURLRef)pathURL, &soundEffet);
AudioServicesPlaySystemSound(soundEffet);
} else {
NSLog(#"error, file not found: %#", fileName);
}
}
This one just doesn't play anything.
I am very sure that the file name that I am using is correct.
Does anyone have any ideas about what changed so that these no longer work? And most important: how do I fix this?
So I figured it out! (Cue the flailing kermit arms.) Reinhard Manner's comment is what pointed me in the right direction.
I did indeed end up using AVAudioPlayer. Here's what I ended up with.
-(void)playSound:(NSString *)fileName
{
NSString *soundFilePath = [[NSBundle mainBundle] pathForResource:fileName ofType: #"mp3"];
NSURL *fileURL = [[NSURL alloc] initFileURLWithPath:soundFilePath];
soundPlayer =[[AVAudioPlayer alloc] initWithContentsOfURL:fileURL error:nil];
if (soundPlayer != nil)
{
[soundPlayer play];
} else {
NSLog(#"could not play with file %#", fileName);
}
}
Not included here is the soundPlayer synthesized at the top of the file and made a a property in the .h file.
I still don't know why AudioToolbox stopped working. But this is what works, and I'm going with it.
Also, Reinhard Manner, you may want to post that type of thing as an answer next time, so that you can get more credit!

GPUImage saving video in background issue

I'm having an issue with saving video from a GPUImage videoCamera to the Camera Roll when my app goes into the background. The file is only saved to the camera roll when the app returns to the foreground / is restarted. I'm no doubt making a beginners code error , if anyone can point it out that would be appreciated.
- (void)applicationDidEnterBackground:(UIApplication *)application {
if (isRecording){
[self stopRecording];
};
if (self.isViewLoaded && self.view.window){
[videoCamera stopCameraCapture];
};
runSynchronouslyOnVideoProcessingQueue(^{
glFinish();
});
NSLog(#"applicationDidEnterBackground");
and then
-(void)stopRecording {
[filterBlend removeTarget:movieWriter];
videoCamera.audioEncodingTarget = nil;
[movieWriter finishRecording];
NSString *path = [NSTemporaryDirectory() stringByAppendingPathComponent:#"file.mov"];
ALAssetsLibrary *al = [[ALAssetsLibrary alloc] init];
[al writeVideoAtPathToSavedPhotosAlbum:[NSURL fileURLWithPath:path] completionBlock:^(NSURL *assetURL, NSError *error) {
if (error) {
NSLog(#"Error %#", error);
} else {
NSLog(#"Success");
}
}];
isRecording = NO;
NSLog(#"Stop recording");
It was exactly as Brad pointed out in his, as usual, insightful comment, the -writeVideoAtPathToSavedPhotosAlbum:completionBlock: wasn't completing till after the app returned to the foreground, I solved it by adding
self.backgroundTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
NSLog(#"Background handler called. Not running background tasks anymore.");
[[UIApplication sharedApplication] endBackgroundTask:self.backgroundTask];
self.backgroundTask = UIBackgroundTaskInvalid;
}];
and
#property (nonatomic) UIBackgroundTaskIdentifier backgroundTask;
Found this solution at http://www.raywenderlich.com/29948/backgrounding-for-ios

I can't seem to get audio to work in my app? I'm using AVAudio framework

Help guys :) I've tried absolutely everything to get the audio with AVAudioPlayer to work in my app. For some reason it will not play on the iPhone simulator. The code is as follows-
#import "ViewController.h"
#import "AVFoundation/AVFoundation.h"
#interface ViewController ()
{
AVAudioPlayer *avPlayer;
}
#end
#implementation ViewController
#synthesize myProgressView;
#synthesize sliderVolumeOutlet;
- (void)viewDidLoad
{
[super viewDidLoad];
NSString *stringPath = [[NSBundle mainBundle]pathForResource:#"audioapp" ofType:#"mp3"];
NSURL *url = [NSURL fileURLWithPath:stringPath];
NSError *error;
avPlayer = [[AVAudioPlayer alloc]initWithContentsOfURL:url error:&error];
[avPlayer setNumberOfLoops:1];
[avPlayer setVolume:self.sliderVolumeOutlet.value];
[NSTimer scheduledTimerWithTimeInterval:.1 target:self selector:#selector(updateProgress) userInfo:nil repeats:YES];
}
The song itself is in the project file, I really don't know what I'm doing wrong.
Check for the error and try it
-(IBAction) playAudio{
NSError *error;
NSURL *url = [NSURL fileURLWithPath:self.audioName];
audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:&error];
audioPlayer.delegate = self;
if (error)
NSLog(#"Error: %#", [error localizedDescription]);
else
[audioPlayer play];
}

Unable to do audio playback in background in iOS5 with AVQueuePlayer

I'm trying to build an app to play local music, but unfortunately, i'm unable to do audio playback in background in iOS5 with AVQueuePlayer.
In my ViewDidLoad, i got this code :
// Player setup
mAudioPlayer = [[AVQueuePlayer alloc] init];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(playerItemDidReachEnd:) name:AVPlayerItemDidPlayToEndTimeNotification object:nil];
[mAudioPlayer addPeriodicTimeObserverForInterval:CMTimeMakeWithSeconds(1.0, 1) queue:NULL usingBlock:^(CMTime time) {
[self updatePositionOnDisplay];
}];
// Audio session setup
NSError *setCategoryErr = nil;
NSError *activationErr = nil;
[[AVAudioSession sharedInstance] setCategory: AVAudioSessionCategoryPlayback error: &setCategoryErr];
[[AVAudioSession sharedInstance] setActive: YES error: &activationErr];
Here is my "playerItemDidReachEnd" method:
- (void)playerItemDidReachEnd:(NSNotification*)notification
{
NSLog(#"playerItemDidReachEnd");
UIBackgroundTaskIdentifier newTaskID = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
[[UIApplication sharedApplication] endBackgroundTask:newTaskID];
}];
NSLog(#"playerItemDidReachEnd 2");
NSLog(#"searching next song");
mCurrentSong = [self getNextSongWithIsSwitched:NO];
if(mCurrentSong != nil){
NSLog(#"Start : %# - %#", mCurrentSong.artist, mCurrentSong.title);
mTapeTitle.text = [NSString stringWithFormat:#"%# - %#", mCurrentSong.artist, mCurrentSong.title];
AVPlayerItem* i = [[AVPlayerItem alloc] initWithURL:[NSURL URLWithString:mCurrentSong.path]];
if(i != nil){
[mAudioPlayer insertItem:i afterItem:nil];
}else
NSLog(#"BING!! no AVPlayerItem created for song's path: %#", mCurrentSong.path);
[i release];
}else{
NSLog(#"no song found");
[mAudioPlayer pause];
isPlaying = NO;
[mPlayButton setSelected:NO];
}
[[UIApplication sharedApplication] endBackgroundTask:newTaskID];
newTaskID = UIBackgroundTaskInvalid;
}
When I start the playback, it works, and keep playing when i switch off the screen. BUT when the song is over, here are the logs
2012-03-01 10:00:27.342 DEMO[3096:707] playerItemDidReachEnd
2012-03-01 10:00:27.360 DEMO[3096:707] playerItemDidReachEnd 2
2012-03-01 10:00:27.363 DEMO[3096:707] searching next song
2012-03-01 10:00:27.381 DEMO[3096:707] Start : Moby - Ah-Ah
But no song start effectively...
Can anyone tell me what's wrong with my code ??
Thanks a lot.
try to comment next lines
[[UIApplication sharedApplication] endBackgroundTask:newTaskID];
newTaskID = UIBackgroundTaskInvalid;
if it works then you need to add an observer to a mAudioPlayer for "currentItem.status" when status AVPlayerStatusReadyToPlay then end background task

Find assets in library - add to a AVMutableComposition - export = crash

I've been struggling with adding assets from the iPhone Photo Library to a AVMutableComposition and then export them. Here is what I got:
Finding the assets: (here I grab the AVURLAsset)
-(void) findAssets {
ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
// Enumerate just the photos and videos group by using ALAssetsGroupSavedPhotos.
[library enumerateGroupsWithTypes:ALAssetsGroupSavedPhotos usingBlock:^(ALAssetsGroup *group, BOOL *stop) {
// Within the group enumeration block, filter to enumerate just videos.
[group setAssetsFilter:[ALAssetsFilter allVideos]];
[group enumerateAssetsUsingBlock:^(ALAsset *alAsset, NSUInteger index, BOOL *innerStop){
// The end of the enumeration is signaled by asset == nil.
if (alAsset) {
ALAssetRepresentation *representation = [alAsset defaultRepresentation];
NSURL *url = [representation url];
AVURLAsset *avAsset = [AVURLAsset URLAssetWithURL:url options:nil];
// Do something interesting with the AV asset.
[thumbs addObject:alAsset];
[assets addObject:avAsset];
}else if(alAsset == nil){
[self createScroll];
}
}];
}
failureBlock: ^(NSError *error) {
// Typically you should handle an error more gracefully than this.
NSLog(#"No groups");
}];
[library release];
}
Here I add a asset to my composition (I use the first object in the array for testing only.
-(void) addToCompositionWithAsset:(AVURLAsset*)_asset{
NSError *editError = nil;
composition = [AVMutableComposition composition];
AVURLAsset* sourceAsset = [assets objectAtIndex:0];
Float64 inSeconds = 1.0;
Float64 outSeconds = 2.0;
// calculate time
CMTime inTime = CMTimeMakeWithSeconds(inSeconds, 600);
CMTime outTime = CMTimeMakeWithSeconds(outSeconds, 600);
CMTime duration = CMTimeSubtract(outTime, inTime);
CMTimeRange editRange = CMTimeRangeMake(inTime, duration);
[composition insertTimeRange:editRange ofAsset:sourceAsset atTime:composition.duration error:&editError];
if (!editError) {
CMTimeGetSeconds (composition.duration);
}
}
And finally I export the comp and here it crashes
-(void)exportComposition {
AVAssetExportSession *exportSession = [[AVAssetExportSession alloc] initWithAsset:composition presetName:AVAssetExportPresetPassthrough];
NSLog (#"can export: %#", exportSession.supportedFileTypes);
NSArray *dirs = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectoryPath = [dirs objectAtIndex:0];
NSString *exportPath = [documentsDirectoryPath stringByAppendingPathComponent:EXPORT_NAME];
[[NSFileManager defaultManager] removeItemAtPath:exportPath error:nil];
NSURL *exportURL = [NSURL fileURLWithPath:exportPath];
exportSession.outputURL = exportURL;
exportSession.outputFileType = AVFileTypeQuickTimeMovie;//#"com.apple.quicktime-movie";
[exportSession exportAsynchronouslyWithCompletionHandler:^{
NSLog (#"i is in your block, exportin. status is %d",
exportSession.status);
switch (exportSession.status) {
case AVAssetExportSessionStatusFailed:
case AVAssetExportSessionStatusCompleted: {
[self performSelectorOnMainThread:#selector (exportDone:)
withObject:nil
waitUntilDone:NO];
break;
}
};
}];
}
Does anyone have an idea of what it might be? It crashes on
AVAssetExportSession *exportSession = [[AVAssetExportSession alloc] initWithAsset:composition presetName:AVAssetExportPresetPassthrough];
And I tried different presets and outputFileTypes.
Thanks
* SOLVED *
I have to answer my own question now when I have solved. It's amazing that I've been struggling with this for a whole day and then I fix it right after posting a question :)
I changed and moved:
composition = [AVMutableComposition
composition];
to:
composition = [[AVMutableComposition
alloc] init];
I think I was too tired when I was working on this yesterday. Thanks guys!

Resources