- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
EXPORT STATUS 4 Error Domain=AVFoundationErrorDomain Code=-11820 "Cannot Complete Export" UserInfo={NSLocalizedDescription=Cannot Complete Export, NSLocalizedRecoverySuggestion=Try exporting again.}
尝试导出包含 AVMutableVideoCompositionLayerInstruction
的 AVMutableComposition
和使用 的
.AVMutableVideoComposition
时遇到间歇性错误AVAssetExportSession
目标是合并无限数量的视频并使用 layerInstructions 在剪辑之间应用过渡。
附言错误不一致。它在尝试合并 5 个剪辑和 18 个剪辑时有效,但在尝试合并 17 个剪辑时无效。
我已经在下面发布了我的代码。非常感谢任何帮助。
编辑:问题似乎与多个 AVMutableCompositionTrack(s) 的创建有关。如果创建超过 15 或 16 个,则会发生错误。但是,我认为创建多个 AVMutableCompositionTrack 是重叠所有视频和创建重叠过渡的必要条件。
编辑 2:选择较短的视频时,会在发生错误之前处理更多的视频。因此,它看起来像是一个内存问题,轨道正在被释放。但是,基于内存管理工具似乎没有内存泄漏。
-(void)prepareMutableCompositionForPlayback{
AVMutableComposition *mutableComposition = [[AVMutableComposition alloc] init];
AVMutableVideoCompositionInstruction *mainInstruction = [AVMutableVideoCompositionInstruction videoCompositionInstruction];
mainInstruction.backgroundColor = [[UIColor blackColor] CGColor];
NSMutableArray *instructionsArray = [[NSMutableArray alloc] init];
videoStartTime = kCMTimeZero;
for(int i = 0; i < videoAssetsArray.count; i++){
AVAsset *videoAsset = [videoAssetsArray objectAtIndex:i];
CMTime currentVideoDuration = [videoAsset duration];
AVMutableCompositionTrack *videoTrack = [mutableComposition addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid];
[videoTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, currentVideoDuration) ofTrack:[[videoAsset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0] atTime:videoStartTime error:nil];
CGSize videoSize = [videoTrack naturalSize];
if([videoAsset tracksWithMediaType:AVMediaTypeAudio].count > 0){
AVMutableCompositionTrack *audioTrack = [mutableComposition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];
[audioTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, currentVideoDuration) ofTrack:[[videoAsset tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0] atTime:videoStartTime error:nil];
}
//INSTRUCTIONS - TRANSITIONS
AVMutableVideoCompositionLayerInstruction *layerInstruction = [AVMutableVideoCompositionLayerInstruction videoCompositionLayerInstructionWithAssetTrack:videoTrack];
int transitionNumber = [[videoTransitionsArray objectAtIndex:i] intValue];
float transitionDuration = [[videoTransitionsDurationArray objectAtIndex:i] floatValue];
if(i == 0){
[layerInstruction setOpacityRampFromStartOpacity:1.0 toEndOpacity:0.0 timeRange:CMTimeRangeMake(CMTimeSubtract(currentVideoDuration, CMTimeMakeWithSeconds(transitionDuration, 600)), CMTimeMakeWithSeconds(transitionDuration, 600))];
}
else{
int previousTransitionNumber = [[videoTransitionsArray objectAtIndex:i - 1] intValue];
float previousTransitionDuration = [[videoTransitionsDurationArray objectAtIndex:i - 1] floatValue];
if(i < videoAssetsArray.count - 1){
[layerInstruction setOpacityRampFromStartOpacity:1.0 toEndOpacity:1.0 timeRange:CMTimeRangeMake(videoStartTime, CMTimeMakeWithSeconds(previousTransitionDuration, 600))];
[layerInstruction setOpacityRampFromStartOpacity:1.0 toEndOpacity:0.0 timeRange:CMTimeRangeMake(CMTimeAdd(videoStartTime, CMTimeSubtract(currentVideoDuration, CMTimeMakeWithSeconds(transitionDuration, 600))), CMTimeMakeWithSeconds(transitionDuration, 600))];
}
else{
[layerInstruction setOpacityRampFromStartOpacity:1.0 toEndOpacity:1.0 timeRange:CMTimeRangeMake(videoStartTime, CMTimeMakeWithSeconds(previousTransitionDuration, 600))];
}
}
[instructionsArray addObject:layerInstruction];
if(i < videoAssetsArray.count - 1){
//TAKING INTO ACCOUNT THE TRANSITION DURATION TO OVERLAP VIDEOS
videoStartTime = CMTimeAdd(videoStartTime, CMTimeSubtract(currentVideoDuration, CMTimeMakeWithSeconds(transitionDuration, 600)));
}
else{
//TRANSITION NOT APPLIED TO THE END OF THE LAST CLIP
videoStartTime = CMTimeAdd(videoStartTime, currentVideoDuration);
}
}
mainInstruction.timeRange = CMTimeRangeMake(kCMTimeZero,videoStartTime);
mainInstruction.layerInstructions = instructionsArray;
AVMutableVideoComposition *videoComposition = [AVMutableVideoComposition videoComposition];
videoComposition.instructions = [NSArray arrayWithObjects:mainInstruction,nil];
videoComposition.frameDuration = CMTimeMake(1, 30);
videoComposition.renderSize = CGSizeMake(1920, 1080);
NSArray* paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *videoOutputPath = [documentsDirectory stringByAppendingPathComponent:@"videoRecordingFinalOutput.mov"];
NSURL *videoOutputURL = [[NSURL alloc] initFileURLWithPath:videoOutputPath];
AVAssetExportSession *videoExportSession = [[AVAssetExportSession alloc] initWithAsset:mutableComposition presetName:AVAssetExportPresetHighestQuality];
videoExportSession.outputURL = videoOutputURL;
videoExportSession.videoComposition = videoComposition;
videoExportSession.outputFileType = AVFileTypeQuickTimeMovie;
[videoExportSession exportAsynchronouslyWithCompletionHandler:^{
NSLog(@"EXPORT STATUS %ld %@", (long)videoExportSession.status, videoExportSession.error);
if(videoExportSession.error == NULL){
NSLog(@"EXPORT SUCCESSFUL");
[library writeVideoAtPathToSavedPhotosAlbum:videoOutputURL
completionBlock:^(NSURL *assetURL, NSError *error) {
if(error) {
NSError *error = nil;
if([[NSFileManager defaultManager] fileExistsAtPath:videoOutputPath]){
[[NSFileManager defaultManager] removeItemAtPath:videoOutputPath error:&error];
if(error){
NSLog(@"VIDEO FILE DELETE FAILED");
}
else{
NSLog(@"VIDEO FILE DELETED");
}
}
}
else{
NSError *error = nil;
if([[NSFileManager defaultManager] fileExistsAtPath:videoOutputPath]){
[[NSFileManager defaultManager] removeItemAtPath:videoOutputPath error:&error];
if(error){
NSLog(@"VIDEO FILE DELETE FAILED");
}
else{
NSLog(@"VIDEO FILE DELETED");
}
}
}
}];
}
else{
NSError *error = nil;
if([[NSFileManager defaultManager] fileExistsAtPath:videoOutputPath]){
[[NSFileManager defaultManager] removeItemAtPath:videoOutputPath error:&error];
if(error){
NSLog(@"VIDEO FILE DELETE FAILED");
}
else{
NSLog(@"VIDEO FILE DELETED");
}
}
}
}];
}
最佳答案
与其为每个剪辑创建新的 videoTracks,不如尝试仅使用 2 个 videoTracks 并在这 2 个中插入 timeRanges。并在 2 个轨道之间进行过渡
所以第一个视频将被插入到 videoTrack1 中,第二个视频将被插入到 videoTrack2 中,这样就可以应用过渡,然后再次将第三个剪辑插入到轨道 1 中,依此类推。
关于ios - AVAssetExportSession 间歇性错误 11820 "Cannot Complete Export"Suggestion=再次尝试导出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35170799/
已结束。此问题正在寻求书籍、工具、软件库等的推荐。它不满足Stack Overflow guidelines 。目前不接受答案。 我们不允许提出寻求书籍、工具、软件库等推荐的问题。您可以编辑问题,以便
我的计算机上安装了 SE JDK 1.8.0_45。我希望编译器的源版本和目标版本都是 1.7。 我在 gradle 中做到了这一点,但我不知道如何在 IntelliJ IDEA 14.1.3(社区版
我正致力于根据以前成功搜索中使用的术语在我们的搜索应用程序(使用 Solr)中提供自动建议功能。在 Solr 建议文档 ( http://wiki.apache.org/solr/Suggester
我想过滤来自我的建议者的自动完成结果 假设我有一张书 table Table (Id Guid, BookName String, BookOwner id) 我希望每个用户都能从自己的书中获得一个自
你好 Stack Overflow 的人。我想就以下问题提出一些建议。我正在使用 Java。 我有一个包含多个字符串的数组#1。例如,其中两个字符串可能是:“一个苹果落在牛顿的头上”和“苹果长在树上”
当有人使用我的应用程序时,我想关闭在软/虚拟键盘上显示“建议的单词”(仅在某些 Activity 上)。对于默认的 Android 键盘,可以在“设置”下(在 Word Suggestion Sett
我正在尝试在 Solr 上使用自动完成功能,我找到的方法是使用 Solr Suggester .但是,它没有按预期工作。如果有人调用 http://localhost:8983/solr/techpr
Google建议如何工作?根据遥远的Google数据库中的信息,它如何快速地更新客户端上的网页?如果网页经常更新,为什么页面看起来不“跳动”? 最佳答案 它使用AJAX。 当您编写查询时,它会搜索与您
每当我运行 Build & Reload来自 RStudio 的 Build Pane ,我收到消息 ==> Rcmd.exe INSTALL --no-multiarch rwiots Err
几天来,我正在使用 NetBeans 6.8 进行 PHP 工作。 但是即使包含一个类文件并且方法是公共(public)的并且使用了 phpDoc,NetBeans 每次都会在窗口中显示“No Sug
我不知道我在这里使用的术语是否正确。然而,这就是我想要实现的目标,我想就如何实现这一目标提出一些建议。我想要一个可见边框的圆圈。现在这是困难的部分,我什至不知道如何开始。我想以这样一种方式来操纵圆圈,
我即将开发一个处理极其有值(value)的数据的应用程序。如果用户丢失这些数据,代价将非常高昂,因此我有兴趣了解更多有关满足我们需求的最佳架构设计的信息。 用户每天都会在 iPhone 中输入这些数据
wiki page of the Solr Suggester component没有提到如何搜索提供的字段?仅是前缀,还是也可以进行中缀搜索? 最佳答案 是的,支持。编辑你的 solrconfig.
我创建了一个新的 Azure 搜索建议器,但使用以下代码实现了模糊搜索: ISearchIndexClient indexClient = CreateSearchIndexClient(); var
是否可以让 Elasticsearch 完成建议程序按排序顺序返回结果?我正在遵循 this Elasticsearch blog post 中的示例并增加了额外的酒店: {"name": "Merc
我无法借助 search:suggest 函数提供这个简单的自动完成功能。 基于 Marklogic 演示数据中的奥斯卡语料库,我尝试提供一个建议查询,例如,即使用户当前正在写入“Robert Lo”
这是用 C 语言编写的 CGI 程序的一部分。当客户端单击链接时,我希望开始下载文件,并使用建议的默认文件名。 我知道规范明确指出 Content-disposition header 中指定的文件名
我正在尝试将谷歌建议链接到我的网站。我认为我正在使用的链接或我尝试读取文件的方式可能有问题。无论如何,这是我在我的 php 文件中使用的链接和代码 $filehandle=fopen("http://
我正在寻找一个不错的模板引擎或一小段代码来扩展 Java 字符串中类似 Ant 的变量。示例: String result = expand ("${firstName} ${familyName}"
关闭。这个问题是off-topic .它目前不接受答案。 想改进这个问题? Update the question所以它是on-topic对于堆栈溢出。 8年前关闭。 Improve this que
我是一名优秀的程序员,十分优秀!