Iphone 使用AvasseTrader从远程资源读取(流)

Iphone 使用AvasseTrader从远程资源读取(流),iphone,objective-c,ios,video-streaming,avfoundation,Iphone,Objective C,Ios,Video Streaming,Avfoundation,我的主要目标是从服务器流式传输视频,并在流式传输时逐帧剪切视频(以便OpenGL可以使用它)。为此,我使用了在互联网上随处可见的代码(我记得它来自苹果的GLVideoFrame示例代码): 但是我总是在[[Avassetrader alloc]initWithAsset:error://上得到这个异常 NSInvalidArgumentException -- *** -[AVAssetReader initWithAsset:error:] Cannot initialize an insta

我的主要目标是从服务器流式传输视频,并在流式传输时逐帧剪切视频(以便OpenGL可以使用它)。为此,我使用了在互联网上随处可见的代码(我记得它来自苹果的GLVideoFrame示例代码):

但是我总是在
[[Avassetrader alloc]initWithAsset:error://上得到这个异常

NSInvalidArgumentException -- *** -[AVAssetReader initWithAsset:error:] Cannot initialize an instance of AVAssetReader with an asset at non-local URL 'http://devimages.apple.com/iphone/samples/bipbop/bipbopall.m3u8'
所以我的两个问题是:

  • 异常是否真的告诉我,
    avassetrader
    必须有一个本地URL?它可以用于流媒体吗(就像其他
    AVFoundation
    类一样)
  • 如果
    AVFoundation
    方法不起作用,还有什么其他建议可以同时对视频流和帧进行分割

  • 非常感谢您的帮助。

    与所使用的文件或协议的种类相比,AVFoundation似乎并不能区分本地文件和非本地文件。使用mp4/mov与通过m3u8使用HTTP实时流媒体协议之间有着非常明显的区别,但使用本地或远程mp4的区别有点模糊

    要扩展上述内容,请执行以下操作:

    a) 如果您的“远程”资产是一个M3U8(也就是说,您正在使用HTTP“实时”流媒体),那么没有任何机会。无论M3U8是在本地文件系统中还是在远程服务器上,由于多种原因,Avassetrader和所有与AVAsset相关的功能都无法工作<代码>但是,AVPlayer、AVPlayerItem等可以正常工作。

    b) 如果是MP4/MOV,则需要进一步调查<代码>本地MP4/MOV的工作完美无瑕。在远程MP4/MOV的情况下,我能够创建(或从AVPlayerItem、AVPlayer或AVAssetTracks中检索)一个AVURLAsset,有时我可以使用它成功初始化Avassetrader(我也将在“有时”上展开,很快)。但是,在远程MP4的情况下,
    copyNextSampleBuffer始终返回nil。由于在调用copyNextSampleBuffer之前有几件事是有效的,因此我不能100%确定:

    i) 在所有其他步骤成功后,copyNextSampleBuffer不适用于远程mp4,这是预期/预期的功能

    ii)远程MP4的“其他步骤”似乎完全起作用,这是苹果实施的一个意外,当我们点击copyNextSampleBuffer时,这种不兼容性就凸显了出来…………这些“其他步骤”是什么,我将很快详细介绍

    iii)尝试为远程MP4调用copyNextSampleBuffer时出错

    所以@Paula你可以试着用远程MOV/MP4做进一步的调查

    以下是我尝试从视频中捕获帧的方法供参考:

    (a)

    直接从视频URL创建AVURLAsset

    使用[asset Tracks SwithMediaType:AVMediaTypeVideo]检索视频曲目

    使用视频曲目作为源,准备AvasseTraderTrack输出

    使用AVURLAsset创建AvasseTrader

    将AVAssetReaderTrackOutput添加到AVAssetReader并开始踩踏

    使用copyNextSampleBuffer检索图像

    (b)

    从视频URL创建AVPlayerItem,然后从中创建AVPlayer(或直接从URL创建AVPlayer)

    检索AVPlayer的“资产”属性,并使用“LoadValuesAsSynchronousLyForkeys:”加载其“曲目”

    分离AVMediaTypeVideo类型的曲目(或在加载曲目后在资源上调用tracksWithMediaType:即可),并使用视频曲目创建AvasseTraderTrackOutput

    使用AVPlayer的“资源”、“startReading”创建AvasseTrader,然后使用copyNextSampleBuffer检索图像

    (c)

    直接从视频URL创建AVPlayerItem+AVPlayer或AVPlayer

    KVO AVPlayerItem的“tracks”属性,加载曲目后,分离AVMediaTypeVideo类型的AVAssetTracks

    从AVPlayerItem/AVPlayer/AVAssetTrack的“资产”属性检索AVAsset

    其余步骤与方法(b)类似

    (d)

    直接从视频URL创建AVPlayerItem+AVPlayer或AVPlayer

    KVO AVPlayerItem的“tracks”属性,加载曲目后,将AVMediaTypeVideo类型的曲目分开

    创建AVMutableComposition,并初始化AVMediaTypeVideo类型的关联AVMutableCompositionTrack

    将先前检索到的视频曲目中的相应CMTimeRange插入此AVMutableCompositionTrack

    与(b)和(c)类似,现在创建AvasseTrader和AvasseTraderTrackOutput,但不同之处在于使用AVMutableComposition作为初始化AvasseTrader的基础AVAsset,使用AVMutableCompositionTrack作为AvasseTraderTrackOutput的基础AVAssetTrack

    “startReading”并使用copyNextSampleBuffer从AvasseTrader获取帧

    附言:我在这里尝试了方法(d)来回避这样一个事实,即直接从AVPlayerItem或AVPlayer检索的AVAsset没有运行。因此,我想从我手中已有的Avassetracks中创建一个新的AVAsset。诚然,这本书很粗糙,而且可能毫无意义(如果不是原始的AVAsset,那么最终还能从哪里检索到曲目信息呢!),但无论如何,这本书还是值得一试。

    以下是不同类型文件的结果摘要:

    1) 本地MOV/MP4-所有4种方法都能完美工作

    2) 远程MOV/MP4–在进近(b)到(d)中正确检索资产和轨迹,并且Avassetrader也已初始化,但copyNextSampleBuffer始终返回零。中科院
    NSInvalidArgumentException -- *** -[AVAssetReader initWithAsset:error:] Cannot initialize an instance of AVAssetReader with an asset at non-local URL 'http://devimages.apple.com/iphone/samples/bipbop/bipbopall.m3u8'
    
    AVURLAsset* soundTrackAsset = [[AVURLAsset alloc]initWithURL:[NSURL URLWithString:@"http://www.yoururl.com/yourfile.mp3"] options:nil];
    
    AVMutableCompositionTrack *compositionAudioSoundTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];
    [compositionAudioSoundTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, audioAsset.duration) 
                                   ofTrack:[[soundTrackAsset tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0] 
                                    atTime:kCMTimeZero error:nil];