VisioForge

Last updated: 2026年1月

DirectShow.NET 替代方案:VisioForge .Net SDK 迁移指南

从 DirectShow.NET(已停止维护)迁移到 VisioForge .NET SDK 的分步指南,适用于 .NET 6-10 上的视频捕获、播放和处理。

从 DirectShow.NET(directshowlib)迁移到现代 .NET 6-10 视频捕获、播放和处理 SDK 的 C# 开发者

为什么要替换 DirectShow.NET?

DirectShow.NET 自2010年2月以来已被放弃——超过15年没有更新。它为 Microsoft 的 DirectShow API 提供原始 COM 接口定义,而 Microsoft 自身已弃用 DirectShow,转而使用 Media Foundation。

风险影响
Microsoft 已弃用 DirectShow没有新功能、编解码器或平台支持
库已停止维护.NET Framework 2.0,不支持 .NET 6+
COM 复杂性基本任务需要数百行代码,手动内存管理
编解码器搜寻必须查找、安装和注册第三方 DirectShow 滤镜
滤镜图调试不透明的管道故障,无诊断工具
仅限 WindowsCOM/DirectShow 无法在 macOS、Linux 或移动设备上运行
无现代编解码器没有第三方滤镜就无法使用原生 H.265、AV1、VP9
注册表问题现代 Windows 上的滤镜注册问题

DirectShow概念解析

了解DirectShow架构如何映射到VisioForge SDK有助于规划您的迁移。下表展示了DirectShow的每个核心概念如何转换为现代.NET等效项。

DirectShow架构到VisioForge等效项

DirectShow概念VisioForge等效项
Filter Graph (IGraphBuilder)管道 — SDK自动管理,或显式MediaBlocksPipeline
Source Filter(设备/文件)源设置:VideoCaptureDeviceSourceSettings、RTSPSourceSettings等
Transform Filter(效果/编码器)内置视频/音频效果 + 编码器类(H264EncoderSettings等)
Renderer Filter(视频窗口)VideoView控件(WinForms、WPF、MAUI、Avalonia)
Mux Filter(AVI/MP4 mux)输出格式类:MP4Output、AVIOutput、MKVOutput、WebMOutput
引脚连接自动 — 或在Media Blocks SDK中显式Block.Connect()
媒体类型(AM_MEDIA_TYPE)自动处理 — 无需手动格式协商
过滤器类别(设备枚举)DeviceEnumerator.Shared.VideoSourcesAsync() / AudioSourcesAsync()
DirectShow过滤器注册(regsvr32)NuGet包 — 无需系统注册
GraphEdit调试工具管道事件、日志记录、类型化异常

哪个 VisioForge SDK 替换什么?

DirectShow.NET 用途到 VisioForge 替代

DirectShow.NET 用途VisioForge 替代
通过滤镜图进行 C# 摄像头捕获Video Capture SDK .Net — `VideoCaptureCoreX`
C# IP 摄像头捕获(RTSP/MJPEG)Video Capture SDK .Net — `RTSPSourceSettings`
C# 屏幕捕获和录制Video Capture SDK .Net — `ScreenCaptureSourceSettings`
通过 `IGraphBuilder` 播放文件Media Player SDK .Net — `MediaPlayerCoreX`
通过 `IDvdControl2` 播放 DVDMedia Player SDK .Net — DVD 导航 API
通过 `IAMTVTuner` 电视调谐器Video Capture SDK .Net — `VideoCaptureCore`
文件转码Video Edit SDK .Net — `VideoEditCoreX`
自定义滤镜图Media Blocks SDK .Net — 模块化管道(400+ 模块)
`ISampleGrabber` 帧访问任何 SDK 上的 `OnVideoFrameBuffer` 事件

C# DirectShow 接口映射

C# DirectShow 接口映射

