Wrapper FFmpeg solido per C # /. NET


91

Ho cercato sul web per un po 'di tempo un solido wrapper FFmpeg per C # /. NET . Ma devo ancora trovare qualcosa di utile. Ho trovato i seguenti tre progetti, ma sembra che tutti siano morti all'inizio della fase alpha.

FFmpeg.NET
ffmpeg-sharp
FFLIB.NET

Quindi la mia domanda è se qualcuno conosce un progetto wrapper più maturo?
Non sto cercando un motore di transcodifica completo con code di lavori e altro. Solo un semplice wrapper, quindi non devo effettuare una chiamata dalla riga di comando e quindi analizzare l'output della console, ma posso effettuare chiamate ai metodi e utilizzare eventlisteners per il progresso.

E sentiti libero di menzionare eventuali progetti attivi, anche se sono ancora nelle prime fasi.



1
Qualcosa di nuovo con questo? Il tuo wrapper ha fatto progressi?
Avi

3
@Lillemanden hai mai rilasciato o open source il tuo wrapper?
Nick Benedict

È interessante che la domanda abbia quasi 6 anni ma l'OP (@JacobPoulRichardt) non ha accettato nessuna delle risposte.
Ofer Zelig

1
Ho finito per utilizzare un wrapper che ho realizzato da solo, e come tale non ho utilizzato nessuno dei progetti suggeriti. Dato che non lavoro più con ffmpeg, non ho avuto il tempo di tornare indietro e provarne nessuno. Ma ho votato contro la maggior parte delle risposte dopo averle scorse. Quindi non credo davvero di poter dire che nessuna delle risposte sia più "corretta" delle altre.
Jacob Poul Richardt

Risposte:


23

Questo è un mio wrapper: https://github.com/AydinAdn/MediaToolkit

MediaToolkit può:

  • Converti file video in vari altri formati video.
  • Eseguire attività di transcodifica video.
    • Opzioni configurabili: Bit rate, Frame rate, Resolution / size, Aspect ratio,Duration of video
  • Eseguire attività di transcodifica audio.
    • Opzioni configurabili: Audio sample rate
  • Converti video in formati fisici utilizzando gli standard televisivi FILM, PAL o NTSC
    • I medium sono: DVD, DV, DV50, VCD,SVCD

Lo sto aggiornando man mano che procedo e puoi usarlo, puoi anche installarlo utilizzando la console di Gestione pacchetti.

PM> Install-Package MediaToolkit

Il tuo toolkit può eseguire il mux / rendering di clip video e audio diverse in una data risoluzione di output?
Antonio Petricca

No, è stato progettato per essere utilizzato da persone che cercano conversioni semplici. Detto questo, molto presto arriverà la v2 che ti permetterà di fare tutto ciò che FFmpeg ha da offrire.
Aydin

Grazie Aydin, tienimi informato su questa nuova versione.
Antonio Petricca

Sembra favoloso! Buon lavoro finora!
SpoiledTechie.com

Ehi Aydin, può registrare anche lo schermo?
TEK

14

Dopo aver provato diversi wrapper, sono andato con questo: FFmpeg auto-generato associazioni non sicure per C # /. NET e Mono .

È un set di binding di interoperabilità di basso livello per ogni classe nello spazio dei nomi FFmpeg. Forse non è così comodo da usare come un vero wrapper, ma IMO è la soluzione migliore per lavorare con FFmpeg in .Net, se vuoi fare cose non banali.

Professionisti:

  • Lavori
  • Affidabile: nessun codice wrapper di terze parti per introdurre bug, supponendo che ti fidi di FFMpeg stesso.
  • È sempre aggiornato all'ultima versione di FFmpeg
  • Pacchetto singolo nuget per tutte le associazioni
  • La documentazione XML è inclusa ma è comunque possibile utilizzare la documentazione in linea FFmpeg .

