如何在从 URL 流式传输视频时仅捕获音频或视频?

How to capture just the audio or video while streaming a video from a URL?

我想在 iOS 应用程序上从 Web 流式传输视频时仅捕获音频和视频(无音频)。

我用谷歌搜索了它,但找不到类似的资源。

有可能吗?

是否有一些相关资源的指针?

谢谢。

更新:
谢谢林赛的回答。该解决方案似乎有效。
我有另一个问题。如果我需要在播放(流式传输)视频时对视频的一部分执行此操作(例如当用户单击“开始录制”和“停止录制”时),您会怎么做?你觉得也可以吗?

非常有趣的问题。这是我想出的:

据我所知,您无法直接保存从您的 MPMoviePlayerController 播放的视频流,但您可以将数据 保存为 您的视频正在播放通过使用 dataWithContentsOfURL:。然后一旦数据保存成功,你就可以把它拆分成视频and/or音频组件,ex:

- (void)saveFullVideo {

    // Create a temporary file path to hold the
    // complete version of the video
    NSURL *tmpDirURL = [NSURL fileURLWithPath:NSTemporaryDirectory() isDirectory:YES];
    NSURL *fileURL = [[tmpDirURL URLByAppendingPathComponent:@"temp"]
       URLByAppendingPathExtension:@"mov"]; // <-- assuming the streaming video's a .mov file

    NSError *error = nil;
    NSData *urlData = [NSData dataWithContentsOfURL:streamingURL];
    [urlData writeToURL:fileURL options:NSAtomicWrite error:&error];

    // If the data is written to the temporary file path
    // successfully, split it into video and audio components
    if (!error) {
        [self saveVideoComponent:fileURL];
        [self saveAudioComponent:fileURL];
    }
}

- (void)saveVideoComponent:(NSURL*)videoUrl {

    AVURLAsset* videoAsset  = [[AVURLAsset alloc]initWithURL:videoUrl options:nil];

    AVMutableComposition *composition = [AVMutableComposition composition];

    // Create a mutable track of type video
    AVMutableCompositionTrack *videoCompositionTrack = [composition addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid];

    NSError *error = nil;

    // Get the video portion of the track and insert it
    // into the mutable video composition track
    AVAssetTrack *video = [[videoAsset tracksWithMediaType:AVMediaTypeVideo] firstObject];
    [videoCompositionTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, videoAsset.duration) ofTrack:video atTime:kCMTimeZero error:&error];

    // Create a session to export this composition
    AVAssetExportSession* assetExport = [[AVAssetExportSession alloc] initWithAsset:composition presetName:AVAssetExportPresetPassthrough];

    // Create the path to which you'll export the video
    NSString *docPath = [NSSearchPathForDirectoriesInDomains
                         (NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
    NSString *exportPath = [docPath stringByAppendingPathComponent:@"/video_path.mp4"];
    NSURL *exportUrl = [NSURL fileURLWithPath:exportPath];

    // Remove the old file at the export path if one exists
    if ([[NSFileManager defaultManager] fileExistsAtPath:exportPath])
    {
        [[NSFileManager defaultManager] removeItemAtPath:exportPath error:nil];
    }

    assetExport.outputFileType = AVFileTypeMPEG4;

    assetExport.outputURL = exportUrl;
    assetExport.shouldOptimizeForNetworkUse = YES;

    [assetExport exportAsynchronouslyWithCompletionHandler:
     ^(void )
     {
         switch (assetExport.status)
         {
             case AVAssetExportSessionStatusCompleted: {
                 NSLog(@"Video export Saved to path: %@", exportUrl);
                 break;
             } case AVAssetExportSessionStatusFailed: {
                 NSLog(@"Export Failed");
                 NSLog(@"ExportSessionError: %@", [assetExport.error localizedDescription]);
                 break;
             } case AVAssetExportSessionStatusCancelled: {
                 NSLog(@"Export Cancelled");
                 NSLog(@"ExportSessionError: %@", [assetExport.error localizedDescription]);
                 break;
             } default: {
                 NSLog(@"Export Default condition");
             }    
         }
     }];
}

- (void)saveAudioComponent:(NSURL*)videoUrl {

    AVURLAsset* videoAsset  = [[AVURLAsset alloc]initWithURL:videoUrl options:nil];

    AVMutableComposition *composition = [AVMutableComposition composition];

    // Create a mutable track of type audio
    AVMutableCompositionTrack *audioCompositionTrack = [composition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];

    NSError *error = nil;

    // Get the audio portion of the track and insert it
    // into the mutable audio composition track
    AVAssetTrack *audio = [[videoAsset tracksWithMediaType:AVMediaTypeAudio] firstObject];
    [audioCompositionTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, videoAsset.duration) ofTrack:audio atTime:kCMTimeZero error:&error];


    // Create a session to export this composition
    AVAssetExportSession* assetExport = [[AVAssetExportSession alloc] initWithAsset:composition presetName:AVAssetExportPresetPassthrough];

    // Create the path to which you'll export the audio
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory = [paths objectAtIndex:0];
    NSString *dataPath = [documentsDirectory stringByAppendingPathComponent:@"VideoFolder"];
    // Create folder if needed
    [[NSFileManager defaultManager] createDirectoryAtPath:dataPath withIntermediateDirectories:YES attributes:nil error:nil];

    NSString *exportPath = [dataPath stringByAppendingPathComponent:@"audio_path.caf"];
    NSURL *exportUrl = [NSURL fileURLWithPath:exportPath];

    // Remove the old file at the export path if one exists
    if ([[NSFileManager defaultManager] fileExistsAtPath:exportPath])
    {
        [[NSFileManager defaultManager] removeItemAtPath:exportPath error:nil];
    }

    assetExport.outputFileType = AVFileTypeCoreAudioFormat;

    assetExport.outputURL = exportUrl;
    assetExport.shouldOptimizeForNetworkUse = YES;

    [assetExport exportAsynchronouslyWithCompletionHandler:
     ^(void )
     {
         switch (assetExport.status)
         {
             case AVAssetExportSessionStatusCompleted: {
                 NSLog(@"Audio export Saved to path: %@", exportUrl);
                 //[self playAudio:exportUrl];
                 break;
             } case AVAssetExportSessionStatusFailed: {
                 NSLog(@"Export Failed");
                 NSLog(@"ExportSessionError: %@", [assetExport.error localizedDescription]);
                 break;
             } case AVAssetExportSessionStatusCancelled: {
                 NSLog(@"Export Cancelled");
                 NSLog(@"ExportSessionError: %@", [assetExport.error localizedDescription]);
                 break;
             } default: {
                 NSLog(@"Export Default condition");
             }
         }
     }];
}