DirectShow.NET 接口VisioForge 等效
`IGraphBuilder`SDK 自动构建管道
`ICaptureGraphBuilder2``VideoCaptureCoreX` 构造函数
`IMediaControl` (Run/Stop/Pause)`StartAsync()` / `StopAsync()` / `PauseAsync()`
`IMediaEvent`SDK 事件(`OnError`、`OnStop` 等)
`IVideoWindow``VideoView` 控件(WinForms/WPF/MAUI/Avalonia)
`ISampleGrabber``OnVideoFrameBuffer` 事件
`IBaseFilter`不需要——SDK 内部管理滤镜
`IPin` / 引脚连接不需要——SDK 自动连接管道
`DsDevice.GetDevicesOfCat()``DeviceEnumerator.Shared.VideoSourcesAsync()`
`FilterCategory.VideoInputDevice``DeviceEnumerator.Shared.VideoSourcesAsync()`
`FilterCategory.AudioInputDevice``DeviceEnumerator.Shared.AudioSourcesAsync()`
`IAMTVTuner``VideoCaptureCore.TVTuner` 属性
`IDvdControl2``MediaPlayerCore.DVD_*` 方法
`Marshal.ReleaseComObject()``await sdk.DisposeAsync()`

C# 摄像头捕获与预览

DirectShow.NET — 摄像头捕获(迁移前)

C#
// 80+ lines of COM interop
var graphBuilder = (IGraphBuilder)new FilterGraph();
var captureGraph = (ICaptureGraphBuilder2)new CaptureGraphBuilder2();
int hr = captureGraph.SetFiltergraph(graphBuilder);
DsError.ThrowExceptionForHR(hr);

// Find video device
var devices = DsDevice.GetDevicesOfCat(FilterCategory.VideoInputDevice);
IBaseFilter sourceFilter;
hr = graphBuilder.AddSourceFilterForMoniker(
    devices[0].Mon, null, devices[0].Name, out sourceFilter);
DsError.ThrowExceptionForHR(hr);

// Render preview
hr = captureGraph.RenderStream(
    PinCategory.Preview, MediaType.Video, sourceFilter, null, null);
DsError.ThrowExceptionForHR(hr);

// Set video window
var videoWindow = (IVideoWindow)graphBuilder;
videoWindow.put_Owner(panelHandle);
videoWindow.put_WindowStyle(WindowStyle.Child | WindowStyle.ClipSiblings);
videoWindow.SetWindowPosition(0, 0, panel.Width, panel.Height);

// Start
var mediaControl = (IMediaControl)graphBuilder;
hr = mediaControl.Run();
DsError.ThrowExceptionForHR(hr);

// Cleanup (must release EVERY COM object)
Marshal.ReleaseComObject(sourceFilter);
Marshal.ReleaseComObject(captureGraph);
Marshal.ReleaseComObject(graphBuilder);

VisioForge — C# 摄像头捕获(迁移后)

C#
var capture = new VideoCaptureCoreX(videoView);
var devices = await DeviceEnumerator.Shared.VideoSourcesAsync();
capture.Video_Source = new VideoCaptureDeviceSourceSettings(devices[0]);
await capture.StartAsync();

// Cleanup
await capture.StopAsync();
await capture.DisposeAsync();

C# 摄像头录制为 MP4

DirectShow.NET — 摄像头转 MP4(迁移前)

C#
// Must find H.264 encoder filter, MP4 mux filter, file writer
// Each requires separate COM object management
var graphBuilder = (IGraphBuilder)new FilterGraph();
var captureGraph = (ICaptureGraphBuilder2)new CaptureGraphBuilder2();
captureGraph.SetFiltergraph(graphBuilder);

// Add source
var devices = DsDevice.GetDevicesOfCat(FilterCategory.VideoInputDevice);
IBaseFilter sourceFilter;
graphBuilder.AddSourceFilterForMoniker(
    devices[0].Mon, null, devices[0].Name, out sourceFilter);

