我在Windows Azure上运行一个Web角色来接收AAC音频文件(通过base64字符串上传)并将它们存储到blob中。到目前为止还可以。
接下来,我还必须将它们转换为MP3,并将MP3存储到blob中。我决定使用类似于ffmpeg.exe -i path的东西。aac 道路。mp3 。
问题是:
- 如何调用外部ffmpeg.exe内部的web服务的web角色?
- 是什么路径 ?
如果你知道请帮助我。
我建议您使用本地存储资源,您可以从blob存储下载AAC文件,并将它们转换为MP3。然后上传回blob存储
旁注是,您也可以使用Path.GetTempFileName()来获取AAC/MP3文件的临时文件名,但我不鼓励这样做(即使我以前这样做过)。
至于实际运行的ffmpeg,您可能需要浏览AzureVideoConv的代码,这是我不久前构建的。你会发现很多有用的代码。
下面是实际ffmpeg调用的示例(注意,我从blob存储下载了exe,以避免使用外部exe文件膨胀我的azure包,并在需要时轻松更新ffmpeg.exe):
internal void ConvertFile(string inputFileName, Guid taskID)
{
string tmpName = string.Format(
"{0}\{1}.flv",
Path.GetTempPath(), inputFileName.Substring(inputFileName.LastIndexOf("\")+1));
ProcessStartInfo psi = new ProcessStartInfo();
psi.FileName = this._processorExecutable;
psi.Arguments = string.Format(@"-i ""{0}"" -y ""{1}""", inputFileName, tmpName);
psi.CreateNoWindow = true;
psi.ErrorDialog = false;
psi.UseShellExecute = false;
psi.WindowStyle = ProcessWindowStyle.Hidden;
psi.RedirectStandardOutput = true;
psi.RedirectStandardInput = false;
psi.RedirectStandardError = true;
try
{
// Start the process with the info we specified.
// Call WaitForExit and then the using statement will close.
using (Process exeProcess = Process.Start(psi))
{
exeProcess.PriorityClass = ProcessPriorityClass.High;
string outString = string.Empty;
// use ansynchronous reading for at least one of the streams
// to avoid deadlock
exeProcess.OutputDataReceived += (s, e) => {
outString += e.Data;
};
exeProcess.BeginOutputReadLine();
// now read the StandardError stream to the end
// this will cause our main thread to wait for the
// stream to close (which is when ffmpeg quits)
string errString = exeProcess.StandardError.ReadToEnd();
Trace.WriteLine(outString);
Trace.TraceError(errString);
byte[] fileBytes = File.ReadAllBytes(tmpName);
if (fileBytes.Length > 0)
{
this._sSystem.SaveOutputFile(
fileBytes,
tmpName.Substring(tmpName.LastIndexOf("\")+1),
taskID
);
}
}
}
catch (Exception e)
{
Trace.TraceError(e.Message);
}
}
说明项目最后一次检入使用的是Windows Azure SDK 1.3
非常感谢@astaykov。你做得很好。虽然它不是针对我的情况(我需要一段特定的代码,而不是整个大项目),但它确实启发了我。为了说明我的情况,我将用我自己的方式回答这个问题——注意,我是根据@astaykov的代码做的,在某个地方直接复制粘贴。
-
首先为角色配置本地存储资源。然后通过以下代码获取它的路径:
LocalResource converter_path = RoleEnvironment.GetLocalResource("AudioConvertSpace"); string rootPathName = converter_path.RootPath;
-
获取ffmpeg.exe, xxx的路径。本地存储中的Aac 和xxx.mp3:
string aac_path = rootPathName + "\" + "fmwa-" + guidguid + ".aac"; string mp3_path = rootPathName + "\" + "fmwa-" + guidguid + ".mp3"; string exe_path = rootPathName + "\" + "ffmpeg.exe";
-
将。aac文件写入本地存储:
System.IO.File.WriteAllBytes(aac_path, decoded_audio_byte_array);
-
请记住,本地存储不能保证稳定或持久,所以检查ffmpeg.exe是否存在——如果它不存在,请从blob下载。
if (System.IO.File.Exists(exe_path) == false) { var exeblob = _BlobContainer.GetBlobReference("ffmpeg.exe"); exeblob.DownloadToFile(exe_path, null); }
-
启动并运行ffmpeg.exe进程:
ProcessStartInfo psi = new ProcessStartInfo(); psi.FileName = exe_path; psi.Arguments = string.Format(@"-i ""{0}"" -y ""{1}""", aac_path, mp3_path); psi.CreateNoWindow = true; psi.ErrorDialog = false; psi.UseShellExecute = false; psi.WindowStyle = ProcessWindowStyle.Hidden; psi.RedirectStandardOutput = true; psi.RedirectStandardInput = false; psi.RedirectStandardError = true; Process exeProcess = Process.Start(psi); exeProcess.PriorityClass = ProcessPriorityClass.High; string outString = string.Empty; exeProcess.OutputDataReceived += (s, e) => { outString += e.Data; }; exeProcess.BeginOutputReadLine(); string errString = exeProcess.StandardError.ReadToEnd(); Trace.WriteLine(outString); Trace.TraceError(errString); exeProcess.WaitForExit();
-
上传ffmpeg.exe的输出到blob存储:
byte[] mp3_audio_byte_array = System.IO.File.ReadAllBytes(mp3_path); var mp3blob = _BlobContainer.GetBlobReference("fmwa-"+guidguid+".mp3"); mp3blob.Properties.ContentType = "audio/mp3"; mp3blob.UploadByteArray(mp3_audio_byte_array);
-
清理临时文件:
System.IO.File.Delete(aac_path); System.IO.File.Delete(mp3_path);