Contro:

  • Livello basso: devi sapere come lavorare con i puntatori a strutture c .
  • Richiede un po 'di lavoro inizialmente per farlo funzionare. Suggerisco di imparare dagli esempi ufficiali .

Nota: questo thread riguarda l'utilizzo dell'API FFmpeg, ma per alcuni casi d'uso, è meglio usare semplicemente l'interfaccia della riga di comando di ffmpeg.exe .


Sei riuscito a usarlo da un progetto mirato a .Net Framework (non core)? Non sono sicuro di cosa mi manchi qui
Yoav Feuerstein

@YoavFeuerstein Sì.
orca


10

Ho usato FFmpeg da un'applicazione ASP.NET / Windows Service (.NET). Ma ho finito per utilizzare la riga di comando, senza analizzare la console. Usando questo - ho avuto un modo semplice per controllare - gli aggiornamenti di FFmpeg e l'esecuzione di più conversioni su più core.


Ok, ho iniziato con qualcosa di simile. Ma spero ancora che qualcuno abbia una soluzione migliore.
Jacob Poul Richardt,

4

Puoi usare questo pacchetto nuget:

So che hai chiesto del progetto maturo , ma non ho visto nessun progetto che soddisfi le mie aspettative, quindi ho deciso di crearne uno mio. Puoi facilmente mettere in coda le conversioni ed eseguirle parallelamente, metodi per convertire i media in diversi formati, inviare i tuoi argomenti a ffmpeg e analizzare l'output da ffmpeg + listener di eventi con l'avanzamento corrente.

Install-Package Xabe.FFmpeg

Sto cercando di creare un wrapper FFmpeg multipiattaforma facile da usare.

Puoi trovare ulteriori informazioni su questo su https://xabe.net/product/xabe_ffmpeg/

Maggiori informazioni qui: https://xabe.net/product/xabe_ffmpeg/#documentation

La conversione è semplice:

IConversionResult result = await Conversion.ToMp4(Resources.MkvWithAudio, output).Start();

Se vuoi progressi:

IConversion conversion = Conversion.ToMp4(Resources.MkvWithAudio, output);
conversion.OnProgress += (duration, length) => { currentProgress = duration; } 
await conversion.Start();

Ciao ... devo usare FFMPEG per transcodificare un flusso di dati proveniente da una pagina web e inviarlo a un server RTMP. Ho l'array di byte nel mio programma winform C #. Devo solo transcodificare e inviare al server RTMP. Posso farlo usando questo wrapper? L'ho fatto usando un server nodejs usando socketio in Linux. In quella piattaforma, invio il flusso binario attraverso lo stdin e ricevo lo stato di conversione in stderr. Posso farlo usando il wrapper Xabe?
jstuardo

3

Sto giocando con una libreria wrapper ffmpeg chiamata MediaHandler Pro da

http://www.mediasoftpro.com

sembra promettente finora.


Come ha funzionato per te? Inoltre, viene MediaHandlergenerato ffmpeg.execome processo per svolgere il proprio lavoro o esiste una libreria P / Invoke effettiva?
Glenn Slayden

Ho finito per usarlo in un paio di progetti. Ha funzionato bene in un ambiente di produzione sotto carico pesante. è passato un po 'di tempo da quando l'ho usato, ma da quello che ricordo, sì, genera ffmpeg.exe come processo.
Christophe Chang,

3