// Find and add H.264 encoder (must be installed on system!)
// This varies by system — no guarantee the filter exists
Guid h264Clsid = new Guid("some-encoder-guid");
IBaseFilter encoder = (IBaseFilter)Activator.CreateInstance(
    Type.GetTypeFromCLSID(h264Clsid));
graphBuilder.AddFilter(encoder, "H.264 Encoder");

// Find and add MP4 mux
// Find and add file writer
// Connect source → encoder → mux → writer pins manually
// Each pin connection can fail silently or throw cryptic COM errors

// Configure encoder properties via ICodecAPI or IPropertyBag
// Different for every encoder filter...

var mediaControl = (IMediaControl)graphBuilder;
mediaControl.Run();

// Cleanup: release 5+ COM objects

VisioForge — C# 摄像头录制为 MP4(迁移后)

C#
var capture = new VideoCaptureCoreX(videoView);
var devices = await DeviceEnumerator.Shared.VideoSourcesAsync();
capture.Video_Source = new VideoCaptureDeviceSourceSettings(devices[0]);
capture.Outputs_Add(new MP4Output("recording.mp4"), true);
await capture.StartAsync();

C# 视频文件播放

DirectShow.NET — 视频播放(迁移前)

C#
var graphBuilder = (IGraphBuilder)new FilterGraph();
int hr = graphBuilder.RenderFile("video.mp4", null);
DsError.ThrowExceptionForHR(hr);

var videoWindow = (IVideoWindow)graphBuilder;
videoWindow.put_Owner(panelHandle);
videoWindow.put_WindowStyle(WindowStyle.Child);
videoWindow.SetWindowPosition(0, 0, panel.Width, panel.Height);

var mediaControl = (IMediaControl)graphBuilder;
mediaControl.Run();

// Seeking
var mediaSeeking = (IMediaSeeking)graphBuilder;
long position = 50000000; // 5 seconds in 100ns units
mediaSeeking.SetPositions(
    ref position, AMSeekingSeekingFlags.AbsolutePositioning,
    null, AMSeekingSeekingFlags.NoPositioning);

VisioForge — C# 视频播放器(迁移后)

C#
var player = new MediaPlayerCoreX(videoView);
await player.OpenAsync(new Uri("video.mp4"));
await player.PlayAsync();

// Seeking
await player.SeekAsync(TimeSpan.FromSeconds(5));

C# 视频帧捕获

DirectShow.NET — ISampleGrabber 帧捕获(迁移前)

C#
// Must insert ISampleGrabber into filter graph
var sampleGrabber = (ISampleGrabber)new SampleGrabber();
var mediaType = new AMMediaType();
mediaType.majorType = MediaType.Video;
mediaType.subType = MediaSubType.RGB24;
sampleGrabber.SetMediaType(mediaType);

graphBuilder.AddFilter((IBaseFilter)sampleGrabber, "Grabber");
// Connect pins...
sampleGrabber.SetBufferSamples(true);

// In callback: manually read buffer, create Bitmap from raw bytes
sampleGrabber.GetCurrentBuffer(ref bufferSize, buffer);
// Manual pixel format conversion, stride calculation, etc.

VisioForge — C# 视频帧捕获(迁移后)

C#
capture.OnVideoFrameBuffer += (s, e) =>
{
    // Frame data available as managed buffer
    // Or convert to SKBitmap/Bitmap directly
    var bitmap = e.Frame.ToBitmap();
    ProcessFrame(bitmap);
};

C# IP摄像头(RTSP)捕获

DirectShow.NET — RTSP捕获(迁移前)

C#
// Must find and install RTSP source filter (e.g., LAV, ffdshow)
// No standard DirectShow RTSP filter ships with Windows
var graphBuilder = (IGraphBuilder)new FilterGraph();

// Add RTSP source filter (if installed)
Guid rtspFilterClsid = new Guid("some-rtsp-filter-guid");
IBaseFilter rtspSource = (IBaseFilter)Activator.CreateInstance(
    Type.GetTypeFromCLSID(rtspFilterClsid));
