Reputation: 9128
I would like to capture just audio and just video (without audio) while streaming a video from Web on my iOS application.
I have googled it but could not find one similar resource.
Is it possible at all?
Any pointers to some related resources?
Thanks.
Update:
Thanks for your answer Lyndsey. The solution seems to work.
I have another question. If I need to do this job to a portion of the video (like when the user clicks on Start Recording and Stop Recording) while playing (streaming) the video, how would you do that? Do you think it is also possible?
Upvotes: 0
Views: 276
Reputation: 37290
Pretty interesting question. Here's what I came up with:
As far as I know, you can't directly save the video stream playing from your MPMoviePlayerController
, but you can save the data as your video is streaming by using dataWithContentsOfURL:
. Then once the data is saved successfully, you can split it into video and/or audio components, 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");
}
}
}];
}
Upvotes: 1