我想压缩一个大尺寸的视频并将其上传到服务器。我怎么能这样做,我对此一无所知。
请帮助我....
答案 0 :(得分:1)
首先 - 压缩视频内容不太可能以任何有意义的方式减小其大小。 您应该关注的是不同的编解码器和编码机制,以减小其大小。
请看ffmpeg:ffmpeg dot org
您可以通过System.Diagnostics.Process类在命令行上调用此工具。 然后,您可以告诉它处理视频文件。 这将允许您更改视频使用的编码和编解码器。 注意 - 缩小尺寸会降低视频质量。 您可能还希望缩小视频的分辨率以获得最大的缩小。
视频和音频是无法使用传统工具(如winzip或winrar)压缩的媒体类型,最终会显示较小的文件。 通常,您最终只会将文件大小减少1%。 要减小文件大小,您需要更改视频编码,这在某些情况下会降低质量。
ffmpeg -i myVideo.avi -fs 20M myOutputVideo.avi
此命令行将采用100 mb或更大的myVideo.avi,并尝试降级质量/编码比特率以获得20mb的输出大小。
public static void ShrinkVideo(string pathToVideo,int desiredMbSize,string outFile)
{
ProcessStartInfo psi = new ProcessStartInfo("ffmpeg.exe");
psi.Arguments = string.Format("-i \"{0}\" -fs {1}M \"{2}\"",pathToVideo,desiredMbSize,outFile);
Process proc = new Process(psi);
proc.Start();
}
我还没有测试过这段代码 - 但它应该按照你想要的方式做一些事情。如果您收到错误 - 回复。
BTW-这依赖于ffmpeg.exe - 这是第三方可执行文件。 它通常被广泛使用 - 它被认为是最兼容和多功能的视频编码器之一 - 得到社区的很好支持。
答案 1 :(得分:1)
在Android的DS文件中使用以下代码
public Task CompressVideo(字符串路径) {
var task = new TaskCompletionSource<string>();
var _workingDirectory = Android.OS.Environment.ExternalStorageDirectory.AbsolutePath;
var sourceMp4 = path;
var destinationPath1 = IntentHelper.CreateNewVideoPath();
FFMpeg ffmpeg = new FFMpeg(Android.App.Application.Context, _workingDirectory);
TransposeVideoFilter vfTranspose = new TransposeVideoFilter(TransposeVideoFilter.NINETY_CLOCKWISE);
var filters = new List<VideoFilter>();
filters.Add(vfTranspose);
Task.Run(() =>
{
var sourceClip = new Clip(System.IO.Path.Combine(_workingDirectory, sourceMp4)) { videoFilter = VideoFilter.Build(filters) };
var onComplete = new MyCommand((_) =>
{
CurrentActivity.RunOnUiThread(() =>
{
task.SetResult(destinationPath1);
//progress.Dismiss();
});
});
var onMessage = new MyCommand((message) =>
{
System.Console.WriteLine(message);
});
var callbacks = new FFMpegCallbacks(onComplete, onMessage);
string[] cmds = new string[] {
"-y",
"-i",
sourceClip.path,
"-strict", "experimental",
"-vcodec", "libx264",
"-preset", "ultrafast",
"-crf","38", "-acodec","aac", "-ar", "44100" ,
"-q:v", "12",
"-vf",sourceClip.videoFilter,
destinationPath1 ,
};
ffmpeg.Execute(cmds, callbacks);
return task.Task;
});
return task.Task;
}
public class MyCommand : ICommand
{
public delegate void ICommandOnExecute(object parameter = null);
public delegate bool ICommandOnCanExecute(object parameter);
private ICommandOnExecute _execute;
private ICommandOnCanExecute _canExecute;
public MyCommand(ICommandOnExecute onExecuteMethod)
{
_execute = onExecuteMethod;
}
public MyCommand(ICommandOnExecute onExecuteMethod, ICommandOnCanExecute onCanExecuteMethod)
{
_execute = onExecuteMethod;
_canExecute = onCanExecuteMethod;
}
#region ICommand Members
public event EventHandler CanExecuteChanged
{
add { throw new NotImplementedException(); }
remove { throw new NotImplementedException(); }
}
public bool CanExecute(object parameter)
{
if (_canExecute == null && _execute != null)
return true;
return _canExecute.Invoke(parameter);
}
public void Execute(object parameter)
{
if (_execute == null)
return;
_execute.Invoke(parameter);
}
#endregion
}
现在在iOS的依赖关系文件中使用此代码
public Task CompressVideo(string inputPath) {
var task = new TaskCompletionSource<string>();
var export = new AVAssetExportSession(AVAsset.FromUrl(new NSUrl(inputPath)), AVAssetExportSession.PresetMediumQuality);
string videoFilename = System.IO.Path.Combine(GetVideoDirectoryPath(), GetUniqueFileName(".mp4"));
export.OutputUrl = NSUrl.FromFilename(videoFilename);
export.OutputFileType = AVFileType.Mpeg4;
export.ShouldOptimizeForNetworkUse = true;
export.ExportAsynchronously(() =>
{
if (export.Status == AVAssetExportSessionStatus.Completed)
{
var videoData = NSData.FromUrl(NSUrl.FromString(export.OutputUrl.ToString()));
NSError err = null;
if (videoData.Save(videoFilename, false, out err))
task.SetResult(videoFilename);
else
task.SetResult(null);
}
else
task.SetResult(null);
});
return task.Task;