graphBuilder.AddFilter(rtspSource, "RTSP Source");

// Configure URL via IFileSourceFilter or custom interface
var fileSource = (IFileSourceFilter)rtspSource;
fileSource.Load("rtsp://camera-ip:554/stream", null);

// Must manually connect pins to decoder, renderer
// No reconnection logic — if stream drops, graph stops
// No authentication helpers
// No ONVIF support

VisioForge — RTSP捕获(迁移后)

C#
var capture = new VideoCaptureCoreX(videoView);
capture.Video_Source = new RTSPSourceSettings(
    new Uri("rtsp://camera-ip:554/stream"))
{
    Login = "admin",
    Password = "password",
    ReconnectOnDrop = true
};
capture.Outputs_Add(new MP4Output("recording.mp4"), true);
await capture.StartAsync();

C# 屏幕捕获和录制

DirectShow.NET — 屏幕捕获(迁移前)

C#
// DirectShow has no built-in screen capture filter
// Must use third-party filter or custom push source
// Common approach: manually capture GDI/BitBlt in a thread,
// feed frames through a custom IBaseFilter implementation

// 200+ lines of custom filter code:
// - Implement IBaseFilter, IPin, IMediaSample
// - Manual frame rate timing with Thread.Sleep
// - Manual pixel format conversion
// - No GPU acceleration
// - No mouse cursor rendering
// - No multi-monitor support

VisioForge — 屏幕捕获(迁移后)

C#
var capture = new VideoCaptureCoreX(videoView);
capture.Video_Source = new ScreenCaptureSourceSettings()
{
    FrameRate = new VideoFrameRate(30),
    Rectangle = new Rect(0, 0, 1920, 1080),
    CaptureCursor = true
};
capture.Outputs_Add(new MP4Output("screen.mp4"), true);
await capture.StartAsync();

C# 麦克风音频录制

DirectShow.NET — 音频捕获(迁移前)

C#
var graphBuilder = (IGraphBuilder)new FilterGraph();
var captureGraph = (ICaptureGraphBuilder2)new CaptureGraphBuilder2();
captureGraph.SetFiltergraph(graphBuilder);

// Find audio device
var audioDevices = DsDevice.GetDevicesOfCat(
    FilterCategory.AudioInputDevice);
IBaseFilter audioSource;
graphBuilder.AddSourceFilterForMoniker(
    audioDevices[0].Mon, null, audioDevices[0].Name,
    out audioSource);

// Must find WAV/MP3 encoder filter
// Must find file writer filter
// Must connect pins manually
// Configure sample rate/channels via IAMStreamConfig

var mediaControl = (IMediaControl)graphBuilder;
mediaControl.Run();

// Manual COM cleanup for all objects

VisioForge — 音频捕获(迁移后)

C#
var capture = new VideoCaptureCoreX();
var audioDevices = await DeviceEnumerator.Shared
    .AudioSourcesAsync();
capture.Audio_Source = new AudioCaptureDeviceSourceSettings(
    audioDevices[0]);
capture.Audio_Record = true;
capture.Video_Record = false;
capture.Outputs_Add(new MP4Output("audio.mp4"), true);
await capture.StartAsync();

C# 自定义处理管道

DirectShow.NET — 自定义过滤器图(迁移前)

C#
// Building a custom graph: source > resize > overlay > encode > mux > write
// Each step requires finding/creating a filter, adding to graph,
// connecting pins with compatible media types

var graphBuilder = (IGraphBuilder)new FilterGraph();
// Add source filter...
// Add resize filter (must find one that's installed)...
// Add overlay filter (must write custom or find one)...
// Add H.264 encoder (system-dependent)...
// Add MP4 mux (system-dependent)...
// Add file writer...
// Connect each pair of pins manually...
// Handle format negotiation failures...
// Total: 150-300 lines, fragile, system-dependent

