偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

使用C#封裝FFmpeg實(shí)現(xiàn)視頻格式轉(zhuǎn)換,你學(xué)會(huì)了嗎?

開(kāi)發(fā) 架構(gòu)
FFmpeg是一個(gè)功能強(qiáng)大的開(kāi)源多媒體框架,可以用于視頻和音頻的編碼、解碼、轉(zhuǎn)碼等操作。本文將介紹如何使用C#封裝FFmpeg,實(shí)現(xiàn)一個(gè)簡(jiǎn)單但功能完整的視頻格式轉(zhuǎn)換工具。

1. 簡(jiǎn)介

FFmpeg是一個(gè)功能強(qiáng)大的開(kāi)源多媒體框架,可以用于視頻和音頻的編碼、解碼、轉(zhuǎn)碼等操作。本文將介紹如何使用C#封裝FFmpeg,實(shí)現(xiàn)一個(gè)簡(jiǎn)單但功能完整的視頻格式轉(zhuǎn)換工具。

2. 環(huán)境準(zhǔn)備

  • Visual Studio 2022
  • .NET 6.0或更高版本
  • FFmpeg可執(zhí)行文件 (ffmpeg.exe) 可以從官網(wǎng)下載:https://ffmpeg.org/download.html

3. 項(xiàng)目實(shí)現(xiàn)

3.1 創(chuàng)建FFmpeg包裝類(lèi)

首先,我們創(chuàng)建一個(gè)FFmpegWrapper類(lèi)來(lái)封裝FFmpeg的核心功能:

using System.Diagnostics;

public class FFmpegWrapper
{
    private readonly string _ffmpegPath;

    // FFmpeg進(jìn)程執(zhí)行的事件委托
    public delegate void OnProgressHandler(double percentage);
    public event OnProgressHandler OnProgress;

    // 構(gòu)造函數(shù)
    public FFmpegWrapper(string ffmpegPath)
    {
        _ffmpegPath = ffmpegPath;
        if (!File.Exists(_ffmpegPath))
        {
            throw new FileNotFoundException("FFmpeg executable not found!", _ffmpegPath);
        }
    }

    /// <summary>
    /// 獲取視頻信息
    /// </summary>
    public async Task<VideoInfo> GetVideoInfoAsync(string inputPath)
    {
        if (!File.Exists(inputPath))
        {
            throw new FileNotFoundException("Input video file not found!", inputPath);
        }

        var startInfo = new ProcessStartInfo
        {
            FileName = _ffmpegPath,
            Arguments = $"-i \"{inputPath}\"",
            RedirectStandardError = true,
            UseShellExecute = false,
            CreateNoWindow = true
        };

        using var process = new Process { StartInfo = startInfo };
        process.Start();

        string output = await process.StandardError.ReadToEndAsync();
        await process.WaitForExitAsync();

        // 解析視頻信息
        return ParseVideoInfo(output);
    }

    /// <summary>
    /// 轉(zhuǎn)換視頻格式
    /// </summary>
    public async Task ConvertVideoAsync(string inputPath, string outputPath, VideoConversionOptions options)
    {
        if (!File.Exists(inputPath))
        {
            throw new FileNotFoundException("Input video file not found!", inputPath);
        }

        // 構(gòu)建FFmpeg命令
        string arguments = BuildFFmpegArguments(inputPath, outputPath, options);

        var startInfo = new ProcessStartInfo
        {
            FileName = _ffmpegPath,
            Arguments = arguments,
            RedirectStandardError = true,
            UseShellExecute = false,
            CreateNoWindow = true
        };

        using var process = new Process { StartInfo = startInfo };

        // 添加輸出數(shù)據(jù)接收處理
        process.ErrorDataReceived += (sender, e) =>
        {
            if (e.Data != null)
            {
                UpdateProgress(e.Data);
            }
        };

        process.Start();
        process.BeginErrorReadLine();

        await process.WaitForExitAsync();

        if (process.ExitCode != 0)
        {
            throw new Exception($"FFmpeg process exited with code {process.ExitCode}");
        }
    }