Ho cercato la stessa cosa e originariamente ho utilizzato MediaToolKit (menzionato in un'altra risposta) che ha funzionato alla grande per le conversioni, ma ora ho bisogno di qualcosa di un po 'più robusto.

Un'opzione che sembra matura e ancora attiva è: https://github.com/hudl/HudlFfmpeg Di cui puoi leggere di più qui: http://public.hudl.com/bits/archives/2014/08/15/announcing -hudlffmpeg-ac-framework-to-make-ffmpeg-interaction-simple /

Un'altra opzione, che potrebbe non essere adatta in molti casi, è richiamare l'exe direttamente dal codice c #: http://www.codeproject.com/Articles/774093/Another-FFmpeg-exe-Csharp-Wrapper


2

1
Grazie per il collegamento, ma per quanto posso vedere hai scritto il tuo in Java, non int C #.
Jacob Poul Richardt

Ciao lillemanden, il link che ho fornito è effettivamente implementato in Java, e se scarichi lo zip in fondo all'articolo, vedrai che al suo interno c'è un file di archivio jar. Grazie, Ilya
Ilya

Il link in risposta sembra morto: "Questo sito non può essere raggiunto - ivolo.mit.edu ha impiegato troppo tempo per rispondere."
Pang

2

Ecco qua ... La maggior parte di questo codice ha più di 2 anni, quindi manca un sacco di cose asincrone e usa una convenzione di denominazione obsoleta. Funzionando in un ambiente di produzione per un bel po 'di tempo ~ JT

internal static class FFMpegArgUtils
    {
        public static string GetEncodeVideoFFMpegArgs(string sSourceFile, MP4Info objMp4Info, double nMbps, int iWidth, int iHeight, bool bIncludeAudio, string sOutputFile)
        {
            //Ensure file contains a video stream, otherwise this command will fail
            if (objMp4Info != null && objMp4Info.VideoStreamCount == 0)
            {
                throw new Exception("FFMpegArgUtils::GetEncodeVideoFFMpegArgs - mp4 does not contain a video stream");
            }

            int iBitRateInKbps = (int)(nMbps * 1000);


            StringBuilder sbArgs = new StringBuilder();
            sbArgs.Append(" -y -threads 2 -i \"" + sSourceFile + "\" -strict -2 "); // 0 tells it to choose how many threads to use

            if (bIncludeAudio == true)
            {
                //sbArgs.Append(" -acodec libmp3lame -ab 96k");
                sbArgs.Append(" -acodec aac -ar 44100 -ab 96k");
            }
            else
            {
                sbArgs.Append(" -an");
            }


            sbArgs.Append(" -vcodec libx264 -level 41 -r 15 -crf 25 -g 15  -keyint_min 45 -bf 0");

            //sbArgs.Append(" -vf pad=" + iWidth + ":" + iHeight + ":" + iVideoOffsetX + ":" + iVideoOffsetY);
            sbArgs.Append(String.Format(" -vf \"scale=iw*min({0}/iw\\,{1}/ih):ih*min({0}/iw\\,{1}/ih),pad={0}:{1}:({0}-iw)/2:({1}-ih)/2\"",iWidth, iHeight));

            //Output File
            sbArgs.Append(" \"" + sOutputFile + "\"");
            return sbArgs.ToString();
        }

        public static string GetEncodeAudioFFMpegArgs(string sSourceFile, string sOutputFile)
        {
            var args = String.Format(" -y -threads 2 -i \"{0}\" -strict -2  -acodec aac -ar 44100 -ab 96k -vn \"{1}\"", sSourceFile, sOutputFile);
            return args;


            //return GetEncodeVideoFFMpegArgs(sSourceFile, null, .2, 854, 480, true, sOutputFile);
            //StringBuilder sbArgs = new StringBuilder();
            //int iWidth = 854;
            //int iHeight = 480;
            //sbArgs.Append(" -y -i \"" + sSourceFile + "\" -strict -2 "); // 0 tells it to choose how many threads to use
            //sbArgs.Append(" -acodec aac -ar 44100 -ab 96k");
            //sbArgs.Append(" -vcodec libx264 -level 41 -r 15 -crf 25 -g 15  -keyint_min 45 -bf 0");
            //sbArgs.Append(String.Format(" -vf \"scale=iw*min({0}/iw\\,{1}/ih):ih*min({0}/iw\\,{1}/ih),pad={0}:{1}:({0}-iw)/2:({1}-ih)/2\"", iWidth, iHeight));
            //sbArgs.Append(" \"" + sOutputFile + "\"");
            //return sbArgs.ToString();
        }
    }

internal class CreateEncodedVideoCommand : ConsoleCommandBase
    {
        public event ProgressEventHandler OnProgressEvent;

        private string _sSourceFile;
        private  string _sOutputFolder;
        private double _nMaxMbps;

        public double BitrateInMbps
        {
            get { return _nMaxMbps; }
        }

        public int BitrateInKbps
        {
            get { return (int)Math.Round(_nMaxMbps * 1000); }
        }

        private int _iOutputWidth;
        private int _iOutputHeight;

        private bool _bIsConverting = false;
        //private TimeSpan _tsDuration;
        private double _nPercentageComplete;
        private string _sOutputFile;
        private string _sOutputFileName;


        private bool _bAudioEnabled = true;
        private string _sFFMpegPath;
        private string _sExePath;
        private string _sArgs;
        private MP4Info _objSourceInfo;
        private string _sOutputExt;

        /// <summary>
        /// Encodes an MP4 to the specs provided, quality is a value from 0 to 1
        /// </summary>
        /// <param name="nQuality">A value from 0 to 1</param>
        /// 
        public CreateEncodedVideoCommand(string sSourceFile, string sOutputFolder, string sFFMpegPath, double nMaxBitrateInMbps, MP4Info objSourceInfo, int iOutputWidth, int iOutputHeight, string sOutputExt)
        {
            _sSourceFile = sSourceFile;
            _sOutputFolder = sOutputFolder;
            _nMaxMbps = nMaxBitrateInMbps;
            _objSourceInfo = objSourceInfo;
            _iOutputWidth = iOutputWidth;
            _iOutputHeight = iOutputHeight;
            _sFFMpegPath = sFFMpegPath;
            _sOutputExt = sOutputExt;
        }

        public void SetOutputFileName(string sOutputFileName)
        {
            _sOutputFileName = sOutputFileName;
        }


        public override void Execute()
        {
            try
            {
                _bIsConverting = false;

                string sFileName = _sOutputFileName != null ? _sOutputFileName : Path.GetFileNameWithoutExtension(_sSourceFile) + "_" + _iOutputWidth + "." + _sOutputExt;
                _sOutputFile = _sOutputFolder + "\\" + sFileName;

                _sExePath = _sFFMpegPath;
                _sArgs = FFMpegArgUtils.GetEncodeVideoFFMpegArgs(_sSourceFile, _objSourceInfo,_nMaxMbps, _iOutputWidth, _iOutputHeight, _bAudioEnabled, _sOutputFile);

                InternalExecute(_sExePath, _sArgs);
            }
            catch (Exception objEx)
            {
                DispatchException(objEx);
            }
        }

        public override string GetCommandInfo()
        {
            StringBuilder sbInfo = new StringBuilder();
            sbInfo.AppendLine("CreateEncodeVideoCommand");
            sbInfo.AppendLine("Exe: " + _sExePath);
            sbInfo.AppendLine("Args: " + _sArgs);
            sbInfo.AppendLine("[ConsoleOutput]");
            sbInfo.Append(ConsoleOutput);
            sbInfo.AppendLine("[ErrorOutput]");
            sbInfo.Append(ErrorOutput);

            return base.GetCommandInfo() + "\n" + sbInfo.ToString();
        }

        protected override void OnInternalCommandComplete(int iExitCode)
        {
            DispatchCommandComplete( iExitCode == 0 ? CommandResultType.Success : CommandResultType.Fail);
        }

        override protected void OnOutputRecieved(object sender, ProcessOutputEventArgs objArgs)
        {
            //FMPEG out always shows as Error
            base.OnOutputRecieved(sender, objArgs);

            if (_bIsConverting == false && objArgs.Data.StartsWith("Press [q] to stop encoding") == true)
            {
                _bIsConverting = true;
            }
            else if (_bIsConverting == true && objArgs.Data.StartsWith("frame=") == true)
            {
                //Capture Progress
                UpdateProgressFromOutputLine(objArgs.Data);
            }
            else if (_bIsConverting == true && _nPercentageComplete > .8 && objArgs.Data.StartsWith("frame=") == false)
            {
                UpdateProgress(1);
                _bIsConverting = false;
            }
        }

        override protected void OnProcessExit(object sender, ProcessExitedEventArgs args)
        {
            _bIsConverting = false;
            base.OnProcessExit(sender, args);
        }

        override public void Abort()
        {
            if (_objCurrentProcessRunner != null)
            {
                //_objCurrentProcessRunner.SendLineToInputStream("q");
                _objCurrentProcessRunner.Dispose();
            }
        }

        #region Helpers

        //private void CaptureSourceDetailsFromOutput()
        //{
        //    String sInputStreamInfoStartLine = _colErrorLines.SingleOrDefault(o => o.StartsWith("Input #0"));
        //    int iStreamInfoStartIndex = _colErrorLines.IndexOf(sInputStreamInfoStartLine);
        //    if (iStreamInfoStartIndex >= 0)
        //    {
        //        string sDurationInfoLine = _colErrorLines[iStreamInfoStartIndex + 1];
        //        string sDurantionTime = sDurationInfoLine.Substring(12, 11);

        //        _tsDuration = VideoUtils.GetDurationFromFFMpegDurationString(sDurantionTime);
        //    }
        //}

        private void UpdateProgressFromOutputLine(string sOutputLine)
        {
            int iTimeIndex = sOutputLine.IndexOf("time=");
            int iBitrateIndex = sOutputLine.IndexOf(" bitrate=");

            string sCurrentTime = sOutputLine.Substring(iTimeIndex + 5, iBitrateIndex - iTimeIndex - 5);
            double nCurrentTimeInSeconds = double.Parse(sCurrentTime);
            double nPercentageComplete = nCurrentTimeInSeconds / _objSourceInfo.Duration.TotalSeconds;

            UpdateProgress(nPercentageComplete);
            //Console.WriteLine("Progress: " + _nPercentageComplete);
        }

        private void UpdateProgress(double nPercentageComplete)
        {
            _nPercentageComplete = nPercentageComplete;
            if (OnProgressEvent != null)
            {
                OnProgressEvent(this, new ProgressEventArgs( _nPercentageComplete));
            }
        }

        #endregion

        //public TimeSpan Duration { get { return _tsDuration; } }

        public double Progress { get { return _nPercentageComplete;  } }
        public string OutputFile { get { return _sOutputFile; } }

        public bool AudioEnabled
        {
            get { return _bAudioEnabled; }
            set { _bAudioEnabled = value; }
        }
}

public abstract class ConsoleCommandBase : CommandBase, ICommand
    {
        protected ProcessRunner _objCurrentProcessRunner;
        protected   List<String> _colOutputLines;
        protected List<String> _colErrorLines;


        private int _iExitCode;

        public ConsoleCommandBase()
        {
            _colOutputLines = new List<string>();
            _colErrorLines = new List<string>();
        }

        protected void InternalExecute(string sExePath, string sArgs)
        {
            InternalExecute(sExePath, sArgs, null, null, null);
        }

        protected void InternalExecute(string sExePath, string sArgs, string sDomain, string sUsername, string sPassword)
        {
            try
            {
                if (_objCurrentProcessRunner == null || _bIsRunning == false)
                {
                    StringReader objStringReader = new StringReader(string.Empty);

                    _objCurrentProcessRunner = new ProcessRunner(sExePath, sArgs);

                    _objCurrentProcessRunner.SetCredentials(sDomain, sUsername, sPassword);

                    _objCurrentProcessRunner.OutputReceived += new ProcessOutputEventHandler(OnOutputRecieved);
                    _objCurrentProcessRunner.ProcessExited += new ProcessExitedEventHandler(OnProcessExit);
                    _objCurrentProcessRunner.Run();

                    _bIsRunning = true;
                    _bIsComplete = false;
                }
                else
                {
                    DispatchException(new Exception("Processor Already Running"));
                }
            }
            catch (Exception objEx)
            {
                DispatchException(objEx);
            }
        }

        protected virtual void OnOutputRecieved(object sender, ProcessOutputEventArgs args)
        {
            try
            {
                if (args.Error == true)
                {
                    _colErrorLines.Add(args.Data);
                    //Console.WriteLine("Error: " + args.Data);
                }
                else
                {
                    _colOutputLines.Add(args.Data);
                    //Console.WriteLine(args.Data);
                }
            }
            catch (Exception objEx)
            {
                DispatchException(objEx);
            }
        }

        protected virtual void OnProcessExit(object sender, ProcessExitedEventArgs args)
        {
            try
            {
                Console.Write(ConsoleOutput);
                _iExitCode = args.ExitCode;

                _bIsRunning = false;
                _bIsComplete = true;

                //Some commands actually fail to succeed
                //if(args.ExitCode != 0)
                //{
                //    DispatchException(new Exception("Command Failed: " + this.GetType().Name + "\nConsole: " + ConsoleOutput + "\nConsoleError: " + ErrorOutput));
                //}

                OnInternalCommandComplete(_iExitCode);

                if (_objCurrentProcessRunner != null)
                {
                    _objCurrentProcessRunner.Dispose();
                    _objCurrentProcessRunner = null;    
                }
            }
            catch (Exception objEx)
            {
                DispatchException(objEx);
            }
        }

        abstract protected void OnInternalCommandComplete(int iExitCode);

        protected string JoinLines(List<String> colLines)
        {
            StringBuilder sbOutput = new StringBuilder();
            colLines.ForEach( o => sbOutput.AppendLine(o));
            return sbOutput.ToString();
        }

        #region Properties
        public int ExitCode
        {
            get { return _iExitCode; }
        }
        #endregion

        public override string GetCommandInfo()
        {
            StringBuilder sbCommandInfo = new StringBuilder();
            sbCommandInfo.AppendLine("Command:  " + this.GetType().Name);
            sbCommandInfo.AppendLine("Console Output");
            if (_colOutputLines != null)
            {
                foreach (string sOutputLine in _colOutputLines)
                {
                    sbCommandInfo.AppendLine("\t" + sOutputLine);
                }
            }
            sbCommandInfo.AppendLine("Error Output");
            if (_colErrorLines != null)
            {
                foreach (string sErrorLine in _colErrorLines)
                {
                    sbCommandInfo.AppendLine("\t" + sErrorLine);
                }
            }
            return sbCommandInfo.ToString();
        }

        public String ConsoleOutput { get { return JoinLines(_colOutputLines); } }
        public String ErrorOutput { get { return JoinLines(_colErrorLines);} }

    }

CommandBase : ICommand
    {
        protected IDedooseContext _context;
        protected Boolean _bIsRunning = false;
        protected Boolean _bIsComplete = false;

        #region Custom Events
        public event CommandCompleteEventHandler OnCommandComplete;
        event CommandCompleteEventHandler ICommand.OnCommandComplete
        {
            add { if (OnCommandComplete != null) { lock (OnCommandComplete) { OnCommandComplete += value; } } else { OnCommandComplete = new CommandCompleteEventHandler(value); } }
            remove { if (OnCommandComplete != null) { lock (OnCommandComplete) { OnCommandComplete -= value; } } }
        }

        public event UnhandledExceptionEventHandler OnCommandException;
        event UnhandledExceptionEventHandler ICommand.OnCommandException
        {
            add { if (OnCommandException != null) { lock (OnCommandException) { OnCommandException += value; } } else { OnCommandException = new UnhandledExceptionEventHandler(value); } }
            remove { if (OnCommandException != null) { lock (OnCommandException) { OnCommandException -= value; } } }
        }

        public event ProgressEventHandler OnProgressUpdate;
        event ProgressEventHandler ICommand.OnProgressUpdate
        {
            add { if (OnProgressUpdate != null) { lock (OnProgressUpdate) { OnProgressUpdate += value; } } else { OnProgressUpdate = new ProgressEventHandler(value); } }
            remove { if (OnProgressUpdate != null) { lock (OnProgressUpdate) { OnProgressUpdate -= value; } } }
        }
        #endregion

        protected CommandBase()
        {
            _context = UnityGlobalContainer.Instance.Context;
        }

        protected void DispatchCommandComplete(CommandResultType enResult)
        {
            if (enResult == CommandResultType.Fail)
            {
                StringBuilder sbMessage = new StringBuilder();
                sbMessage.AppendLine("Command Commpleted with Failure: "  + this.GetType().Name);
                sbMessage.Append(GetCommandInfo());
                Exception objEx = new Exception(sbMessage.ToString());
                DispatchException(objEx);
            }
            else
            {
                if (OnCommandComplete != null)
                {
                    OnCommandComplete(this, new CommandCompleteEventArgs(enResult));
                }
            }
        }

        protected void DispatchException(Exception objEx)
        {
            if (OnCommandException != null)
            { 
                OnCommandException(this, new UnhandledExceptionEventArgs(objEx, true)); 
            }
            else
            {
                _context.Logger.LogException(objEx, MethodBase.GetCurrentMethod());
                throw objEx;
            }
        }

        protected void DispatchProgressUpdate(double nProgressRatio)
        {
            if (OnProgressUpdate != null) { OnProgressUpdate(this, new ProgressEventArgs(nProgressRatio)); } 
        }

        public virtual string GetCommandInfo()
        {
            return "Not Implemented: " + this.GetType().Name;
        }

        public virtual void Execute() { throw new NotImplementedException(); }
        public virtual void Abort() { throw new NotImplementedException(); }

        public Boolean IsRunning { get { return _bIsRunning; } }
        public Boolean IsComplete { get { return _bIsComplete; } }

        public double GetProgressRatio()
        {
            throw new NotImplementedException();
        }
    }

public delegate void CommandCompleteEventHandler(object sender, CommandCompleteEventArgs e);

    public interface ICommand
    {
        event CommandCompleteEventHandler OnCommandComplete;
        event UnhandledExceptionEventHandler OnCommandException;
        event ProgressEventHandler OnProgressUpdate;

        double GetProgressRatio();
        string GetCommandInfo();

        void Execute();
        void Abort();
    }

// per la roba del runner del processo cerca ProcessRunner di Roger Knapp


1
        string result = String.Empty;
        StreamReader srOutput = null;
        var oInfo = new ProcessStartInfo(exePath, parameters)
        {
            UseShellExecute = false,
            CreateNoWindow = true,
            RedirectStandardOutput = true,
            RedirectStandardError = true
        };

        var output = string.Empty;

        try
        {
            Process process = System.Diagnostics.Process.Start(oInfo);
            output = process.StandardError.ReadToEnd();
            process.WaitForExit();
            process.Close();
        }
        catch (Exception)
        {
            output = string.Empty;
        }
        return output;

Questo wrapper non consentirà al metodo di cadere in un ciclo. Prova questo, ha funzionato per me.


1

Ho biforcato FFPMEG.net da codeplex.

Ancora attivamente in lavorazione.

https://github.com/spoiledtechie/FFMpeg.Net

Non usa le dll, ma piuttosto l'exe. Quindi tende ad essere più stabile.


Sembra quello che sto cercando, ma come si implementa questo nel loro progetto?
TEK

Aggiungi questo progetto al tuo progetto, quindi assicurati che FFMPEG sia inserito correttamente nel progetto. È ancora in lavorazione.
SpoiledTechie.com

Posso codificare e decodificare un frame come byte [] usando questo FFMPEG.net? ad esempio, byte [] encodeh264 (byte []) e byte [] decodeh264 (byte []).
Ahmad

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.