VisioForge Media Blocks — 自定义管道(迁移后)

C#
var pipeline = new MediaBlocksPipeline();

var source = new SystemVideoSourceBlock(
    new VideoCaptureDeviceSourceSettings(device));
var resize = new ResizeBlock(1920, 1080);
var overlay = new TextOverlayBlock("Recording...");
var encoder = new H264EncoderBlock();
var sink = new MP4SinkBlock("output.mp4");

pipeline.Connect(source.Output, resize.Input);
pipeline.Connect(resize.Output, overlay.Input);
pipeline.Connect(overlay.Output, encoder.Input);
pipeline.Connect(encoder.Output, sink.Input);

await pipeline.StartAsync();

迁移清单

  • 审计 DirectShow.NET 使用情况——查找所有 `using DirectShowLib` 引用
  • 识别滤镜图用途——捕获、播放、转码或自定义处理
  • 选择 VisioForge SDK——Video Capture、Media Player、Video Edit 或 Media Blocks
  • 安装 NuGet 包——将 DirectShowLib NuGet 替换为 VisioForge 包
  • 替换滤镜图代码
  • 移除 COM 清理代码——VisioForge 使用 `IAsyncDisposable`
  • 移除第三方 DirectShow 滤镜依赖——VisioForge 包含编解码器
  • 面向现代 .NET——.NET 6-10
  • 跨平台测试
  • 移除 DirectShow 滤镜注册——不再需要

迁移后的收获

方面DirectShow.NET迁移后
代码行数每个功能100+行每个功能5-10行
框架.NET Framework 2.0.NET 6-10
平台仅限 WindowsWindows、macOS、Linux、iOS、Android
API 风格原始 COM,手动引脚连接类型化 async C# API
编解码器查找并安装 DirectShow 滤镜内置(H.264、H.265、AV1、VP9)
内存管理手动 `Marshal.ReleaseComObject``IAsyncDisposable`
调试不透明的 COM 错误(HRESULT)类型化异常、事件
视频效果需要查找效果滤镜40+ 内置(GPU + CPU)
音频效果40+(EQ、混响、合唱、3D)
流媒体不可用RTMP、HLS、SRT、NDI
检测不可用运动(MOG2)、人脸(Haar/DNN/DLib)、行人(HOG+SVM)、条形码
硬件编码需要查找编码器滤镜NVENC、QSV、AMF、VideoToolbox
IP 摄像头手动滤镜图RTSP、RTMP、HLS、ONVIF(自动重连)
维护已放弃(2010)活跃开发

Frequently Asked Questions

DirectShow.NET 还在维护吗?
不。DirectShow.NET 自2010年2月以来已被放弃。Microsoft 也已弃用底层 DirectShow API,转而使用 Media Foundation。
C# 视频捕获的最佳 DirectShow.NET 替代方案是什么?
VisioForge Video Capture SDK .Net 用类型化 async API 替换 DirectShow 滤镜图。需要80多行 COM 互操作的摄像头捕获变成5行 C# 代码,并提供内置录制、硬件编码和跨平台支持。
VisioForge 能替换自定义 DirectShow 滤镜图吗?
可以。VisioForge Media Blocks SDK 提供了一个包含400多个模块的模块化管道,替代自定义滤镜图构建。
VisioForge 支持 .NET 6、.NET 8、.NET 9 和 .NET 10 吗?
是的。所有 VisioForge .Net SDK 包支持 .NET 6 到 .NET 10,包括跨平台部署。
我还需要在系统上安装 DirectShow 滤镜吗?
不需要。VisioForge 捆绑了自己的编解码器和解码器。H.264、H.265、AV1、VP9、AAC 等编解码器开箱即用。
我可以从 DirectShow.NET 逐步迁移吗?
可以。VisioForge SDK 可以与 DirectShow.NET 在同一项目中共存。一次替换一个滤镜图。

开始迁移

相关迁移指南