以 mp4 格式录制、保存和/或转换视频?
Posted
技术标签:
【中文标题】以 mp4 格式录制、保存和/或转换视频?【英文标题】:Record, save and/or convert video in mp4 format? 【发布时间】:2013-12-15 11:13:55 【问题描述】:我有以下问题 - 我正在尝试创建一个录制视频的应用程序,然后将其保存到相机胶卷,然后我将该视频上传到网络。问题是唯一支持的格式是“mp4”,但我的视频是“mov”。
所以我的问题是如何将相机中的视频保存为“mp4”格式,或者将其保存为“mov”,然后将其转换为“mp4”。
这是我的代码:
这就是我打开相机的方式:
picker = [[UIImagePickerController alloc] init];
picker.sourceType = UIImagePickerControllerSourceTypeCamera;
picker.delegate = self;
picker.showsCameraControls = YES;
picker.allowsEditing = YES;
picker.mediaTypes = [[NSArray alloc] initWithObjects: (NSString *) kUTTypeMovie, nil];
[self presentViewController:picker animated:YES completion:nil];
这就是我保存视频的方式:
NSString *mediaType = [info objectForKey: UIImagePickerControllerMediaType];
if (CFStringCompare ((__bridge_retained CFStringRef) mediaType, kUTTypeMovie, 0) == kCFCompareEqualTo)
NSString *moviePath = [[info objectForKey:UIImagePickerControllerMediaURL] path];
videoURL = info[UIImagePickerControllerMediaURL];
if (UIVideoAtPathIsCompatibleWithSavedPhotosAlbum(moviePath))
UISaveVideoAtPathToSavedPhotosAlbum(moviePath, self, nil, nil);
[nextScreenButton setTitle:@"ПРОДЪЛЖИ" forState:UIControlStateNormal];
[self dismissViewControllerAnimated:YES completion:nil];
提前致谢!
【问题讨论】:
【参考方案1】:在 Swift 中将视频转换为 mp4 的 Swift 5 代码
首先你需要导入这个
import AVFoundation
然后您可以编写此代码并将 URL 传递给它。
func videoConvert(videoURL: URL)
let avAsset = AVURLAsset(url: videoURL as URL, options: nil)
let startDate = NSDate()
//Create Export session
let exportSession = AVAssetExportSession(asset: avAsset, presetName: AVAssetExportPresetPassthrough)
// exportSession = AVAssetExportSession(asset: composition, presetName: mp4Quality)
//Creating temp path to save the converted video
let documentsDirectory = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0]
let myDocumentPath = NSURL(fileURLWithPath: documentsDirectory).appendingPathComponent("temp.mp4")?.absoluteString
let url = NSURL(fileURLWithPath: myDocumentPath!)
let documentsDirectory2 = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0] as NSURL
let filePath = documentsDirectory2.appendingPathComponent("VideoConvert.mp4")
deleteFile(filePath: filePath!)
//Check if the file already exists then remove the previous file
if FileManager.default.fileExists(atPath: myDocumentPath!)
do
try FileManager.default.removeItem(atPath: myDocumentPath!)
catch let error
print(error)
//URL
print(filePath!.absoluteString)
exportSession!.outputURL = filePath
exportSession!.outputFileType = AVFileType.mp4
exportSession!.shouldOptimizeForNetworkUse = true
let start = CMTimeMakeWithSeconds(0.0, preferredTimescale: 0)
let range = CMTimeRangeMake(start: start, duration: avAsset.duration)
exportSession!.timeRange = range
exportSession!.exportAsynchronously(completionHandler: () -> Void in
switch exportSession!.status
case .failed:
print("%@",exportSession!.error ?? "Failed to get error")
case .cancelled:
print("Export canceled")
case .completed:
//Video conversion finished
let endDate = NSDate()
let time = endDate.timeIntervalSince(startDate as Date)
print(time)
print("Successful!")
print(exportSession!.outputURL)
default:
break
)
为了调用你可以使用的函数
videoConvert(videoURL: fileUrl!)
或
self.videoConvert(videoURL: fileUrl!)
然后您将转换视频并存储到名为 VideoConvert.mp4
的 document 目录中感谢@Jigar Thakkar 的回答。
【讨论】:
【参考方案2】:这里是将mov视频快速转换为mp4的代码
func encodeVideo(videoURL: NSURL)
let avAsset = AVURLAsset(URL: videoURL, options: nil)
var startDate = NSDate()
//Create Export session
exportSession = AVAssetExportSession(asset: avAsset, presetName: AVAssetExportPresetPassthrough)
// exportSession = AVAssetExportSession(asset: composition, presetName: mp4Quality)
//Creating temp path to save the converted video
let documentsDirectory = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0]
let myDocumentPath = NSURL(fileURLWithPath: documentsDirectory).URLByAppendingPathComponent("temp.mp4").absoluteString
let url = NSURL(fileURLWithPath: myDocumentPath)
let documentsDirectory2 = NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask)[0] as NSURL
let filePath = documentsDirectory2.URLByAppendingPathComponent("rendered-Video.mp4")
deleteFile(filePath)
//Check if the file already exists then remove the previous file
if NSFileManager.defaultManager().fileExistsAtPath(myDocumentPath)
do
try NSFileManager.defaultManager().removeItemAtPath(myDocumentPath)
catch let error
print(error)
url
exportSession!.outputURL = filePath
exportSession!.outputFileType = AVFileTypeMPEG4
exportSession!.shouldOptimizeForNetworkUse = true
var start = CMTimeMakeWithSeconds(0.0, 0)
var range = CMTimeRangeMake(start, avAsset.duration)
exportSession.timeRange = range
exportSession!.exportAsynchronouslyWithCompletionHandler(() -> Void in
switch self.exportSession!.status
case .Failed:
print("%@",self.exportSession?.error)
case .Cancelled:
print("Export canceled")
case .Completed:
//Video conversion finished
var endDate = NSDate()
var time = endDate.timeIntervalSinceDate(startDate)
print(time)
print("Successful!")
print(self.exportSession.outputURL)
default:
break
)
func deleteFile(filePath:NSURL)
guard NSFileManager.defaultManager().fileExistsAtPath(filePath.path!) else
return
do
try NSFileManager.defaultManager().removeItemAtPath(filePath.path!)
catch
fatalError("Unable to delete file: \(error) : \(__FUNCTION__).")
斯威夫特 3
func encodeVideo(_ videoURL: URL)
let avAsset = AVURLAsset(url: videoURL, options: nil)
let startDate = Foundation.Date()
//Create Export session
exportSession = AVAssetExportSession(asset: avAsset, presetName: AVAssetExportPresetPassthrough)
// exportSession = AVAssetExportSession(asset: composition, presetName: mp4Quality)
//Creating temp path to save the converted video
let documentsDirectory = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0]
let myDocumentPath = URL(fileURLWithPath: documentsDirectory).appendingPathComponent("temp.mp4").absoluteString
let url = URL(fileURLWithPath: myDocumentPath)
let documentsDirectory2 = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0] as URL
let filePath = documentsDirectory2.appendingPathComponent("rendered-Video.mp4")
deleteFile(filePath)
//Check if the file already exists then remove the previous file
if FileManager.default.fileExists(atPath: myDocumentPath)
do
try FileManager.default.removeItem(atPath: myDocumentPath)
catch let error
print(error)
exportSession!.outputURL = filePath
exportSession!.outputFileType = AVFileTypeMPEG4
exportSession!.shouldOptimizeForNetworkUse = true
let start = CMTimeMakeWithSeconds(0.0, 0)
let range = CMTimeRangeMake(start, avAsset.duration)
exportSession.timeRange = range
exportSession!.exportAsynchronously(completionHandler: () -> Void in
switch self.exportSession!.status
case .failed:
print("%@",self.exportSession?.error)
case .cancelled:
print("Export canceled")
case .completed:
//Video conversion finished
let endDate = Foundation.Date()
let time = endDate.timeIntervalSince(startDate)
print(time)
print("Successful!")
print(self.exportSession.outputURL)
self.mediaPath = self.exportSession.outputURL?.path as NSString!
//self.mediaPath = String(self.exportSession.outputURL!)
// self.mediaPath = self.mediaPath.substringFromIndex(7)
default:
break
)
func deleteFile(_ filePath:URL)
guard FileManager.default.fileExists(atPath: filePath.path) else
return
do
try FileManager.default.removeItem(atPath: filePath.path)
catch
fatalError("Unable to delete file: \(error) : \(#function).")
【讨论】:
给你声誉不足以回答这个问题。惊人的。谢谢。【参考方案3】:您可以在此处指定视频类型、质量和压缩视频的输出网址。
见以下方法:
- (void) saveVideoToLocal:(NSURL *)videoURL
@try
NSArray *documentsDirectory = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *docPath = [documentsDirectory objectAtIndex:0];
NSString *videoName = [NSString stringWithFormat:@"sampleVideo.mp4"];
NSString *videoPath = [docPath stringByAppendingPathComponent:videoName];
NSURL *outputURL = [NSURL fileURLWithPath:videoPath];
NSLog(@"Loading video");
[self convertVideoToLowQuailtyWithInputURL:videoURL outputURL:outputURL handler:^(AVAssetExportSession *exportSession)
if (exportSession.status == AVAssetExportSessionStatusCompleted)
NSLog(@"Compression is done");
];
@catch (NSException *exception)
NSLog(@"Exception :%@",exception.description);
//---------------------------------------------------------------
- (void)convertVideoToLowQuailtyWithInputURL:(NSURL*)inputURL outputURL:(NSURL*)outputURL handler:(void (^)(AVAssetExportSession*))handler
[[NSFileManager defaultManager] removeItemAtURL:outputURL error:nil];
AVURLAsset *asset = [AVURLAsset URLAssetWithURL:inputURL options:nil];
AVAssetExportSession *exportSession = [[AVAssetExportSession alloc] initWithAsset:asset presetName:AVAssetExportPresetPassthrough];
exportSession.outputURL = outputURL;
exportSession.outputFileType = AVFileTypeMPEG4;
[exportSession exportAsynchronouslyWithCompletionHandler:^(void)
handler(exportSession);
];
是的,您可以使用AVAssetExportSession
压缩视频。在这里,我将压缩视频保存到应用程序的document directory
。您可以在this code 中查看详细工作情况。
如果您仍有问题,请参考this 和this。
【讨论】:
【参考方案4】:你做对了。现在你需要将这个 mov 文件转换为 mp4,如下所示。
NSString *mediaType = [info objectForKey: UIImagePickerControllerMediaType];
NSString *videoPath1 = @"";
if (CFStringCompare ((__bridge_retained CFStringRef) mediaType, kUTTypeMovie, 0) == kCFCompareEqualTo)
if (UIVideoAtPathIsCompatibleWithSavedPhotosAlbum(moviePath))
NSString *docDir = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *moviePath = [[info objectForKey:UIImagePickerControllerMediaURL] path];
videoPath1 =[NSString stringWithFormat:@"%@/xyz.mov",docDir];
NSURL *videoURL = [info objectForKey:UIImagePickerControllerMediaURL];
NSData *videoData = [NSData dataWithContentsOfURL:videoURL];
[videoData writeToFile:videoPath1 atomically:NO];
// UISaveVideoAtPathToSavedPhotosAlbum(moviePath, self, nil, nil);
AVURLAsset *avAsset = [AVURLAsset URLAssetWithURL:[NSURL fileURLWithPath:videoPath1] options:nil];
NSArray *compatiblePresets = [AVAssetExportSession exportPresetsCompatibleWithAsset:avAsset];
if ([compatiblePresets containsObject:AVAssetExportPresetLowQuality])
AVAssetExportSession *exportSession = [[AVAssetExportSession alloc]initWithAsset:avAsset presetName:AVAssetExportPresetPassthrough];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
videoPath = [NSString stringWithFormat:@"%@/xyz.mp4", [paths objectAtIndex:0]];
exportSession.outputURL = [NSURL fileURLWithPath:videoPath];
NSLog(@"videopath of your mp4 file = %@",videoPath); // PATH OF YOUR .mp4 FILE
exportSession.outputFileType = AVFileTypeMPEG4;
// CMTime start = CMTimeMakeWithSeconds(1.0, 600);
// CMTime duration = CMTimeMakeWithSeconds(3.0, 600);
// CMTimeRange range = CMTimeRangeMake(start, duration);
// exportSession.timeRange = range;
// UNCOMMENT ABOVE LINES FOR CROP VIDEO
[exportSession exportAsynchronouslyWithCompletionHandler:^
switch ([exportSession status])
case AVAssetExportSessionStatusFailed:
NSLog(@"Export failed: %@", [[exportSession error] localizedDescription]);
break;
case AVAssetExportSessionStatusCancelled:
NSLog(@"Export canceled");
break;
default:
break;
UISaveVideoAtPathToSavedPhotosAlbum(videoPath, self, nil, nil);
[exportSession release];
];
[nextScreenButton setTitle:@"ПРОДЪЛЖИ" forState:UIControlStateNormal];
[self dismissViewControllerAnimated:YES completion:nil];
【讨论】:
谢谢,伙计,这行得通。还有一件事——.mp4视频文件只有3秒,如何让它像.mov文件一样长? 请查看我编辑的答案。我评论了范围部分。它会工作 谢谢,最后一件事 - 它在我的相册中保存了两个视频,如何让它只保存 mp4 视频文件? 两个视频都是mov还是1是mov而1是mp4? 完全看不懂这个。您在 if 语句中定义了 videoPath1 并在外部使用它。该代码无法编译。您能否更新一个至少可以编译的答案。以上是关于以 mp4 格式录制、保存和/或转换视频?的主要内容,如果未能解决你的问题,请参考以下文章