首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計疑難解答

C# 錄屏直接上傳服務器不落地:FFmpeg 管道流 + HTTP 分塊傳輸實現

     編輯:程式設計疑難解答

核心思路

不生成本地文件,而是將編碼器輸出直接通過管道/流寫入 HTTP 請求體(Chunked Transfer Encoding),服務器端流式接收寫入磁盤或對象存儲。

方案架構

┌─────────────┐     原始視頻流      ┌─────────────┐     HTTP Chunked      ┌─────────────┐
│  屏幕捕獲   │ ─────────────────▶ │  FFmpeg編碼  │ ────────────────────▶ │  服務器接收  │
│  (Desktop   │  (管道/共享內存)    │  (H.264/    │  (multipart/form-data │  (流式寫入   │
│   Duplication)│                   │   VP8/HEVC)  │   或原始二進制流)      │  文件/OSS)  │
└─────────────┘                    └─────────────┘                        └─────────────┘

關鍵技術點

  1. 屏幕捕獲:Windows Desktop Duplication API (DXGI) 效能最高,或 Graphics.CopyFromScreen(簡單但慢)。推薦成熟庫 ScreenCapture.NET、SharpDX。
  2. FFmpeg 管道輸出:
    ffmpeg -f rawvideo -pix_fmt bgra -s 1920x1080 -r 30 -i pipe:0 \
           -c:v libx264 -preset ultrafast -tune zerolatency -f mp4 -movflags frag_keyframe+empty_moov pipe:1
    • pipe:0 讀取 stdin(原始幀),pipe:1 輸出 stdout(MP4 片段)。
    • -movflags frag_keyframe+empty_moov 產生可流式播放的 fMP4(無需 moov 原子在文件尾)。
  3. C# 啟動 FFmpeg 進程並連接流:
    var psi = new ProcessStartInfo {
        FileName = "ffmpeg.exe",
        Arguments = @"-f rawvideo -pix_fmt bgra -s 1920x1080 -r 30 -i pipe:0 -c:v libx264 -preset ultrafast -tune zerolatency -f mp4 -movflags frag_keyframe+empty_moov pipe:1",
        UseShellExecute = false,
        RedirectStandardInput = true,
        RedirectStandardOutput = true,
        CreateNoWindow = true
    };
    var ffmpeg = Process.Start(psi);
    // 寫入原始幀到 ffmpeg.StandardInput.BaseStream
    // 讀取 ffmpeg.StandardOutput.BaseStream 並 POST 到服務器
  4. HTTP 分塊上傳:
    using (var client = new HttpClient()) {
        client.DefaultRequestHeaders.TransferEncodingChunked = true;
        using (var content = new StreamContent(ffmpeg.StandardOutput.BaseStream)) {
            content.Headers.ContentType = new MediaTypeHeaderValue("video/mp4");
            var response = await client.PostAsync("https://api.example.com/upload/stream", content);
        }
    }
    服務器端 需支持 Chunked 請求體流式讀取(ASP.NET Core Request.Body、Node.js req.pipe()、Java request.getInputStream()、Go r.Body、Nginx proxy_request_buffering off)。

替代方案:WebRTC / MediaRecorder (瀏覽器端)

若是 Web 端錄屏,直接用 navigator.mediaDevices.getDisplayMedia() + MediaRecorder 產生 Blob 片段,WebSocket/WebRTC 實時推流到媒體服務器,完全無本地文件。

避坑指南

  • 內存壓力:若網絡波動,FFmpeg 輸出緩衝區會堆積,需設置 Process.StandardOutput.BaseStream 讀取速度 ≥ 寫入速度,或限制碼率(-b:v 2M)。
  • 編碼延遲:ultrafast + zerolatency 將延遲壓至 100-200ms,適合實時場景。
  • 服務器存儲:流式寫入時無法預知文件大小,建議先寫臨時文件,錄制結束重命名,或直接寫入 MinIO/S3(支持分片上傳)。
  • Windows 7/8 不支持 Desktop Duplication:需降級用 GDI 捕獲或要求 Win 10+。

開源項目參考

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved