I have a problem tracing the underlying issue behind my asset export session failure. The issue is for one video only, and I believe the problem is in its audio track, since I successfully exported the asset without the audio track (only the video track).
The video track is decoded with AVAssetReader and the sample buffers are processed before being rewritten into a new video track; the audio track is passed with no decoding nor any intermediate processing. However, even without processing the video sample buffers, the same failure occurred.
I also tried doing it the other way round--with audio only and no video track--and still other videos worked just fine and this particular video failed. I suppose there's an inherent problem with the video's audio track, but I can't infer what the problem is, and hence I can't tackle it. Here's my code:
AVAssetExportSession* assetExport = [[AVAssetExportSession alloc] initWithAsset:composition
presetName:AVAssetExportPresetHighestQuality];
assetExport.outputFileType = #"com.apple.quicktime-movie";
assetExport.outputURL = [NSURL fileURLWithPath:path];
__weak typeof(self) weakSelf = self;
[assetExport exportAsynchronouslyWithCompletionHandler:^{
switch (assetExport.status) {
case AVAssetExportSessionStatusCompleted: NSLog(#"Asset combined");
break;
case AVAssetExportSessionStatusFailed: NSLog(#"Asset combination failed");
break;
default: NSLog(#"Asset combination completed with unknown status: %#", #(assetExport.status));
break;
}
}];
The problem is supposed to be in the asset export session; track insertion to the AVMutableComposition worked just fine. Here's the error message of the AVAssetExportSession:
Error Domain=AVFoundationErrorDomain Code=-11800 "The operation could not be completed"
UserInfo={NSUnderlyingError=0x6040001338d0 {Error Domain=NSOSStatusErrorDomain Code=-12780 "(null)"},
NSLocalizedFailureReason=An unknown error occurred (-12780), NSLocalizedDescription=The operation could not be completed}
I know this is an old question, but as it's not resolved, I will give the solution to error code 12780.
Most of the time the problem is the output URL.
Make sure that the URLis created like this:
URL(fileURLWithPath: "")
so for example:
let temp_output = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent("temp_exported.mov")
Wild guess: the audio track was separated from its owning AVAsset, which then went out of scope. Try keeping a reference to the audio track's AVAsset until you call exportAsynchronouslyWithCompletionHandler.
I spent about two days with this issue...
I didn't figure out the root cause, however, I found setting a audioMix to AVAssetExportSession worked.
AVMutableAudioMix *videoAudioMixTools = [AVMutableAudioMix audioMix];
AVMutableAudioMixInputParameters *firstAudioParam = [AVMutableAudioMixInputParameters audioMixInputParametersWithTrack:assetAudioTrack];
[firstAudioParam setVolumeRampFromStartVolume:1.0 toEndVolume:1.0 timeRange:CMTimeRangeMake(kCMTimeZero, CMTimeSubtract(endCropTime, startCropTime))];
[firstAudioParam setTrackID:compositionAudioTrack.trackID];
videoAudioMixTools.inputParameters = [NSArray arrayWithObject:firstAudioParam];
exportSession.audioMix = videoAudioMixTools;
It seems like that this forces to decode and re-encode audio track.
Related
All of my apps used to save directly to the Photos Album and that was it. Time for me to get with the times and start using a UIDocumentInteractionController.
I found dozens of examples and tutorials. Very few of them dealt with photos. But they all pretty much said the same thing.
If I send a photo anywhere except the Photos Album, no errors occur and it works. Saving to Photos Album, it generates the large message below but it still saves the image to the Photos Album. For some reason, the word Video is in the message when trying to save a PNG.
Every aspect of the code works, except for this ugly error message that only appears when saving to the Photos Album.
My concern is Apple rejecting my apps due to that error message.
Has anyone ever dealt with this before? Any help would be appreciated.
2018-10-27 19:50:40.085701-0400 TestImportandExport[28346:31506523] [Generic] Video /Users/xxxxxxxxxxxx/Library/Developer/CoreSimulator/Devices/C1A267C3-5261-47BB-B4EF-92D93254D8A1/data/Containers/Data/Application/7FCD6086-B523-44AE-824E-D0E23886BF45/Documents/TestImportandExport_Sample_Image.png cannot be saved to the photo library: Error Domain=AVFoundationErrorDomain Code=-11828 "Cannot Open" UserInfo={NSUnderlyingError=0x6000029525b0 {Error Domain=NSOSStatusErrorDomain Code=-12847 "(null)"}, NSLocalizedFailureReason=This media format is not supported., NSURL=file:///Users/xxxxxxxxxxxx/Library/Developer/CoreSimulator/Devices/C1A267C3-5261-47BB-B4EF-92D93254D8A1/data/Containers/Data/Application/7FCD6086-B523-44AE-824E-D0E23886BF45/Documents/TestImportandExport_Sample_Image.png, NSLocalizedDescription=Cannot Open}
Here is the code: ( I apologize for being an Objective-C dinosaur )
NSString *imagePath = [NSString stringWithFormat:#"%#/TestImportandExport_Sample_Image.png",[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject]];
[[NSFileManager defaultManager] removeItemAtPath:imagePath error:nil];
[UIImagePNGRepresentation(mainImage.image) writeToFile:imagePath atomically:YES];
documentInteractionController = [[UIDocumentInteractionController alloc] init];
documentInteractionController = [UIDocumentInteractionController interactionControllerWithURL:[NSURL fileURLWithPath:imagePath] ];
documentInteractionController.delegate = self;
documentInteractionController.name = #"TestImportandExport_Sample_Image.png";
[documentInteractionController presentOptionsMenuFromRect:sender.frame inView:self.view animated:NO];
I'm trying to merge a video and an audio together using AVAssetExportSession and AVMutableComposition. My code works for most of the cases(audio and video). But it fails for some videos. The failed videos are working fine with quicktime player and other players. The failed videos are failing when I simply exporting even without any audiomerging option(code given below).
[AVURLAsset assetWithURL:[NSURL fileURLWithPath:videoPath]];
AVAssetExportSession* _assetExport = [[AVAssetExportSession alloc] initWithAsset:videoAsset presetName:AVAssetExportPresetHighestQuality];
NSURL *exportUrl = [NSURL fileURLWithPath:exportPath];
if ([[NSFileManager defaultManager] fileExistsAtPath:exportPath])
{
[[NSFileManager defaultManager] removeItemAtPath:exportPath error:nil];
}
_assetExport.outputFileType = #"com.apple.quicktime-movie";
_assetExport.outputURL = exportUrl;
_assetExport.shouldOptimizeForNetworkUse = YES;
[_assetExport exportAsynchronouslyWithCompletionHandler:
^(void ) {
if (AVAssetExportSessionStatusCompleted == _assetExport.status) {
} else if (AVAssetExportSessionStatusFailed == _assetExport.status) {
NSLog(#"AVAssetExportSessionStatusFailed with error--%#", _assetExport.error);
}
}
];
And the error I got is the following..
Error Domain=AVFoundationErrorDomain Code=-11800 "The operation could not be completed" UserInfo={NSUnderlyingError=0x600000053aa0 {Error Domain=NSOSStatusErrorDomain Code=-12769 "(null)"}, NSLocalizedFailureReason=An unknown error occurred (-12769), NSLocalizedDescription=The operation could not be completed}
I'm not posting the full code for merging here because the above basic code even fails with the mentioned videos.
Any tips or hints with the error codes will be really helpful. Thanks in advance.
I resolved this problem by using the AVAssetExportPresetPassthrough export preset…
let exportSession = AVAssetExportSession(asset: composition, presetName: AVAssetExportPresetPassthrough)
This should use the resolution of the imported video in the exported file.
Check what codec used to compress that video first.
It seems that setting the export preset to "AVAssetExportPreset1280x720" for example, fixes the problem. But in my case I really need to keep the original resolution so that's not an option..
Thanks for reading my issue. :D
here is my question
i was using AVAudioRecorder to recording audio files as Vocal resources, aim to insert vocal to my video at different times.
But there is an error when i insert vocal to my vocal track (AVMutableCompositionTrack),and the error msg just tell me this
Error Domain=AVFoundationErrorDomain
Code=-11800
"The operation could not be completed"
UserInfo={NSUnderlyingError=0x137104220
{Error Domain=NSOSStatusErrorDomain Code=-12780 "(null)"},
NSLocalizedFailureReason=An unknown error occurred (-12780),
NSLocalizedDescription=The operation could not be completed}
when i was inserting vocal to my vocal track,i was using the same way just like inserting music track. here is my code of insert music track
/*this is my testing code of inserting music track to my video project*/
self.musicTrack = [self.projectComposition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:3];
NSString *file = [[NSBundle mainBundle] pathForResource:#"Lost!" ofType:#"mp3"];
NSURL *musicURL = [NSURL fileURLWithPath:file];
AVURLAsset *music = [AVURLAsset assetWithURL:musicURL];
AVAssetTrack *musicTrack = [music tracksWithMediaType:AVMediaTypeAudio].firstObject;
NSError *err;
[self.musicTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, CMTimeMakeWithSeconds(10, kCMTimeMaxTimescale)) ofTrack:musicTrack atTime:CMTimeMakeWithSeconds(0, kCMTimeMaxTimescale) error:&err];
[self.musicTrack insertTimeRange:CMTimeRangeMake(CMTimeMakeWithSeconds(15, kCMTimeMaxTimescale),
CMTimeMakeWithSeconds(5, kCMTimeMaxTimescale))
ofTrack:musicTrack
atTime:CMTimeMakeWithSeconds(20, kCMTimeMaxTimescale)
error:&err];
[self.musicTrack insertTimeRange:CMTimeRangeMake(CMTimeMakeWithSeconds(24, kCMTimeMaxTimescale),
CMTimeMakeWithSeconds(10, kCMTimeMaxTimescale))
ofTrack:musicTrack
atTime:CMTimeMakeWithSeconds(30, kCMTimeMaxTimescale)
error:&err];
[self.musicTrack insertTimeRange:CMTimeRangeMake(CMTimeMakeWithSeconds(0, kCMTimeMaxTimescale),
CMTimeMakeWithSeconds(10, kCMTimeMaxTimescale))
ofTrack:musicTrack
atTime:CMTimeMakeWithSeconds(45, kCMTimeMaxTimescale)
error:&err];
self.musicParameters = [AVMutableAudioMixInputParameters audioMixInputParametersWithTrack:self.musicTrack];
[self.musicParameters setVolume:.8f atTime:kCMTimeZero];
the code 👆 was worked just fine
and here is my code of inserting vocals
self.vocalTrack = [self.projectComposition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:4];
self.vocalParameters = [AVMutableAudioMixInputParameters audioMixInputParametersWithTrack:self.vocalTrack];
NSError *err;
for (NSInteger i = 0; i < self.vocalResourceArray.count; i++) {
RAGE_VocalModel * vm = self.vocalResourceArray[i];
[self.vocalTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, vm.vocal_Duration) ofTrack:vm.vocal_AssetTrack atTime:vm.vocal_StartTime error:&err];
/*error caught from here*/
if (err) {
[self.vocalTrack removeTimeRange:CMTimeRangeMake(kCMTimeZero, vm.vocal_Duration)];
NSLog(#"Error during insert vocal track\nerr:%#",err);
}
}
[self.vocalParameters setVolume:1.f atTime:kCMTimeZero];
and also i was using same code inserting my video's sound to target sound track,works fine.
so i was thinking there might be an issue when i recording my audio file maybe?something error of my audio format setting maybe?
here is my audio recording setting
NSString * rec_id = [NSString stringWithFormat:#"%zd",arc4random()];
NSURL *recordingFile = [NSURL fileURLWithPath:[[TARGET_DIR stringByAppendingPathComponent:#"Records"] stringByAppendingPathComponent:[NSString stringWithFormat:#"R%#.aac",rec_id]]];
NSDictionary *setting = #{
AVFormatIDKey : #(kAudioFormatMPEG4AAC),
AVSampleRateKey : #44100,
AVNumberOfChannelsKey : #1,
AVEncoderAudioQualityKey : #(AVAudioQualityHigh),
};
and i was recording audio by using this
self.recorder = [[AVAudioRecorder alloc]initWithURL:recordingFile settings:setting error:&err];
and...well.... works fine,no error caught.
anyway,i tried to check the audio file in sandbox,it's playable[on MAC OS / Windows].
any ideas about what's going on? this issue was caught me almost 2 months,still finding solution.
Update:
is it possible due to using block? i was formatting vocalModel using block handle
👇
[RAGE_VocalModel vocalModelWithURL:recorder.url withCompleteHandle:^(RAGE_VocalModel *model) {
model.vocal_StartTime = Recording_Temp_Start_Time;
Recording_Temp_Start_Time = kCMTimeZero;;
[self.vocalResourceArray addObject:model];
NSLog(#"thread = %zd",[NSThread currentThread]);
}];
that's remind me something when i was trying to insert music track,i was using enumerateByBlock to insert every source tracks to project tracks before,and caught the same error(well..possible not the exactly same,but still caught unknown error) during insert music track.
btw,music was in my app bundle for now,and vocal file is in sandbox.
i'll update my question as soon as i found more information.
UPDATE #2
it's not the block's fault ,i was tried to just using alloc-init then setting all the properties of my vocal model.same issue at same line.
here i found some solution about my issue to temporary solve this part of my issue
can not insert resource to track
what i found is ,it's might due to the audio file is not completed formatted , so i was just save the file URL in my vocal model, when i insert resource to my audio/sound/music track,i just load an temp AVURLAsset and pump out audio track,then insert to my AVMutableCompositionTrack , that's works pretty fine.
but i still believe it's might not the best solution of this issue.
wish could help.
So I've been trying to use AVAssetExportSession to trim a square video. But for some reason I just keep getting this error:
Error Domain=AVFoundationErrorDomain Code=-11800 "The operation could not be completed" UserInfo=0x1a03be70 {NSLocalizedDescription=The operation could not be completed, NSUnderlyingError=0x1a04c5e0 "The operation couldn’t be completed. (OSStatus error -12769.)", NSLocalizedFailureReason=An unknown error occurred (-12769)}
From Apple's website I found out that -11800 is an unknown error, but what about OSStatus error -12769? I searched everywhere on the internet and I had not seen any question/problem related to this error code. Please help. Thanks!
My code here:
AVAsset *asset = [[AVURLAsset alloc]initWithURL:self.originalVidUrl options:nil];
AVAssetTrack *clipVideoTrack = [[asset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0];
if (clipVideoTrack.naturalSize.width==clipVideoTrack.naturalSize.height) {
NSLog(#"Square video");
NSArray *presets = [AVAssetExportSession exportPresetsCompatibleWithAsset:asset];
if ([presets containsObject:AVAssetExportPresetHighestQuality]) {
self.exportSession = [[AVAssetExportSession alloc]initWithAsset:asset presetName:AVAssetExportPresetHighestQuality];
self.exportSession.outputURL = [NSURL fileURLWithPath: self.tmpVidPath];
self.exportSession.outputFileType = AVFileTypeMPEG4;
CMTime start = ...
CMTime duration = ...
CMTimeRange range = CMTimeRangeMake(start, duration);
self.exportSession.timeRange = range;
[self.exportSession exportAsynchronouslyWithCompletionHandler:^{
switch ([self.exportSession status]) {
case AVAssetExportSessionStatusFailed:
NSLog(#"%#",self.exportSession.error);
break;
case AVAssetExportSessionStatusCancelled:
NSLog(#"Export canceled");
break;
default:
NSLog(#"Export Success, File Saved.");
break;
}
}];
}
}
P.S. this code works for videos taken with the native camera app (i.e. non-square/non-processed videos).
I think I found the solution, but I have no idea why or how it worked.
Simply change the preset name from AVAssetExportPresetHighestQuality to AVAssetExportPreset1280x720, and you're good to go!
I've built an AVMutableComposition and VideoComposition from AVAssets and am able to play it. I am also able to export it using AVAssetExportSession, however AVAssetExportSession does not offer much control of the settings, so I'm exporting it using AVAssetReader/AVAssetWriter, but unfortunately I'm getting an error I don't understand and an only partially written output file.
Here is the code I have so far. I've left out the writer and as much other stuff as possible (including some error checking) that I think is irrelevant to make the code easier to read because it's a lot. Note that I haven't yet dealt with the audio track -- I'm trying to do this one step at a time, but maybe that's my problem?
The variable asset is the AVMutableComposition.
// ------- reader
_assetReader = [AVAssetReader assetReaderWithAsset:asset error:error];
_assetReader.timeRange = CMTimeRangeMake(kCMTimeZero, asset.duration);
_duration = asset.duration;
// --- video reader
NSArray *videoTracks = [asset tracksWithMediaType:AVMediaTypeVideo];
NSDictionary *videoOptions = [NSDictionary dictionaryWithObject:[NSNumber numberWithInt:kCVPixelFormatType_32BGRA] forKey:(id)kCVPixelBufferPixelFormatTypeKey];
_assetReaderOutput = [AVAssetReaderVideoCompositionOutput assetReaderVideoCompositionOutputWithVideoTracks:videoTracks
videoSettings:videoOptions];
((AVAssetReaderVideoCompositionOutput *)_assetReaderOutput).videoComposition = composition;
[_assetReader addOutput:_assetReaderOutput];
// -- leaving out the export settings and construction
// of the assetWriter since that doesn't seem to be the issue
// -- here's the actual export:
[self.assetWriter startWriting];
[self.assetWriter startSessionAtSourceTime:kCMTimeZero];
[self.assetReader startReading];
CMSampleBufferRef buffer;
while ( [self.assetReader status]==AVAssetReaderStatusReading )
{
if(![self.assetWriterInput isReadyForMoreMediaData])
continue;
buffer = [self.assetReaderOutput copyNextSampleBuffer];
NSLog(#"READING");
if(buffer)
[self.assetWriterInput appendSampleBuffer:buffer];
NSLog(#"WRITTING...");
}
if( self.assetReader.status == AVAssetReaderStatusFailed ) {
NSLog( #"%#", self.assetReader.error ); //<--------- I get a problem here
}
//Finish the session:
[self.assetWriterInput markAsFinished];
[self.assetWriter finishWriting];
NSLog(#"Write Ended");
The problem is the loop exits after a short time and I get this output:
Error Domain=AVFoundationErrorDomain Code=-11800 "The operation could not be completed" UserInfo=0x17f1dfa0 {NSLocalizedDescription=The operation could not be completed, NSUnderlyingError=0x191617f0 "The operation couldn’t be completed. (OSStatus error -308.)", NSLocalizedFailureReason=An unknown error occurred (-308)}
It seems I was following some bad sample code, rather than correct sample code provided by apple, which is pretty clear, if extremely verbose, about how to do this:
https://developer.apple.com/library/Mac/DOCUMENTATION/AudioVideo/Conceptual/AVFoundationPG/Articles/05_Export.html#//apple_ref/doc/uid/TP40010188-CH9-SW2
Although I've completely rewritten my code, I think the specific problem I was having was not calling CFRelease on my CMSampleBufferRef returned from [self.assetReaderOutput copyNextSampleBuffer]. You need to do that inside the loop.