    /// <summary>
    /// 構(gòu)建FFmpeg命令參數(shù)
    /// </summary>
    private string BuildFFmpegArguments(string inputPath, string outputPath, VideoConversionOptions options)
    {
        var args = new List<string>
        {
            "-i", $"\"{inputPath}\"",
            "-y" // 覆蓋輸出文件
        };

        // 添加視頻編碼器
        if (!string.IsNullOrEmpty(options.VideoCodec))
        {
            args.Add("-c:v");
            args.Add(options.VideoCodec);
        }

        // 添加音頻編碼器
        if (!string.IsNullOrEmpty(options.AudioCodec))
        {
            args.Add("-c:a");
            args.Add(options.AudioCodec);
        }

        // 設(shè)置視頻比特率
        if (options.VideoBitrate > 0)
        {
            args.Add("-b:v");
            args.Add($"{options.VideoBitrate}k");
        }

        // 設(shè)置音頻比特率
        if (options.AudioBitrate > 0)
        {
            args.Add("-b:a");
            args.Add($"{options.AudioBitrate}k");
        }

        // 設(shè)置分辨率
        if (!string.IsNullOrEmpty(options.Resolution))
        {
            args.Add("-s");
            args.Add(options.Resolution);
        }

        // 添加輸出文件路徑
        args.Add($"\"{outputPath}\"");

        return string.Join(" ", args);
    }

    /// <summary>
    /// 更新轉(zhuǎn)換進(jìn)度
    /// </summary>
    private void UpdateProgress(string data)
    {
        // 解析FFmpeg輸出,計(jì)算進(jìn)度
        if (data.Contains("time="))
        {
            try
            {
                var timeIndex = data.IndexOf("time=");
                var timeStr = data.Substring(timeIndex + 5, 11);
                var time = TimeSpan.Parse(timeStr);

                // 假設(shè)我們已經(jīng)知道總時(shí)長(zhǎng),這里簡(jiǎn)化處理
                double percentage = (time.TotalSeconds / 100.0) * 100;
                OnProgress?.Invoke(Math.Min(percentage, 100));
            }
            catch
            {
                // 解析失敗時(shí)忽略
            }
        }
    }

    /// <summary>
    /// 解析視頻信息
    /// </summary>
    private VideoInfo ParseVideoInfo(string ffmpegOutput)
    {
        var videoInfo = new VideoInfo();

        // 解析時(shí)長(zhǎng)
        var durationMatch = System.Text.RegularExpressions.Regex.Match(ffmpegOutput, @"Duration: (\d{2}):(\d{2}):(\d{2})\.(\d{2})");
        if (durationMatch.Success)
        {
            videoInfo.Duration = TimeSpan.Parse($"{durationMatch.Groups[1]}:{durationMatch.Groups[2]}:{durationMatch.Groups[3]}.{durationMatch.Groups[4]}");
        }

        // 解析分辨率
        var resolutionMatch = System.Text.RegularExpressions.Regex.Match(ffmpegOutput, @"(\d{2,4})x(\d{2,4})");
        if (resolutionMatch.Success)
        {
            videoInfo.Width = int.Parse(resolutionMatch.Groups[1].Value);
            videoInfo.Height = int.Parse(resolutionMatch.Groups[2].Value);
        }

        return videoInfo;
    }
}

/// <summary>
/// 視頻轉(zhuǎn)換選項(xiàng)類(lèi)
/// </summary>
public class VideoConversionOptions
{
    public string VideoCodec { get; set; }
    public string AudioCodec { get; set; }
    public int VideoBitrate { get; set; }
    public int AudioBitrate { get; set; }
    public string Resolution { get; set; }
}

/// <summary>
/// 視頻信息類(lèi)
/// </summary>
public class VideoInfo
{
    public TimeSpan Duration { get; set; }
    public int Width { get; set; }
    public int Height { get; set; }
}

3.2 使用示例

下面是如何使用FFmpegWrapper類(lèi)的示例代碼:

static async Task Main(string[] args)
{
    try
    {
        // 初始化FFmpeg包裝器
        var ffmpeg = new FFmpegWrapper(@"D:\Software\ffmpeg-master-latest-win64-gpl-shared\bin\ffmpeg.exe");

        // 設(shè)置進(jìn)度回調(diào)
        ffmpeg.OnProgress += (percentage) =>
        {
            Console.WriteLine($"轉(zhuǎn)換進(jìn)度: {percentage:F2}%");
        };

        // 獲取視頻信息
        string inputPath = @"D:\Video\1.mp4";
        var videoInfo = await ffmpeg.GetVideoInfoAsync(inputPath);
        Console.WriteLine($"視頻時(shí)長(zhǎng): {videoInfo.Duration}");
        Console.WriteLine($"分辨率: {videoInfo.Width}x{videoInfo.Height}");

        // 設(shè)置轉(zhuǎn)換選項(xiàng)
        var options = new VideoConversionOptions
        {
            VideoCodec = "libx264", // H.264編碼
            AudioCodec = "aac",     // AAC音頻編碼
            VideoBitrate = 2000,    // 2000kbps視頻比特率
            AudioBitrate = 128,     // 128kbps音頻比特率
            Resolution = "1280x720" // 720p分辨率
        };

        // 執(zhí)行轉(zhuǎn)換
        string outputPath = @"D:\output.mkv";
        await ffmpeg.ConvertVideoAsync(inputPath, outputPath, options);

        Console.WriteLine("視頻轉(zhuǎn)換完成!");
    }
    catch (Exception ex)
    {
        Console.WriteLine($"錯(cuò)誤: {ex.Message}");
    }
}

圖片圖片

4. 常見(jiàn)視頻轉(zhuǎn)換場(chǎng)景

4.1 轉(zhuǎn)換為MP4格式

var options = new VideoConversionOptions
{
    VideoCodec = "libx264",
    AudioCodec = "aac",
    VideoBitrate = 2000,
    AudioBitrate = 128
};
await ffmpeg.ConvertVideoAsync("input.avi", "output.mp4", options);

4.2 轉(zhuǎn)換為WebM格式

var options = new VideoConversionOptions
{
    VideoCodec = "libvpx-vp9",
    AudioCodec = "libvorbis",
    VideoBitrate = 1500,
    AudioBitrate = 128
};
await ffmpeg.ConvertVideoAsync("input.mp4", "output.webm", options);

4.3 壓縮視頻

var options = new VideoConversionOptions
{
    VideoCodec = "libx264",
    AudioCodec = "aac",
    VideoBitrate = 1000, // 降低比特率
    Resolution = "1280x720" // 降低分辨率
};
await ffmpeg.ConvertVideoAsync("input.mp4", "compressed.mp4", options);

5. 總結(jié)

本文介紹了如何使用C#封裝FFmpeg實(shí)現(xiàn)視頻格式轉(zhuǎn)換功能。通過(guò)封裝,我們可以:

  • 更方便地調(diào)用FFmpeg功能
  • 監(jiān)控轉(zhuǎn)換進(jìn)度
  • 獲取視頻信息
  • 靈活設(shè)置轉(zhuǎn)換參數(shù)

這個(gè)實(shí)現(xiàn)可以作為基礎(chǔ),根據(jù)實(shí)際需求進(jìn)行擴(kuò)展,比如添加更多的轉(zhuǎn)換選項(xiàng)、支持更多的格式等。

責(zé)任編輯:武曉燕 來(lái)源: 技術(shù)老小子
相關(guān)推薦

2024-10-16 11:28:42

2024-12-31 00:08:37

C#語(yǔ)言dynamic?

2024-09-10 10:34:48

2024-11-06 11:38:59

C#單例模式

2024-12-23 10:06:45

C#深拷貝技術(shù)

2022-06-16 07:50:35

數(shù)據(jù)結(jié)構(gòu)鏈表

2024-05-07 07:58:47

C#程序類(lèi)型

2024-05-17 08:42:52

AttributeMyClass方法

2024-02-02 11:03:11

React數(shù)據(jù)Ref

2024-10-21 07:05:14

C#特性語(yǔ)言

2022-03-05 23:29:18

LibuvwatchdogNode.js

2024-01-29 08:21:59

AndroidOpenCV車(chē)牌

2025-06-20 09:57:42

2024-07-03 08:15:39

C#字符串表達(dá)式

2023-08-01 12:51:18

WebGPT機(jī)器學(xué)習(xí)模型

2024-01-02 12:05:26

Java并發(fā)編程

2021-12-01 07:19:44

C# Npoi Excel

2024-07-29 10:35:44

KubernetesCSI存儲(chǔ)

2023-12-27 07:31:45

json產(chǎn)品場(chǎng)景

2023-10-30 07:05:31

點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)