You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

iOS17及以上版本AVMutableComposition insertTimeRange方法崩溃排查求助

iOS17+下AVMutableComposition insertTimeRange崩溃排查

崩溃现象

Firebase上报少量崩溃案例:调用AVMutableComposition的insertTimeRange:ofAsset:atTime:error:方法时,抛出-[__NSArrayM insertObject:atIndex:]: object cannot be nil异常,且多数发生在iOS17.0及以上版本。

用户实现代码:

- (AVMutableComposition *)createtrimAsset:(AVAsset *)asset
                             andStartTime:(CGFloat)startTime
                                  endTime:(CGFloat)endTime{

    NSError *error = nil;
    CGFloat timescale = 1000000;
    AVMutableComposition *mutableComposition = [AVMutableComposition composition];
    CMTime sStartTime = CMTimeMakeWithSeconds(CMTimeGetSeconds(asset.duration)*startTime, timescale);
    CMTime eEndTime = CMTimeMakeWithSeconds(CMTimeGetSeconds(asset.duration)*endTime, timescale);
    [mutableComposition insertTimeRange:CMTimeRangeMake(sStartTime, CMTimeSubtract(eEndTime, sStartTime)) ofAsset:asset atTime:kCMTimeZero error:&error];
    return mutableComposition;
}

用户已尝试设置asset=nil、asset.duration=0或NAN等场景,均未复现崩溃。

可能触发原因

  1. 时间范围合法性问题:若传入的startTime >= endTime,会导致计算出的时间范围时长为负或零;或时间范围超出asset的实际时长,iOS17的AVFoundation内部处理此类非法参数时,可能尝试插入nil对象到数组,引发崩溃。
  2. Asset未完全加载:同步获取asset.duration时,若asset是网络资源、iCloud资源或未完成加载的本地资源,CMTimeGetSeconds(asset.duration)可能返回无效值(如NAN),导致时间范围计算异常,触发内部逻辑崩溃。
  3. Asset的Track异常:asset本身有效,但内部无可用track(如损坏的视频文件、格式不兼容的资源),iOS17对这类场景的处理逻辑与旧版本不同,内部尝试添加nil track到数组时崩溃。
  4. iOS17 AVFoundation行为变更:iOS17对AVMutableComposition的参数校验逻辑更严格,某些在旧版本中仅返回error的非法操作,现在会直接触发内部崩溃。

排查建议

  • 校验时间范围合法性:
    添加前置判断,确保时间范围有效且未超出asset时长:

    if (startTime >= endTime) return nil;
    CMTime assetDuration = asset.duration;
    CGFloat assetDurationSec = CMTimeGetSeconds(assetDuration);
    if (isnan(assetDurationSec) || assetDurationSec <= 0) return nil;
    
    CMTime sStartTime = CMTimeMakeWithSeconds(assetDurationSec * startTime, timescale);
    CMTime eEndTime = CMTimeMakeWithSeconds(assetDurationSec * endTime, timescale);
    if (CMTimeCompare(sStartTime, assetDuration) >= 0 || CMTimeCompare(eEndTime, assetDuration) > 0) return nil;
    
    CMTime rangeDuration = CMTimeSubtract(eEndTime, sStartTime);
    if (CMTimeCompare(rangeDuration, kCMTimeZero) <= 0) return nil;
    
  • 异步加载Asset属性:
    避免同步读取未加载完成的asset属性,改用异步加载确保数据有效:

    [asset loadValuesAsynchronouslyForKeys:@[@"duration", @"tracks"] completionHandler:^{
        NSError *error = nil;
        AVKeyValueStatus durationStatus = [asset statusOfValueForKey:@"duration" error:&error];
        AVKeyValueStatus tracksStatus = [asset statusOfValueForKey:@"tracks" error:&error];
        
        if (durationStatus == AVKeyValueStatusLoaded && tracksStatus == AVKeyValueStatusLoaded && asset.tracks.count > 0) {
            // 在此执行trim逻辑
            AVMutableComposition *composition = [self createtrimAsset:asset andStartTime:startTime endTime:endTime];
            // 回调处理结果
        } else {
            // 处理加载失败或无track的情况
        }
    }];
    
  • 检查并处理Error:
    调用insertTimeRange后务必检查error参数,获取更多崩溃线索:

    BOOL success = [mutableComposition insertTimeRange:range ofAsset:asset atTime:kCMTimeZero error:&error];
    if (!success) {
        NSLog(@"Insert time range failed: %@", error);
        return nil;
    }
    
  • 测试特殊Asset场景:
    针对iOS17,测试以下场景是否能复现崩溃:

    • HEVC格式视频、Live Photo导出的视频资源
    • 未下载完成的iCloud视频
    • 损坏/不兼容格式的视频文件
    • 时长极短(如小于1秒)的视频
  • 校验Asset的Track状态:
    在调用insertTimeRange前,确保asset存在可用track:

    if (!asset || asset.tracks.count == 0) return nil;
    

内容的提问来源于stack exchange,提问作者yongfeng jin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 22:50:05