首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> C# >> 關於C#

C# DirectX 視訊播放實作指南:Microsoft.DirectX.AudioVideoPlayback 完整教學

     編輯:關於C#

前言

DirectX 是微軟提供的多媒體 API 函式庫,抽象化硬體差異,提供統一介面操作顯示卡、聲音卡、輸入裝置。Managed DirectX (MDX) 讓 .NET 開發者能直接使用 DirectX 功能。本文示範使用 `Microsoft.DirectX.AudioVideoPlayback` 命名空間實作簡易視訊播放器,涵蓋開檔、播放、暫停、停止、全螢幕、視訊畫面宿主等核心功能。

環境準備

  1. 安裝 DirectX SDK:下載 `dxsdk_apr2005.exe` (或更新版本) 並安裝
  2. 參考組件:專案右鍵 → Add Reference → Browse 找到 `Microsoft.DirectX.AudioVideoPlayback.dll` (通常在 `C:\Windows\Microsoft.NET\Managed DirectX\v9.02.2904\`)
  3. 引入命名空間:`using Microsoft.DirectX.AudioVideoPlayback;`

核心類別架構

類別用途關鍵成員
Video視訊播放核心類別Owner, Play(), Pause(), Stop(), CurrentPosition, Duration, State, Fullscreen
Audio音訊播放核心類別同上,無視訊畫面
TextureRenderEventArgs自訂繪製事件參數進階自訂渲染用

Video 類別關鍵屬性/方法

成員型別說明
OwnerControl視訊畫面宿主控制項 (通常是 Panel)
CurrentPositiondouble目前播放位置 (秒),可讀寫 (Seek)
Durationdouble視訊總長度 (秒),唯讀
StateStateFlags播放狀態:Playing, Paused, Stopped, Buffering
Fullscreenbool全螢幕模式切換
Play()void開始/繼續播放
Pause()void暫停播放
Stop()void停止並重置位置
Dispose()void釋放非受控資源 (重要!)

完整實作:WinForms 視訊播放器

1. 表單設計

  • Panel `panelVideo` (Dock=Top, Size=540x346) - 視訊畫面宿主
  • Button `btnOpen` (Text="開啟") - 選擇檔案
  • Button `btnPlay` (Text="播放") - 播放
  • Button `btnPause` (Text="暫停") - 暫停
  • Button `btnStop` (Text="停止") - 停止
  • OpenFileDialog `ofdVideo` (Filter="視訊檔案|*.avi;*.mp4;*.wmv;*.mpg;*.mov|所有檔案|*.*")
  • TrackBar `trkPosition` - 進度條 (可選)
  • Timer `tmrUpdate` (Interval=500) - 更新進度條

2. 完整程式碼


using System;
using System.Drawing;
using System.Windows.Forms;
using Microsoft.DirectX.AudioVideoPlayback;

namespace VideoPlayerDemo
{
    public partial class MainForm : Form
    {
        private Video _video = null;
        private bool _isSeeking = false;

        public MainForm()
        {
            InitializeComponent();
            InitializePlayer();
        }

        private void InitializePlayer()
        {
            // 初始化按鈕狀態
            UpdateButtonStates(false);
            
            // 進度條事件
            trkPosition.MouseDown += (s, e) => _isSeeking = true;
            trkPosition.MouseUp += (s, e) => 
            {
                _isSeeking = false;
                if (_video != null)
                    _video.CurrentPosition = trkPosition.Value;
            };
            
            // 定時器更新進度
            tmrUpdate.Tick += (s, e) => UpdatePosition();
        }

        // 開啟檔案
        private void btnOpen_Click(object sender, EventArgs e)
        {
            ofdVideo.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyVideos);
            if (ofdVideo.ShowDialog() == DialogResult.OK)
            {
                OpenVideoFile(ofdVideo.FileName);
            }
        }

        private void OpenVideoFile(string filePath)
        {
            try
            {
                // 釋放舊視訊物件
                if (_video != null)
                {
                    _video.Stop();
                    _video.Dispose();
                    _video = null;
                }

                // 建立新視訊物件
                _video = new Video(filePath);
                
                // 設定宿主控制項 (關鍵步驟!)
                _video.Owner = panelVideo;
                
                // 重設 Panel 大小觸發重繪
                int w = panelVideo.Width, h = panelVideo.Height;
                panelVideo.Width = w; panelVideo.Height = h;
                
                // 播放第一幀顯示靜態畫面
                _video.Play();
                _video.Pause();
                
                // 更新 UI
                UpdateButtonStates(true);
                trkPosition.Maximum = (int)Math.Ceiling(_video.Duration);
                trkPosition.Value = 0;
                lblDuration.Text = FormatTime(_video.Duration);
                
                // 啟動更新定時器
                tmrUpdate.Start();
            }
            catch (Exception ex)
            {
                MessageBox.Show($"開啟視訊失敗:{ex.Message}", "錯誤", MessageBoxButtons.OK, MessageBoxIcon.Error);
                UpdateButtonStates(false);
            }
        }

        // 播放
        private void btnPlay_Click(object sender, EventArgs e)
        {
            _video?.Play();
        }

        // 暫停
        private void btnPause_Click(object sender, EventArgs e)
        {
            _video?.Pause();
        }

        // 停止
        private void btnStop_Click(object sender, EventArgs e)
        {
            if (_video != null)
            {
                _video.Stop();
                trkPosition.Value = 0;
                lblPosition.Text = "00:00";
            }
        }

        // 更新播放位置
        private void UpdatePosition()
        {
            if (_video == null || _isSeeking) return;
            
            try
            {
                double pos = _video.CurrentPosition;
                trkPosition.Value = (int)Math.Min(pos, trkPosition.Maximum);
                lblPosition.Text = FormatTime(pos);
                
                // 自動停止更新 (視訊結束)
                if (_video.State == StateFlags.Stopped)
                {
                    tmrUpdate.Stop();
                    UpdateButtonStates(false);
                }
            }
            catch { /* 忽略存取已釋放物件的例外 */ }
        }

        private void UpdateButtonStates(bool hasVideo)
        {
            btnPlay.Enabled = hasVideo;
            btnPause.Enabled = hasVideo;
            btnStop.Enabled = hasVideo;
            trkPosition.Enabled = hasVideo;
        }

        private string FormatTime(double seconds)
        {
            TimeSpan t = TimeSpan.FromSeconds(seconds);
            return t.ToString(t.Hours > 0 ? @"hh\:mm\:ss" : @"mm\:ss");
        }

        // 表單關閉時釋放資源
        protected override void OnFormClosing(FormClosingEventArgs e)
        {
            tmrUpdate.Stop();
            _video?.Dispose();
            base.OnFormClosing(e);
        }
    }
}

進階功能實作

音量控制


// Video/Audio 類別有 Audio 屬性可存取音訊控制
private void trkVolume_Scroll(object sender, EventArgs e)
{
    if (_video?.Audio != null)
    {
        // 音量範圍:-10000 (靜音) 到 0 (最大)
        _video.Audio.Volume = -10000 + (trkVolume.Value * 100); // 0-100 對應
    }
}

// 靜音切換
private void btnMute_Click(object sender, EventArgs e)
{
    if (_video?.Audio != null)
    {
        _video.Audio.Volume = btnMute.Text == "靜音" ? -10000 : 0;
        btnMute.Text = btnMute.Text == "靜音" ? "取消靜音" : "靜音";
    }
}

全螢幕切換


private void btnFullscreen_Click(object sender, EventArgs e)
{
    if (_video != null)
    {
        _video.Fullscreen = !_video.Fullscreen;
        btnFullscreen.Text = _video.Fullscreen ? "離開全螢幕" : "全螢幕";
    }
}

// 雙擊畫面切換全螢幕
private void panelVideo_DoubleClick(object sender, EventArgs e)
{
    btnFullscreen_Click(sender, e);
}

播放速度控制 (需 DirectShow 介面,MDX 不直接支援)


// 進階:透過 IMediaSeeking / IMediaControl 介面 (需 COM 互操作)
// 此處略過,建議改用 MediaFoundation 或 LibVLCSharp 獲得更好控制

支援更多格式:安裝編碼器

  • DirectX 依賴系統安裝的 DirectShow 解碼器
  • 常見格式:AVI (內建)、WMV (內建)、MPEG (需編碼器)、MP4/H.264 (需 LAV Filters / K-Lite Codec Pack)
  • 建議:專案部署時檢查必要編碼器,或改用內建編碼器的 MediaFoundation / LibVLCSharp

常見問題與解決方案

問題原因解決
找不到 Microsoft.DirectX.AudioVideoPlayback未安裝 Managed DirectX / 參考路徑錯誤安裝 DirectX SDK,手動加入參考 DLL
視訊畫面不顯示 / 黑畫面Owner 未正確設定 / Panel 可見度 / 格式不支援確認 _video.Owner = panelVideo;Panel.Visible=true;安裝編碼器
播放無聲音音訊裝置被佔用 / 格式不支援 / 靜音檢查系統音量、_video.Audio.Volume、安裝音訊解碼器
記憶體洩漏 / 重複開啟崩潰未正確 Dispose 舊 Video 物件開啟新檔前必須 _video?.Dispose()
拖曳進度條閃爍Timer 更新與手動 Seek 衝突使用 _isSeeking 旗標同步
MP4/H.264 無法播放系統缺少 H.264 DirectShow 解碼器安裝 LAV Filters 或 K-Lite Codec Pack,或改用 MediaFoundation

現代替代方案比較

方案優點缺點適用場景
Managed DirectX (本文)原生 .NET、API 簡單、輕量已停止更新、格式支援有賴系統編碼器、無硬體加速控制簡易播放器、Legacy 專案維護
MediaFoundation (MF.NET)Windows 內建、硬體加速、支援 H.264/HEVC、低延遲API 複雜、需 COM 互操作、文件較少高效能播放、UWP/WinUI 應用
LibVLCSharp跨平台、格式支援最全、功能豐富、活躍維護需部署 libvlc 原生庫、體積較大專業播放器、跨平台應用
FFmpeg + SharpFFmpeg完全控制、最強編解碼極高複雜度、需深度音視訊知識轉碼、串流、特殊處理
WPF MediaElementXAML 整合、支援硬體加速格式受限於 WPF/系統、Seek 不精確、記憶體洩漏歷史問題簡易 WPF 應用

總結

`Microsoft.DirectX.AudioVideoPlayback` 提供了極簡單的 API 讓 C# 開發者快速加入視訊播放功能。核心要點:

  1. Owner 屬性:必須指定宿主控制項 (Panel) 才能顯示畫面
  2. 生命週期管理:開啟新檔前 `Dispose()` 舊物件,表單關閉時 `Dispose()`
  3. 狀態機:Play/Pause/Stop 切換 State,配合 Timer 更新 UI
  4. 格式相容性:依賴系統 DirectShow 解碼器,生產環境建議安裝 LAV Filters

對於新專案,建議評估 **LibVLCSharp** (跨平台、功能完整) 或 **MediaFoundation** (Windows 原生、高效能)。但理解 MDX 基礎架構,有助於掌握音視訊播放的核心概念:解碼器、渲染器、時鐘、緩衝、同步。

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