Search code examples
c#formsffmpeg

I want it to do the ffmpeg convert while the application continues to run


Downloading with yd-dl.exe is successful, but it does not convert the downloaded video to mp4 with ffmpeg. When I stop compiling the project in visual studio, it converts the ffmpeg file to mp4.

using System;
using System.Diagnostics;
using System.IO;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace YouTube_MP4_indir
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            pictureBox2.Visible = false;
            pictureBox3.Visible = false;
        }

        private async void btnDownload_Click(object sender, EventArgs e)
        {
            searchBox.Enabled = false;
            btnDownload.Enabled = false;
            pictureBox2.Visible = true;
            pictureBox3.Visible = false;

            string url = searchBox.Text.Trim();
            if (string.IsNullOrEmpty(url))
            {
                DialogResult result = MessageBox.Show("Lütfen geçerli bir YouTube URL'si giriniz.", "Uyarı", MessageBoxButtons.OK, MessageBoxIcon.Warning);

                if (result == DialogResult.OK)
                {
                    searchBox.Text = "";
                    searchBox.Enabled = true;
                    btnDownload.Enabled = true;
                }

                pictureBox2.Visible = false;
                pictureBox3.Visible = false;
                return;
            }

            string desktopPath = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
            string videosFolderPath = Path.Combine(desktopPath, "Videolar");

            if (!Directory.Exists(videosFolderPath))
            {
                Directory.CreateDirectory(videosFolderPath);
            }

            string videoTitle = await GetVideoTitle(url);

            if (string.IsNullOrEmpty(videoTitle))
            {
                MessageBox.Show("Video başlığı alınamadı.", "Hata", MessageBoxButtons.OK, MessageBoxIcon.Error);
                pictureBox2.Visible = false;
                pictureBox3.Visible = false;
                return;
            }

            string inputFilePath = Path.Combine(videosFolderPath, $"{videoTitle}.mp4");
            string outputFilePath = Path.Combine(videosFolderPath, $"{videoTitle}-dönüştürülmüş.mp4");

            try
            {
                var ytDlpPath = Path.Combine(Application.StartupPath, "files", "yt-dlp.exe");

                var startInfo = new ProcessStartInfo()
                {
                    FileName = ytDlpPath,
                    Arguments = $"-f bestvideo[height<=1080]+bestaudio/best --merge-output-format mp4 --output \"{inputFilePath}\" {url}",
                    UseShellExecute = false,
                    CreateNoWindow = true,
                    RedirectStandardOutput = true,
                    RedirectStandardError = true
                };

                var process = Process.Start(startInfo);
                string output = await process.StandardOutput.ReadToEndAsync();
                string error = await process.StandardError.ReadToEndAsync();

                await process.WaitForExitAsync();

                if (process.ExitCode == 0)
                {
                    // Paralel olarak FFmpeg dönüştürme işlemini başlat
                    _ = Task.Run(() => ConvertToMp4(inputFilePath, outputFilePath));

                    MessageBox.Show("İndirme tamamlandı. Video dönüştürülüyor.", "Bilgi", MessageBoxButtons.OK, MessageBoxIcon.Information);

                    searchBox.Text = "";
                    searchBox.Enabled = true;
                    btnDownload.Enabled = true;

                    pictureBox2.Visible = false;
                    pictureBox3.Visible = true;
                }
                else
                {
                    MessageBox.Show("Lütfen sadece video linki giriniz", "Uyarı", MessageBoxButtons.OK, MessageBoxIcon.Warning);

                    pictureBox2.Visible = false;
                    pictureBox3.Visible = false;
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show("Hata: " + ex.Message, "Hata", MessageBoxButtons.OK, MessageBoxIcon.Error);

                pictureBox2.Visible = false;
                pictureBox3.Visible = false;
            }
        }

        private async Task<string> GetVideoTitle(string url)
        {
            try
            {
                var ytDlpPath = Path.Combine(Application.StartupPath, "files", "yt-dlp.exe");

                var startInfo = new ProcessStartInfo()
                {
                    FileName = ytDlpPath,
                    Arguments = $"-e {url}",
                    UseShellExecute = false,
                    CreateNoWindow = true,
                    RedirectStandardOutput = true,
                    RedirectStandardError = true
                };

                var process = Process.Start(startInfo);
                string output = await process.StandardOutput.ReadToEndAsync();
                await process.WaitForExitAsync();

                return output.Trim();
            }
            catch (Exception ex)
            {
                MessageBox.Show("Hata: " + ex.Message, "Hata", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return null;
            }
        }

        private async Task ConvertToMp4(string inputFilePath, string outputFilePath)
        {
            try
            {
                var ffmpegPath = Path.Combine(Application.StartupPath, "files", "ffmpeg.exe");

                var startInfo = new ProcessStartInfo
                {
                    FileName = ffmpegPath,
                    Arguments = $"-i \"{inputFilePath}\" -c:v libx264 -preset ultrafast -crf 23 -s hd1080 \"{outputFilePath}\"",
                    UseShellExecute = false,
                    CreateNoWindow = true,
                    RedirectStandardOutput = true,
                    RedirectStandardError = true
                };

                var process = Process.Start(startInfo);
                string output = await process.StandardOutput.ReadToEndAsync();
                string error = await process.StandardError.ReadToEndAsync();

                await process.WaitForExitAsync();

                if (process.ExitCode == 0)
                {
                    MessageBox.Show("Dönüştürme işlemi başarılı.", "Bilgi", MessageBoxButtons.OK, MessageBoxIcon.Information);

                    if (File.Exists(inputFilePath))
                    {
                        File.Delete(inputFilePath);
                    }
                }
                else
                {
                    MessageBox.Show("Dönüştürme sırasında bir hata oluştu: " + error, "Hata", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show("Hata: " + ex.Message, "Hata", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private Form2 form2;

        private void button2_Click(object sender, EventArgs e)
        {
            if (form2 == null || form2.IsDisposed)
            {
                form2 = new Form2();
                form2.Show();
            }
            else
            {
                form2.BringToFront();
            }
        }
    }
}

Downloading with yd-dl.exe is successful. as soon as the video is downloaded I want to convert it to mp4 with ffmpeg but it won't convert without stopping the project.


Solution

  • You are handling the read from stdout and stderr in the wrong way. Getting their output must be done via an event handler instead of using await. That's why the applications aren't doing anything until you terminate, because they are blocked trying to read the console output. You must use this approach if you don't want it to block:

    Asynchronous way (I copied from here):

    using System.Diagnostics;
    
    Process process = new Process();
    
    void LaunchProcess()
    {
        process.EnableRaisingEvents = true;
        process.OutputDataReceived += new System.Diagnostics.DataReceivedEventHandler(process_OutputDataReceived);
        process.ErrorDataReceived += new System.Diagnostics.DataReceivedEventHandler(process_ErrorDataReceived);
        process.Exited += new System.EventHandler(process_Exited);
    
        process.StartInfo.FileName = "some.exe";
        process.StartInfo.Arguments = "param1 param2";
        process.StartInfo.UseShellExecute = false;
        process.StartInfo.RedirectStandardError = true;
        process.StartInfo.RedirectStandardOutput = true;
    
        process.Start();
        process.BeginErrorReadLine();
        process.BeginOutputReadLine();          
        
        //below line is optional if we want a blocking call
        //process.WaitForExit();
    }
    
    void process_Exited(object sender, EventArgs e)
    {
        Console.WriteLine(string.Format("process exited with code {0}\n", process.ExitCode.ToString()));
    }
    
    void process_ErrorDataReceived(object sender, DataReceivedEventArgs e)
    {
        Console.WriteLine(e.Data + "\n");
    }
    
    void process_OutputDataReceived(object sender, DataReceivedEventArgs e)
    {
        Console.WriteLine(e.Data + "\n");
    }