Как вызвать ffmpeg.exe для конвертации аудио файлов в Windows Azure? - PullRequest
7 голосов
/ 04 января 2012

Я запускаю веб-роль в Windows Azure для получения аудиофайлов AAC (загруженных строкой base64) и сохранения их в BLOB-объектах. сейчас он работает нормально.

Далее, мне также нужно конвертировать их в MP3 и сохранять их в BLOB-объектах. Я решил использовать что-то вроде ffmpeg.exe -i путь .aac путь .mp3 .

Проблемы в том, что:

  1. Как вызвать внешний ffmpeg.exe внутри веб-службы веб-роли?
  2. каким будет путь ?

Пожалуйста, помогите мне, если знаете. Заранее спасибо.

Ответы [ 2 ]

9 голосов
/ 04 января 2012

Я предлагаю вам использовать Local Storage Resource для своей веб-роли, где вы можете загрузить файлы AAC из хранилища BLOB-объектов и преобразовать их в MP3.Затем загрузите обратно в хранилище BLOB-объектов.

Примечание: вы также можете использовать Path.GetTempFileName () , чтобы получить временное имя для файлов AAC / MP3, но я неРекомендуется сделать это (даже если бы я делал это раньше).

Что касается запуска actall ffmpeg, вы можете просмотреть код для AzureVideoConv , который я построил.некоторое время назад.Там вы найдете много полезного кода.

Вот пример фактического вызова ffmpeg (обратите внимание, что я загружаю exe-файл из хранилища больших двоичных объектов, чтобы избежать раздувания пакета azure с внешними exe-файлами, ипри необходимости легко обновите 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

8 голосов
/ 05 января 2012

Спасибо большое @astaykov.Ты сделал хорошую работу.Хотя это не является специфическим для моего случая (мне нужен конкретный кусок кода вместо целого большого проекта), но это действительно вдохновило меня.Для уточнения моего случая я собираюсь ответить на этот вопрос самостоятельно - обратите внимание, что я сделал это на основе кода @ astaykov, где-то непосредственно скопировал и вставил .

  1. Во-первых, настройте роль с Local Storage Resource .Затем получите его путь по следующему коду:

        LocalResource converter_path = 
               RoleEnvironment.GetLocalResource("AudioConvertSpace");
        string rootPathName = converter_path.RootPath;
    
  2. получите путь к 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";
    
  3. записать файл .aac в локальное хранилище:

        System.IO.File.WriteAllBytes(aac_path, decoded_audio_byte_array);
    
  4. имейте в виду, что локальное хранилище не гарантируется как стабильное или долговечное, поэтому проверьте наличие файла ffmpeg.exe - если он не существует, загрузите его с BLOB-объекта.

        if (System.IO.File.Exists(exe_path) == false)
        {
            var exeblob = _BlobContainer.GetBlobReference("ffmpeg.exe");
            exeblob.DownloadToFile(exe_path, null);
        }
    
  5. инициализируйте и запустите процесс 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();
    
  6. загрузите вывод ffmpeg.exe в хранилище больших двоичных объектов:

        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);
    
  7. очистить временные файлы:

        System.IO.File.Delete(aac_path);
        System.IO.File.Delete(mp3_path);
    
...