# VisioForge Documentation and Website Content **Author:** VisioForge **License:** CC-BY-4.0 (https://creativecommons.org/licenses/by/4.0/) **Generated:** 2026-09-01 13:58:00 UTC (ce6e9447def) **MCP Server:** https://mcp.visioforge.com/mcp (public, no auth — prefer for structured queries) **Content Sources:** 1362 help documentation pages + 66 website pages --- # Help Documentation ## Delphi ActiveX SDK Setup - Installation and Configuration **URL:** https://www.visioforge.com/help/docs/delphi/general/ **Description:** Install and configure TVFMediaPlayer, TVFVideoCapture, and TVFVideoEdit components in Delphi. Covers 64-bit package setup, .otares errors, and IDE integration. **Tags:** All-in-One Media Framework, Delphi, ActiveX, Windows, VCL # Delphi/ActiveX Libraries for Multimedia Development Welcome to our developer documentation hub for Delphi/ActiveX multimedia libraries. This resource provides in-depth technical information, code examples, and implementation guides for developers working with our specialized components. ## Core Library Benefits Our libraries empower Delphi developers to create sophisticated multimedia applications with minimal coding effort. The components are engineered for maximum performance and reliability in professional development environments. Key advantages include: - Simplified implementation of complex multimedia features - Optimized performance for resource-intensive operations - Cross-version compatibility with multiple Delphi releases - Extensive customization options for specialized requirements ## Documentation Organization ### Technical Reference Materials Each library section contains detailed API references, implementation examples, and recommended practices. Navigate to the specific library documentation for complete information about: - Component properties and attributes - Method signatures and parameters - Event handlers and callback functions - Type definitions and constants ### Code Examples and Tutorials Our documentation includes practical code snippets and complete implementation examples to accelerate your development process. These examples demonstrate effective techniques for common multimedia programming scenarios. ## Installation Troubleshooting Guide When integrating our libraries into your development environment, you might encounter these known technical issues: ### 64-bit Architecture Compatibility Delphi's 64-bit compilation environment requires special configuration in some cases: - [Resolving Delphi 64-bit package installation problems](install-64bit/) - Handling memory alignment requirements in 64-bit environments - Addressing pointer size differences between architectures ### Resource File Management Proper resource handling is essential for stable operation: - [Fixing Delphi package installation issues with .otares files](install-otares/) - Resolving resource locking during development - Managing resource file paths in deployed applications ## Getting Started To begin implementing our libraries in your projects, follow the library-specific installation guides and review the sample applications. Our documentation provides step-by-step instructions to help you achieve optimal results. ---END OF PAGE--- ## Install VisioForge SDK on Delphi 64-bit — Setup Guide **URL:** https://www.visioforge.com/help/docs/delphi/general/install-64bit/ **Description:** Fix 64-bit BPL loading issues in Delphi IDE. Covers design-time vs runtime packages, library path configuration for x86/x64, and common error solutions. **Tags:** All-in-One Media Framework, Delphi, ActiveX, Windows, VCL # Mastering Delphi 64-bit Package Installation ## Introduction to 64-bit Development in Delphi The evolution to 64-bit computing represents a significant advancement for Delphi developers, opening doors to enhanced performance, expanded memory addressing capabilities, and improved resource utilization. Since the introduction of 64-bit support in Delphi XE2, developers have gained the powerful ability to compile native 64-bit Windows applications. This capability enables software to harness modern hardware architectures, access substantially larger memory spaces, and deliver optimized performance for data-intensive operations. However, this technological progression introduces a distinctive set of complexities, particularly regarding the installation and management of component packages (`.bpl` files). Many Delphi developers encounter perplexing obstacles when attempting to integrate 64-bit packages into their development workflow, leading to frustration and lost productivity. This in-depth guide explores these challenges thoroughly and provides meticulously detailed, actionable solutions. The fundamental issue originates from a critical architectural characteristic: **the Delphi Integrated Development Environment (IDE) remains a 32-bit application**, even in the most recent releases. This architectural discrepancy between the 32-bit IDE and the 64-bit compilation target creates numerous misunderstandings and technical difficulties related to package management. Understanding this architectural limitation constitutes the essential first step toward establishing a seamless development experience. We will thoroughly examine why the 32-bit IDE requires 32-bit design-time packages, explore proper project configuration techniques for both 32-bit and 64-bit targets, clarify the critical function of runtime packages, and outline extensive testing methodologies to ensure your applications perform flawlessly across both architectural environments. ## The Architectural Limitation: Why the 32-bit IDE Requires 32-bit Design-Time Packages ### Understanding the IDE's Architecture The Delphi IDE serves as the principal environment for visual component design, code editing, debugging operations, and comprehensive project management. When designers place components onto forms using the Form Designer, modify properties through the Object Inspector, or utilize specialized component editors, the IDE must load and execute code contained within the component's design-time package. Because `bds.exe` (the Delphi IDE executable) operates as a 32-bit process, it functions exclusively within the 32-bit memory address space and must adhere to the constraints of 32-bit execution environments. The IDE physically cannot load or execute 64-bit code directly—this represents a hardware and operating system limitation, not merely a software restriction. Any attempt to load a 64-bit DLL (or in Delphi terminology, a 64-bit `.bpl` package) into a 32-bit process will result in immediate failure, typically manifesting as error messages like "Can't load package %s" or obscure operating system error codes. ### Critical Design-Time Requirements For the IDE to function properly during design activities—enabling visual component manipulation, property configuration, and utilization of design-time features—it *must* load the **32-bit (x86)** version of component packages. This requirement is non-negotiable due to the fundamental architecture of the IDE and operating system memory management principles. This architectural limitation frequently leads to confusion among developers, creating misconceptions that only 32-bit packages are necessary, or generating questions about why separate 64-bit packages exist if the IDE cannot utilize them. The critical distinction lies in understanding the separation between **design time** operations (occurring within the 32-bit IDE) and **compile/run time** processes (where applications can target either 32-bit or 64-bit architectures). ## Step-by-Step Implementation: Installing 32-bit Design-Time Packages ### Essential First Step: Installing 32-bit Components Based on the architectural explanation above, the mandatory initial step always involves installing the 32-bit version of component packages into the Delphi IDE. This process establishes the foundation for all subsequent development activities. 1. **Acquire Necessary Package Files:** Ensure you possess both 32-bit and 64-bit compiled package files (`.bpl` and `.dcp`). The 32-bit files typically carry identifier suffixes such as `_x86`, `_Win32`, or may lack platform specifiers in older Delphi versions. Conversely, 64-bit packages normally include `_x64` or `_Win64` designations. These files typically generate automatically when building component library projects targeting both Win32 and Win64 platforms. When using third-party components, reputable vendors should supply both architectural versions. 2. **Launch Development Environment:** Start the Delphi IDE with appropriate user permissions. 3. **Access Package Installation Interface:** Navigate through the menu system to `Component > Install Packages...`. 4. **Initiate Package Addition:** Click the "Add..." button to begin the installation process. 5. **Locate 32-bit Package Files:** Browse to the directory containing your **32-bit** compiled package files (`.bpl`). Carefully select the 32-bit `.bpl` file and click "Open" to proceed. 6. **Complete Installation Process:** The package should appear in the "Design packages" list, typically enabled by default. Confirm the installation by clicking "OK". ### Verification and Troubleshooting The IDE will attempt to load the 32-bit package. When successful, your components should appear in the Tool Palette, enabling immediate use in the Form Designer. If the IDE fails to load the package, verify that you selected the correct 32-bit `.bpl` file and ensure that all dependency packages required by your target package are properly installed and accessible. **Critical Warning:** Never attempt to install 64-bit `.bpl` files using the `Component > Install Packages...` menu option. Such attempts will invariably fail because the 32-bit IDE architecture cannot load 64-bit code modules. ## Advanced Configuration: Setting Project Library Paths for Dual Platform Development ### Configuring Compiler Search Paths While the IDE utilizes 32-bit packages during design-time operations, the Delphi compiler requires precise information about where to locate appropriate files (`.dcu`, `.dcp`, `.obj`) for your specific target platform during compilation (either 32-bit or 64-bit). These settings are configured through project options, specifically within the library path configuration section. Importantly, these settings must be established separately for each target platform. 1. **Access Project Configuration:** Navigate to `Project > Options...` in the IDE menu. 2. **Select Appropriate Platform:** It is absolutely crucial to configure paths separately for each target platform. Utilize the "Target Platform" dropdown menu located at the top of the Project Options dialog. Begin configuration with the "32-bit Windows" selection. 3. **Navigate to Library Configuration Section:** In the options tree displayed on the left side, select `Delphi Compiler > Library` to access path settings. 4. **Configure 32-bit Library Paths:** Within the "Library path" field, click the ellipsis (...) button to open the path editor. Add the directory containing your compiled **32-bit** units (`.dcu` files) and the **32-bit** package's `.dcp` file for the components you've installed. Ensure this path specifically references the 32-bit output directory of your component library. 5. **Switch to 64-bit Configuration:** Change the "Target Platform" dropdown selection to "64-bit Windows". Notice that the "Library path" field might display different content or appear empty. 6. **Configure 64-bit Library Paths:** Repeat the previous path configuration process, but this time add directories containing your compiled **64-bit** units (`.dcu` files) and the **64-bit** package's `.dcp` file. This path *must* differ from the 32-bit path and correctly reference the 64-bit output directory. 7. **Review Additional Path Settings:** While the Library path configuration is essential for locating `.dcu` and `.dcp` files, also examine the `Browsing path` settings (used by code insight features) and verify the `DCP output directory` location is properly configured if you are building packages yourself. Configure these paths for both 32-bit and 64-bit platforms as well. 8. **Save Configuration Changes:** Click "OK" to preserve the project options settings. ### Avoiding Common Configuration Errors **Frequent Mistake:** Many developers forget to switch the "Target Platform" dropdown *before* setting the path for that platform. Configuring the 64-bit path while "32-bit Windows" remains selected (or vice-versa) represents a common source of compilation errors later in the development process. By correctly establishing these platform-specific library paths, you provide the compiler with precise information about where to locate necessary `.dcu` and `.dcp` files for the architecture currently under construction. ## Runtime Package Management Strategies ### Deciding on Linking Approaches Beyond instructing the compiler where to find units during compilation, you must determine how your final executable will link against component libraries. This critical decision is controlled through the "Runtime Packages" settings section. You have two principal options: 1. **Static Linking Approach:** If you leave the "Link with runtime packages" option unchecked (or remove all packages from the list), the compiler will directly incorporate necessary code and resources from your components into the final `.exe` file. This approach produces larger executable files but eliminates the requirement to distribute separate `.bpl` files alongside your application. 2. **Dynamic Linking (Runtime Packages) Approach:** If you enable "Link with runtime packages" and specify required packages, the compiler will *not* embed component code into your `.exe`. Instead, your application will dynamically load necessary `.bpl` files during execution. This strategy creates smaller executable files but requires deploying corresponding 32-bit or 64-bit `.bpl` files with your application distribution. ### Detailed Configuration Process 1. **Access Project Options:** Navigate to `Project > Options...` in the IDE menu. 2. **Select Target Platform:** Choose either "32-bit Windows" or "64-bit Windows" from the platform dropdown. 3. **Navigate to Package Settings:** Select `Packages > Runtime Packages` in the options navigation tree. 4. **Configure Linking Method:** Enable or disable the "Link with runtime packages" option based on your preferred linking approach determined earlier. 5. **Specify Required Packages:** When utilizing runtime packages, ensure the list contains the correct base names of packages your application requires (e.g., `MyComponentPackage`). Do *not* include platform suffixes or file extensions in these entries. Delphi automatically appends appropriate platform identifiers and loads the correct `_x86.bpl` or `_x64.bpl` files (or equivalent naming based on Delphi version/settings) during runtime. 6. **Configure Secondary Platform:** Switch the "Target Platform" selection and configure runtime package settings identically for the alternative platform. Typically, the decision to use or not use runtime packages remains consistent across both platforms, but package lists might differ if utilizing platform-specific libraries. 7. **Preserve Configuration:** Click "OK" to save the settings. ### Deployment Considerations **Critical Deployment Requirement:** If you choose dynamic linking with runtime packages, remember that you *must* distribute the correct architectural version (32-bit or 64-bit) of those `.bpl` files with your application. The 32-bit executable requires 32-bit `.bpl` files, while the 64-bit executable needs 64-bit `.bpl` files. Place these files either in the same directory as the `.exe` or in locations accessible through the system's PATH environment variable. ## Comprehensive Testing and Verification Methodologies ### Multi-platform Verification Configuration alone cannot guarantee success. Thorough testing becomes essential to confirm that everything functions as expected across both target platforms. 1. **Multi-platform Compilation:** Build your project explicitly for both "32-bit Windows" and "64-bit Windows" target platforms. Address any compiler errors that emerge during this process. Errors occurring during compilation frequently indicate incorrectly configured library paths (detailed in Step 2). 2. **32-bit Execution Testing:** Execute the compiled 32-bit application. Thoroughly test all functionality that depends on the components in question. Specifically look for: 3. Proper visual appearance and interactive behavior of components. 4. Absence of exceptions during component instantiation or method invocation. 5. If using runtime packages, verify the application launches without "Package XYZ not found" error messages. 6. **64-bit Execution Testing:** Execute the compiled 64-bit application. Perform identical tests as conducted with the 32-bit version. Pay particular attention to: 7. Any behavioral differences compared to the 32-bit version. 8. Runtime errors such as Access Violations, which might indicate underlying 64-bit compatibility issues in the component code or application logic (e.g., incorrect pointer arithmetic, integer size assumptions). 9. For runtime packages, check again for missing package errors, ensuring 64-bit `.bpl` files are properly accessible. 10. **Edge Case Evaluation:** Include testing scenarios that explore boundary conditions, particularly regarding memory usage if that represents a motivation for transitioning to 64-bit. Load extensive datasets and perform complex operations involving the components to stress-test the implementation. ### Interpreting Test Results Any discrepancies or errors encountered during runtime on one platform but not the other strongly suggest either a problem in package configuration (Steps 2 or 3) or potential 64-bit compatibility issues within the component or application code itself. Such issues require careful diagnosis and targeted resolution. ## Advanced Troubleshooting Guide ### Resolving Common Installation Issues - **"Package XYZ.bpl can't be installed because it is not a design time package."**: This error typically indicates an attempt to install a package via `Component > Install Packages` that lacks necessary design-time registrations or configuration flags. Verify that the package project is correctly configured as a design-time package or combined design-time & runtime package. - **"Can't load package XYZ.bpl. %1 is not a valid Windows application." / "The specified module could not be found."**: This almost certainly indicates an attempt to install a **64-bit** BPL into the 32-bit IDE via `Component > Install Packages`. Remember to install only 32-bit BPL files through this interface. The "module not found" variant may also occur if the package has dependencies that aren't properly installed or cannot be located. - **[Compiler Error] F1026 File not found: 'ComponentUnit.dcu'**: This error occurs during compilation (not at design time). It indicates the compiler cannot locate the required `.dcu` file for the currently selected target platform. Carefully review your `Project Options > Delphi Compiler > Library > Library path` settings for the *specific platform* you are currently compiling (Step 2). Ensure the path correctly references the appropriate directory (32-bit or 64-bit) containing the necessary `.dcu` files. - **[Linker Error] E2202 Required package 'XYZ' not found**: Similar to F1026, but occurring during the linking phase. This frequently indicates the `.dcp` file for the package cannot be found. Verify the Library Path (Step 2) includes the directory containing the correct platform's `.dcp` file. Additionally, ensure the package name appears correctly in `Project Options > Packages > Runtime Packages` if utilizing dynamic linking (Step 3). - **Runtime Error: "Package XYZ not found"**: This indicates your application was compiled to use runtime packages, but the required `.bpl` file (matching the application's architecture) cannot be located during application startup. Ensure the correct 32-bit or 64-bit `.bpl` files are deployed alongside your `.exe` file (as described in Step 3). - **Runtime Access Violations (AVs) only in 64-bit:** This typically indicates 64-bit compatibility issues in the code (either in your application or the component implementation). Common sources include: - Pointer arithmetic assuming `SizeOf(Pointer)=4` (valid only in 32-bit code). - Incorrect use of `Integer` instead of `NativeInt`/`NativeUInt` for handles or pointer-sized values. - Direct calls to Windows API functions using incorrect data types for 64-bit environments. - Data structure alignment issues. Debugging the 64-bit application becomes necessary to identify the specific cause of these violations. ## Working with Third-Party Component Packages ### Best Practices for External Components The principles outlined throughout this guide apply equally to third-party components. Reputable component vendors typically provide: 1. Detailed instructions for proper installation procedures. 2. Separate 32-bit and 64-bit compiled `.bpl`, `.dcp`, and `.dcu` files. 3. An installation utility that handles file placement in appropriate locations and potentially automates the installation of 32-bit design-time packages into the IDE. If an installer is provided, utilize it as your first approach. However, always validate project options (Library Paths, Runtime Packages) afterward, as installers may not perfectly configure paths for every possible project configuration or Delphi version. If you receive only raw library files without an installer, follow Steps 1-3 manually, carefully identifying and configuring paths for both 32-bit and 64-bit versions supplied by the vendor. When encountering issues, consult the vendor's documentation or contact their technical support team for assistance. ## Summary and Recommendations ### Key Implementation Strategies Successfully managing Delphi packages for both 32-bit and 64-bit development fundamentally depends on understanding the 32-bit nature of the IDE and meticulously configuring project options for each target platform independently. Always install the 32-bit package for design-time use, then carefully establish platform-specific Library Paths and Runtime Package settings to ensure the compiler and your final application can locate and utilize the correct files for the target architecture. While this approach introduces additional complexity compared to purely 32-bit development, the structured methodology enables you to leverage the substantial benefits of 64-bit compilation while maintaining a fully functional design-time experience within the familiar Delphi IDE environment. Consistent testing across both platforms represents the final, crucial verification step to guarantee robust, reliable applications that perform optimally in both 32-bit and 64-bit environments. --- Need additional information? Please [contact support](https://support.visioforge.com/) for assistance with specific scenarios or component issues. ---END OF PAGE--- ## Fix .otares File Errors in Delphi SDK Packages Guide **URL:** https://www.visioforge.com/help/docs/delphi/general/install-otares/ **Description:** Resolve missing .otares file errors in Delphi - troubleshoot resource issues, fix compilation errors, and restore package functionality. **Tags:** All-in-One Media Framework, Delphi, ActiveX, Windows, VCL # Fixing .otares File Errors in Delphi Packages ## How to Solve the .otares File Not Found Error in Delphi When working with Delphi packages, developers frequently encounter the frustrating .otares file not found error that can completely halt your development workflow. This practical guide explains the problem, identifies common causes, and provides tested solutions to get your projects back on track. ### What is an .otares File? To effectively troubleshoot this issue, you need to understand the role of .otares files in Delphi: - Resource files specific to Delphi development environments - Contain compiled resources including images, icons, and binary assets - Generated during package compilation processes - Critical for packages with visual components or resource-dependent features ### Typical Error Messages You'll likely encounter these errors during compilation or installation: ``` [dcc32 Error] E1026 File not found: 'Package_Name.otares' [dcc32 Error] E1026 Could not locate resource file 'Component_Package.otares' [dcc32 Error] Package compilation failed due to missing .otares file ``` ### When This Issue Typically Occurs These errors commonly appear when: 1. Installing third-party component packages 2. Upgrading to newer Delphi versions 3. Moving projects between development machines 4. Collaborating with team members on shared projects ### Why .otares File Errors Happen Several factors can trigger these errors: 1. **Missing Resource Files**: The .otares file isn't in the expected location 2. **Incorrect Path References**: Package configuration references wrong location 3. **Version Compatibility Issues**: Resource file compiled for different Delphi version 4. **Corrupted Resources**: The file exists but is damaged 5. **Permission Problems**: Environment lacks access rights to the resource location ### Step-by-Step Solution Guide Follow these practical steps to resolve .otares-related issues: 1. **Find and Examine the .dpk File** 2. Navigate to your package's source directory 3. Open the .dpk file in Delphi IDE or text editor 4. Review all resource references 5. Focus on `$R` directives 6. **Identify Problematic Resource Directives** 7. Search for lines starting with `$R` or `{$R}` 8. These lines specify resource file inclusions 9. Example of problematic directives: ``` {$R 'Component_Package.otares'} {$R '.\resources\ComponentResources.otares'} ``` 1. **Apply the Fix** **Comment out the problematic resource reference:** ``` // Original line {$R 'Component_Package.otares'} // Modified version // {$R 'Component_Package.otares'} ``` 1. **Rebuild the Package** 2. Save all changes to the .dpk file 3. Restart the Delphi IDE to ensure changes are recognized 4. Clean the project (Project → Clean) 5. Rebuild the package (Project → Build) 6. If successful, install the package ### Advanced Solutions for Persistent Issues When basic fixes don't work, try these advanced approaches: 1. **Recreate Resource Files** 2. Locate the original source files 3. Use Resource Compiler to rebuild the .otares file 4. Update package references to the new file 5. **Check Package Dependencies** 6. Look for circular dependencies 7. Verify installation order is correct 8. Ensure version compatibility 9. **Verify Environment Configuration** 10. Check BDSCOMMONDIR setting 11. Verify PATH variables for resource locations 12. Confirm library paths in IDE options --- For personalized assistance with this issue, [contact our support team](https://support.visioforge.com/) and our technical experts will guide you through resolving your specific package installation problems. ---END OF PAGE--- ## Delphi and ActiveX Video SDK - Playback, Capture, Editing **URL:** https://www.visioforge.com/help/docs/delphi/ **Description:** VCL components and ActiveX controls for video playback, capture, screen recording, and editing in Delphi and C++ Builder. **Tags:** All-in-One Media Framework, Delphi, ActiveX, Windows, VCL, Streaming, Editing **API:** TVFMediaPlayer, TVFVideoCapture, TVFVideoEdit # All-in-One Media Framework A set of Delphi/ActiveX libraries for video processing, playback, and capture called All-in-One Media Framework. These libraries help developers create professional video editing, playback, and capture applications with minimal effort and maximum performance. The framework provides a comprehensive solution for media handling in Delphi applications, offering high-performance video processing capabilities that would otherwise require extensive low-level programming. Developers can implement complex video workflows with simple component-based architecture. You can find the following library documentation here: ## Libraries - [TVFMediaPlayer](mediaplayer/) - Full-featured media player component with playlist support, frame-accurate seeking, and advanced playback controls - [TVFVideoCapture](videocapture/) - Powerful video capture component supporting webcams, capture cards, IP cameras, and screen recording - [TVFVideoEdit](videoedit/) - Professional video editing component with timeline support, transitions, filters, and output to multiple formats ## Implementation Examples The framework includes numerous examples demonstrating how to implement common media tasks: - Video players with custom controls and visualizations - Multi-camera recording applications - Video editing software with timeline support - Format conversion utilities - Streaming media applications ## General Information ActiveX packages can be used in multiple programming languages and development environments including Visual C++, Visual Basic, and C++ Builder. These components extend your software capabilities, accelerating development and improving performance. With ActiveX integration, you can incorporate existing software components into your projects, boosting efficiency and functionality. Our framework is compatible with all Delphi versions from Delphi 6 to Delphi 11 and beyond, making it suitable for both legacy projects and new development. The components maintain a consistent API across different Delphi versions, simplifying migration between different IDE versions. ## Technical Specifications - **Supported Media Formats**: MP4, AVI, MOV, MKV, MPEG, WMV and many others - **Audio Support**: AAC, MP3, PCM, WMA and other popular audio codecs - **Video Codecs**: H.264, H.265/HEVC, MPEG-4, VP9, AV1 and more - **Capture Sources**: Webcams, HDMI capture cards, IP cameras, screen capture - **Hardware Acceleration**: NVIDIA NVENC, Intel Quick Sync, AMD AMF ## x64 Support Limitations With Delphi XE2 and later, you can develop 64-bit applications. Our framework fully supports these 64-bit applications, allowing you to leverage modern computing power and handle larger memory requirements. 64-bit support enables processing of higher resolution videos and more complex editing operations that would be impossible in 32-bit environments. Microsoft Visual Basic 6 does not support 64-bit applications. If you're using Visual Basic 6, you'll need to use the 32-bit version of our framework due to VB6's inherent limitations. While 32-bit applications can access up to 4GB of memory with proper configuration, for demanding video applications, we recommend using Delphi or other development environments with 64-bit support. ## Development Best Practices When integrating the framework into your applications, consider these best practices: - Initialize components at design time when possible for better IDE integration - Use hardware acceleration for demanding operations like encoding and decoding - Implement proper error handling for media operations - Consider memory management for large media files - Test with various media sources to ensure compatibility --- For more information about the framework, visit the [All-in-One Media Framework (Delphi/ActiveX)](https://www.visioforge.com/all-in-one-media-framework) product page. ---END OF PAGE--- ## TVFMediaPlayer Delphi Changelog - Version History v3 to v10 **URL:** https://www.visioforge.com/help/docs/delphi/mediaplayer/changelog/ **Description:** TVFMediaPlayer changelog - track version history from 3.0 to 10.0 with 4K support, encryption, effects, streaming, and performance updates. **Tags:** All-in-One Media Framework, Delphi, ActiveX, DirectShow, Windows, VCL, Playback, Streaming **API:** TVFMediaPlayer # TVFMediaPlayer Library Changelog This document details the evolution of the TVFMediaPlayer library, chronicling the significant features, enhancements, optimizations, and bug fixes introduced across various versions. It serves as a comprehensive reference for developers tracking the library's progress and understanding the capabilities added over time. ## Version 10.0: Enhanced Media Handling and Customization Version 10.0 represents a significant step forward, focusing on improved media introspection, logging, customization, and compatibility. ### Core Enhancements - **Enhanced Media Information Reader:** This version significantly boosts the capabilities of the media information reader. It enables faster, more accurate extraction of metadata from an extensive array of media file types. Developers gain reliable access to critical details like duration, resolution, codec specifics, bitrates, and embedded tags, which streamlines media management and enhances the display capabilities within applications. - **Improved Logging Capabilities:** Logging has been substantially refined, offering developers more granular control. Configuration options now include distinct log levels (Debug, Info, Warning, Error) and flexible output destinations such as files, the console, or custom endpoints. This facilitates more effective issue diagnosis during development and robust monitoring of application behavior in production, ultimately leading to quicker troubleshooting and increased application stability. - **Standard Metadata Tag Support:** A cornerstone of this release is the introduction of comprehensive support for reading standard metadata tags embedded within popular video and audio containers. This includes formats like MP4, WMV, MP3, AAC, M4A, and Ogg Vorbis. Applications utilizing TVFMediaPlayer can now seamlessly extract and leverage common tags such as title, artist, album, genre, year, and cover art, thereby enriching the user experience by providing valuable context for the media being played. ### Capture and Effects Improvements - **Configurable Auto-Split Filenames:** The new `SeparateCapture_Filename_Mask` property provides fine-grained control over filenames when using the auto-split capture feature based on duration or size. This allows for customized naming conventions, improving organization and workflow for segmented recordings. - **JSON Settings Serialization:** Configuration settings for the media player can now be easily serialized to and deserialized from the widely-used JSON format. This simplifies saving and loading player configurations, enabling persistent settings and easier integration with configuration management systems. - **Custom Video Effects Pipeline:** Flexibility in video processing is enhanced with the ability to insert custom video effects using third-party filters identified by their CLSID. These filters can be strategically placed either before or after the main effects filter or sample grabber, allowing for sophisticated, tailored video manipulation pipelines. - **Optimized Video Effects:** Video effects processing has been optimized to take full advantage of the latest generations of Intel CPUs, resulting in smoother playback and lower resource consumption when applying effects. ### Source and Compatibility Fixes - **MP3 Splitter for Playback Issues:** An MP3 splitter has been integrated to specifically address and resolve playback inconsistencies encountered with certain non-standard or problematic MP3 files, ensuring broader compatibility. - **Updated VLC Source Filter:** The underlying VLC source filter has been updated to libVLC version 2.2.2.0. This update brings notable improvements, particularly in handling RTMP and HTTPS streams, and resolves previously identified memory leaks, contributing to enhanced stability and broader streaming protocol support. - **Pan and Blur Effect Fixes:** Specific issues related to the Pan effect in x64 builds and the Blur effect have been addressed and resolved, ensuring consistent visual effect behavior across different architectures. - **FFMPEG Source Memory Leak Resolved:** A memory leak associated with the FFMPEG source component has been identified and fixed, improving long-term stability and resource management during playback. ## Version 9.2: Engine Updates and Reader Enhancements This interim release focused on updating core components and further refining the media information capabilities. - **Updated VLC Engine:** The integrated VLC engine was updated to libVLC version 2.2.1.0, incorporating upstream fixes and improvements from the VLC project for better stability and format compatibility. - **Enhanced Media Information Reader:** Building upon previous improvements, the media information reader received further enhancements for broader file support and more accurate metadata extraction. - **Updated FFMPEG Engine:** The FFMPEG engine components were updated, ensuring compatibility with newer codecs and formats while incorporating performance optimizations. ## Version 9.1: Advanced Security Integration Version 9.1 introduced robust security features through integration with the Video Encryption SDK. - **Video Encryption SDK v9 Support:** This version added compatibility with the Video Encryption SDK v9. This enables developers to implement strong AES-256 encryption for their video content, using either separate key files or embedded binary data as keys, significantly enhancing content protection capabilities. ## Version 9.0: Audio Enhancements and Logo Flexibility Version 9.0 brought significant improvements to audio handling and visual branding options. - **Animated GIF Logo Support:** The capability to use image logos was expanded to include support for animated GIFs, allowing for more dynamic and engaging visual branding within the video playback interface. - **Audio Enhancements:** A suite of audio enhancement features was introduced, including audio normalization to ensure consistent volume levels, automatic gain control (AGC) to dynamically adjust volume, and manual gain controls for precise audio level adjustments. - **Percentage-Based Audio Volume:** The API for controlling audio volume was modernized to use a percentage-based system (0-100%), providing a more intuitive and standardized way to manage audio levels compared to previous methods. ## Version 8.6: Decoder Expansion and API Additions This release focused on expanding codec support, adding flexibility through custom filters, and refining the API. - **H264 CPU/Intel QuickSync Decoder:** A highly optimized H264 video decoder was added, leveraging both CPU resources and Intel QuickSync hardware acceleration where available. This significantly improves performance for decoding one of the most common video codecs. - **Custom DirectShow Video Filter Support:** Developers gained the ability to integrate their own custom DirectShow video filters into the playback graph, allowing for highly specialized video processing tasks. - **`OnNewFilePlaybackStarted` Event:** A new event, `OnNewFilePlaybackStarted`, was introduced. This event fires specifically when a new file begins playing within a playlist context, enabling applications to react precisely to transitions between media items. - **Updated Decoders:** The Ogg Vorbis audio decoder and WebM video decoders were updated to their latest versions, ensuring compatibility and performance improvements. - **Frame Grabber API Update:** The API for grabbing individual video frames was updated, potentially offering improved performance or flexibility. - **Bug Fixes:** Various unspecified bug fixes were implemented to improve overall stability and reliability. ## Version 8.5: Rotation, 4K Readiness, and Rendering Options Version 8.5 introduced innovative video manipulation features and prepared the engine for ultra-high-definition content. - **On-the-Fly Video Rotation:** A new video effect was added, enabling real-time rotation of the video stream during playback (e.g., 90, 180, 270 degrees). - **Updated FFMPEG Source:** The FFMPEG source component was updated, likely incorporating support for newer formats or improving performance. - **4K-Ready Video Effects:** Existing video effects were optimized and tested to ensure they perform efficiently with 4K resolution video content. - **VMR-9/EVR Zoom Shift Bug Fix:** A specific bug related to unexpected image shifting when using zoom with the VMR-9 or EVR video renderers was corrected. - **Direct2D Video Renderer (Beta):** A new video renderer based on Direct2D was introduced as a beta feature. This renderer included support for live video rotation and aimed to leverage modern graphics APIs for potentially improved performance and quality. - **Bug Fixes:** Included various general bug fixes to enhance stability. ## Version 8.4: Decoder Updates and Stability This was primarily a maintenance release focused on updating core components. - **Updated FFMPEG Decoder:** The FFMPEG decoder components were updated, likely incorporating fixes and improvements from the FFMPEG project. - **Bug Fixes:** Addressed various unspecified bugs for improved stability. ## Version 8.3: Stability Release This release focused solely on addressing bugs identified in previous versions. - **Bug Fixes:** Implemented various fixes to enhance the overall reliability and stability of the library. ## Version 8.0: Introducing the VLC Engine Version 8.0 marked a significant architectural addition by integrating the powerful VLC engine. - **VLC Engine Integration:** The renowned VLC engine was integrated as an alternative playback backend for video and audio files. This brought VLC's extensive format support and robust streaming capabilities to TVFMediaPlayer applications. - **Bug Fixes:** Included various general bug fixes. ## Version 7.x Series: Effects, Encryption, and Playlists The Version 7 series introduced key features related to playback control, security, and visual effects. ### Version 7.20 - **Reverse Playback:** Added the capability to play video files in reverse, opening up creative possibilities and specialized application use cases. - **Bug Fixes:** Addressed various bugs. ### Version 7.12 - **Video Encryption Support:** Initial support for video encryption was added, providing basic content protection mechanisms. - **Bug Fixes:** Included general stability improvements. ### Version 7.7 - **Fade-In/Fade-Out Effect:** A common and useful video transition effect, fade-in/fade-out, was added to the available video effects. - **Playlist Support:** Functionality for creating and managing playlists was introduced, allowing sequences of media files to be played automatically. - **Bug Fixes:** Addressed various issues. ### Version 7.5 - **Improved Chroma Key:** The chroma key (green screen) effect was enhanced for better quality and more precise control. - **Enhanced Text Logo:** The feature for overlaying text logos onto the video was improved. - **Modified Video Effects API:** The API for applying video effects underwent modifications, potentially for improved usability or to accommodate new features. - **Bug Fixes:** Included various stability fixes. ### Version 7.0 - **Windows 8 RTM Support:** Ensured compatibility with the release version of Windows 8. - **Enhanced Video Effects:** Further improvements were made to the quality and performance of existing video effects. - **New FFMPEG Playback Engine:** Introduced a new playback engine based on FFMPEG components, offering an alternative to the default DirectShow-based playback and expanding format compatibility. ## Version 6.x Series: Windows 8 Compatibility and Optimizations The Version 6 series focused on adapting to the then-new Windows 8 operating system and improving performance. ### Version 6.3 - **Windows 8 Customer Preview Support:** Added compatibility for the pre-release Customer Preview version of Windows 8. - **Improved Video Effects:** Continued refinement of video effect performance and quality. ### Version 6.0 - **Enhanced OpenCL Support:** Improved utilization of OpenCL for GPU acceleration tasks, potentially boosting performance for effects or decoding on compatible hardware. - **Windows 8 Developer Preview Support:** Added early support for the Developer Preview version of Windows 8. - **Improved Video Effects:** General enhancements to the video effects subsystem. ## Version 3.x Series: Early Features and Optimizations The Version 3 series laid groundwork features and focused on CPU-specific optimizations. ### Version 3.9 - **New Installers:** Introduced a new main installer and separate redistributable installers for easier deployment. - **Minor Bug Fixes:** Addressed minor outstanding issues. ### Version 3.7 - **Improved Video Effects:** Enhancements made to the video effects features. - **New Demo Applications:** Added new demo applications to showcase library capabilities. - **Netbook CPU Optimizations:** Included specific performance optimizations tailored for Intel Core II/Atom and AMD netbook processors. - **Minor Bug Fixes:** General stability improvements. ### Version 3.5 - **Improved Video Effects:** Continued work on enhancing video effects. - **Intel Core i7 Optimizations:** Added new performance optimizations specifically for the then-new Intel Core i7 CPU architecture. ### Version 3.0 - **Motion Detection:** Introduced a motion detection feature, enabling applications to react to changes within the video stream. - **Chroma Key:** Added initial chroma key (green screen) functionality. - **MMS/WMV Source Support:** Included support for streaming using the MMS protocol and playing WMV (Windows Media Video) files. - **CPU Optimizations:** Added performance optimizations targeted at Intel Atom and Core i3/i5/i7 processors. - **Direct Stream Processing:** Enabled the capability to directly access and process decoded video and audio stream data, offering advanced manipulation possibilities. ---END OF PAGE--- ## TVFMediaPlayer Deployment Guide — Delphi and ActiveX **URL:** https://www.visioforge.com/help/docs/delphi/mediaplayer/deployment/ **Description:** Deploy TVFMediaPlayer apps with silent installers or manual setup. Covers codec packages, DirectShow filters, VC++ redistributables, and dependencies. **Tags:** All-in-One Media Framework, Delphi, ActiveX, DirectShow, Windows, VCL, Playback, IP Camera **API:** TVFMediaPlayer # Deployment Guide for TVFMediaPlayer Deploying applications built with the TVFMediaPlayer library requires ensuring that all necessary components are correctly installed and configured on the target machine. This guide provides detailed instructions for both automated and manual deployment methods, catering to different scenarios and technical requirements. Whether you prefer the simplicity of silent installers or the granular control of manual setup, this document covers the essential steps to successfully deploy your Delphi or ActiveX media player application. ## Understanding Deployment Requirements Before deploying your application, it's crucial to understand the dependencies of the TVFMediaPlayer library. The library relies on several core components, including base runtimes, specific codecs (like FFMPEG or VLC for certain sources), and Microsoft Visual C++ Redistributables. The deployment method you choose will determine how these dependencies are handled. ### Core Components - **Base Library:** Contains the essential engine and DirectShow filters for basic playback functionality. - **Codec Packages:** Optional but often necessary for supporting a wide range of media formats and network streams (e.g., IP cameras). FFMPEG and VLC are common choices provided. - **Runtime Dependencies:** Microsoft Visual C++ Redistributable packages are required for the core library components to function correctly. Choosing the right deployment strategy depends on factors like user privileges on the target machine, the need for unattended installation, and the specific features of your application (e.g., which media sources it needs to support). ## Method 1: Automated Installation (Admin Rights Required) Using the provided silent installers is the most straightforward method for deploying the TVFMediaPlayer library components. These installers handle the registration of necessary files and ensure all dependencies are correctly placed. This method requires administrative privileges on the target machine as it involves system-level changes like registering COM components and potentially modifying the system PATH. ### Available Installers VisioForge provides separate installers for the base library and optional codec packages, with versions for both Delphi and ActiveX, and for x86 and x64 architectures. #### Base Package (Mandatory) This package installs the core TVFMediaPlayer components and essential DirectShow filters. It's always required, regardless of the media sources your application uses. Choose the installer corresponding to your development environment (Delphi or ActiveX) and target architecture (x86 or x64). - **Delphi:** - [x86 Installer](https://files.visioforge.com/redists_delphi/redist_media_player_base_delphi.exe) - [x64 Installer](https://files.visioforge.com/redists_delphi/redist_media_player_base_delphi_x64.exe) - **ActiveX:** - [x86 Installer](https://files.visioforge.com/redists_delphi/redist_media_player_base_ax.exe) - [x64 Installer](https://files.visioforge.com/redists_delphi/redist_media_player_base_ax_x64.exe) #### FFMPEG Package (Optional - For File/IP Camera Sources) If your application needs to play local files or stream from IP cameras using the FFMPEG engine, you must deploy this package. FFMPEG provides a wide range of codec support. - **FFMPEG:** - [x86 Installer](https://files.visioforge.com/redists_delphi/redist_media_player_ffmpeg.exe) - *Note: An x64 FFMPEG installer link was not explicitly provided in the original source; assume x86 covers most needs or consult VisioForge documentation for x64 specifics if required.* #### VLC Source Package (Optional - For File/IP Camera Sources) As an alternative or addition to FFMPEG, you can use the VLC engine for file and IP camera sources. This requires deploying the VLC package. Ensure you select the correct architecture. - **VLC:** - [x86 Installer](https://files.visioforge.com/redists_net/redist_dotnet_vlc_x86.exe) - [x64 Installer](https://files.visioforge.com/redists_net/redist_dotnet_vlc_x64.exe) ### Installer Usage These installers are designed for silent execution, making them suitable for inclusion in larger application setup routines or for deployment via scripts. Run the executable(s) with administrator privileges on the target machine. ``` # Example: Running the base Delphi x86 installer silently redist_media_player_base_delphi.exe /S ``` *(Note: The exact silent switch might vary; consult the installer documentation or use standard switches like `/S`, `/silent`, or `/q` if `/S` doesn't work).* ## Method 2: Manual Installation (Admin Rights Recommended) Manual installation offers more control but requires careful execution of each step. This method is suitable when automated installers cannot be used, or when deploying to environments with specific restrictions. While some steps might be achievable without full admin rights, registering COM components typically requires elevation. ### Prerequisites Before copying library files, ensure the necessary runtime dependencies are present on the target system. #### Install VC++ 2010 SP1 Redistributable The TVFMediaPlayer library relies on the Microsoft Visual C++ 2010 SP1 runtime. Install the appropriate version (x86 or x64) for your application's target architecture. - **VC++ 2010 SP1:** - [x86 Redistributable](https://files.visioforge.com/shared/vcredist_2010_x86.exe) - [x64 Redistributable](https://files.visioforge.com/shared/vcredist_2010_x64.exe) Run these installers before proceeding with the library file deployment. ### Deploying Core Library Files Follow these steps to manually install the base library components: 1. **Copy Core DLLs:** Locate the `Redist\Filters` folder within your TVFMediaPlayer installation directory. Copy all the DLL files from this folder to a deployment directory on the target machine. A common practice is to place these DLLs in the same folder as your application's executable. 2. **Register DirectShow Filters:** The core functionality relies on several DirectShow filters (`.ax` files). These must be registered with the Windows operating system using Component Object Model (COM) registration. - **Identify Filters:** The key filters to register are: - `VisioForge_Audio_Effects_4.ax` - `VisioForge_Dump.ax` - `VisioForge_RGB2YUV.ax` - `VisioForge_Video_Effects_Pro.ax` - `VisioForge_YUV2RGB.ax` - *(Note: Other `.ax` files might be present; register all `.ax` files found in the `Redist\Filters` directory).* - **Registration Method:** Use the `regsvr32.exe` command-line tool, which is part of Windows. Open an Command Prompt **as Administrator** and run the command for each `.ax` file. ``` # Example: Registering a filter (run from the directory containing the .ax file) regsvr32.exe VisioForge_Video_Effects_Pro.ax ``` Alternatively, VisioForge provides a utility `reg_special.exe` in the redistributables. Copy this utility to the folder containing the `.ax` files and run it with administrator privileges to register all filters in that directory automatically. Refer to Microsoft's documentation for troubleshooting `regsvr32.exe` errors: [How to use the Regsvr32 tool](https://support.microsoft.com/en-us/topic/how-to-use-the-regsvr32-tool-and-troubleshoot-regsvr32-error-messages-a98d960a-7392-e6fe-d90a-3f4e0cb543e5). 3. **Update System PATH (Optional but Recommended):** If the filter DLLs and `.ax` files are placed in a directory separate from your application's executable, you must add the path to this directory to the system's `PATH` environment variable. This allows the operating system and your application to locate these essential files. Failure to do this can result in "DLL not found" or filter registration errors. ### Deploying Optional Packages Manually #### FFMPEG Deployment 1. **Copy Files:** Copy the entire contents of the `Redist\FFMPEG` folder from your TVFMediaPlayer installation to a deployment directory on the target machine (e.g., a subfolder within your application's installation directory). 2. **Update System PATH:** Add the full path to the folder where you copied the FFMPEG files to the Windows system `PATH` environment variable. This is crucial for the library to find and load the FFMPEG components. #### VLC Deployment (Example: x86) 1. **Copy Files:** Copy the entire contents of the `Redist\VLC` folder (specifically the x86 version if applicable) to a deployment directory. 2. **Register VLC Filter:** Locate the `.ax` file within the copied VLC files (e.g., `axvlc.dll` or similar, though the original text only generically mentions ".ax file") and register it using `regsvr32.exe` with administrator privileges. 3. **Set Environment Variable:** Create a new system environment variable named `VLC_PLUGIN_PATH`. Set its value to the full path of the `plugins` subfolder within the directory where you copied the VLC files (e.g., `C:\YourApp\VLC\plugins`). This tells the VLC engine where to find its necessary plugin modules. ## Verification and Troubleshooting After deployment, thoroughly test your application on the target machine. - Check basic playback functionality. - Test any specific features that rely on optional packages (FFMPEG or VLC), such as playing various file formats or connecting to IP cameras. - If errors occur, double-check: - Admin rights during installation/registration. - Correct installation of VC++ Redistributables. - Successful registration of all `.ax` files (check `regsvr32.exe` output). - Accurate configuration of `PATH` and `VLC_PLUGIN_PATH` environment variables. - Correct architecture (x86/x64) match between your application, the library components, and runtime dependencies. --- Need further assistance? Contact [VisioForge Support](https://support.visioforge.com/). Explore more examples on our [GitHub](https://github.com/visioforge/). ---END OF PAGE--- ## Play Multiple Video Streams with Delphi SDK Player **URL:** https://www.visioforge.com/help/docs/delphi/mediaplayer/file-multiple-video-streams/ **Description:** Handle multiple video streams in files - select camera angles, switch resolutions, and manage tracks with code examples for Delphi, C++, and VB6. **Tags:** All-in-One Media Framework, Delphi, ActiveX, DirectShow, C++, Windows, VCL, Playback, MKV **API:** TVFMediaPlayer, CVFMediaPlayer # Playing Video Files with Multiple Video Streams ## Understanding Multiple Video Streams ### What Are Multiple Video Streams? Multiple video streams refer to different video tracks contained within a single media file. These streams can vary in several ways: - Different camera angles of the same scene - Alternate versions with varying resolutions or bitrates - Primary and secondary content (such as picture-in-picture) - Different aspect ratios or formats of the same content - Versions with or without special effects or graphics ### Supported File Formats Many popular container formats support multiple video streams, including: - **Matroska (MKV)**: Widely recognized for its flexibility and robust support for multiple streams - **MP4/MPEG-4**: Common in both professional and consumer applications - **AVI**: Although older, still widely used in some contexts - **WebM**: Popular for web-based applications - **TS/MTS**: Used in broadcast applications and consumer video cameras Each format has its own characteristics and limitations regarding how it handles multiple video streams, but the `TVFMediaPlayer` component provides a unified approach to working with them. ## Implementing Multiple Video Stream Playback ### Setting Up the Media Player The first step is to properly initialize the `TVFMediaPlayer` object. This involves creating the instance, configuring basic properties, and preparing it for playback. Snippets are fragments of one procedure The Pascal snippets in the three sub-sections below are excerpts from a single procedure (`TForm1.SetupAndPlayMultiStream`), split for narrative clarity. The full pasteable listing is at the [end of this section](#complete-pascal-listing). ``` // Excerpt — see "Complete Pascal listing" below for the full procedure. procedure TForm1.SetupAndPlayMultiStream; var MediaPlayer1: TVFMediaPlayer; begin MediaPlayer1 := TVFMediaPlayer.Create(Self); // Set container size and position if needed MediaPlayer1.Parent := Panel1; // Assuming Panel1 is your container MediaPlayer1.Align := alClient; // Configure initial state MediaPlayer1.DoubleBuffered := True; MediaPlayer1.AutoPlay := False; // We'll control playback explicitly // ... continued below end; ``` ### Configuring the Media Source Next, we need to specify the media file and configure how it should be loaded: ``` // Excerpt — body of TForm1.SetupAndPlayMultiStream (continued). // Set the file name - use full path for reliability MediaPlayer1.FilenameOrURL := 'C:\Videos\multistream-video.mkv'; // Enable audio playback (default DirectSound audio renderer will be used) MediaPlayer1.Audio_Play := True; // Configure audio settings if needed MediaPlayer1.Audio_Volume := 85; // Set volume to 85% // Set the source mode to DirectShow // Other options include SM_File_FFMPEG or SM_File_VLC MediaPlayer1.Source_Mode := SM_File_DS; ``` ### Selecting and Switching Video Streams The key to working with multiple video streams is the `Source_VideoStreamIndex` property. This zero-based index allows you to select which video stream should be rendered: ``` // Excerpt — body of TForm1.SetupAndPlayMultiStream (final part). // Set video stream index to 1 (second stream, as index is zero-based) MediaPlayer1.Source_VideoStreamIndex := 1; // Start playback MediaPlayer1.Play(); end; ``` ### Complete Pascal listing The three excerpts above merged into one self-contained, copy-pasteable procedure: ``` procedure TForm1.SetupAndPlayMultiStream; var MediaPlayer1: TVFMediaPlayer; begin MediaPlayer1 := TVFMediaPlayer.Create(Self); // Container + initial state MediaPlayer1.Parent := Panel1; MediaPlayer1.Align := alClient; MediaPlayer1.DoubleBuffered := True; MediaPlayer1.AutoPlay := False; // Source + audio configuration MediaPlayer1.FilenameOrURL := 'C:\Videos\multistream-video.mkv'; MediaPlayer1.Audio_Play := True; MediaPlayer1.Audio_Volume := 85; MediaPlayer1.Source_Mode := SM_File_DS; // Pick a non-default video stream and start playback MediaPlayer1.Source_VideoStreamIndex := 1; MediaPlayer1.Play(); end; ``` ## C++ MFC Implementation ### Setting Up the Media Player Here's how to implement multiple video stream playback using C++ with MFC: ``` // In your header file (MyDlg.h) private: CVFMediaPlayer* m_pMediaPlayer; // In your implementation file (MyDlg.cpp) BOOL CMyDlg::OnInitDialog() { CDialog::OnInitDialog(); // Create the MediaPlayer instance m_pMediaPlayer = new CVFMediaPlayer(); // Initialize the control CWnd* pContainer = GetDlgItem(IDC_PLAYER_CONTAINER); // Your container control m_pMediaPlayer->Create(NULL, NULL, WS_CHILD | WS_VISIBLE, CRect(0, 0, 0, 0), pContainer, 1001); // Configure display settings — CWnd::GetClientRect(LPRECT) returns void // and fills the rect by reference, so we must declare a CRect first. CRect rc; pContainer->GetClientRect(&rc); m_pMediaPlayer->SetWindowPos(NULL, 0, 0, rc.Width(), rc.Height(), SWP_NOZORDER); m_pMediaPlayer->PutDoubleBuffered(TRUE); m_pMediaPlayer->PutAutoPlay(FALSE); return TRUE; } ``` ### Configuring the Media Source ``` void CMyDlg::PlayMultiStreamVideo() { // Set the file path and configure source m_pMediaPlayer->PutFilenameOrURL(_T("C:\\Videos\\multistream-video.mkv")); // Configure audio m_pMediaPlayer->PutAudio_Play(TRUE); m_pMediaPlayer->PutAudio_Volume(85); // Set source mode to DirectShow m_pMediaPlayer->PutSource_Mode(SM_File_DS); // Select the second video stream (index 1) m_pMediaPlayer->PutSource_VideoStreamIndex(1); // Start playback m_pMediaPlayer->Play(); } // Don't forget to clean up void CMyDlg::OnDestroy() { if (m_pMediaPlayer != NULL) { m_pMediaPlayer->DestroyWindow(); delete m_pMediaPlayer; m_pMediaPlayer = NULL; } CDialog::OnDestroy(); } ``` ## VB6 Implementation Here's how to implement multiple video stream playback in Visual Basic 6: ``` ' Declare the MediaPlayer object at form level Private WithEvents MediaPlayer1 As TVFMediaPlayer Private Sub Form_Load() ' Create the MediaPlayer instance Set MediaPlayer1 = New TVFMediaPlayer ' Set container properties MediaPlayer1.CreateControl MediaPlayer1.Parent = Frame1 ' Assuming Frame1 is your container MediaPlayer1.Left = 0 MediaPlayer1.Top = 0 MediaPlayer1.Width = Frame1.ScaleWidth MediaPlayer1.Height = Frame1.ScaleHeight ' Configure initial state MediaPlayer1.DoubleBuffered = True MediaPlayer1.AutoPlay = False End Sub Private Sub btnPlay_Click() ' Set the file name - use full path for reliability MediaPlayer1.FilenameOrURL = "C:\Videos\multistream-video.mkv" ' Enable audio playback MediaPlayer1.Audio_Play = True MediaPlayer1.Audio_Volume = 85 ' Set volume to 85% ' Set the source mode to DirectShow MediaPlayer1.Source_Mode = SM_File_DS ' Select the second video stream (index 1) MediaPlayer1.Source_VideoStreamIndex = 1 ' Start playback MediaPlayer1.Play End Sub Private Sub Form_Unload(Cancel As Integer) ' Clean up resources Set MediaPlayer1 = Nothing End Sub ``` ## Conclusion The ability to play video files with multiple streams opens up numerous possibilities for creating rich, interactive multimedia experiences. The `TVFMediaPlayer` component provides a straightforward approach to implementing this functionality, with flexible options to suit different application requirements. By following the techniques outlined in this guide, you can effectively incorporate multiple video stream support into your applications, enhancing user experience and expanding the capabilities of your multimedia projects. --- Please get in touch with [support](https://support.visioforge.com/) if you need assistance with this functionality. Visit our [GitHub](https://github.com/visioforge/) page for additional code samples and implementation examples. ---END OF PAGE--- ## Media Player SDK for Delphi - TVFMediaPlayer Guide **URL:** https://www.visioforge.com/help/docs/delphi/mediaplayer/ **Description:** Embed video and audio playback in Delphi apps with TVFMediaPlayer, including playback controls, seeking, volume, frame capture, audio tracks, and fullscreen. **Tags:** All-in-One Media Framework, Delphi, ActiveX, DirectShow, Windows, VCL, Playback, Streaming **API:** TVFMediaPlayer # Media Player SDK for Delphi [Media Player SDK Delphi](https://www.visioforge.com/all-in-one-media-framework) This page covers using Media Player SDK with Delphi to build multimedia playback applications around the `TVFMediaPlayer` VCL component. ## Main Component ### TVFMediaPlayer `TVFMediaPlayer` is a `TCustomPanel` descendant that exposes the full playback API. Drop it on a form at design time, or create it programmatically and attach it to a host panel. ``` var MediaPlayer1: TVFMediaPlayer; begin MediaPlayer1 := TVFMediaPlayer.Create(Self); MediaPlayer1.Parent := Panel1; MediaPlayer1.Align := alClient; end; ``` ## Basic Playback ### Play a File Set `FilenameOrURL` to the input path (or network URL), pick a source engine via `Source_Mode`, then call `Play`. ``` procedure TForm1.PlayFile(const Filename: WideString); begin MediaPlayer1.FilenameOrURL := Filename; MediaPlayer1.Source_Mode := SM_File_FFMPEG; // SM_File_DS, SM_File_VLC, SM_File_LAV MediaPlayer1.Audio_Play := True; MediaPlayer1.Play; end; ``` ### Playback Controls `Play` returns `True` on success. `Pause`, `Resume`, and `Stop` are procedures. ``` procedure TForm1.btnPlayClick(Sender: TObject); begin MediaPlayer1.Play; end; procedure TForm1.btnPauseClick(Sender: TObject); begin MediaPlayer1.Pause; end; procedure TForm1.btnResumeClick(Sender: TObject); begin MediaPlayer1.Resume; end; procedure TForm1.btnStopClick(Sender: TObject); begin MediaPlayer1.Stop; end; ``` The current state is exposed by the read-only `Status` property (`ST_PLAY`, `ST_PAUSE`, `ST_FREE`). ``` if MediaPlayer1.Status = ST_PLAY then StatusBar1.SimpleText := 'Playing'; ``` ## Seeking Position is expressed in milliseconds. `Position_Get_Time` returns the current position, `Position_Set_Time` seeks to an absolute position, and `Info_Video_DurationMSec(0)` returns the total duration of the first video stream. ``` procedure TForm1.SeekTo(PositionMs: Integer); begin MediaPlayer1.Position_Set_Time(PositionMs); end; function TForm1.GetDurationMs: Integer; begin Result := MediaPlayer1.Info_Video_DurationMSec(0); end; function TForm1.GetPositionMs: Integer; begin Result := MediaPlayer1.Position_Get_Time; end; ``` Frame-accurate seeking is also available via `Position_Get_Frame` and `Position_Set_Frame`. ## Audio Control `TVFMediaPlayer` supports up to eight independent audio output streams. Volume and balance are addressed by zero-based stream index. ``` procedure TForm1.SetVolume(StreamIndex, Volume: Integer); begin // Volume range: 0..100 (SDK scales internally) MediaPlayer1.Audio_Volume_Set(StreamIndex, Volume); end; function TForm1.GetVolume(StreamIndex: Integer): Integer; begin Result := MediaPlayer1.Audio_Volume_Get(StreamIndex); end; procedure TForm1.SetBalance(StreamIndex, Balance: Integer); begin // Balance range: -100 (left) to +100 (right) MediaPlayer1.Audio_Balance_Set(StreamIndex, Balance); end; ``` To mute audio, set the volume to zero and restore the previous value on unmute, or toggle `Audio_Play` before starting playback. ``` procedure TForm1.Mute; begin FSavedVolume := MediaPlayer1.Audio_Volume_Get(0); MediaPlayer1.Audio_Volume_Set(0, 0); end; procedure TForm1.Unmute; begin MediaPlayer1.Audio_Volume_Set(0, FSavedVolume); end; ``` ## Playback Speed `SetSpeed` accepts a multiplier between 0.01 and 100.0. ``` procedure TForm1.SetPlaybackSpeed(Rate: Double); begin // Rate: 0.5 (half speed) to 2.0 (double speed) MediaPlayer1.SetSpeed(Rate); end; ``` ## Network URL Playback The same `FilenameOrURL` property accepts network URLs. Pick the engine that best supports the protocol — `SM_File_VLC` and `SM_File_FFMPEG` cover the broadest set of streaming sources; `SM_MMS_WMV_DS` is dedicated to MMS/WMV streams. ``` procedure TForm1.PlayURL(const URL: WideString); begin MediaPlayer1.FilenameOrURL := URL; MediaPlayer1.Source_Mode := SM_File_FFMPEG; MediaPlayer1.Play; end; procedure TForm1.PlayRTSP; begin MediaPlayer1.FilenameOrURL := 'rtsp://192.168.1.100:554/stream'; MediaPlayer1.Source_Mode := SM_File_FFMPEG; MediaPlayer1.Play; end; procedure TForm1.PlayHLS; begin MediaPlayer1.FilenameOrURL := 'https://server.example.com/playlist.m3u8'; MediaPlayer1.Source_Mode := SM_File_FFMPEG; MediaPlayer1.Play; end; ``` ## Frame Capture `Frame_Save` writes the current frame to disk in the chosen image format. `Frame_GetCurrent` fills a `TBitmap` you supply. ``` procedure TForm1.CaptureFrame; begin // Frame_Save(Filename, Format, Quality) MediaPlayer1.Frame_Save('C:\Snapshots\frame.jpg', IM_JPEG, 85); end; procedure TForm1.CaptureFrameToBitmap; var Bitmap: TBitmap; begin Bitmap := TBitmap.Create; try MediaPlayer1.Frame_GetCurrent(Bitmap); Image1.Picture.Assign(Bitmap); finally Bitmap.Free; end; end; ``` Optionally resize the saved frame by configuring `Frame_Save_Resize`, `Frame_Save_Resize_Width`, and `Frame_Save_Resize_Height` before the call. ## Audio and Subtitle Tracks The `Info_Audio_*` and `Info_Text_*` helpers enumerate streams discovered inside the source file. Audio streams are enabled or disabled individually with `Audio_SetStream`. ``` procedure TForm1.PopulateAudioTracks; var i: Integer; begin cbAudioTracks.Items.Clear; for i := 0 to MediaPlayer1.Info_Audio_Streams_Count - 1 do cbAudioTracks.Items.Add(MediaPlayer1.Info_Audio_Codec(i)); end; procedure TForm1.SelectAudioTrack(Index: Integer); var i: Integer; begin // Enable the chosen track and disable the others for i := 0 to MediaPlayer1.Info_Audio_Streams_Count - 1 do MediaPlayer1.Audio_SetStream(i, i = Index); end; procedure TForm1.PopulateSubtitles; var i: Integer; begin cbSubtitles.Items.Clear; for i := 0 to MediaPlayer1.Info_Text_Streams_Count - 1 do cbSubtitles.Items.Add(MediaPlayer1.Info_Text_Name(i)); end; ``` `Info_Text_Language(i)` and `Info_Text_Codec(i)` are also available for richer subtitle metadata. ## Fullscreen Mode Toggle fullscreen via the `Screen_VR_FullScreen` property. This works with the configured video renderer. ``` procedure TForm1.ToggleFullscreen; begin MediaPlayer1.Screen_VR_FullScreen := not MediaPlayer1.Screen_VR_FullScreen; end; ``` ## Events `TVFMediaPlayer` exposes three core playback events. `OnStart` and `OnStop` take no parameters; `OnError` receives the error text. ``` procedure TForm1.MediaPlayer1Start; begin StatusBar1.SimpleText := 'Playing'; end; procedure TForm1.MediaPlayer1Stop; begin StatusBar1.SimpleText := 'Stopped'; end; procedure TForm1.MediaPlayer1Error(ErrorText: WideString); begin ShowMessage('Error: ' + ErrorText); end; ``` To track position updates, poll `Position_Get_Time` from a `TTimer` while `Status = ST_PLAY`: ``` procedure TForm1.PositionTimerTick(Sender: TObject); var Position, Duration: Integer; begin if MediaPlayer1.Status <> ST_PLAY then Exit; Position := MediaPlayer1.Position_Get_Time; Duration := MediaPlayer1.Info_Video_DurationMSec(0); if Duration > 0 then begin TrackBar1.Max := Duration; TrackBar1.Position := Position; end; LabelPosition.Caption := Format('%d:%.2d / %d:%.2d', [Position div 60000, (Position div 1000) mod 60, Duration div 60000, (Duration div 1000) mod 60]); end; ``` ## Supported Formats | Type | Formats | | --- | --- | | Video | MP4, AVI, MKV, MOV, WMV, FLV, WebM | | Audio | MP3, AAC, FLAC, WAV, OGG, WMA | | Streaming | RTSP, RTMP, HTTP, HLS, DASH | Format coverage depends on the selected `Source_Mode` — the FFmpeg and VLC engines cover the broadest range out of the box; DirectShow (`SM_File_DS`) relies on the codecs installed on the system. ## Resources and Further Information To explore the capabilities and usage of the `TVFMediaPlayer` library in more depth, see the following official resources: - **Product page:** [VisioForge Media Player SDK](https://www.visioforge.com/all-in-one-media-framework) - **API reference:** [Delphi Media Player API Reference](https://api.visioforge.org/delphi/media_player_sdk/index.html) - **Changelog:** [Recent updates and fixes](changelog/) - **Installation guide:** [Setting up the library](install/) - **Deployment:** [Distributing your application](deployment/) - **License agreement:** [End User License Agreement](../../eula/) ## Tutorials and Code Samples Practical examples demonstrating how to implement specific features: - [How to play a video file with multiple video streams?](file-multiple-video-streams/) - *(More tutorials will be added here as they become available)* ---END OF PAGE--- ## Install TVFMediaPlayer ActiveX Control in C++ Builder **URL:** https://www.visioforge.com/help/docs/delphi/mediaplayer/install/builder/ **Description:** Install TVFMediaPlayer in C++ Builder - step-by-step guide for versions 5, 6, 2006, and later with prerequisites, setup, and troubleshooting. **Tags:** All-in-One Media Framework, Delphi, ActiveX, DirectShow, Windows, VCL, Playback, Streaming, MP4 **API:** TVFMediaPlayer # Installing TVFMediaPlayer in C++ Builder Welcome to the detailed guide for integrating the powerful TVFMediaPlayer library into your Embarcadero C++ Builder development environment. This document covers the installation process for legacy versions like C++ Builder 5 and 6, as well as modern versions from 2006 onwards. We will explore the necessary prerequisites, step-by-step installation procedures for different IDE versions, considerations for 32-bit (x86) and 64-bit (x64) architectures, and common troubleshooting steps. ## Introduction to TVFMediaPlayer and VisioForge Media Framework TVFMediaPlayer is a versatile multimedia component developed by VisioForge. It's part of the larger VisioForge Media Framework, designed to provide developers with a robust set of tools for handling audio and video playback, capture, processing, and streaming within their applications. TVFMediaPlayer specifically focuses on playback capabilities, supporting a wide array of formats and offering extensive control over media rendering. The component is delivered as an ActiveX control, making it easily integrable into environments that support COM technology, such as C++ Builder. Utilizing ActiveX allows for visual design-time integration and straightforward programmatic access to the player's features. ## Prerequisites Before proceeding with the installation, ensure your development environment meets the following requirements: 1. **Supported C++ Builder Version:** You need a working installation of Embarcadero C++ Builder. This guide covers: - C++ Builder 5 - C++ Builder 6 - C++ Builder 2006 - C++ Builder 2007, 2009, 2010, XE series (XE to XE8), 10.x series (Seattle, Berlin, Tokyo, Rio, Sydney), 11.x (Alexandria), and later versions. While the core process remains similar for newer versions, minor UI variations might exist. 2. **Operating System:** A compatible Windows operating system (Windows 7 or later, including Windows 8, 10, 11, and corresponding Server versions). Ensure your OS matches the target architecture (32-bit or 64-bit) of your C++ Builder projects. 3. **Administrative Privileges:** The installation of the VisioForge Media Framework and the registration of ActiveX controls typically require administrative privileges on your machine. Ensure you are running the installer and C++ Builder with sufficient permissions, especially if User Account Control (UAC) is enabled. 4. **Dependencies:** The VisioForge installer usually bundles necessary runtime dependencies (like specific DirectX or Media Foundation components). However, keeping your Windows system updated is generally recommended. ## Step 1: Download the All-in-One Media Framework The TVFMediaPlayer component is distributed as part of the VisioForge All-in-One Media Framework SDK. You must download the correct version: - **Target:** Download the **ActiveX** version of the SDK. Do not download the .NET or VCL versions, as they are intended for different development environments. - **Source:** Obtain the installer directly from the official VisioForge website. Navigate to the [product page](https://www.visioforge.com/all-in-one-media-framework) and locate the download link for the ActiveX SDK. Ensure you are downloading the latest stable release unless you have specific requirements for an older version. ## Step 2: Install the VisioForge Media Framework Once the download is complete, proceed with the installation: 1. **Locate the Installer:** Find the downloaded executable file. 2. **Run as Administrator:** Right-click the installer file and select "Run as administrator". This is crucial for ensuring the ActiveX controls are correctly registered in the Windows Registry. 3. **Follow the Wizard:** The installation wizard will guide you through the process. - Accept the license agreement. - Choose the installation directory (the default location is usually suitable). - Select the components to install. Ensure that the core framework and the MediaPlayer components are selected. Typically, the default selection is sufficient. - The installer will copy the necessary files (DLLs, AX files, etc.) and register the ActiveX controls on your system. 4. **Completion:** Once the installation finishes, click "Finish". The TVFMediaPlayer ActiveX control is now available on your system, ready to be imported into the C++ Builder IDE. ## Step 3: Import the TVFMediaPlayer ActiveX Control into C++ Builder The method for importing the ActiveX control differs slightly between older and newer versions of C++ Builder. ### A. For C++ Builder 5 and 6 These classic versions have a straightforward import mechanism: 1. **Launch C++ Builder:** Open your C++ Builder 5 or 6 IDE. 2. **Open or Create a Project:** You can import the control into an existing project or a new one. The import process adds the component to the IDE's palette, making it available for all projects. 3. **Import ActiveX Control:** Navigate to the main menu and select `Component` → `Import ActiveX Controls...`. 4. **Select the Control:** A dialog box will appear listing all registered ActiveX controls on your system. Scroll through the list and find `VisioForge Media Player` (it might also be listed as `VFMediaPlayer Class` or similar, depending on registry details). Check the box next to it. 5. **Install:** Click the `Install...` button. 6. **Package Creation/Selection:** C++ Builder will prompt you to install the component into a package. You can choose an existing package (like `dclusr.dpk`) or create a new one. For simplicity, adding it to the default user package is often sufficient. Click `OK`. 7. **Confirmation:** A confirmation dialog will ask if you want to rebuild the package. Click `Yes`. 8. **Compilation and Installation:** C++ Builder will compile the package containing the wrapper code for the ActiveX control. Upon successful compilation, a message will confirm the installation. Click `OK`. 9. **Component Palette:** The TVFMediaPlayer component should now appear on the C++ Builder Component Palette, likely under a tab named `ActiveX` or `VisioForge`. You can now drag and drop it onto your forms like any other standard VCL component. ### B. For C++ Builder 2006 and Later (including XE, 10.x, 11.x) Modern C++ Builder versions use a more structured component import process, typically involving creating or using a dedicated design-time package: 1. **Launch C++ Builder:** Open your C++ Builder IDE (2006 or newer). 2. **Create a New Package:** It's generally best practice to install third-party components into their own package. - Go to `File` → `New` → `Other...`. - In the `New Items` dialog, navigate to `C++Builder Projects` (or similar category) and select `Package`. Click `OK`. 3. **Import Component:** With the new package project active (e.g., `Package1.cbproj`), go to the main menu and select `Component` → `Import Component...`. 4. **Select Import Type:** In the `Import Component` wizard, choose the `Import ActiveX Control` option and click `Next >`. 5. **Select the Control:** Similar to the older versions, find `VisioForge Media Player` in the list of registered controls, select it, and click `Next >`. 6. **Component Details:** The wizard will display details about the control. You can typically accept the defaults for `Palette Page` (e.g., `ActiveX`), `Unit Dir Name`, and `Search Path`. Click `Next >`. *Note: Some developers prefer to create a dedicated "VisioForge" palette page.* 7. **Package Selection:** Choose the action `Add unit to .cbproj` (where `` is the name of the package you created in step 2). Click `Finish`. *Self-Correction: The screenshot reference 'mpbcb2006\_5.webp' seems misplaced in the original document's flow. It likely referred to saving or build options, which are handled next.* 8. **Save the Package:** C++ Builder will generate the necessary wrapper unit (e.g., `VFMediaPlayerLib_TLB.cpp` / `.h`). Save the package project (`.cbproj`) and the associated files when prompted. Choose a meaningful name and location for your package (e.g., `VisioForgeMediaPlayerPkg`). 9. **Compile and Install the Package:** - In the `Project Manager` pane, right-click on the package project's `.bpl` file (e.g., `VisioForgeMediaPlayerPkg.bpl`). - Select `Compile` to ensure the wrapper code builds correctly. - After a successful compilation, right-click the `.bpl` file again and select `Install`. 10. **Confirmation:** The IDE will install the package, making the TVFMediaPlayer component available on the specified Component Palette page (e.g., `ActiveX`). ## Step 4: Using the TVFMediaPlayer Component After successful installation, you can use the component in your C++ Builder applications: 1. **Design-Time:** Open a form in the Form Designer. Locate the `TVFMediaPlayer` component on the Component Palette (usually on the `ActiveX` or `VisioForge` tab). Click and drop it onto your form. You can resize and position it as needed. Use the Object Inspector to configure its basic properties. 2. **Run-Time:** Access the component's methods and properties programmatically in your C++ code. For example, to load and play a file: ``` // Assuming MediaPlayer1 is the name of the TVFMediaPlayer component on your form MediaPlayer1->FilenameOrURL = "C:\\path\\to\\your\\video.mp4"; MediaPlayer1->Play(); ``` 3. **Event Handling:** Use the Object Inspector's `Events` tab to assign handlers to various player events (e.g., `OnPlay`, `OnStop`, `OnError`). ## Architecture Considerations (x86 vs. x64) The VisioForge Media Framework provides both 32-bit (x86) and 64-bit (x64) versions of its libraries and ActiveX controls. It's crucial to match the component architecture with your C++ Builder project's target platform: - **32-bit Projects (Win32 Target Platform):** Use the x86 version of the TVFMediaPlayer ActiveX control. The standard installation typically registers the x86 version correctly. When importing/installing the component package (especially in modern IDEs), ensure you are building and installing the package for the Win32 platform. - **64-bit Projects (Win64 Target Platform):** Use the x64 version of the TVFMediaPlayer ActiveX control. The VisioForge installer should register both versions. - **IDE Design-Time:** Importantly, the C++ Builder IDE itself is often a 32-bit application (even in recent versions). This means that for visual form design, the IDE needs to load the **x86** version of the ActiveX control. - **Compilation/Runtime:** When you compile your project for the Win64 target platform, the application will require the **x64** version of the control at runtime. - **Package Management:** In modern C++ Builder versions, you might need to: 1. Create and install a design-time package targeting Win32 (using the x86 control) for use in the IDE. 2. Ensure the corresponding runtime package (or necessary library files) for Win64 are correctly configured in your project's build settings and deployed with your 64-bit application. Consult the VisioForge documentation and C++ Builder's platform management features for specifics. Some developers manage separate packages for Win32 and Win64 targets. **Recommendation:** While legacy C++ Builder versions are covered, VisioForge strongly recommends using modern versions of C++ Builder (XE series or later). These versions offer better support for 64-bit development, improved IDE features, and compatibility with current Windows operating systems and VisioForge SDK updates. Support for C++ Builder 5/6 might be limited. ## Troubleshooting Common Issues - **Control Not Found in Import List:** Ensure the VisioForge Media Framework (ActiveX version) was installed correctly with administrative privileges. Try reinstalling the framework. Manually registering the `.ocx` control using `regsvr32` (run from an Administrator command prompt) might be necessary in rare cases (e.g., `regsvr32 "C:\Program Files\VisioForge\All-in-One Media Framework ActiveX\Redist\VisioForge_Media_Player.ocx"` - adjust path as needed, or use `Redist\x64` for the 64-bit control). - **Package Installation Fails:** Check the build output for errors. Ensure the package project settings (paths, target platform) are correct. Verify you have write permissions to the C++ Builder library/package directories. - **Component Works in IDE but Fails at Runtime (or vice-versa):** This often points to an architecture mismatch (x86 vs. x64). Review the "Architecture Considerations" section carefully. Ensure the correct version (32-bit or 64-bit) of the VisioForge runtime files is accessible to your compiled application. Deploy the required VisioForge redistributables with your application if necessary. - **Errors During Playback (`CreateObject` fails, etc.):** Double-check that the `FilenameOrURL` property points to a valid, accessible media file. Ensure the necessary codecs for the media format are installed on the system (though VisioForge often includes internal decoders or utilizes Media Foundation/DirectShow). Check the VisioForge `OnError` event for specific error codes or messages. ## Conclusion Integrating TVFMediaPlayer into C++ Builder provides a powerful solution for adding media playback to your applications. By following the appropriate steps for your IDE version, carefully managing x86/x64 architectures, and understanding the package system, you can successfully incorporate this component. Remember to consult the official VisioForge documentation and examples for more advanced usage and API details. --- For further assistance or specific issues not covered here, please contact VisioForge [support](https://support.visioforge.com/). Explore more advanced examples and source code on the VisioForge [GitHub](https://github.com/visioforge/) repository. ---END OF PAGE--- ## Install Media Player SDK in Delphi — 32/64-bit Setup **URL:** https://www.visioforge.com/help/docs/delphi/mediaplayer/install/delphi/ **Description:** Install VisioForge Media Player SDK in Delphi 10.x-12.x — VCL/FMX components, package registration, library paths. Windows 32/64-bit supported. **Tags:** All-in-One Media Framework, Delphi, ActiveX, Windows, VCL, Playback, MP4 **API:** TVFMediaPlayer # Installing TVFMediaPlayer in Delphi Welcome to the detailed guide for installing the VisioForge Media Player SDK, specifically the `TVFMediaPlayer` component, into your Delphi development environment. This guide covers installations for classic Delphi versions like Delphi 6 and 7, as well as modern versions from Delphi 2005 onwards, including the latest releases supporting 64-bit development. ## Understanding TVFMediaPlayer `TVFMediaPlayer` is a powerful VCL component from VisioForge designed for seamless integration of video and audio playback capabilities into Delphi applications. It simplifies tasks such as playing various media formats, capturing snapshots, controlling playback speed, managing audio streams, and much more. Built upon a robust media engine, it offers high performance and extensive format support, making it a versatile choice for multimedia application development in Delphi. This guide assumes you have a working installation of Embarcadero Delphi or a compatible older version (Borland Delphi). ## Step 1: Prerequisites and Downloading the Framework Before proceeding with the installation, ensure your development environment meets the necessary prerequisites. Primarily, you need a licensed or trial version of Delphi installed on your Windows machine. The `TVFMediaPlayer` component is distributed as part of the VisioForge All-in-One Media Framework. This framework bundles various VisioForge SDKs, providing a comprehensive toolkit for media handling. 1. **Navigate to the Product Page:** Open your web browser and go to the official VisioForge [All-in-One Media Framework product page](https://www.visioforge.com/all-in-one-media-framework). 2. **Select the Delphi Version:** Locate the download section specifically for Delphi. VisioForge typically offers versions tailored for different development platforms. 3. **Download:** Click the download link to obtain the installer executable (`.exe`) file. Save this file to a known location on your computer, such as your Downloads folder. The downloaded file contains not only the `TVFMediaPlayer` component but also other related libraries, source code (if applicable based on licensing), necessary runtime files, and documentation. ## Step 2: Running the Installer Once the download is complete, you need to run the installer to place the necessary SDK files onto your system. 1. **Locate the Installer:** Navigate to the folder where you saved the downloaded `.exe` file. 2. **Run as Administrator:** Right-click the installer file and select "Run as administrator". This is crucial because the installer needs to register components and potentially write to system directories, requiring elevated privileges. 3. **Follow On-Screen Instructions:** The installer wizard will guide you through the process. Typically, this involves: - Accepting the license agreement. - Choosing the installation directory (the default location is usually appropriate, e.g., `C:\Program Files\VisioForge\All-in-One Media Framework Delphi\`). Note this path, as you'll need it later. - Selecting components to install (ensure the Media Player SDK is selected). - Confirming the installation. 4. **Complete Installation:** Allow the installer to finish copying files and performing necessary setup tasks. This process unpacks the SDK, including the pre-compiled units (`.dcu`), the component package (`.dpk` / `.dproj`), and the required runtime DLLs. The Delphi component ships as precompiled units — the package `.pas` source is not distributed. ## Step 3: Integrating with the Delphi IDE After running the main installer, the next critical step is integrating the `TVFMediaPlayer` component into the Delphi IDE so you can use it visually in the form designer and reference its units in your code. The process differs slightly between older (Delphi 6/7) and newer (Delphi 2005+) versions. **Important:** For all Delphi versions, it's recommended to run the Delphi IDE itself **as administrator** during the package installation process. This helps avoid potential permission issues when compiling and registering the component package. ### Installation in Delphi 6 / Delphi 7 These older versions require manual configuration of paths and package installation. 1. **Launch Delphi (as Administrator):** Start your Delphi 6 or Delphi 7 IDE with administrative privileges. 2. **Open IDE Options:** Go to the `Tools` menu and select `Environment Options`. 3. **Configure Library Path:** - Navigate to the `Library` tab. - In the `Library path` field, click the ellipsis (`...`) button. - Click the `Add` or `New` button (icon might vary) and browse to the package folder for your Delphi version — this is where the precompiled `.dcu` units live, e.g. `C:\Program Files\VisioForge\All-in-One Media Framework Delphi\Media Player\Packages\Delphi 7`. Add this path. This tells Delphi where to find the compiled units during compilation. - Click `OK` to close the path editor. 4. **Configure Browsing Path:** - While still in the `Library` tab, locate the `Browsing path` field (it might be combined or separate depending on the exact Delphi version/update). - Add the same package folder path here as well. This helps the IDE locate files for features like code completion and navigation. - Click `OK` to save the Environment Options. 5. **Open the Package File:** - Go to the `File` menu and select `Open...`. - Navigate to the `Media Player\Packages\Delphi 7` (or `Delphi 6`) subfolder within the VisioForge installation directory (e.g., `C:\Program Files\VisioForge\All-in-One Media Framework Delphi\Media Player\Packages\Delphi 7`). - Open the package file `VisioForge_Media_Player.dpk`. This is a single package — there are no separate runtime and design-time packages. 6. **Compile the Package:** - With `VisioForge_Media_Player.dpk` open as the active project in the Project Manager, click the `Compile` button (or use `Project -> Compile`). Resolve any compilation errors if they occur (though typically unnecessary with official packages). 7. **Install the Package:** - Once compiled successfully, click the `Install` button in the Project Manager. 8. **Confirmation:** You should see a confirmation message indicating that the package(s) were installed. The `TVFMediaPlayer` component (and potentially others from the SDK) should now appear on the Delphi component palette, likely under a "VisioForge" or similar category tab. *Note on Architecture:* Delphi 6/7 are strictly 32-bit (x86) environments. Therefore, you will only be installing and using the 32-bit version of the `TVFMediaPlayer` component. The SDK might contain 64-bit files, but they are not applicable here. ### Installation in Delphi 2005 and Later (XE, 10.x, 11.x, 12.x) Modern Delphi versions offer a more streamlined process and robust support for multiple platforms (Win32, Win64). 1. **Launch Delphi (as Administrator):** Start your Delphi IDE (e.g., Delphi 11 Alexandria, Delphi 12 Athens) with administrative privileges. 2. **Open IDE Options:** Go to `Tools -> Options`. 3. **Configure Library Path:** - In the Options dialog, navigate to `Language -> Delphi -> Library` (the exact path might slightly vary between versions). - Select the target platform for which you want to configure the path (e.g., `Windows 32-bit`, `Windows 64-bit`). It's recommended to configure both if you plan to build for both architectures. - Click the ellipsis (`...`) button next to the `Library path` field. - Add the path to the package folder that matches your Delphi version and platform, e.g. `C:\Program Files\VisioForge\All-in-One Media Framework Delphi\Media Player\Packages\Delphi 13` (Win32) or `C:\Program Files\VisioForge\All-in-One Media Framework Delphi\Media Player\Packages\Delphi 13 x64` (Win64). This folder holds the precompiled `.dcu` units. - Click `Add` and then `OK`. Repeat for the other platform if desired. 4. **Configure Browsing Path (Optional but Recommended):** - Under the same `Library` section, add that package folder path to the `Browsing path` field as well. - Click `OK` to save the Options. 5. **Open the Package File:** - Go to `File -> Open Project...`. - Navigate to the `Media Player\Packages` directory within the VisioForge installation. Find the subfolder corresponding to your Delphi version and platform (e.g., `Delphi XE11`, `Delphi XE12`, `Delphi 13`, or the matching `Delphi x64` folder for 64-bit). - Open the package project `VisioForge_Media_Player.dproj` (or `VisioForge_Media_Player.dpk`). There is a single package that provides both runtime and design-time functionality. 6. **Compile and Install:** - In the Project Manager, right-click on the package project (`.dpk` file). - Select `Compile` from the context menu. - Once compiled successfully, right-click again and select `Install`. 7. **Confirmation:** Delphi will confirm the installation, and the components will appear on the palette. *Note on Architecture:* Modern Delphi supports both 32-bit (Win32) and 64-bit (Win64) targets. The VisioForge SDK typically provides pre-compiled units (`.dcu`) for both. When you compile and install the package, Delphi usually handles registering it for the currently active platform. You can switch platforms in the Project Manager and rebuild/reinstall if necessary, although often the IDE handles this association correctly after the initial install. ## Step 4: Project Configuration After installing the component package into the IDE, you need to ensure your individual *projects* can find the necessary VisioForge files at compile and runtime. 1. **Project Options:** Open your Delphi project (`.dpr` file). Go to `Project -> Options`. 2. **Library Path:** Navigate to `Delphi Compiler -> Search path` (or similar depending on version). 3. **Add SDK Path:** For each target platform (`Windows 32-bit`, `Windows 64-bit`) you intend to use: - Add the path to the package folder that matches the target platform, e.g. `C:\Program Files\VisioForge\All-in-One Media Framework Delphi\Media Player\Packages\Delphi 13` for Win32 and `C:\Program Files\VisioForge\All-in-One Media Framework Delphi\Media Player\Packages\Delphi 13 x64` for Win64. This ensures the compiler can find the precompiled `.dcu` units. Each Delphi version and platform has its own `Packages\Delphi ` (and `Delphi x64`) folder. 4. **Save Changes:** Click `OK` or `Save` to apply the project options. Setting the project search path correctly is crucial. If the compiler complains about not finding units like `MediaPlayerMain` or `MediaPlayerTypes`, incorrect or missing search paths are the most common cause. ## Step 5: Verification To confirm the installation was successful: 1. **Check Component Palette:** Look for the "VisioForge" tab (or similar) on the component palette in the Delphi IDE. You should see the `TVFMediaPlayer` icon. 2. **Create a Test Application:** - Create a new VCL Forms Application (`File -> New -> VCL Forms Application - Delphi`). - Drag and drop the `TVFMediaPlayer` component from the palette onto the main form. - If the component appears on the form without errors, the design-time installation is likely correct. - Add a simple button. In its `OnClick` event handler, add a basic line of code to interact with the player, for example: ``` procedure TForm1.Button1Click(Sender: TObject); begin // Ensure VFMediaPlayer1 is the name of your component instance VFMediaPlayer1.FilenameOrURL := 'C:\path\to\your\test_video.mp4'; // Replace with an actual media file path VFMediaPlayer1.Play(); end; ``` - Compile the project (`Project -> Compile`). If it compiles without "File not found" errors related to VisioForge units, the path configuration is likely correct. - Run the application. If it runs and you can play the media file using the button, the runtime setup is working. ## Common Installation Problems and Troubleshooting While the process is generally straightforward, occasional issues can arise: - **IDE Permissions:** Forgetting to run the Delphi IDE as administrator during package installation can lead to errors writing to registry or system folders, preventing component registration. **Solution:** Close Delphi, restart it as administrator, and try the package installation steps again. - **Path Configuration Errors:** Incorrect paths in either the IDE `Library Path` or the project's `Search Path` are common. **Solution:** Double-check that the paths point *exactly* to the VisioForge SDK's `Packages\Delphi ` (or `Delphi x64`) directory containing the `.dcu` units. Ensure paths are correct for the specific target platform (Win32/Win64). - **Package Compilation Errors:** Sometimes, conflicts with other installed packages or issues within the package source itself can cause compilation failures. **Solution:** Ensure you are using the correct package version for your specific Delphi version. Consult VisioForge support or forums if errors persist. - **64-bit Specific Issues:** Installing packages for the 64-bit platform can sometimes present unique challenges, especially in older Delphi versions that first introduced Win64 support. Refer to the linked article [Delphi 64-bit package installation problem](../../../general/install-64bit/) for specific known issues and workarounds. - **`.otares` File Issues:** Some Delphi versions utilize `.otares` files for resources. Problems during package installation related to these files can occur. See the linked article [Delphi package installation problem with .otares](../../../general/install-otares/). - **Missing Runtime DLLs:** The `TVFMediaPlayer` often relies on underlying DLLs (e.g., FFmpeg components) for its functionality. While the main installer usually handles these, ensure they are correctly placed either in your application's output directory, a directory in the system PATH, or the System32/SysWOW64 folders as appropriate. Deployment requires distributing these necessary DLLs with your application. Check the VisioForge documentation for a list of required runtime files. ## Further Steps and Resources With `TVFMediaPlayer` successfully installed, you can now explore its extensive features. - **Explore Properties and Events:** Use the Delphi Object Inspector to examine the numerous properties and events available for the `TVFMediaPlayer` component. - **Consult Documentation:** Refer to the official VisioForge documentation installed with the SDK or available online for detailed API references and usage examples. - **Code Samples:** Visit the VisioForge [GitHub repository](https://github.com/visioforge/) to find demo projects and code snippets showcasing various functionalities. - **Seek Support:** If you encounter persistent issues or have specific questions not covered here, contact [VisioForge support](https://support.visioforge.com/) for assistance. --- Please get in touch with [support](https://support.visioforge.com/) to get help with this tutorial. Visit our [GitHub](https://github.com/visioforge/) page to get more code samples. ---END OF PAGE--- ## TVFMediaPlayer Installation Guide for Delphi and ActiveX **URL:** https://www.visioforge.com/help/docs/delphi/mediaplayer/install/ **Description:** Install TVFMediaPlayer in Delphi, C++ Builder, Visual Basic 6, Visual Studio, and ActiveX environments with detailed setup instructions. **Tags:** All-in-One Media Framework, Delphi, ActiveX, Windows, VCL, Playback, Streaming **API:** TVFMediaPlayer # Install the TVFMediaPlayer Library Welcome to the detailed installation guide for the VisioForge TVFMediaPlayer library, a core component of the powerful All-in-One Media Framework. This guide provides comprehensive steps for installing the library across various Integrated Development Environments (IDEs), ensuring you can leverage its rich media playback capabilities effectively in your projects. The TVFMediaPlayer library offers developers robust tools for integrating audio and video playback, processing, and streaming functionalities into their applications. It is available in two primary forms to cater to different development ecosystems: 1. **Native Delphi Package:** Optimized specifically for Embarcadero Delphi developers, offering seamless integration, design-time support, and leveraging the full potential of the VCL framework. 2. **ActiveX Control (OCX):** Designed for broad compatibility, allowing integration into environments that support ActiveX technology, such as C++ Builder, Microsoft Visual Basic 6 (VB6), Microsoft Visual Studio (for C#, VB.NET, C++ MFC projects), and other ActiveX containers. This dual availability ensures that whether you are working within the Delphi ecosystem or utilizing other popular development tools, you can harness the power of TVFMediaPlayer. ## Before You Begin: System Requirements and Prerequisites Before proceeding with the installation, ensure your development environment meets the necessary requirements: - **Operating System:** Windows 7, 8, 8.1, 10, 11, or Windows Server 2012 R2 and newer (both x86 and x64 versions are supported). - **Development Environment:** A compatible IDE such as: - Embarcadero Delphi (refer to specific framework version for compatible Delphi releases, typically XE2 or newer). - Embarcadero C++ Builder (refer to specific framework version for compatibility). - Microsoft Visual Studio 2010 or newer (for C#, VB.NET, C++ MFC development using ActiveX). - Microsoft Visual Basic 6 (requires the IDE installed). - Any other IDE or development tool capable of hosting ActiveX controls. - **Dependencies:** - **DirectX:** Microsoft DirectX 9 or later is generally required. While modern Windows versions include compatible DirectX runtimes, ensure they are up-to-date. - **.NET Framework (for .NET usage):** If using the ActiveX control within .NET applications (C#, VB.NET), ensure the appropriate .NET Framework version targeted by your project is installed. - **Administrator Privileges:** Running the installer typically requires administrator rights to register components and write to system directories. ## Step-by-Step General Installation Process The core installation process involves downloading the All-in-One Media Framework installer and running it. Follow these steps carefully: 1. **Download the Framework:** - Navigate to the official [All-in-One Media Framework product page](https://www.visioforge.com/all-in-one-media-framework) on the VisioForge website. - Locate the downloads section. You might find different versions (e.g., Trial, Full) or builds. Download the latest stable release suitable for your needs. Pay attention to whether you need the Delphi-specific package installer or the general ActiveX installer if they are provided separately (often, one installer contains both). - Save the installer executable (`.exe`) file to a convenient location on your computer. 2. **Run the Installer:** - Locate the downloaded setup file (e.g., `visioforge_media_framework_activex_full.exe`, or the Delphi edition installer). - Right-click the file and select "Run as administrator" to ensure necessary permissions. - If prompted by User Account Control (UAC), confirm that you want to allow the installer to make changes to your device. 3. **Follow the Installation Wizard:** - **Welcome Screen:** The installer will launch, typically starting with a welcome message. Click "Next" to proceed. - **License Agreement:** Read the End-User License Agreement (EULA) carefully. You must accept the terms to continue the installation. Select the appropriate option and click "Next". - **Select Destination Location:** Choose the directory where the framework files, examples, and documentation will be installed. The default location is usually `C:\Program Files\VisioForge\All-in-One Media Framework ActiveX\` (or `C:\Program Files\VisioForge\All-in-One Media Framework Delphi\` for the Delphi edition). You can browse for a different path if needed. Click "Next". - **Select Components (If Applicable):** Some installers might allow you to choose which components to install (e.g., specific framework features, documentation, examples for different languages). Ensure the core Media Player components and any relevant examples (Delphi, C#, VB.NET, C++, VB6) are selected. Click "Next". - **Select Start Menu Folder:** Choose the name for the Start Menu folder where shortcuts will be created. Click "Next". - **Ready to Install:** Review your selected options. If everything is correct, click "Install" to begin the file copying and system registration process. - **Installation Progress:** The wizard will show the progress of the installation. This may take a few minutes. During this phase, the necessary DLLs and OCX files are copied, and the ActiveX control is registered in the Windows Registry. - **Completion:** Once the installation is finished, you will see a completion screen. It might offer options to view documentation or launch an example project. Click "Finish" to exit the wizard. 4. **Post-Installation Verification:** - Navigate to the installation directory you selected (e.g., `C:\Program Files\VisioForge\All-in-One Media Framework ActiveX\`). - Verify that the core library files (`.dll`, `.ocx`), documentation (`.chm` or `Docs` folder), and example projects (`Examples` folder) are present. - Check the Start Menu folder for shortcuts to documentation and examples. - It's highly recommended to try compiling and running one of the provided sample projects for your specific IDE to confirm the installation was successful and the components are correctly registered and accessible. ## IDE-Specific Integration After the general installation, you need to integrate the TVFMediaPlayer library into your chosen development environment. ### Delphi (Native Packages) Using the native Delphi packages provides the best experience for Delphi developers, including design-time component integration. - **Detailed Guide:** For comprehensive instructions specific to Delphi, including adding the library path and installing the component package (`VisioForge_Media_Player.dpk`), please refer to the dedicated **[Delphi Installation Guide](delphi/)**. - **Key Benefits:** Direct component palette access, property inspectors, event handlers integrated within the IDE, and optimized performance for VCL applications. ### ActiveX Integration (C++ Builder, VB6, Visual Studio, etc.) If you are not using Delphi or prefer the ActiveX approach, you'll need to add the `VisioForge_Media_Player.ocx` control to your project. #### C++ Builder Integrating the ActiveX control in C++ Builder involves importing it into the IDE. - **Detailed Guide:** Refer to the **[C++ Builder Installation Guide](builder/)** for step-by-step instructions on importing the ActiveX control, which typically involves using the IDE's "Import Component" or "Import ActiveX Control" feature to generate necessary wrapper code. - **Process Overview:** This usually involves navigating `Component -> Import Component...`, selecting "Import ActiveX Control", finding the "VisioForge Media Player SDK" (or similar name) in the list of registered controls, and letting the IDE generate the corresponding C++ wrapper classes that allow you to interact with the control. #### Visual Basic 6 (VB6) VB6 relies heavily on ActiveX technology, making integration straightforward. 1. **Open Project:** Launch Visual Basic 6 and open your existing project or create a new one. 2. **Access Components Dialog:** Go to the main menu and select `Project -> Components...`. This will open the Components dialog box, listing registered controls. 3. **Locate and Select Control:** Scroll through the list under the "Controls" tab. Look for an entry like "VisioForge Media Player SDK Control" or similar (the exact name might vary slightly depending on the version). Check the box next to it. 4. **Add via Browse (If Not Listed):** If the control is not listed (perhaps due to a registration issue), click the "Browse..." button. Navigate to the VisioForge installation directory (the `Redist` subfolder containing `VisioForge_Media_Player_VB6.ocx`) and select the `.ocx` file. Click "Open". This should register and add the control to the list. Ensure its checkbox is ticked. 5. **Confirm:** Click "OK" or "Apply" in the Components dialog. 6. **Use Control:** The TVFMediaPlayer icon should now appear in your VB6 Toolbox. You can click and drag it onto your forms to use it visually. You can then interact with its properties and methods via code. #### Visual Studio (C#, VB.NET, C++ MFC) Visual Studio manages ActiveX controls through the COM Interoperability layer. 1. **Open Project:** Launch Visual Studio and open your Windows Forms (C# or VB.NET), WPF, or MFC project. 2. **Open Toolbox:** Ensure the Toolbox is visible (`View -> Toolbox`). 3. **Add Control to Toolbox:** - Right-click inside the Toolbox, preferably within a relevant tab like "General" or "All Windows Forms", or create a new tab (e.g., "VisioForge"). - Select "Choose Items...". - Wait for the "Choose Toolbox Items" dialog to load. This can sometimes take a moment as it scans registered components. - Navigate to the "COM Components" tab. - Scroll through the list and look for "VisioForge Media Player SDK Control" or a similar name. Check the box next to it. - **Add via Browse (If Not Listed):** If you cannot find it, click the "Browse..." button. Navigate to the VisioForge installation directory (the `Redist` subfolder for 32-bit, or `Redist\x64` for 64-bit) and select the `VisioForge_Media_Player.ocx` file. Click "Open". This should add it to the list; make sure its checkbox is now selected. - Click "OK". 4. **Use Control:** The TVFMediaPlayer control icon will now be available in your Visual Studio Toolbox. Drag and drop it onto your form (Windows Forms) or use it programmatically (WPF, MFC). Visual Studio will automatically generate the necessary Interop assemblies (wrappers) to allow managed code (.NET) or C++ to interact with the COM-based ActiveX control. ## Troubleshooting Common Installation Issues Encountering problems during installation? Here are some common issues and solutions: - **Control Not Registered / Not Appearing in IDE:** - Ensure the installer was run with administrator privileges. - The installer registers the control automatically, but you can re-register it manually. Open an **Administrator Command Prompt**, navigate to the directory containing the OCX (e.g., `cd "C:\Program Files\VisioForge\All-in-One Media Framework ActiveX\Redist"` for 32-bit, or `cd "C:\Program Files\VisioForge\All-in-One Media Framework ActiveX\Redist\x64"` for 64-bit), and run `regsvr32 VisioForge_Media_Player.ocx`. A success message should appear. - Check for conflicts with other media libraries or older VisioForge versions. Consider uninstalling previous versions first. - **Installation Fails or Rolls Back:** - Ensure you meet all system requirements, including DirectX and .NET versions. - Temporarily disable antivirus software, which might interfere with the registration process. Remember to re-enable it afterward. - Check for sufficient disk space on the target drive. - **Issues in Specific IDEs:** - **Delphi:** Ensure the library path is correctly added in `Tools -> Options -> Library Path` and that the correct `BPL` files are installed. Rebuilding packages might help. - **Visual Studio:** Delete the `obj` and `bin` folders in your project, delete any existing Interop assemblies related to VisioForge, remove the control reference, restart Visual Studio, and try adding the control again. Ensure your project targets a compatible .NET Framework version if applicable. ## Updating the Framework To update to a newer version of the All-in-One Media Framework: 1. **Check for Compatibility:** Review the release notes for the new version to understand changes and potential compatibility issues with your existing projects. 2. **Backup Projects:** Always back up your projects before updating a major library dependency. 3. **Uninstall Existing Version (Recommended):** It's generally best practice to uninstall the current version via the Windows Control Panel ("Add or Remove Programs" or "Apps & features") before installing the new one. This helps prevent file conflicts or registration issues. 4. **Download and Install:** Download the new version's installer and follow the standard installation procedure outlined earlier in this guide. 5. **Recompile Projects:** Open your projects in their respective IDEs. You may need to remove and re-add references or components if the underlying interfaces have changed significantly (though this is less common with minor updates). Recompile your entire project. 6. **Test Thoroughly:** Test your application extensively to ensure all media functionalities work as expected with the updated library. ## Uninstallation To remove the TVFMediaPlayer library and the All-in-One Media Framework: 1. **Close IDEs:** Ensure all development environments that might be using the library files are closed. 2. **Use Windows Uninstaller:** - Go to the Windows Control Panel or Settings app. - Navigate to "Programs and Features" or "Apps & features". - Locate "VisioForge Media Framework" (or similar name) in the list of installed programs. - Select it and click "Uninstall". - Follow the prompts in the uninstallation wizard. This process should remove the installed files and attempt to unregister the ActiveX control. 3. **Manual Cleanup (Optional):** In some rare cases, or if you want to ensure a complete removal, you might manually check and delete: - The main installation directory (e.g., `C:\Program Files\VisioForge\`). - Any remaining configuration files or registry entries (advanced users only, proceed with caution). - Interop assemblies generated within your project folders (`obj`, `bin`). ## Licensing and Activation The All-in-One Media Framework typically operates under a commercial license, often with a trial period. - **Trial Version:** The downloaded installer might initially function as a trial, which may have limitations (e.g., nag screens, time limits, restricted features). - **Purchasing a License:** To unlock the full capabilities and use the framework in production applications, you must purchase a license from the VisioForge website. - **Activation:** After purchase, you will usually receive a license key or instructions on how to activate the software. This might involve entering the key into a specific property of the control at runtime or using a license activation tool provided by VisioForge. Refer to the documentation accompanying your purchased license for exact details. ## Getting Support If you encounter issues not covered here or need further assistance: - **Official Documentation:** Check the `Docs` folder in your installation directory or the online documentation on the VisioForge website. The `CHM` help file often contains detailed API references and usage examples. - **Sample Projects:** Explore the example projects provided for your IDE. They demonstrate common use cases and correct implementation techniques. - **VisioForge Support:** Visit the support section on the VisioForge website. This may include forums, a knowledge base, or direct contact options for licensed users. ## Conclusion Installing the TVFMediaPlayer library, whether as a native Delphi package or an ActiveX control, is a straightforward process when following these detailed steps. By ensuring system requirements are met, carefully executing the installation wizard, and correctly integrating the components into your chosen IDE, you can quickly begin developing powerful multimedia applications. Remember to consult the specific IDE guides (Delphi, C++ Builder) linked herein and the official documentation for deeper insights and advanced configurations. With the framework successfully installed, you are well-equipped to explore the extensive features of the VisioForge All-in-One Media Framework. ---END OF PAGE--- ## Installing TVFMediaPlayer Library in Visual Basic 6 **URL:** https://www.visioforge.com/help/docs/delphi/mediaplayer/install/visual-basic-6/ **Description:** Install and integrate TVFMediaPlayer in VB6 - ActiveX setup, 32-bit considerations, basic playback implementation, and deployment practices. **Tags:** All-in-One Media Framework, Delphi, ActiveX, DirectShow, Windows, VCL, Playback, Streaming, Screen Capture **API:** TVFMediaPlayer # Integrating TVFMediaPlayer with Visual Basic 6: A Comprehensive Guide Microsoft Visual Basic 6 (VB6), despite its age, remains a relevant platform for many legacy applications. Its simplicity and rapid application development (RAD) capabilities made it incredibly popular. One way to extend the functionality of VB6 applications, particularly in multimedia processing, is by leveraging ActiveX controls. The TVFMediaPlayer library, developed by VisioForge, offers a powerful suite of multimedia features accessible to VB6 developers through its ActiveX interface. This guide provides a comprehensive walkthrough for installing, configuring, and utilizing the TVFMediaPlayer library within a Visual Basic 6 project. We will cover the nuances of working with ActiveX in VB6, address the inherent 32-bit limitations, and provide practical steps for integration and basic usage. ## Understanding ActiveX and VB6 Compatibility ActiveX controls are reusable software components based on Microsoft's Component Object Model (COM) technology. They allow developers to add specific functionalities to applications without writing the underlying code from scratch. Visual Basic 6 has excellent built-in support for ActiveX, enabling developers to easily incorporate third-party controls like TVFMediaPlayer into their projects via a graphical interface. This seamless integration means that VB6 developers can access the advanced multimedia capabilities of the VisioForge library—such as video playback, audio manipulation, screen capture, and network streaming—directly within the familiar VB6 IDE. ### The 32-bit Constraint A crucial point to understand is that Visual Basic 6 is strictly a 32-bit development environment. It was created during an era when 64-bit computing was not mainstream for desktop applications. Consequently, VB6 cannot create or directly interact with 64-bit components or processes. This limitation dictates that only the 32-bit (x86) version of the TVFMediaPlayer ActiveX control can be used with VB6. While modern systems are predominantly 64-bit, Windows maintains compatibility layers (WoW64 - Windows 32-bit on Windows 64-bit) that allow 32-bit applications like those built with VB6, and the 32-bit ActiveX controls they use, to run correctly on 64-bit operating systems. Despite being confined to a 32-bit architecture, the TVFMediaPlayer library is optimized to deliver robust and reliable performance. Developers can confidently build sophisticated multimedia applications in VB6, leveraging the full feature set provided by the 32-bit control. ## Prerequisites Before you begin the installation process, ensure you have the following: 1. **Microsoft Visual Basic 6:** A working installation of the VB6 IDE is required. This includes the necessary service packs (typically SP6). 2. **SDK:** Download the latest version of the SDK that includes the ActiveX components. Ensure you download the installer appropriate for your needs (often a combined x86/x64 installer, but only the x86 components will be registered for VB6 use). 3. **Administrator Privileges:** Installing the SDK and registering the ActiveX control typically requires administrator rights on the development machine. ## Step-by-Step Installation and Integration Follow these steps to integrate the TVFMediaPlayer control into your Visual Basic 6 project: ### **Step 1: Install the TVFMediaPlayer control** Run the downloaded VisioForge SDK installer. Follow the on-screen prompts. The installer will copy the necessary library files (`.ocx`, `.dll`) to your system and attempt to register the ActiveX control in the Windows Registry. Pay attention to the installation directory, though typically the registration process makes the control available system-wide. ### **Step 2: Create or Open a VB6 Project** Launch the Visual Basic 6 IDE. You can either start a new Standard EXE project or open an existing one where you wish to add multimedia capabilities. *Caption: Creating a new Standard EXE project in Visual Basic 6.* ### **Step 3: Add the TVFMediaPlayer Component** To make the ActiveX control available in your project's Toolbox, you need to add it through the "Components" dialog. - Go to the `Project` menu and select `Components...`. Alternatively, right-click on the Toolbox and choose `Components...`. *Caption: Accessing the Components dialog from the Project menu.* - The "Components" dialog lists all registered ActiveX controls on your system. Scroll down the list under the "Controls" tab. - Locate and check the box next to "VisioForge Media Player" (the exact name might vary slightly depending on the installed version). *Caption: Selecting the 'VisioForge Media Player' control in the Components dialog.* - Click `OK` or `Apply`. ### **Step 4: Use the Control in Your Project** After adding the component, its icon will appear in the VB6 Toolbox. *Caption: The TVFMediaPlayer control added to the Visual Basic 6 Toolbox.* You can now select the TVFMediaPlayer icon from the Toolbox and draw it onto any form in your project, just like any standard VB6 control (e.g., Button, TextBox). This creates an instance of the media player object on your form. You can resize and position it as needed using the form designer. #### **Basic Usage: Controlling the Player** Once the TVFMediaPlayer control (`VFMediaPlayer1` by default, if it's the first one added) is on your form, you can interact with it programmatically using VB6 code. ## Deployment Considerations When you distribute your VB6 application that uses the TVFMediaPlayer control, you must ensure the necessary runtime files are included and correctly registered on the target user's machine. 1. **Required Files:** Identify the specific `.ocx` file for the TVFMediaPlayer control and any dependent `.dll` files provided by the VisioForge SDK. These files need to be shipped with your application installer. 2. **Registration:** The ActiveX control (`.ocx` file) must be registered in the Windows Registry on the target machine. Standard installer tools (like Inno Setup, InstallShield, or even older VB6 packaging tools) usually provide mechanisms to register ActiveX controls during installation. Alternatively, the `regsvr32.exe` command-line utility can be used manually or via a script: ``` regsvr32.exe "C:\\Program Files (x86)\\YourApp\\VisioForge_Media_Player_VB6.ocx" ``` Remember to use the correct path and run the command with administrator privileges. Since it's a 32-bit control, even on a 64-bit system, you typically use the `regsvr32.exe` found in the `C:\Windows\SysWOW64` directory, although the system often handles this redirection automatically. 3. **Licensing:** Ensure you comply with the VisioForge licensing terms for deployment. Some versions might require a runtime license key to be set programmatically within your application. ## Troubleshooting Common Issues - **Control Not Appearing in Components:** - Ensure the VisioForge SDK was installed correctly with administrator rights. - Try manually registering the `.ocx` file using `regsvr32.exe` from an elevated command prompt. - Verify you are looking for the correct name in the Components list. - **"Runtime Error '429': ActiveX component can't create object":** - This usually indicates the control is not properly registered on the machine where the application is running. Re-register the `.ocx` file. - Ensure all dependent DLLs are present in the application's directory or a system path. - **Playback Issues (No Video/Audio, Errors):** - Verify the path to the media file is correct and accessible. - Ensure necessary codecs are installed on the system (though TVFMediaPlayer often includes internal decoders or uses DirectShow/Media Foundation). - Check the VisioForge documentation for specific error codes or properties that might give more detail. - Implement proper error handling around player methods (`Play`, `Stop`, property setting) to diagnose issues. ## Beyond VB6: Modernization While TVFMediaPlayer provides a bridge for adding modern multimedia features to legacy VB6 applications, organizations should also consider long-term strategies. Migrating VB6 applications to newer platforms like .NET (using C# or VB.NET) or web-based technologies can offer significant advantages in terms of performance, security, maintainability, and access to the latest development tools and libraries. VisioForge also offers .NET-native versions of its libraries, which would be the preferred choice in a modernized application. ## Conclusion The TVFMediaPlayer library, through its ActiveX control, offers a powerful and accessible way for Visual Basic 6 developers to incorporate advanced multimedia functionalities into their applications. By understanding the installation process, the 32-bit limitations, basic control usage, and deployment requirements outlined in this guide, developers can effectively leverage VisioForge technology to enhance their VB6 projects. While VB6 is a legacy platform, tools like TVFMediaPlayer help extend its useful life for specific application needs. --- For further assistance or more complex scenarios, please get in touch with [VisioForge support](https://support.visioforge.com/). Explore the extensive code samples available on the VisioForge [GitHub repository](https://github.com/visioforge/) for more advanced examples and techniques. ---END OF PAGE--- ## Add ActiveX Media Player to Visual Studio C++/C#/VB.NET **URL:** https://www.visioforge.com/help/docs/delphi/mediaplayer/install/visual-studio/ **Description:** Import TVFMediaPlayer ActiveX control into Visual Studio 2010+ projects. Step-by-step COM wrapper generation, toolbox setup, and .NET SDK migration guide. **Tags:** Media Player SDK, All-in-One Media Framework, Delphi, ActiveX, Windows, VCL, Playback, MP4, AVI, MOV, WMV, C# **API:** TVFMediaPlayer # Installing TVFMediaPlayer ActiveX in Visual Studio 2010 and Later This guide provides detailed instructions for integrating the VisioForge Media Player (`TVFMediaPlayer`) ActiveX control into your Microsoft Visual Studio projects (version 2010 and newer). We will cover the necessary steps for C++, C#, and Visual Basic .NET environments, explain the underlying mechanisms, and discuss important considerations, including why migrating to the native .NET SDK is highly recommended for modern development. ## Understanding ActiveX and its Role in Modern Development ActiveX, a technology developed by Microsoft, allows software components (controls) to interact with one another regardless of the language they were originally written in. It's based on the Component Object Model (COM). In the context of Visual Studio, ActiveX controls can be embedded within application forms to provide specific functionalities, such as media playback in the case of `TVFMediaPlayer`. While historically significant, ActiveX usage has declined, especially within the .NET ecosystem. Modern .NET frameworks offer more integrated, robust, and secure ways to incorporate UI components and functionality. However, legacy applications or specific interoperability scenarios might still necessitate the use of ActiveX controls. When you use an ActiveX control in a .NET project (C# or VB.Net), Visual Studio doesn't interact with it directly. Instead, it automatically generates **Runtime Callable Wrappers (RCW)**. These wrappers are essentially .NET assemblies that act as intermediaries, translating .NET calls into COM calls that the ActiveX control understands, and vice versa. This process allows managed (.NET) code to utilize unmanaged (COM/ActiveX) components. ## Prerequisites Before you begin, ensure you have the following: 1. **Microsoft Visual Studio:** Version 2010 or a later edition installed. 2. **TVFMediaPlayer ActiveX Control:** The VisioForge Media Player ActiveX control must be properly installed and registered on your development machine. You can typically download this from the VisioForge website or distributor. **Crucially**, you might need both the 32-bit (x86) and 64-bit (x64) versions registered, even if you are only developing a 64-bit application. Visual Studio's designer often runs as a 32-bit process and requires the x86 version to display the control visually during design time. The runtime will use the version corresponding to your project's target architecture (x86 or x64). 3. **Project:** An existing or new C++, C#, or VB.NET project where you intend to use the media player. ## Step-by-Step Installation in Visual Studio The process involves adding the `TVFMediaPlayer` control to the Visual Studio Toolbox, which then allows you to drag and drop it onto your application's forms or windows. ### **Step 1: Create or Open Your Project** Launch Visual Studio and create a new project or open an existing one. The example screenshots below use a C# Windows Forms application, but the steps are analogous for C++ (MFC, perhaps) and VB.NET WinForms. - For C# WinForms: `File -> New -> Project -> Visual C# -> Windows Forms App (.NET Framework)` - For VB.NET WinForms: `File -> New -> Project -> Visual Basic -> Windows Forms App (.NET Framework)` - For C++ MFC: `File -> New -> Project -> Visual C++ -> MFC/ATL -> MFC App` ### **Step 2: Open the Toolbox** If the Toolbox is not visible, you can open it via the `View` menu (`View -> Toolbox` or `Ctrl+Alt+X`). The Toolbox contains standard UI controls and components. ### **Step 3: Add the ActiveX Control to the Toolbox** To make the `TVFMediaPlayer` control available, you need to add it to the Toolbox: 1. Right-click within an empty area of the Toolbox (e.g., under the "General" tab or create a new tab). 2. Select "Choose Items..." from the context menu. ### **Step 4: Select the TVFMediaPlayer Control** 1. The "Choose Toolbox Items" dialog will appear. Navigate to the "COM Components" tab. This tab lists all registered ActiveX controls on your system. 2. Scroll through the list or use the filter box to find the "VisioForge Media Player" control (the exact name might vary slightly based on the installed version). 3. Check the checkbox next to the control's name. 4. Click "OK". Visual Studio will now add the control to your Toolbox and, if you are in a C# or VB.Net project, it will generate the necessary RCW assemblies (often named `AxInterop.VisioForgeMediaPlayerLib.dll` and `Interop.VisioForgeMediaPlayerLib.dll`) and add references to them in your project. ### **Step 5: Add the Control to Your Form** 1. Locate the newly added "VisioForge Media Player" icon in the Toolbox. 2. Click and drag the icon onto your application's form or design surface. An instance of the `TVFMediaPlayer` control will appear on your form. You can resize and position it as needed using the designer. ### **Step 6: Interacting with the Control (Code)** You can now interact with the media player control programmatically through its properties, methods, and events. Select the control in the designer, and use the Properties window (`F4`) to configure its appearance and basic behavior. To control playback, handle events, etc., you'll write code. Here's a simple C# example to load and play a video file when a button is clicked: ``` // Assuming your TVFMediaPlayer control is named 'axMediaPlayer1' // and you have a button named 'buttonPlay' private void buttonPlay_Click(object sender, EventArgs e) { // Prompt user to select a video file OpenFileDialog openFileDialog = new OpenFileDialog(); openFileDialog.Filter = "Media Files|*.mp4;*.avi;*.mov;*.wmv|All Files|*.*"; if (openFileDialog.ShowDialog() == DialogResult.OK) { try { // Set the filename for the ActiveX control axMediaPlayer1.FilenameOrURL = openFileDialog.FileName; // Start playback axMediaPlayer1.Play(); } catch (Exception ex) { MessageBox.Show($"Error playing file: {ex.Message}"); } } } // Example of handling an event (e.g., playback completed) private void axMediaPlayer1_OnStop(object sender, EventArgs e) { MessageBox.Show("Playback stopped or finished."); } // Remember to attach the event handler, usually in the Form's Load event or constructor public Form1() { InitializeComponent(); axMediaPlayer1.OnStop += axMediaPlayer1_OnStop; // Attach the event handler } ``` Similar code can be written in VB.NET, accessing the same properties (`FilenameOrURL`, `Play()`) and events (`OnStop`). In C++, you would typically use COM interfaces directly or MFC wrappers if using that framework. ## Important: The Case for the Native .NET SDK While the steps above show how to use the ActiveX control, **for all new .NET development (C#, VB.NET), we strongly recommend using the native VisioForge Media Player SDK for .NET.** The ActiveX approach, while functional, carries several significant disadvantages in the modern .NET world: 1. **Complexity:** Relies on COM Interop and RCW generation, adding layers of abstraction that can sometimes be fragile or lead to unexpected behavior. 2. **Performance:** COM Interop can introduce performance overhead compared to native .NET code. 3. **Deployment:** Requires proper registration of the ActiveX control (x86 and potentially x64) on the end-user's machine using `regsvr32`, which can complicate deployment and require administrative privileges. Native .NET libraries are typically deployed just by copying files (XCopy deployment) or via NuGet. 4. **Limited Integration:** ActiveX controls don't integrate as seamlessly with modern .NET UI frameworks like WPF or MAUI. While they can sometimes be hosted, it's often awkward and limited compared to native controls. 5. **Bitness Mismatches:** Managing x86/x64 versions and ensuring the correct one is used by the application and the VS designer can be error-prone. 6. **Technology Age:** ActiveX is a legacy technology with limited ongoing evolution compared to the rapidly advancing .NET platform. **Advantages of the Native .NET SDK:** - **Native Controls:** Provides dedicated, optimized controls for WinForms, WPF, and MAUI. - **Full .NET Integration:** Leverages the full power of the .NET framework, including async/await, LINQ, modern event patterns, and easier data binding. - **Simplified Deployment:** Usually involves just referencing the SDK assemblies or NuGet packages. No COM registration needed. - **Enhanced Features:** Often includes more features, better performance, and more granular control than the corresponding ActiveX version. - **Improved Stability & Maintainability:** Native code is generally easier to debug, maintain, and less prone to interop issues. - **Future-Proofing:** Aligns your application with modern .NET development practices. You can find the native [.Net version of the SDK here](https://www.visioforge.com/media-player-sdk-net). It offers a significantly superior development experience and results for .NET applications. ## Troubleshooting Common Issues - **Control Not Appearing in "COM Components":** Ensure the `TVFMediaPlayer` ActiveX control is correctly installed and registered. Try running the registration command (`regsvr32 `) manually as an administrator. Remember to register both x86 and x64 versions if available and needed. - **Error Adding Control to Form:** This often points to a mismatch between the Visual Studio designer process (usually x86) and the registered control version. Make sure the x86 version is registered. - **Runtime Errors (File Not Found, Class Not Registered):** Verify the control (correct bitness for your app's target) is registered on the target machine where the application is run. Check project references to ensure the Interop assemblies are correctly included. - **Events Not Firing:** Double-check that event handlers are correctly attached to the control's events in your code. ## Conclusion Integrating the `TVFMediaPlayer` ActiveX control into Visual Studio 2010+ is achievable by adding it via the "Choose Toolbox Items" dialog. Visual Studio handles the generation of wrapper assemblies for .NET projects, allowing interaction via standard properties, methods, and events. However, due to the complexities, limitations, and deployment challenges associated with ActiveX/COM Interop in the .NET environment, **it is strongly advised to use the native VisioForge Media Player SDK for .NET for any new WinForms, WPF, or MAUI development.** The native SDK provides a more robust, performant, and developer-friendly experience aligned with modern application development practices. --- Need further assistance? Please contact [VisioForge Support](https://support.visioforge.com/) or explore more examples on our [GitHub](https://github.com/visioforge/) page. ---END OF PAGE--- ## Audio Capture to MP3 Files in Delphi, C++ MFC & VB6 **URL:** https://www.visioforge.com/help/docs/delphi/videocapture/audio-capture-mp3/ **Description:** Implement MP3 audio capture in Delphi, C++, and VB6 - configure LAME encoder, manage bitrates, and create high-quality audio recordings. **Tags:** All-in-One Media Framework, Delphi, ActiveX, Windows, VCL, Capture, Encoding, MP3 # Audio Capture to MP3 Files in Delphi, C++ MFC & VB6 ## Introduction Audio capture capabilities are essential for many modern applications, from voice recording tools to multimedia creation software. This guide walks through the implementation of MP3 audio capture functionality in Delphi, C++ MFC, and VB6 applications using the VideoCapture component. MP3 remains one of the most widely used audio formats due to its excellent compression and broad compatibility. By implementing proper MP3 audio capture in your applications, you can provide users with efficient, high-quality audio recording capabilities. ## Prerequisites Before implementing MP3 audio capture, ensure you have: - Development environment with Delphi, Visual C++ (for MFC), or Visual Basic 6 - VideoCapture component properly installed and referenced in your project - Basic understanding of audio encoding concepts - Required permissions for audio device access in your application ## LAME Encoder Configuration The LAME MP3 encoder provides extensive customization options for audio quality, bitrate management, and channel configuration. Properly configuring these settings is crucial for achieving the desired audio quality while managing file size. ### Configuring Basic Encoding Parameters The following code snippets demonstrate how to configure basic LAME encoding parameters: ``` // Delphi VideoCapture1.Audio_LAME_CBR_Bitrate := StrToInt(cbLameCBRBitrate.Items[cbLameCBRBitrate.ItemIndex]); VideoCapture1.Audio_LAME_VBR_Min_Bitrate := StrToInt(cbLameVBRMin.Items[cbLameVBRMin.ItemIndex]); VideoCapture1.Audio_LAME_VBR_Max_Bitrate := StrToInt(cbLameVBRMax.Items[cbLameVBRMax.ItemIndex]); VideoCapture1.Audio_LAME_Sample_Rate := StrToInt(cbLameSampleRate.Items[cbLameSampleRate.ItemIndex]); VideoCapture1.Audio_LAME_VBR_Quality := tbLameVBRQuality.Position; VideoCapture1.Audio_LAME_Encoding_Quality := tbLameEncodingQuality.Position; ``` ``` // C++ MFC // CComboBox::GetCurSel returns CB_ERR (-1) when nothing is selected — skip the // assignment in that case so the property keeps its previously configured value. int nIndex; nIndex = m_cbLameCBRBitrate.GetCurSel(); if (nIndex != CB_ERR) m_VideoCapture.Audio_LAME_CBR_Bitrate = (int)m_cbLameCBRBitrate.GetItemData(nIndex); nIndex = m_cbLameVBRMin.GetCurSel(); if (nIndex != CB_ERR) m_VideoCapture.Audio_LAME_VBR_Min_Bitrate = (int)m_cbLameVBRMin.GetItemData(nIndex); nIndex = m_cbLameVBRMax.GetCurSel(); if (nIndex != CB_ERR) m_VideoCapture.Audio_LAME_VBR_Max_Bitrate = (int)m_cbLameVBRMax.GetItemData(nIndex); nIndex = m_cbLameSampleRate.GetCurSel(); if (nIndex != CB_ERR) m_VideoCapture.Audio_LAME_Sample_Rate = (int)m_cbLameSampleRate.GetItemData(nIndex); m_VideoCapture.Audio_LAME_VBR_Quality = m_tbLameVBRQuality.GetPos(); m_VideoCapture.Audio_LAME_Encoding_Quality = m_tbLameEncodingQuality.GetPos(); ``` ``` ' VB6 VideoCapture1.Audio_LAME_CBR_Bitrate = CInt(cbLameCBRBitrate.List(cbLameCBRBitrate.ListIndex)) VideoCapture1.Audio_LAME_VBR_Min_Bitrate = CInt(cbLameVBRMin.List(cbLameVBRMin.ListIndex)) VideoCapture1.Audio_LAME_VBR_Max_Bitrate = CInt(cbLameVBRMax.List(cbLameVBRMax.ListIndex)) VideoCapture1.Audio_LAME_Sample_Rate = CInt(cbLameSampleRate.List(cbLameSampleRate.ListIndex)) VideoCapture1.Audio_LAME_VBR_Quality = tbLameVBRQuality.Value VideoCapture1.Audio_LAME_Encoding_Quality = tbLameEncodingQuality.Value ``` ### Setting Audio Channel Modes Channel configuration affects both sound quality and file size. The following code demonstrates how to set the channel mode: ``` // Delphi if rbLameStandardStereo.Checked then VideoCapture1.Audio_LAME_Channels_Mode := CH_Standard_Stereo else if rbLameJointStereo.Checked then VideoCapture1.Audio_LAME_Channels_Mode := CH_Joint_Stereo else if rbLameDualChannels.Checked then VideoCapture1.Audio_LAME_Channels_Mode := CH_Dual_Stereo else VideoCapture1.Audio_LAME_Channels_Mode := CH_Mono; ``` ``` // C++ MFC if (m_rbLameStandardStereo.GetCheck()) m_VideoCapture.Audio_LAME_Channels_Mode = VisioForge_Video_Capture::CH_Standard_Stereo; else if (m_rbLameJointStereo.GetCheck()) m_VideoCapture.Audio_LAME_Channels_Mode = VisioForge_Video_Capture::CH_Joint_Stereo; else if (m_rbLameDualChannels.GetCheck()) m_VideoCapture.Audio_LAME_Channels_Mode = VisioForge_Video_Capture::CH_Dual_Stereo; else m_VideoCapture.Audio_LAME_Channels_Mode = VisioForge_Video_Capture::CH_Mono; ``` ``` ' VB6 If rbLameStandardStereo.Value Then VideoCapture1.Audio_LAME_Channels_Mode = CH_Standard_Stereo ElseIf rbLameJointStereo.Value Then VideoCapture1.Audio_LAME_Channels_Mode = CH_Joint_Stereo ElseIf rbLameDualChannels.Value Then VideoCapture1.Audio_LAME_Channels_Mode = CH_Dual_Stereo Else VideoCapture1.Audio_LAME_Channels_Mode = CH_Mono End If ``` ### Advanced LAME Configuration Options For more precise control over the encoding process, configure these advanced LAME options: ``` // Delphi VideoCapture1.Audio_LAME_VBR_Mode := rbLameVBR.Checked; VideoCapture1.Audio_LAME_Copyright := cbLameCopyright.Checked; VideoCapture1.Audio_LAME_Original := cbLameOriginalCopy.Checked; VideoCapture1.Audio_LAME_CRC_Protected := cbLameCRCProtected.Checked; VideoCapture1.Audio_LAME_Force_Mono := cbLameForceMono.Checked; VideoCapture1.Audio_LAME_Strictly_Enforce_VBR_Min_Bitrate := cbLameStrictlyEnforceVBRMinBitrate.Checked; VideoCapture1.Audio_LAME_Voice_Encoding_Mode := cbLameVoiceEncodingMode.Checked; VideoCapture1.Audio_LAME_Keep_All_Frequencies := cbLameKeepAllFrequencies.Checked; VideoCapture1.Audio_LAME_Strict_ISO_Compilance := cbLameStrictISOCompilance.Checked; VideoCapture1.Audio_LAME_Disable_Short_Blocks := cbLameDisableShortBlocks.Checked; VideoCapture1.Audio_LAME_Enable_Xing_VBR_Tag := cbLameEnableXingVBRTag.Checked; VideoCapture1.Audio_LAME_Mode_Fixed := cbLameModeFixed.Checked; ``` ``` // C++ MFC m_VideoCapture.Audio_LAME_VBR_Mode = m_rbLameVBR.GetCheck() ? true : false; m_VideoCapture.Audio_LAME_Copyright = m_cbLameCopyright.GetCheck() ? true : false; m_VideoCapture.Audio_LAME_Original = m_cbLameOriginalCopy.GetCheck() ? true : false; m_VideoCapture.Audio_LAME_CRC_Protected = m_cbLameCRCProtected.GetCheck() ? true : false; m_VideoCapture.Audio_LAME_Force_Mono = m_cbLameForceMono.GetCheck() ? true : false; m_VideoCapture.Audio_LAME_Strictly_Enforce_VBR_Min_Bitrate = m_cbLameStrictlyEnforceVBRMinBitrate.GetCheck() ? true : false; m_VideoCapture.Audio_LAME_Voice_Encoding_Mode = m_cbLameVoiceEncodingMode.GetCheck() ? true : false; m_VideoCapture.Audio_LAME_Keep_All_Frequencies = m_cbLameKeepAllFrequencies.GetCheck() ? true : false; m_VideoCapture.Audio_LAME_Strict_ISO_Compilance = m_cbLameStrictISOCompilance.GetCheck() ? true : false; m_VideoCapture.Audio_LAME_Disable_Short_Blocks = m_cbLameDisableShortBlocks.GetCheck() ? true : false; m_VideoCapture.Audio_LAME_Enable_Xing_VBR_Tag = m_cbLameEnableXingVBRTag.GetCheck() ? true : false; m_VideoCapture.Audio_LAME_Mode_Fixed = m_cbLameModeFixed.GetCheck() ? true : false; ``` ``` ' VB6 VideoCapture1.Audio_LAME_VBR_Mode = rbLameVBR.Value VideoCapture1.Audio_LAME_Copyright = cbLameCopyright.Value VideoCapture1.Audio_LAME_Original = cbLameOriginalCopy.Value VideoCapture1.Audio_LAME_CRC_Protected = cbLameCRCProtected.Value VideoCapture1.Audio_LAME_Force_Mono = cbLameForceMono.Value VideoCapture1.Audio_LAME_Strictly_Enforce_VBR_Min_Bitrate = cbLameStrictlyEnforceVBRMinBitrate.Value VideoCapture1.Audio_LAME_Voice_Encoding_Mode = cbLameVoiceEncodingMode.Value VideoCapture1.Audio_LAME_Keep_All_Frequencies = cbLameKeepAllFrequencies.Value VideoCapture1.Audio_LAME_Strict_ISO_Compilance = cbLameStrictISOCompilance.Value VideoCapture1.Audio_LAME_Disable_Short_Blocks = cbLameDisableShortBlocks.Value VideoCapture1.Audio_LAME_Enable_Xing_VBR_Tag = cbLameEnableXingVBRTag.Value VideoCapture1.Audio_LAME_Mode_Fixed = cbLameModeFixed.Value ``` ## Understanding LAME Configuration Options ### Bitrate Settings - **CBR (Constant Bitrate)**: Maintains the same bitrate throughout the entire recording - **VBR (Variable Bitrate)**: Adjusts bitrate based on audio complexity - **Min/Max Bitrate**: Sets boundaries for VBR encoding - **VBR Quality**: Controls the quality/file size balance in VBR mode ### Channel Modes - **Standard Stereo**: Completely separate left and right channels - **Joint Stereo**: Combines redundant information between channels to save space - **Dual Stereo**: Two completely independent mono channels - **Mono**: Single audio channel ### Special Encoding Options - **Voice Encoding Mode**: Optimizes encoding for voice frequencies - **Force Mono**: Converts stereo input to mono output - **CRC Protection**: Adds error detection data - **Strict ISO Compliance**: Ensures maximum compatibility with all MP3 players ## Configuring Output Format After setting up LAME encoding parameters, specify MP3 as the output format: ``` // Delphi VideoCapture1.OutputFormat := Format_LAME; ``` ``` // C++ MFC m_VideoCapture.OutputFormat = VisioForge_Video_Capture::Format_LAME; ``` ``` ' VB6 VideoCapture1.OutputFormat = Format_LAME ``` ## Setting Audio Capture Mode Set the VideoCapture component to audio-only capture mode: ``` // Delphi VideoCapture1.Mode := Mode_Audio_Capture; ``` ``` // C++ MFC m_VideoCapture.Mode = VisioForge_Video_Capture::Mode_Audio_Capture; ``` ``` ' VB6 VideoCapture1.Mode = Mode_Audio_Capture ``` ## Starting the Audio Capture Once all parameters are configured, initiate the recording process: ``` // Delphi VideoCapture1.Start; ``` ``` // C++ MFC m_VideoCapture.Start(); ``` ``` ' VB6 VideoCapture1.Start ``` ## Best Practices for MP3 Audio Capture - **Quality vs. Size**: For voice recordings, lower bitrates (64-128 kbps) are usually sufficient. For music, use 192 kbps or higher. - **Sample Rate Selection**: 44.1 kHz is standard for most audio. Lower rates can be used for voice-only recordings. - **VBR vs. CBR**: VBR generally provides better quality-to-size ratio but might have compatibility issues with some players. - **Error Handling**: Always implement proper error handling around the recording process. - **User Feedback**: Provide visual feedback during recording (level meters, time elapsed). ## Conclusion Implementing MP3 audio capture in your applications provides users with a widely compatible and efficient recording solution. By properly configuring LAME encoder settings, you can balance audio quality and file size based on your application's specific requirements. The VideoCapture component makes this implementation straightforward in Delphi, C++ MFC, and VB6 applications, allowing you to focus on creating a great user experience around the audio capture functionality. --- For additional code samples and advanced implementation techniques, visit our GitHub repository. If you encounter any issues during implementation, contact our technical support team for assistance. ---END OF PAGE--- ## Delphi Video Capture SDK WAV Audio Recording Guide **URL:** https://www.visioforge.com/help/docs/delphi/videocapture/audio-capture-wav/ **Description:** Capture audio to WAV files in Delphi with codec selection, compression options, and stereo recording using TVFVideoCapture code examples. **Tags:** All-in-One Media Framework, Delphi, ActiveX, Windows, VCL, Capture, WAV # Audio Capture to WAV Files: Developer Implementation Guide ## Introduction Capturing audio to WAV files is a fundamental requirement for many multimedia applications. This guide provides detailed instructions for implementing audio capture functionality with or without compression in your applications. Whether you're developing in Delphi, C++ MFC, or VB6 using our ActiveX controls, this guide will walk you through the entire process from initial setup to final implementation. ## Setting Up Your Development Environment Before you begin implementing audio capture, ensure you have: 1. Installed the SDK in your development environment 2. Added the VideoCapture component to your form/project 3. Set up basic error handling to manage capture exceptions 4. Configured your application to access audio hardware ## Audio Codec Management ### Retrieving Available Audio Codecs The first step in implementing audio capture is to retrieve a list of available audio codecs on the system. This allows you to present users with codec options or to programmatically select the most appropriate codec for your application's needs. #### Delphi Implementation ``` // Iterate through all available audio codecs for i := 0 to VideoCapture1.Audio_Codecs_GetCount - 1 do cbAudioCodec.Items.Add(VideoCapture1.Audio_Codecs_GetItem(i)); ``` #### C++ MFC Implementation ``` // Get all available audio codecs and populate combo box for (int i = 0; i < m_VideoCapture.Audio_Codecs_GetCount(); i++) { CString codec = m_VideoCapture.Audio_Codecs_GetItem(i); m_AudioCodecCombo.AddString(codec); } ``` #### VB6 Implementation ``` ' Iterate through all available audio codecs For i = 0 To VideoCapture1.Audio_Codecs_GetCount - 1 cboAudioCodec.AddItem VideoCapture1.Audio_Codecs_GetItem(i) Next i ``` ### Selecting an Audio Codec Once you've populated the list of available codecs, you'll need to provide a way to select the desired codec for the audio capture operation. This can be done programmatically or via user selection. #### Delphi Implementation ``` // Set the codec based on user selection from combo box VideoCapture1.Audio_Codec := cbAudioCodec.Items[cbAudioCodec.ItemIndex]; ``` #### C++ MFC Implementation ``` // Get the selected codec from the combo box int selectedIndex = m_AudioCodecCombo.GetCurSel(); CString selectedCodec; m_AudioCodecCombo.GetLBText(selectedIndex, selectedCodec); // Set the codec m_VideoCapture.SetAudio_Codec(selectedCodec); ``` #### VB6 Implementation ``` ' Set the codec based on user selection VideoCapture1.Audio_Codec = cboAudioCodec.Text ``` ## Configuring Audio Parameters Proper audio parameter configuration is crucial for achieving the desired quality and file size balance. The three primary parameters to configure are channels, bits per sample (BPS), and sample rate. ### Setting Audio Channels Audio channels determine whether the captured audio is mono (1 channel) or stereo (2 channels). Stereo provides better spatial audio representation but requires more storage space. #### Delphi Implementation ``` // Set the number of audio channels (1 for mono, 2 for stereo) VideoCapture1.Audio_Channels := StrToInt(cbChannels2.Items[cbChannels2.ItemIndex]); ``` #### C++ MFC Implementation ``` // Set audio channels (1 for mono, 2 for stereo) int nIndex = m_ChannelsCombo.GetCurSel(); if (nIndex == CB_ERR) return; // No selection — leave the current value untouched CString strChannels; m_ChannelsCombo.GetLBText(nIndex, strChannels); int channels = _ttoi(strChannels); m_VideoCapture.SetAudio_Channels(channels); ``` #### VB6 Implementation ``` ' Set audio channels (1 for mono, 2 for stereo) VideoCapture1.Audio_Channels = CInt(cboChannels.Text) ``` ### Configuring Bits Per Sample (BPS) The bits per sample (BPS) setting affects the dynamic range and quality of the audio. Common values include 8, 16, and 24 bits, with higher values providing better quality at the cost of larger file sizes. #### Delphi Implementation ``` // Set bits per sample (typically 8, 16, or 24) VideoCapture1.Audio_BPS := StrToInt(cbBPS2.Items[cbBPS2.ItemIndex]); ``` #### C++ MFC Implementation ``` // Set bits per sample int nIndex = m_BPSCombo.GetCurSel(); if (nIndex == CB_ERR) return; // No selection — leave the current value untouched CString strBPS; m_BPSCombo.GetLBText(nIndex, strBPS); int bps = _ttoi(strBPS); m_VideoCapture.SetAudio_BPS(bps); ``` #### VB6 Implementation ``` ' Set bits per sample VideoCapture1.Audio_BPS = CInt(cboBPS.Text) ``` ### Setting Sample Rate The sample rate determines how many audio samples are captured per second. Common values include 8000 Hz, 44100 Hz (CD quality), and 48000 Hz (professional audio). Higher sample rates capture more high-frequency detail but increase file size. #### Delphi Implementation ``` // Set audio sample rate in Hz (common values: 8000, 44100, 48000) VideoCapture1.Audio_SampleRate := StrToInt(cbSamplerate.Items[cbSamplerate.ItemIndex]); ``` #### C++ MFC Implementation ``` // Set sample rate int nIndex = m_SampleRateCombo.GetCurSel(); if (nIndex == CB_ERR) return; // No selection — leave the current value untouched CString strSampleRate; m_SampleRateCombo.GetLBText(nIndex, strSampleRate); int sampleRate = _ttoi(strSampleRate); m_VideoCapture.SetAudio_SampleRate(sampleRate); ``` #### VB6 Implementation ``` ' Set sample rate VideoCapture1.Audio_SampleRate = CInt(cboSampleRate.Text) ``` ## Configuring Output Format ### Selecting PCM/ACM Format The Windows Audio Compression Manager (ACM) supports various audio formats including PCM (uncompressed) and compressed formats. Setting the output format to PCM/ACM enables codec-based compression when a codec other than PCM is selected. #### Delphi Implementation ``` // Set output to PCM/ACM format to enable codec-based compression VideoCapture1.OutputFormat := Format_PCM_ACM; ``` #### C++ MFC Implementation ``` // Set output format to PCM/ACM m_VideoCapture.SetOutputFormat(Format_PCM_ACM); ``` #### VB6 Implementation ``` ' Set output format to PCM/ACM VideoCapture1.OutputFormat = Format_PCM_ACM ``` ## Setting the Audio Capture Mode Before starting the capture operation, you need to set the component to audio capture mode. This ensures that only audio is captured without any video streams. ### Delphi Implementation ``` // Set to audio-only capture mode VideoCapture1.Mode := Mode_Audio_Capture; ``` ### C++ MFC Implementation ``` // Set to audio-only capture mode m_VideoCapture.SetMode(Mode_Audio_Capture); ``` ### VB6 Implementation ``` ' Set to audio-only capture mode VideoCapture1.Mode = Mode_Audio_Capture ``` ## Starting the Audio Capture With all parameters configured, you can now start the audio capture process. This initializes the audio hardware, applies the selected codec and settings, and begins capturing audio to the specified output file. ### Delphi Implementation ``` // Begin audio capture process VideoCapture1.Start; ``` ### C++ MFC Implementation ``` // Begin audio capture process m_VideoCapture.Start(); ``` ### VB6 Implementation ``` ' Begin audio capture process VideoCapture1.Start ``` ## Advanced Implementation Considerations ### User Interface Integration To provide a better user experience, consider implementing: 1. Real-time audio level metering 2. Elapsed time display 3. File size estimation 4. Pause/resume functionality ### Performance Optimization For optimal performance when capturing extended audio sessions: 1. Monitor system memory usage 2. Implement file splitting for long recordings 3. Consider buffering strategies for high-quality captures ## Troubleshooting Common Issues When implementing audio capture, you might encounter these common issues: 1. **No audio devices detected**: Ensure proper hardware connections and drivers 2. **Poor audio quality**: Verify sample rate and bits per sample settings 3. **Codec compatibility issues**: Test with standard codecs like PCM or MP3 4. **High CPU usage**: Consider reducing sample rate or using hardware acceleration ## Conclusion Implementing audio capture to WAV files in your applications requires careful configuration of codecs, audio parameters, and output settings. By following this guide, you can create robust audio capture functionality that balances quality and file size requirements. For complex implementations or specific technical challenges, our support team is available to assist with custom solutions tailored to your application requirements. ## Additional Resources Visit our GitHub page for more code samples and implementation examples that demonstrate advanced audio capture techniques and integration patterns. --- For technical assistance with this implementation, please contact our support team. Additional code samples are available on our GitHub page. ---END OF PAGE--- ## Delphi Audio Output Device Selection | VideoCapture **URL:** https://www.visioforge.com/help/docs/delphi/videocapture/audio-output/ **Description:** Select audio output devices in Delphi - enumerate devices, control volume, adjust balance with code examples for Delphi, C++, and VB6. **Tags:** All-in-One Media Framework, Delphi, ActiveX, Windows, VCL, Capture # Audio Output Device Selection in Delphi This guide provides detailed instructions and code examples for implementing audio output device selection in your video capture applications. Delphi, C++ MFC, and VB6 implementations are covered to help you integrate this functionality into your projects efficiently. ## Available Audio Output Device Enumeration The first step in implementing audio output device selection is retrieving the complete list of available audio output devices on the system. This allows users to choose their preferred audio output device. ### Delphi Implementation ``` // Iterate through all available audio output devices for i := 0 to VideoCapture1.Audio_OutputDevices_GetCount - 1 do // Add each device to the dropdown list cbAudioOutputDevice.Items.Add(VideoCapture1.Audio_OutputDevices_GetItem(i)); ``` ### C++ MFC Implementation ``` // Populate the combobox with all available audio output devices for (int i = 0; i < m_VideoCapture.Audio_OutputDevices_GetCount(); i++) { CString deviceName = m_VideoCapture.Audio_OutputDevices_GetItem(i); m_AudioOutputDeviceCombo.AddString(deviceName); } ``` ### VB6 Implementation ``` ' Iterate through all available audio output devices For i = 0 To VideoCapture1.Audio_OutputDevices_GetCount - 1 ' Add each device to the dropdown list cboAudioOutputDevice.AddItem VideoCapture1.Audio_OutputDevices_GetItem(i) Next i ``` ## Setting the Active Audio Output Device After retrieving the available devices, the next step is to set the selected device as the active audio output device for your application. ### Delphi Implementation ``` // Set the selected device as the active audio output device VideoCapture1.Audio_OutputDevice := cbAudioOutputDevice.Items[cbAudioOutputDevice.ItemIndex]; ``` ### C++ MFC Implementation ``` // Get the selected index from the combobox int selectedIndex = m_AudioOutputDeviceCombo.GetCurSel(); CString selectedDevice; m_AudioOutputDeviceCombo.GetLBText(selectedIndex, selectedDevice); // Set the selected device as the active audio output device. // COM property setters in MFC use the put_ wrapper, not direct assignment. m_VideoCapture.put_Audio_OutputDevice(selectedDevice); ``` ### VB6 Implementation ``` ' Set the selected device as the active audio output device VideoCapture1.Audio_OutputDevice = cboAudioOutputDevice.Text ``` ## Enabling Audio Playback Once the output device is selected, you need to enable audio playback to hear the audio through the selected device. ### Delphi Implementation ``` // Enable audio playback through the selected device VideoCapture1.Audio_PlayAudio := true; ``` ### C++ MFC Implementation ``` // Enable audio playback through the selected device m_VideoCapture.Audio_PlayAudio = TRUE; ``` ### VB6 Implementation ``` ' Enable audio playback through the selected device VideoCapture1.Audio_PlayAudio = True ``` ## Adjusting Audio Volume Levels Providing volume control gives users the ability to customize their audio experience. This section shows how to implement volume adjustment. ### Delphi Implementation ``` // Set the volume level based on trackbar position VideoCapture1.Audio_OutputDevice_SetVolume(tbAudioVolume.Position); ``` ### C++ MFC Implementation ``` // Get the current position of the volume slider int volumeLevel = m_VolumeSlider.GetPos(); // Set the volume level based on slider position m_VideoCapture.Audio_OutputDevice_SetVolume(volumeLevel); ``` ### VB6 Implementation ``` ' Set the volume level based on slider position VideoCapture1.Audio_OutputDevice_SetVolume sldVolume.Value ``` ## Controlling Audio Balance For stereo output, balance control allows users to adjust the relative volume between left and right channels. ### Delphi Implementation ``` // Set the balance level based on trackbar position VideoCapture1.Audio_OutputDevice_SetBalance(tbAudioBalance.Position); ``` ### C++ MFC Implementation ``` // Get the current position of the balance slider int balanceLevel = m_BalanceSlider.GetPos(); // Set the balance level based on slider position m_VideoCapture.Audio_OutputDevice_SetBalance(balanceLevel); ``` ### VB6 Implementation ``` ' Set the balance level based on slider position VideoCapture1.Audio_OutputDevice_SetBalance sldBalance.Value ``` ## Best Practices for Audio Device Implementation - Always check if the audio device is valid before attempting to use it - Provide fallback mechanisms when the selected device becomes unavailable - Consider saving user preferences for audio device selection between sessions - Implement visual feedback when volume or balance settings are changed --- Please contact our [support team](https://support.visioforge.com/) if you need assistance with this implementation. Visit our [GitHub repository](https://github.com/visioforge/) for additional code samples and resources. ---END OF PAGE--- ## Delphi Video Capture SDK Version Changelog and Notes **URL:** https://www.visioforge.com/help/docs/delphi/videocapture/changelog/ **Description:** TVFVideoCapture version history - GPU acceleration, streaming capabilities, format updates from version 4.1 to 11.0 with detailed release notes. **Tags:** All-in-One Media Framework, Delphi, ActiveX, Windows, VCL, Capture, Streaming **API:** TVFVideoCapture, TVFMediaPlayer # TVFVideoCapture Version History ## Release 11.00 - Enhanced GPU Encoding & Modern Delphi Support - **Expanded Framework Compatibility**: Added support for Delphi 10.4 and 11.0 development environments - **Advanced AMD GPU Acceleration**: Implemented MP4 (H264/AAC) video encoding utilizing AMD graphics processing units - **Intel GPU Hardware Encoding**: Added MP4 (H264/AAC) video encoding through Intel integrated and discrete GPUs - **NVIDIA CUDA Acceleration**: Introduced MP4 (H264/AAC) video encoding powered by NVIDIA graphics hardware - **Container Format Improvements**: Enhanced MKV output with optimized performance and reliability - **New Output Format**: Added MOV container format support for Apple ecosystem compatibility ## Release 10.0 - Performance Optimizations & Multi-Platform Support - **MP4 Enhancement**: Thoroughly updated and improved MP4 output capabilities - **Streaming Improvements**: Updated VLC source filter with enhanced RTMP and HTTPS support - **Memory Management**: Fixed critical CUDA encoder memory leak for stable long-duration encoding - **Resource Optimization**: Resolved FFMPEG source memory leak for improved application stability - **Audio Capture**: Enhanced What You Hear filter for superior system audio recording - **64-bit Architecture**: Added x64 VLC source for TVFMediaPlayer and TVFVideoCapture (both Delphi and ActiveX) - **Extended Format Support**: Enhanced YUV2RGB filter with HDYC format support - **Audio Encoding**: Updated LAME encoder with fix for low bitrate mono audio issues - **Development Environment**: Added Delphi 10, 10.1 support for modern development workflows ## Release 8.7 - Core Engine Updates - **VLC Integration**: Updated VLC engine to libVLC 2.2.1.0 for improved streaming capabilities - **Decoder Enhancement**: Updated FFMPEG engine for better format compatibility and performance ## Release 8.6 - Reliability Improvements & Format Support - **Resource Management**: Fixed critical memory leak for improved application stability - **File Handling**: Resolved issues with improperly closed input and output files - **New Format Support**: Added custom WebM filters based on the WebM project specifications ## Release 8.4 - Architecture Expansion - **Modern Delphi**: Added Delphi XE8 support for latest development environments - **64-bit Architecture**: Introduced Delphi and ActiveX x64 versions for performance on modern systems ## Release 8.31 - Development Environment Update - **Framework Compatibility**: Added Delphi XE7 support for expanded development options ## Release 8.3 - API and Performance Improvements - **Interface Enhancement**: Updated ActiveX API for improved developer experience - **Decoder Optimization**: Enhanced FFMPEG decoder for better performance and format support - **Stability**: Implemented several critical bug fixes and performance improvements ## Release 8.0 - Streaming Capabilities - **Network Streaming**: Introduced VLC engine for IP video capture capabilities - **Reliability**: Fixed several bugs for improved stability across all components ## Release 7.15 - Advanced Output Options & Security - **Network Capture**: Improved IP capture engine for better connection stability and performance - **Modern Format Support**: Added MP4 with H264/AAC output for industry-standard compatibility - **Security Feature**: Implemented video encryption for protected content workflows - **System Integration**: Added Virtual Camera output for software integration scenarios - **Stability**: Multiple small bug fixes for improved reliability ## Release 7.0 - Capture Engine Improvements - **Network Performance**: Enhanced IP capture engine with improved throughput and reliability - **Desktop Capture**: Updated screen capture engine for better performance and quality - **Output Options**: Enhanced FFMPEG output for expanded format support - **Visual Effects**: Added Pan/zoom video effect for advanced video manipulation - **Reliability**: Implemented multiple small bug fixes for improved stability ## Release 6.0 - Multi-Source & Windows 8 Compatibility - **Advanced Compositing**: Improved Picture-In-Picture with support for any video source including screen capture and IP cameras - **Streaming Protocol**: Enhanced RTSP sources support for better network video integration - **Special Capture Mode**: Added layered windows screen capture support for complex UI recording - **Hardware Support**: Implemented iCube cameras support for specialized imaging applications - **OS Compatibility**: Added Windows 8 Developer Preview support for forward compatibility - **Visual Processing**: Enhanced video effects with new options and improved performance - **Audio Management**: Introduced multiple audio stream support for AVI and WMV outputs ## Release 5.5 - Stability & Feature Enhancements - **Visual Processing**: Enhanced video effects with improved quality and performance - **Network Video**: Improved IP cameras support for better connectivity and compatibility - **Reliability**: Fixed several bugs for improved overall stability ## Release 5.4 - Modern Delphi Support - **Development Environment**: Added Delphi XE2 support for modern application development - **Stability**: Implemented several bug fixes for improved reliability ## Release 5.3 - Video Processing Improvements - **Visual Effects**: Enhanced video effects with additional options and better performance - **Network Video**: Improved IP cameras support for wider device compatibility - **Reliability**: Fixed multiple bugs for more stable operation ## Release 5.2 - Frame Processing Enhancements - **Visual Effects**: Improved video effects and video frame grabber functionality - **Stability**: Fixed several bugs for enhanced reliability ## Release 5.1 - Network Video & Effects Improvements - **IP Camera Integration**: Enhanced IP camera support for improved connectivity - **Visual Processing**: Improved video effect quality and performance - **Reliability**: Fixed various issues for better stability ## Release 5.0 - Major Format Support Expansion - **Network Video**: Added RTSP/HTTP IP camera support (MJPEG/MPEG-4/H264 with or without audio) - **Modern Format**: Implemented WebM output for open web standards compatibility - **Format Flexibility**: Added MPEG-1/2/4 and FLV output using FFMPEG integration ## Release 4.22 - Screen Capture Improvements - **Desktop Recording**: Fixed bugs in screen capture filter for improved recording quality ## Release 4.21 - Screen Capture Enhancements - **Desktop Recording**: Implemented multiple bug fixes and improvements in screen capture filter ## Release 4.2 - Audio Processing Improvement - **Sound Effects**: Enhanced audio effects filter with improved quality and performance ## Release 4.1 - Modern Delphi Integration - **Development Environment**: Added Delphi 2010 support for the Delphi edition - **Stability**: Fixed several bugs for improved reliability ---END OF PAGE--- ## DirectShow Output Formats in Delphi - Complete Guide **URL:** https://www.visioforge.com/help/docs/delphi/videocapture/custom-output/ **Description:** Implement DirectShow custom output formats in Delphi, C++, VB6 - integrate third-party filters, codecs, and multiplexers with code examples. **Tags:** All-in-One Media Framework, Delphi, ActiveX, DirectShow, Windows, VCL, Capture, Encoding # Code sample - Custom output formats Delphi, C++ MFC, and VB6 sample code. Currently, there are several options for connecting third-party DirectShow filters to get the necessary format. ## The first option - 3 different DirectShow filters An audio codec, a video codec, and a multiplexer – different filter. You can use both DirectShow filters and regular codecs as codecs. ## The second option - an all-in-one DirectShow filter A multiplexer, a video codec, and an audio codec – the same filter. Another difference is whether the filter can write to a file itself, whether you should use the standard File Writer filter, or whether you need another special filter. In the first two cases, VisioForge Video Capture will detect it automatically and set the necessary parameters, but you have to specify the necessary filter yourself in the third case. Now, let us see what the code for different options looks like. ## First option Get lists of audio and video codecs ``` for I := 0 to VideoCapture1.Video_Codecs_GetCount - 1 do cbCustomVideoCodec.Items.Add(VideoCapture1.Video_Codecs_GetItem(i)); for I := 0 to VideoCapture1.Audio_Codecs_GetCount - 1 do cbCustomAudioCodec.Items.Add(VideoCapture1.Audio_Codecs_GetItem(i)); ``` ``` // C++ MFC for (int i = 0; i < m_VideoCapture.Video_Codecs_GetCount(); i++) m_CustomVideoCodecCombo.AddString(m_VideoCapture.Video_Codecs_GetItem(i)); for (int i = 0; i < m_VideoCapture.Audio_Codecs_GetCount(); i++) m_CustomAudioCodecCombo.AddString(m_VideoCapture.Audio_Codecs_GetItem(i)); ``` ``` ' VB6 For i = 0 To VideoCapture1.Video_Codecs_GetCount - 1 cbCustomVideoCodec.AddItem VideoCapture1.Video_Codecs_GetItem(i) Next i For i = 0 To VideoCapture1.Audio_Codecs_GetCount - 1 cbCustomAudioCodec.AddItem VideoCapture1.Audio_Codecs_GetItem(i) Next i ``` Get the list of DirectShow filters ``` for I := 0 to VideoCapture1.DirectShow_Filters_GetCount - 1 do begin cbCustomDSFilterV.Items.Add(VideoCapture1.DirectShow_Filters_GetItem(i)); cbCustomDSFilterA.Items.Add(VideoCapture1.DirectShow_Filters_GetItem(i)); cbCustomMuxer.Items.Add(VideoCapture1.DirectShow_Filters_GetItem(i)); cbCustomFilewriter.Items.Add(VideoCapture1.DirectShow_Filters_GetItem(i)); end; ``` ``` // C++ MFC for (int i = 0; i < m_VideoCapture.DirectShow_Filters_GetCount(); i++) { m_CustomDSFilterVCombo.AddString(m_VideoCapture.DirectShow_Filters_GetItem(i)); m_CustomDSFilterACombo.AddString(m_VideoCapture.DirectShow_Filters_GetItem(i)); m_CustomMuxerCombo.AddString(m_VideoCapture.DirectShow_Filters_GetItem(i)); m_CustomFilewriterCombo.AddString(m_VideoCapture.DirectShow_Filters_GetItem(i)); } ``` ``` ' VB6 For i = 0 To VideoCapture1.DirectShow_Filters_GetCount - 1 cbCustomDSFilterV.AddItem VideoCapture1.DirectShow_Filters_GetItem(i) cbCustomDSFilterA.AddItem VideoCapture1.DirectShow_Filters_GetItem(i) cbCustomMuxer.AddItem VideoCapture1.DirectShow_Filters_GetItem(i) cbCustomFilewriter.AddItem VideoCapture1.DirectShow_Filters_GetItem(i) Next i ``` Select filters and codecs ``` if rbCustomUseVideoCodecsCat.Checked then begin VideoCapture1.Custom_Output_Video_Codec := cbCustomVideoCodec.Items[cbCustomVideoCodec.ItemIndex]; VideoCapture1.Custom_Output_Video_Codec_Use_Filters_Category := false; end else begin VideoCapture1.Custom_Output_Video_Codec := cbCustomDSFilterV.Items[cbCustomDSFilterV.ItemIndex]; VideoCapture1.Custom_Output_Video_Codec_Use_Filters_Category := true; end; if rbCustomUseAudioCodecsCat.Checked then begin VideoCapture1.Custom_Output_Audio_Codec := cbCustomAudioCodec.Items[cbCustomAudioCodec.ItemIndex]; VideoCapture1.Custom_Output_Audio_Codec_Use_Filters_Category := false; end else begin VideoCapture1.Custom_Output_Audio_Codec := cbCustomDSFilterA.Items[cbCustomDSFilterA.ItemIndex]; VideoCapture1.Custom_Output_Audio_Codec_Use_Filters_Category := true; end; VideoCapture1.Custom_Output_Mux_Filter_Name := cbCustomMuxer.Items[cbCustomMuxer.ItemIndex]; ``` ``` // C++ MFC // CComboBox::GetCurSel returns CB_ERR (-1) when no item is selected; guard each // read so GetLBText is never called with -1. int nIndex; if (m_CustomUseVideoCodecsCat.GetCheck()) { nIndex = m_CustomVideoCodecCombo.GetCurSel(); if (nIndex != CB_ERR) { CString videoCodec; m_CustomVideoCodecCombo.GetLBText(nIndex, videoCodec); m_VideoCapture.Custom_Output_Video_Codec = videoCodec; m_VideoCapture.Custom_Output_Video_Codec_Use_Filters_Category = false; } } else { nIndex = m_CustomDSFilterVCombo.GetCurSel(); if (nIndex != CB_ERR) { CString videoCodec; m_CustomDSFilterVCombo.GetLBText(nIndex, videoCodec); m_VideoCapture.Custom_Output_Video_Codec = videoCodec; m_VideoCapture.Custom_Output_Video_Codec_Use_Filters_Category = true; } } if (m_CustomUseAudioCodecsCat.GetCheck()) { nIndex = m_CustomAudioCodecCombo.GetCurSel(); if (nIndex != CB_ERR) { CString audioCodec; m_CustomAudioCodecCombo.GetLBText(nIndex, audioCodec); m_VideoCapture.Custom_Output_Audio_Codec = audioCodec; m_VideoCapture.Custom_Output_Audio_Codec_Use_Filters_Category = false; } } else { nIndex = m_CustomDSFilterACombo.GetCurSel(); if (nIndex != CB_ERR) { CString audioCodec; m_CustomDSFilterACombo.GetLBText(nIndex, audioCodec); m_VideoCapture.Custom_Output_Audio_Codec = audioCodec; m_VideoCapture.Custom_Output_Audio_Codec_Use_Filters_Category = true; } } nIndex = m_CustomMuxerCombo.GetCurSel(); if (nIndex != CB_ERR) { CString muxerName; m_CustomMuxerCombo.GetLBText(nIndex, muxerName); m_VideoCapture.Custom_Output_Mux_Filter_Name = muxerName; } ``` ``` ' VB6 If rbCustomUseVideoCodecsCat.Value Then VideoCapture1.Custom_Output_Video_Codec = cbCustomVideoCodec.List(cbCustomVideoCodec.ListIndex) VideoCapture1.Custom_Output_Video_Codec_Use_Filters_Category = False Else VideoCapture1.Custom_Output_Video_Codec = cbCustomDSFilterV.List(cbCustomDSFilterV.ListIndex) VideoCapture1.Custom_Output_Video_Codec_Use_Filters_Category = True End If If rbCustomUseAudioCodecsCat.Value Then VideoCapture1.Custom_Output_Audio_Codec = cbCustomAudioCodec.List(cbCustomAudioCodec.ListIndex) VideoCapture1.Custom_Output_Audio_Codec_Use_Filters_Category = False Else VideoCapture1.Custom_Output_Audio_Codec = cbCustomDSFilterA.List(cbCustomDSFilterA.ListIndex) VideoCapture1.Custom_Output_Audio_Codec_Use_Filters_Category = True End If VideoCapture1.Custom_Output_Mux_Filter_Name = cbCustomMuxer.List(cbCustomMuxer.ListIndex) ``` ## Second option Get lists of DirectShow filters. ``` for I := 0 to VideoCapture1.DirectShow_Filters_GetCount - 1 do begin cbCustomDSFilterV.Items.Add(VideoCapture1.DirectShow_Filters_GetItem(i)); cbCustomDSFilterA.Items.Add(VideoCapture1.DirectShow_Filters_GetItem(i)); cbCustomMuxer.Items.Add(VideoCapture1.DirectShow_Filters_GetItem(i)); cbCustomFilewriter.Items.Add(VideoCapture1.DirectShow_Filters_GetItem(i)); end; ``` ``` // C++ MFC for (int i = 0; i < m_VideoCapture.DirectShow_Filters_GetCount(); i++) { m_CustomDSFilterVCombo.AddString(m_VideoCapture.DirectShow_Filters_GetItem(i)); m_CustomDSFilterACombo.AddString(m_VideoCapture.DirectShow_Filters_GetItem(i)); m_CustomMuxerCombo.AddString(m_VideoCapture.DirectShow_Filters_GetItem(i)); m_CustomFilewriterCombo.AddString(m_VideoCapture.DirectShow_Filters_GetItem(i)); } ``` ``` ' VB6 For i = 0 To VideoCapture1.DirectShow_Filters_GetCount - 1 cbCustomDSFilterV.AddItem VideoCapture1.DirectShow_Filters_GetItem(i) cbCustomDSFilterA.AddItem VideoCapture1.DirectShow_Filters_GetItem(i) cbCustomMuxer.AddItem VideoCapture1.DirectShow_Filters_GetItem(i) cbCustomFilewriter.AddItem VideoCapture1.DirectShow_Filters_GetItem(i) Next i ``` Select multiplexer (mux) filter ``` VideoCapture1.Custom_Output_Mux_Filter_Name := cbCustomMuxer.Items[cbCustomMuxer.ItemIndex]; VideoCapture1.Custom_Output_Mux_Filter_Is_Encoder := cbCustomMuxFilterIsEncoder.Checked; ``` ``` // C++ MFC CString muxerName; m_CustomMuxerCombo.GetLBText(m_CustomMuxerCombo.GetCurSel(), muxerName); m_VideoCapture.Custom_Output_Mux_Filter_Name = muxerName; m_VideoCapture.Custom_Output_Mux_Filter_Is_Encoder = m_CustomMuxFilterIsEncoder.GetCheck(); ``` ``` ' VB6 VideoCapture1.Custom_Output_Mux_Filter_Name = cbCustomMuxer.List(cbCustomMuxer.ListIndex) VideoCapture1.Custom_Output_Mux_Filter_Is_Encoder = cbCustomMuxFilterIsEncoder.Value ``` If you need a special File Writer filter, you should specify it. This is true for both options described above. ``` VideoCapture1.Custom_Output_Special_FileWriter_Needed := cbUseSpecialFilewriter.Checked; VideoCapture1.Custom_Output_Special_FileWriter_Filter_Name := cbCustomFilewriter.Items[cbCustomFilewriter.ItemIndex]; ``` ``` // C++ MFC m_VideoCapture.Custom_Output_Special_FileWriter_Needed = m_UseSpecialFilewriter.GetCheck(); CString fileWriterName; m_CustomFilewriterCombo.GetLBText(m_CustomFilewriterCombo.GetCurSel(), fileWriterName); m_VideoCapture.Custom_Output_Special_FileWriter_Filter_Name = fileWriterName; ``` ``` ' VB6 VideoCapture1.Custom_Output_Special_FileWriter_Needed = cbUseSpecialFilewriter.Value VideoCapture1.Custom_Output_Special_FileWriter_Filter_Name = cbCustomFilewriter.List(cbCustomFilewriter.ListIndex) ``` Start capture ``` VideoCapture1.Start; ``` ``` // C++ MFC m_VideoCapture.Start(); ``` ``` ' VB6 VideoCapture1.Start ``` --- Please get in touch with [support](https://support.visioforge.com/) to get help with this tutorial. Visit our [GitHub](https://github.com/visioforge/) page to get more code samples. ---END OF PAGE--- ## Deploying TVFVideoCapture Library in Delphi Projects **URL:** https://www.visioforge.com/help/docs/delphi/videocapture/deployment/ **Description:** Deploy TVFVideoCapture in Delphi - install components, register DirectShow filters, configure environment for successful application deployment. **Tags:** All-in-One Media Framework, Delphi, ActiveX, DirectShow, Windows, VCL, Capture, Encoding, IP Camera, MP4, MP3 **API:** TVFVideoCapture # Complete TVFVideoCapture Library Deployment Guide When distributing applications built with the TVFVideoCapture library, you'll need to deploy several framework components to ensure proper functionality on end-user systems. This guide covers all deployment scenarios to help you create reliable installations. ## Deployment Options Overview You have two primary approaches for deploying the necessary components: automatic installers for simpler deployment or manual installation for more customized setups. ## Automatic Silent Installers (Requires Admin Rights) These pre-configured installers handle dependencies automatically and can be integrated into your application's installation process: ### Essential Components - **Base Package** (mandatory for all deployments) - [Delphi Version](https://files.visioforge.com/redists_delphi/redist_video_capture_base_delphi.exe) - [ActiveX Version](https://files.visioforge.com/redists_delphi/redist_video_capture_base_ax.exe) ### Optional Feature Components - **FFMPEG Package** (required for file or IP camera sources) - [x86 Architecture](https://files.visioforge.com/redists_delphi/redist_video_capture_ffmpeg.exe) - **MP4 Output Support** - [x86 Architecture](https://files.visioforge.com/redists_delphi/redist_video_capture_mp4.exe) - **VLC Source Package** (alternative option for file or IP camera sources) - [x86 Architecture](https://files.visioforge.com/redists_delphi/redist_video_capture_vlc.exe) ## Manual Installation Process (Requires Admin Rights) For more control over the deployment process, follow these detailed steps: ### Step 1: Install Required Dependencies 1. Deploy Visual C++ 2010 SP1 redistributables: 2. [x86 Architecture](https://files.visioforge.com/shared/vcredist_2010_x86.exe) 3. [x64 Architecture](https://files.visioforge.com/shared/vcredist_2010_x64.exe) ### Step 2: Deploy Core Components 1. Copy all Media Foundation Platform (MFP) DLLs from the `Redist\Filters` directory to your application folder 2. For ActiveX implementations: copy and register the OCX file using [regsvr32.exe](https://support.microsoft.com/en-us/topic/how-to-use-the-regsvr32-tool-and-troubleshoot-regsvr32-error-messages-a98d960a-7392-e6fe-d90a-3f4e0cb543e5) ### Step 3: Register DirectShow Filters Using [regsvr32.exe](https://support.microsoft.com/en-us/topic/how-to-use-the-regsvr32-tool-and-troubleshoot-regsvr32-error-messages-a98d960a-7392-e6fe-d90a-3f4e0cb543e5), register these essential DirectShow filters: - `VisioForge_Audio_Effects_4.ax` - `VisioForge_Dump.ax` - `VisioForge_RGB2YUV.ax` - `VisioForge_Screen_Capture.ax` - `VisioForge_Video_Effects_Pro.ax` - `VisioForge_Video_Mixer.ax` - `VisioForge_Video_Resize.ax` - `VisioForge_WavDest.ax` - `VisioForge_YUV2RGB.ax` - `VisioForge_FFMPEG_Source.ax` > **Important:** Add the filter directory to the system PATH environment variable if your application executable resides in a different folder. ## Advanced Component Installation ### FFMPEG Integration 1. Copy all files from `Redist\FFMPEG` folder to your deployment 2. Add the FFMPEG folder to the Windows system PATH variable 3. Register all .ax files from the FFMPEG folder ### VLC Integration 1. Copy all files from the `Redist\VLC` folder 2. Register the included .ax file using regsvr32.exe 3. Create an environment variable named `VLC_PLUGIN_PATH` pointing to the `VLC\plugins` directory ### Audio Output Support (LAME) 1. Copy `lame.ax` from the `Redist\Formats` folder 2. Register the `lame.ax` file using regsvr32.exe ### Container Format Support - **WebM Support:** Install free codecs from [xiph.org](https://www.xiph.org) - **Matroska Support:** Deploy `Haali Matroska Splitter` ### MP4 Output Configuration #### Modern Encoder Setup 1. Copy appropriate library files: 2. `libmfxsw32.dll` (for 32-bit deployments) 3. `libmfxsw64.dll` (for 64-bit deployments) 4. Register required components: 5. `VisioForge_H264_Encoder.ax` 6. `VisioForge_MP4_Muxer.ax` 7. `VisioForge_AAC_Encoder.ax` 8. `VisioForge_Video_Resize.ax` #### Legacy Encoder Setup (for older systems) 1. Copy appropriate library files: 2. `libmfxxp32.dll` (for 32-bit deployments) 3. `libmfxxp64.dll` (for 64-bit deployments) 4. Register required components: 5. `VisioForge_H264_Encoder_XP.ax` 6. `VisioForge_MP4_Muxer_XP.ax` 7. `VisioForge_AAC_Encoder_XP.ax` 8. `VisioForge_Video_Resize.ax` ## Bulk Registration Utility To simplify DirectShow filter registration, you can use the `reg_special.exe` utility from the framework setup. Place this executable in your filter directory and run it with administrator privileges to register all filters at once. --- For additional code samples and implementation examples, visit our [GitHub repository](https://github.com/visioforge/). If you encounter any difficulties with deployment, please contact [technical support](https://support.visioforge.com/) for personalized assistance. ---END OF PAGE--- ## DV Camcorder Control in Delphi with TVFVideoCapture **URL:** https://www.visioforge.com/help/docs/delphi/videocapture/dv-camcorder/ **Description:** Control DV camcorders in Delphi with TVFVideoCapture - playback, navigation, transport controls with code examples for Delphi, C++, and VB6. **Tags:** All-in-One Media Framework, Delphi, ActiveX, Windows, VCL, Capture, DV Camera **API:** TVFVideoCapture # Complete Guide to DV Camcorder Control This developer guide demonstrates how to effectively integrate and control Digital Video (DV) camcorders in your applications using the TVFVideoCapture component. The examples below include implementations for Delphi, C++ MFC, and Visual Basic 6, allowing you to choose the development environment that best suits your project requirements. ## Prerequisites for Implementation Before using any of the DV control commands, you must initialize your video capture system by starting either the video preview or capture process. This establishes the necessary connection between your application and the DV device. ## DV Transport Control Commands The following sections provide detailed implementation examples for each of the essential DV transport control functions, allowing you to create professional video manipulation applications. ### Starting Playback Initiate standard playback of your DV content with the `DV_PLAY` command. This command starts playback at normal speed and is essential for basic video viewing functionality. ``` VideoCapture1.DV_SendCommand(DV_PLAY); ``` ``` // C++ MFC m_VideoCapture.DV_SendCommand(DV_PLAY); ``` ``` ' VB6 VideoCapture1.DV_SendCommand DV_PLAY ``` ### Pausing Video Playback Temporarily suspend video playback while maintaining the current position with the `DV_PAUSE` command. This is useful for implementing frame analysis or allowing users to examine specific content. ``` VideoCapture1.DV_SendCommand(DV_PAUSE); ``` ``` // C++ MFC m_VideoCapture.DV_SendCommand(DV_PAUSE); ``` ``` ' VB6 VideoCapture1.DV_SendCommand DV_PAUSE ``` ### Stopping Playback Completely halt playback and reset the DV device to a ready state using the `DV_STOP` command. This typically returns the playback position to the beginning of the current section. ``` VideoCapture1.DV_SendCommand(DV_STOP); ``` ``` // C++ MFC m_VideoCapture.DV_SendCommand(DV_STOP); ``` ``` ' VB6 VideoCapture1.DV_SendCommand DV_STOP ``` ### Advanced Navigation Controls #### Fast Forward Operation Rapidly advance through content with the `DV_FF` command. This allows users to quickly navigate to specific sections of the video. ``` VideoCapture1.DV_SendCommand(DV_FF); ``` ``` // C++ MFC m_VideoCapture.DV_SendCommand(DV_FF); ``` ``` ' VB6 VideoCapture1.DV_SendCommand DV_FF ``` #### Rewind Operation Move backward through content at high speed with the `DV_REW` command. This function enables efficient navigation to previous sections of video. ``` VideoCapture1.DV_SendCommand(DV_REW); ``` ``` // C++ MFC m_VideoCapture.DV_SendCommand(DV_REW); ``` ``` ' VB6 VideoCapture1.DV_SendCommand DV_REW ``` ## Frame-by-Frame Navigation For precision video analysis and editing applications, these commands enable frame-accurate navigation. ### Forward Frame Step Advance exactly one frame forward with the `DV_STEP_FW` command. This enables precise frame analysis and is essential for detailed video editing applications. ``` VideoCapture1.DV_SendCommand(DV_STEP_FW); ``` ``` // C++ MFC m_VideoCapture.DV_SendCommand(DV_STEP_FW); ``` ``` ' VB6 VideoCapture1.DV_SendCommand DV_STEP_FW ``` ### Backward Frame Step Move exactly one frame backward with the `DV_STEP_REV` command. This complements the forward step function and allows for bidirectional frame-accurate navigation. ``` VideoCapture1.DV_SendCommand(DV_STEP_REV); ``` ``` // C++ MFC m_VideoCapture.DV_SendCommand(DV_STEP_REV); ``` ``` ' VB6 VideoCapture1.DV_SendCommand DV_STEP_REV ``` ## Implementation Best Practices When integrating DV control functionality into your applications, consider the following practices: 1. Always verify device connectivity before sending commands 2. Implement proper error handling for cases when commands fail 3. Provide visual feedback to users when transport control states change 4. Consider implementing keyboard shortcuts for common DV control operations ## Additional Resources For more detailed information and advanced implementation techniques, explore our additional documentation and code repositories. Please contact our support team if you need assistance with implementation. Visit our GitHub repository for additional code samples and example projects. ---END OF PAGE--- ## FM Radio and TV Tuning in Delphi — Channel Scanning Guide **URL:** https://www.visioforge.com/help/docs/delphi/videocapture/fm-radio-tv-tuning/ **Description:** Implement FM radio and TV tuning in Delphi - channel scanning, frequency management, signal detection with code examples for Delphi, C++, VB6. **Tags:** All-in-One Media Framework, Delphi, ActiveX, C++, Windows, VCL, Capture, TV Tuner # Implementing FM Radio and TV Tuning in Delphi Applications ## Introduction to TV and Radio Tuning This guide provides detailed implementation examples for Delphi developers working with FM radio and TV tuning functionality. We've included equivalent code samples for C++ MFC and VB6 to support cross-platform development needs. ## Device Management ### Retrieving Available TV Tuners The first step in implementing tuner functionality is identifying available hardware devices: ``` // Iterate through all connected TV Tuner devices and populate dropdown for I := 0 to VideoCapture1.TVTuner_Devices_GetCount - 1 do cbTVTuner.Items.Add(VideoCapture1.TVTuner_Devices_GetItem(i)); ``` ``` // C++ MFC implementation for retrieving TV Tuner devices for (int i = 0; i < m_VideoCapture.TVTuner_Devices_GetCount(); i++) m_cbTVTuner.AddString(m_VideoCapture.TVTuner_Devices_GetItem(i)); ``` ``` ' VB6 implementation for device enumeration For i = 0 To VideoCapture1.TVTuner_Devices_GetCount - 1 cbTVTuner.AddItem VideoCapture1.TVTuner_Devices_GetItem(i) Next i ``` ### Enumerating TV Format Support Different regions use different broadcast standards. Your application should detect and handle these formats: ``` // Load available TV formats (PAL, NTSC, SECAM, etc.) for I := 0 to VideoCapture1.TVTuner_TVFormats_GetCount - 1 do cbTVSystem.Items.Add(VideoCapture1.TVTuner_TVFormats_GetItem(i)); ``` ``` // C++ MFC - Populate TV format dropdown with available standards for (int i = 0; i < m_VideoCapture.TVTuner_TVFormats_GetCount(); i++) m_cbTVSystem.AddString(m_VideoCapture.TVTuner_TVFormats_GetItem(i)); ``` ``` ' VB6 - Get supported TV formats for the selected tuner For i = 0 To VideoCapture1.TVTuner_TVFormats_GetCount - 1 cbTVSystem.AddItem VideoCapture1.TVTuner_TVFormats_GetItem(i) Next i ``` ### Country-Specific Configuration Broadcasting standards vary by country, so your application should provide appropriate region selection: ``` // Load country/region list for localized tuning parameters for I := 0 to VideoCapture1.TVTuner_Countries_GetCount - 1 do cbTVCountry.Items.Add(VideoCapture1.TVTuner_Countries_GetItem(i)); ``` ``` // C++ MFC - Build country selection list for regional settings for (int i = 0; i < m_VideoCapture.TVTuner_Countries_GetCount(); i++) m_cbTVCountry.AddString(m_VideoCapture.TVTuner_Countries_GetItem(i)); ``` ``` ' VB6 - Populate country dropdown for regional broadcast settings For i = 0 To VideoCapture1.TVTuner_Countries_GetCount - 1 cbTVCountry.AddItem VideoCapture1.TVTuner_Countries_GetItem(i) Next i ``` ## Device Configuration ### Selecting a TV Tuner Device Once you've enumerated the available devices, users can select their preferred tuner: ``` // Set the active tuner device based on user selection VideoCapture1.TVTuner_Name := cbTVTuner.Items[cbTVTuner.ItemIndex]; ``` ``` // C++ MFC - Apply user's tuner device selection CString strText; m_cbTVTuner.GetLBText(m_cbTVTuner.GetCurSel(), strText); m_VideoCapture.put_TVTuner_Name(strText); ``` ``` ' VB6 - Set selected tuner as active device VideoCapture1.TVTuner_Name = cbTVTuner.Text ``` ### Reading Current Tuner Configuration After selecting a device, you'll need to read its current settings: ``` // Initialize tuner and read current configuration VideoCapture1.TVTuner_Read; ``` ``` // C++ MFC - Load current tuner settings into application m_VideoCapture.TVTuner_Read(); ``` ``` ' VB6 - Read tuner configuration after device selection VideoCapture1.TVTuner_Read ``` ### Available Operation Modes Tuners support different modes like TV, FM Radio, etc: ``` // Populate operation mode dropdown with available options for I := 0 to VideoCapture1.TVTuner_Modes_GetCount - 1 do cbTVMode.Items.Add(VideoCapture1.TVTuner_Modes_GetItem(i)); ``` ``` // C++ MFC - Get supported operational modes for this device for (int i = 0; i < m_VideoCapture.TVTuner_Modes_GetCount(); i++) m_cbTVMode.AddString(m_VideoCapture.TVTuner_Modes_GetItem(i)); ``` ``` ' VB6 - List available tuner modes (TV, FM Radio, etc) For i = 0 To VideoCapture1.TVTuner_Modes_GetCount - 1 cbTVMode.AddItem VideoCapture1.TVTuner_Modes_GetItem(i) Next i ``` ## Frequency Management ### Reading Current Frequencies Display the current audio and video frequencies to provide user feedback: ``` // Display current video and audio frequencies in Hz edVideoFreq.Text := IntToStr(VideoCapture1.TVTuner_VideoFrequency); edAudiofreq.Text := IntToStr(VideoCapture1.TVTuner_AudioFrequency); ``` ``` // C++ MFC - Show current frequency values in the interface CString strFreq; strFreq.Format(_T("%d"), m_VideoCapture.get_TVTuner_VideoFrequency()); m_edVideoFreq.SetWindowText(strFreq); strFreq.Format(_T("%d"), m_VideoCapture.get_TVTuner_AudioFrequency()); m_edAudioFreq.SetWindowText(strFreq); ``` ``` ' VB6 - Update frequency display fields with current values edVideoFreq.Text = CStr(VideoCapture1.TVTuner_VideoFrequency) edAudioFreq.Text = CStr(VideoCapture1.TVTuner_AudioFrequency) ``` ## Input and Mode Configuration ### Setting Signal Input Source Tuners may support multiple input sources that should be configurable: ``` // Select the appropriate input source based on current configuration cbTVInput.ItemIndex := cbTVInput.Items.IndexOf(VideoCapture1.TVTuner_InputType); ``` ``` // C++ MFC - Update input source selection in UI CString strInputType = m_VideoCapture.get_TVTuner_InputType(); m_cbTVInput.SetCurSel(m_cbTVInput.FindStringExact(-1, strInputType)); ``` ``` ' VB6 - Set input source dropdown to match current configuration cbTVInput.ListIndex = cbTVInput.FindItem(VideoCapture1.TVTuner_InputType) ``` ### Configuring Operation Mode Different tuner modes require specific UI and parameter adjustments: ``` // Set operation mode dropdown to current mode (TV, FM Radio, etc) cbTVMode.ItemIndex := cbTVMode.Items.IndexOf(VideoCapture1.TVTuner_Mode); ``` ``` // C++ MFC - Update mode selector to match current tuner configuration CString strMode = m_VideoCapture.get_TVTuner_Mode(); m_cbTVMode.SetCurSel(m_cbTVMode.FindStringExact(-1, strMode)); ``` ``` ' VB6 - Select current operating mode in dropdown cbTVMode.ListIndex = cbTVMode.FindItem(VideoCapture1.TVTuner_Mode) ``` ### TV Format Configuration Set the appropriate broadcast standard for the region: ``` // Configure the appropriate TV standard (PAL, NTSC, SECAM, etc) cbTVSystem.ItemIndex := cbTVSystem.Items.IndexOf(VideoCapture1.TVTuner_TVFormat); ``` ``` // C++ MFC - Set TV format dropdown to current broadcast standard CString strTVFormat = m_VideoCapture.get_TVTuner_TVFormat(); m_cbTVSystem.SetCurSel(m_cbTVSystem.FindStringExact(-1, strTVFormat)); ``` ``` ' VB6 - Update TV system format selection cbTVSystem.ListIndex = cbTVSystem.FindItem(VideoCapture1.TVTuner_TVFormat) ``` ### Regional Settings Configure region-specific broadcast parameters: ``` // Set country/region for appropriate frequency tables and standards cbTVCountry.ItemIndex := cbTVCountry.Items.IndexOf(VideoCapture1.TVTuner_Country); ``` ``` // C++ MFC - Update country selection to match current setting CString strCountry = m_VideoCapture.get_TVTuner_Country(); m_cbTVCountry.SetCurSel(m_cbTVCountry.FindStringExact(-1, strCountry)); ``` ``` ' VB6 - Set country dropdown to current regional setting cbTVCountry.ListIndex = cbTVCountry.FindItem(VideoCapture1.TVTuner_Country) ``` ## Channel Scanning ### Handling Channel Scan Events Implement the event handler for channel scanning process: ``` // Event handler for channel scanning process // Tracks progress and collects found channels procedure TForm1.VideoCapture1TVTunerTuneChannels(SignalPresent: Boolean; Channel, Frequency, Progress: Integer); begin // Update progress bar with current scan progress pbChannels.Position := Progress; // Add channel to list if signal is detected if SignalPresent then cbTVChannel.Items.Add(IntToStr(Channel)); // Scan complete when Channel = -1 if Channel = -1 then begin pbChannels.Position := 0; ShowMessage('AutoTune complete'); end; end; ``` ``` // C++ MFC - Channel scan event handler implementation // In header file (.h) BEGIN_EVENTSINK_MAP(CMainDlg, CDialog) ON_EVENT(CMainDlg, IDC_VIDEOCAPTURE, 1, OnTVTunerTuneChannels, VTS_BOOL VTS_I4 VTS_I4 VTS_I4) END_EVENTSINK_MAP() // In implementation file (.cpp) void CMainDlg::OnTVTunerTuneChannels(BOOL SignalPresent, long Channel, long Frequency, long Progress) { // Update scan progress indicator m_pbChannels.SetPos(Progress); // Add found channels to the selection list if (SignalPresent) { CString strChannel; strChannel.Format(_T("%d"), Channel); m_cbTVChannel.AddString(strChannel); } // Handle scan completion if (Channel == -1) { m_pbChannels.SetPos(0); MessageBox(_T("AutoTune complete"), _T("Information"), MB_OK | MB_ICONINFORMATION); } } ``` ``` ' VB6 - Channel scan event handler Private Sub VideoCapture1_TVTunerTuneChannels(ByVal SignalPresent As Boolean, ByVal Channel As Long, ByVal Frequency As Long, ByVal Progress As Long) ' Update scan progress display pbChannels.Value = Progress ' Add channel to list when signal is found If SignalPresent Then cbTVChannel.AddItem CStr(Channel) End If ' Handle scan completion If Channel = -1 Then pbChannels.Value = 0 MsgBox "AutoTune complete", vbInformation End If End Sub ``` ### Initiating Channel Scan Start the automatic channel scanning process: ``` // Define frequency constants for clarity const KHz = 1000; const MHz = 1000000; // Initialize tuner with current settings VideoCapture1.TVTuner_Read; // Clear previous channel list cbTVChannel.Items.Clear; // Configure special parameters for FM Radio scanning if ( (cbTVMode.ItemIndex <> -1) and (cbTVMode.Items[cbTVMode.ItemIndex] = 'FM Radio') ) then begin // Set frequency range for FM scanning (100-110MHz) VideoCapture1.TVTuner_FM_Tuning_StartFrequency := 100 * MHz; VideoCapture1.TVTuner_FM_Tuning_StopFrequency := 110 * MHz; // Set 100KHz increments for FM scanning VideoCapture1.TVTuner_FM_Tuning_Step := 100 * KHz; end; // Begin automatic channel scan VideoCapture1.TVTuner_TuneChannels_Start; ``` ``` // C++ MFC - Initiate channel scan with appropriate parameters const int KHz = 1000; const int MHz = 1000000; // Update tuner configuration m_VideoCapture.TVTuner_Read(); // Reset channel list before scanning m_cbTVChannel.ResetContent(); // Configure FM-specific parameters if in radio mode CString strMode; m_cbTVMode.GetLBText(m_cbTVMode.GetCurSel(), strMode); if (strMode == _T("FM Radio")) { // Set FM scan range (100-110MHz) m_VideoCapture.put_TVTuner_FM_Tuning_StartFrequency(100 * MHz); m_VideoCapture.put_TVTuner_FM_Tuning_StopFrequency(110 * MHz); // Use 100KHz steps for FM scanning m_VideoCapture.put_TVTuner_FM_Tuning_Step(100 * KHz); } // Start the channel scanning process m_VideoCapture.TVTuner_TuneChannels_Start(); ``` ``` ' VB6 - Begin channel scanning process Const KHz = 1000 Const MHz = 1000000 ' Read current tuner configuration VideoCapture1.TVTuner_Read ' Clear existing channel list cbTVChannel.Clear ' Special configuration for FM Radio scanning If (cbTVMode.ListIndex <> -1) And (cbTVMode.Text = "FM Radio") Then ' Set FM band scan parameters (100-110MHz) VideoCapture1.TVTuner_FM_Tuning_StartFrequency = 100 * MHz VideoCapture1.TVTuner_FM_Tuning_StopFrequency = 110 * MHz ' Use 100KHz step size for FM scanning VideoCapture1.TVTuner_FM_Tuning_Step = 100 * KHz End If ' Initiate automatic channel scan VideoCapture1.TVTuner_TuneChannels_Start ``` ## Manual Tuning Operations ### Setting Channel by Number Allow direct channel selection by number: ``` // Change to specified channel number VideoCapture1.TVTuner_Channel := StrToInt(edChannel.Text); // Apply tuning changes VideoCapture1.TVTuner_Apply; ``` ``` // C++ MFC - Set tuner to specified channel number CString strChannel; m_edChannel.GetWindowText(strChannel); m_VideoCapture.put_TVTuner_Channel(_ttoi(strChannel)); m_VideoCapture.TVTuner_Apply(); ``` ``` ' VB6 - Tune to specific channel number VideoCapture1.TVTuner_Channel = CInt(edChannel.Text) VideoCapture1.TVTuner_Apply ``` ### Setting Radio Frequency Directly For FM radio, direct frequency tuning is often required: ``` // Set channel to -1 for frequency-based tuning VideoCapture1.TVTuner_Channel := -1; // must be -1 to use frequency // Set specific frequency from input field VideoCapture1.TVTuner_Frequency := StrToInt(edChannel.Text); // Apply frequency change VideoCapture1.TVTuner_Apply; ``` ``` // C++ MFC - Direct frequency tuning implementation CString strFrequency; m_edChannel.GetWindowText(strFrequency); // Set channel to -1 to enable frequency-based tuning m_VideoCapture.put_TVTuner_Channel(-1); // must be -1 to use frequency // Apply the specified frequency m_VideoCapture.put_TVTuner_Frequency(_ttoi(strFrequency)); m_VideoCapture.TVTuner_Apply(); ``` ``` ' VB6 - Manual frequency tuning for radio VideoCapture1.TVTuner_Channel = -1 ' must be -1 to use frequency VideoCapture1.TVTuner_Frequency = CInt(edChannel.Text) VideoCapture1.TVTuner_Apply ``` ## Conclusion This guide covers the essential aspects of implementing FM radio and TV tuning functionality in your Delphi applications. By following these examples, you can create robust tuning interfaces with proper channel scanning, frequency management, and signal detection. For optimal integration into your projects, remember to handle error conditions and provide appropriate user feedback during lengthy operations such as channel scanning. --- Please visit our [GitHub](https://github.com/visioforge/) page for additional code samples and implementation examples. ---END OF PAGE--- ## Camera Brightness, Contrast and Saturation Control in Delphi **URL:** https://www.visioforge.com/help/docs/delphi/videocapture/hardware-adjustments/ **Description:** Adjust camera brightness, contrast, and saturation in Delphi with TVFVideoCapture hardware controls and parameter configuration examples. **Tags:** All-in-One Media Framework, Delphi, ActiveX, Windows, VCL, Capture # Implementing Hardware Video Adjustments in Delphi Applications ## Overview Modern video capture devices offer powerful hardware-level adjustments that can significantly enhance the quality of your video applications. By leveraging these capabilities in your Delphi applications, you can provide users with professional-grade video control features without complex software-based image processing. ## Supported Adjustment Types Most webcams and video capture devices support several adjustment parameters: - Brightness - Contrast - Saturation - Hue - Sharpness - Gamma - White balance - Gain ## Retrieving Available Adjustment Ranges Before setting adjustments, you'll need to determine what ranges are supported by the connected device. The `Video_CaptureDevice_VideoAdjust_GetRanges` method provides this information. ### Delphi Implementation ``` // Retrieve the available range for brightness adjustment // Returns minimum, maximum, step size, default value, and auto-adjustment capability VideoCapture1.Video_CaptureDevice_VideoAdjust_GetRanges(adj_Brightness, min, max, step, default, auto); ``` ### C++ MFC Implementation ``` // C++ MFC implementation for getting brightness adjustment ranges // Store results in integer variables for UI configuration int min, max, step, default_value; BOOL auto_value; m_VideoCapture.Video_CaptureDevice_VideoAdjust_GetRanges( TxVFVideoCapAdjust::adj_Brightness, &min, &max, &step, &default_value, &auto_value); ``` ### VB6 Implementation ``` ' VB6 implementation for retrieving brightness adjustment parameters ' Use these values to configure slider controls and checkboxes Dim min As Integer, max As Integer, step As Integer, default_val As Integer Dim auto_val As Boolean VideoCapture1.Video_CaptureDevice_VideoAdjust_GetRanges adj_Brightness, min, max, step, default_val, auto_val ``` ## Setting Adjustment Values Once you've determined the available ranges, you can use the `Video_CaptureDevice_VideoAdjust_SetValue` method to apply specific settings to the video stream. ### Delphi Implementation ``` // Set the brightness level based on trackbar position // The third parameter enables/disables automatic brightness adjustment VideoCapture1.Video_CaptureDevice_VideoAdjust_SetValue( adj_Brightness, tbAdjBrightness.Position, cbAdjBrightnessAuto.Checked); ``` ### C++ MFC Implementation ``` // C++ MFC implementation for setting brightness value // Uses slider position for manual adjustment value // Checkbox state determines if auto-adjustment is enabled m_VideoCapture.Video_CaptureDevice_VideoAdjust_SetValue( TxVFVideoCapAdjust::adj_Brightness, m_sliderBrightness.GetPos(), m_checkBrightnessAuto.GetCheck() == BST_CHECKED); ``` ### VB6 Implementation ``` ' VB6 implementation for applying brightness settings ' Uses trackbar value for adjustment level ' Checkbox value determines automatic adjustment mode VideoCapture1.Video_CaptureDevice_VideoAdjust_SetValue _ adj_Brightness, _ tbAdjBrightness.Value, _ cbAdjBrightnessAuto.Value = vbChecked ``` ## Best Practices for Video Adjustment Implementation When implementing video adjustments in your applications: 1. Always check device capabilities first, as not all devices support all adjustment types 2. Provide intuitive UI controls like sliders with appropriate min/max values 3. Include auto-adjustment options when available 4. Consider saving user preferences for future sessions 5. Implement real-time preview so users can see the effects of their adjustments ## Additional Resources Please contact our support team for assistance with implementing these features in your application. Visit our GitHub repository for additional code samples and implementation examples. ---END OF PAGE--- ## Delphi Video Capture SDK - TVFVideoCapture Full Guide **URL:** https://www.visioforge.com/help/docs/delphi/videocapture/ **Description:** Build Delphi video and audio capture apps with TVFVideoCapture, including device enumeration, preview, MP4/AVI recording, screen capture, and IP cameras. **Tags:** All-in-One Media Framework, Delphi, ActiveX, Windows, VCL, Capture, Streaming **API:** TVFVideoCapture # Video Capture SDK for Delphi [Video Capture SDK Delphi](https://www.visioforge.com/all-in-one-media-framework) This section covers using the Video Capture SDK with Delphi to build video and audio capture applications. The `TVFVideoCapture` component (declared in `VideoCaptureMain.pas`) is a `TCustomPanel` descendant, so it both renders the preview surface and exposes the full capture API as published properties, methods, and events. ## Main Component ### TVFVideoCapture `TVFVideoCapture` provides complete video and audio capture functionality. You can drop it on a form from the IDE palette or create it at runtime. As it descends from `TCustomPanel`, set `Parent` and `Align` like any other VCL container. ``` var VideoCapture1: TVFVideoCapture; begin VideoCapture1 := TVFVideoCapture.Create(Self); VideoCapture1.Parent := Panel1; VideoCapture1.Align := alClient; end; ``` ## Device Enumeration Populate combo boxes with the video and audio capture devices discovered on the host. The SDK exposes `_GetCount` / `_GetItem(Index)` pairs for every device list. ``` procedure TForm1.EnumerateDevices; var i: Integer; begin // Video capture devices cbVideoDevices.Clear; for i := 0 to VideoCapture1.Video_CaptureDevices_GetCount - 1 do cbVideoDevices.Items.Add(VideoCapture1.Video_CaptureDevices_GetItem(i)); // Audio capture devices cbAudioDevices.Clear; for i := 0 to VideoCapture1.Audio_CaptureDevices_GetCount - 1 do cbAudioDevices.Items.Add(VideoCapture1.Audio_CaptureDevices_GetItem(i)); end; ``` ## Preview Switch the component to `Mode_Video_Preview` to render live video to the panel without writing anything to disk. Audio monitoring is controlled by `Audio_PlayAudio`. ``` procedure TForm1.StartPreview; begin // Select devices by display name VideoCapture1.Video_CaptureDevice := cbVideoDevices.Text; VideoCapture1.Audio_CaptureDevice := cbAudioDevices.Text; // Preview mode (no file output) VideoCapture1.Mode := Mode_Video_Preview; VideoCapture1.Audio_PlayAudio := True; VideoCapture1.Start; end; procedure TForm1.StopPreview; begin VideoCapture1.Stop; end; ``` ## Capturing to a File Switch to `Mode_Video_Capture` and assign `Output_Filename` and `Output_Format`. The `TVFOutputFormat` enum lists every container the component can write (`Format_MP4`, `Format_AVI`, `Format_WMV`, `Format_DV`, `Format_WebM`, `Format_FFMPEG`, `Format_FFMPEGX`, and so on). ``` procedure TForm1.StartCapture; begin VideoCapture1.Video_CaptureDevice := cbVideoDevices.Text; VideoCapture1.Audio_CaptureDevice := cbAudioDevices.Text; VideoCapture1.Audio_RecordAudio := True; // Output file and container VideoCapture1.Output_Filename := 'C:\Videos\capture.mp4'; VideoCapture1.Output_Format := Format_MP4; // Switch to capture mode VideoCapture1.Mode := Mode_Video_Capture; VideoCapture1.Start; end; ``` You can change the output file on the fly without stopping the graph by calling `OutputFilename_ChangeOnTheFly`. ## Snapshots Save the current preview frame to disk in any of the supported `TVFImageFormat` values (`IM_BMP`, `IM_JPEG`, `IM_PNG`, `IM_GIF`, `IM_TIFF`). The third parameter is the JPEG quality (ignored for other formats). ``` procedure TForm1.TakeSnapshot; begin VideoCapture1.Frame_Save('C:\Photos\snapshot.jpg', IM_JPEG, 85); end; ``` To pull the frame straight into a `TBitmap` (for example to display in a `TImage`), use `Frame_GetCurrent`: ``` procedure TForm1.TakeSnapshotToMemory; var Bitmap: TBitmap; begin Bitmap := TBitmap.Create; try VideoCapture1.Frame_GetCurrent(Bitmap); Image1.Picture.Assign(Bitmap); finally Bitmap.Free; end; end; ``` ## IP Cameras (RTSP / HTTP) Switch the mode to `Mode_IP_Preview` or `Mode_IP_Capture` and set `IP_Camera_URL`. Use `IP_Camera_Type` to pick the engine and protocol — for example `IP_RTSP_TCP` for RTSP over TCP via the FFmpeg engine, or `IP_Auto_VLC` to fall back to the bundled VLC source. ``` procedure TForm1.ConnectIPCamera; begin VideoCapture1.IP_Camera_URL := 'rtsp://user:password@192.168.1.100:554/stream'; VideoCapture1.IP_Camera_Type := IP_RTSP_TCP; VideoCapture1.Mode := Mode_IP_Preview; VideoCapture1.Start; end; ``` ## Screen Capture The component records the desktop, an individual display, a region, or a window. Set the capture rectangle (or enable full-screen), choose a frame rate, then switch to `Mode_Screen_Capture`. ``` procedure TForm1.StartScreenCapture; begin // Full-screen capture at 30 fps with the mouse cursor included VideoCapture1.Screen_Capture_FullScreen := True; VideoCapture1.Screen_Capture_FrameRate := 30.0; VideoCapture1.Screen_Capture_Grab_Mouse_Cursor := True; VideoCapture1.Output_Filename := 'C:\Videos\screen.mp4'; VideoCapture1.Output_Format := Format_MP4; VideoCapture1.Mode := Mode_Screen_Capture; VideoCapture1.Start; end; ``` For region capture, disable `Screen_Capture_FullScreen` and supply `Screen_Capture_Left`, `Screen_Capture_Top`, `Screen_Capture_Right`, and `Screen_Capture_Bottom` (all in pixels). See [Screen Capture Implementation](screen-capture/) for the full set of options. ## Video Effects Effects (brightness, contrast, saturation, flip, blur, grayscale, sepia, and many more) are managed with `Video_Effect_Ex`. Enable the effects pipeline first with `Video_Effects_Enabled := True`, then add each effect by `TVFEffectType`. The `Amount` argument is the strength of the effect — for `ef_contrast` it shifts contrast, for `ef_flip_right` it acts as an on/off flag, and so on. ``` procedure TForm1.ApplyVideoEffects; begin VideoCapture1.Video_Effects_Enabled := True; // ID=1, applied for the full graph (StartTime=0, StopTime=0), enabled, // contrast effect with amount = 20 VideoCapture1.Video_Effect_Ex(1, 0, 0, True, ef_contrast, 20.0, ''); // ID=2, horizontal flip VideoCapture1.Video_Effect_Ex(2, 0, 0, True, ef_flip_right, 0.0, ''); end; ``` Remove individual effects with `Video_Effects_Remove(ID)` or clear them all with `Video_Effects_Clear`. ## Text Overlay Use `Video_Effects_Text_Logo` (legacy GDI overlay) or `Video_Effects_Text_Logo_Plus` (modern GDI+ overlay with gradients, rotation, and outline effects) to burn text into the video stream. The example below uses `Video_Effects_Text_Logo_Plus`. ``` procedure TForm1.AddTextOverlay; begin VideoCapture1.Video_Effects_Enabled := True; // ID=10, full duration (0..0), enabled, "My Video" at (10, 10), // Arial 24, not bold/italic/underline/strike-out, white color VideoCapture1.Video_Effects_Text_Logo_Plus( 10, 0, 0, True, 'My Video', 10, 10, 'Arial', 24, False, False, False, False, clWhite); end; ``` ## Events `TVFVideoCapture` raises three core lifecycle events: `OnStart`, `OnStop`, and `OnError`. None of them carry a `Sender` parameter — `OnError` receives the error message as a `WideString`. ``` procedure TForm1.VideoCapture1Start; begin Button1.Caption := 'Stop'; end; procedure TForm1.VideoCapture1Stop; begin Button1.Caption := 'Start'; end; procedure TForm1.VideoCapture1Error(ErrorText: WideString); begin ShowMessage('Capture error: ' + ErrorText); end; ``` Additional events cover live frame access (`OnVideoFrame`, `OnAudioFrame`), motion detection (`OnMotion`), mouse and keyboard activity on the preview surface, VU-meter values, DV transport events, and TV-tuner channel scanning. ## Development Resources For detailed implementation guidance, explore these essential resources: - [Complete Changelog and Version History](changelog/) - [Installation and Configuration Guide](install/) - [Deployment Best Practices](deployment/) - [Licensing Information and EULA](../../eula/) - [Comprehensive API Documentation](https://api.visioforge.org/delphi/video_capture_sdk/index.html) ## Implementation Tutorials ### Audio Recording and Processing Master audio capture with these step-by-step guides: - [MP3 Audio Capture Implementation](audio-capture-mp3/) - Learn how to capture audio streams and encode them directly to MP3 format with configurable bitrates and quality settings. - [WAV Audio Recording with Compression Options](audio-capture-wav/) - Implement high-quality WAV audio recording with optional compression codecs and format configurations. - [Configuring Audio Output Devices](audio-output/) - Guide to selecting and configuring audio output devices for monitoring and playback in your applications. ### Video Capture and Device Control Learn essential video handling techniques: - [AVI Video Capture Implementation](video-capture-avi/) - Develop applications that capture video streams to AVI format with customizable codecs and container settings. - [DV Camcorder Control and Integration](dv-camcorder/) - Connect and control DV camcorders through FireWire/IEEE-1394 with transport controls and metadata handling. - [Device Selection for Video and Audio Sources](video-audio-sources/) - Techniques for enumerating, selecting, and managing multiple capture devices in your applications. - [Hardware Video Adjustment Parameters](hardware-adjustments/) - Access and modify device-level parameters including brightness, contrast, saturation, and white balance. - [Video Input Configuration via Crossbar](video-input-crossbar/) - Learn to configure video input routing through crossbar interfaces for multi-input capture devices. - [Video Renderer Selection and Configuration](video-renderer/) - Choose and configure the optimal video rendering engine for your capture application. ### Advanced Media Techniques Explore sophisticated implementation scenarios: - [Custom Output Format Configuration](custom-output/) - Create specialized output formats with custom compression settings and container configurations. - [FM Radio and TV Tuner Integration](fm-radio-tv-tuning/) - Implement FM radio reception and TV channel tuning in applications with supported hardware. - [Network Streaming with WMV Format](network-streaming-wmv/) - Stream captured video over networks using Windows Media Video format with bandwidth optimization. - [Resolution Management with Resize and Crop](resize-crop/) - Process video frames with dynamic resizing and cropping to achieve custom output dimensions. - [Screen Capture Implementation](screen-capture/) - Capture on-screen content with configurable frame rates and region selection capabilities. - [DV File Capture with Compression Options](video-capture-dv/) - Save video directly to DV format or with recompression for optimized storage requirements. - [MPEG-2 Capture with TV Tuner Integration](mpeg2-capture/) - Utilize hardware MPEG-2 encoders in TV tuners for efficient high-quality broadcast capture. - [Windows Media Video Capture with External Profiles](video-capture-wmv/) - Implement Windows Media Video encoding with external profile configurations for optimized quality and size. ---END OF PAGE--- ## Install TVFVideoCapture ActiveX Control in C++ Builder **URL:** https://www.visioforge.com/help/docs/delphi/videocapture/install/builder/ **Description:** Import and configure TVFVideoCapture ActiveX control in C++ Builder 5/6, 2006, and newer versions with detailed installation steps. **Tags:** All-in-One Media Framework, Delphi, ActiveX, Windows, VCL, Capture **API:** TVFVideoCapture # TVFVideoCapture Integration Guide for C++ Builder This detailed installation guide walks you through the process of integrating the powerful TVFVideoCapture ActiveX control with your C++ Builder projects. We've provided separate instructions for different C++ Builder versions to ensure seamless implementation regardless of your development environment. > Related products: [All-in-One Media Framework (Delphi / ActiveX)](https://www.visioforge.com/all-in-one-media-framework) ## Installation in Borland C++ Builder 5/6 Follow these detailed steps to properly install the TVFVideoCapture control in Borland C++ Builder 5/6: 1. Navigate to the main menu and select **Component → Import ActiveX Controls** 1. From the available controls list, locate and select the **VisioForge Video Capture** item 2. Click the **Install** button to begin importing the ActiveX control 1. When prompted for confirmation, click the **Yes** button to proceed 1. Once the installation process completes successfully, you'll see a confirmation message 2. Click the **OK** button to finalize the installation ## Installation in C++ Builder 2006 and Later Versions For more recent versions of C++ Builder (2006 and newer), follow this expanded installation process: ### Step 1: Create a New Package Begin by creating a new package that will contain the TVFVideoCapture control ### Step 2: Import the ActiveX Component 1. From the main menu, select **Component → Import Component** 1. In the dialog that appears, select the **Import ActiveX Control** radio button 2. Click the **Next** button to continue ### Step 3: Select the TVFVideoCapture Control 1. Browse through the available ActiveX controls 2. Locate and select the **VisioForge Video Capture** item from the list 3. Click the **Next** button to proceed ### Step 4: Configure Output Settings 1. Specify the desired package output folder for the component files 2. Click the **Next** button after selecting an appropriate location ### Step 5: Add Component to Package 1. Ensure the **Add unit to…** radio button is selected 2. Click the **Finish** button to complete the import process ### Step 6: Save and Install the Package 1. Save your project when prompted 1. Install the package to make the component available in your development environment 1. Verify that the TVFVideoCapture ActiveX control has been successfully installed ## Additional Resources and Support After completing the installation, you can begin using the TVFVideoCapture control in your applications. The component provides extensive functionality for video capture and processing operations. For developers looking to explore additional implementation examples and techniques: - Access our [GitHub repository](https://github.com/visioforge/) for code samples and example projects - Contact our [technical support team](https://support.visioforge.com/) for personalized assistance with integration challenges - Review our documentation for detailed API references and advanced usage scenarios By following this installation guide, you'll have successfully integrated the TVFVideoCapture ActiveX control into your C++ Builder development environment, enabling powerful video capture capabilities in your applications. ---END OF PAGE--- ## TVFVideoCapture Installation Guide for Delphi 6 to 11 **URL:** https://www.visioforge.com/help/docs/delphi/videocapture/install/delphi/ **Description:** Install TVFVideoCapture packages in Delphi 6/7 through Delphi 11+ with complete setup instructions, library paths, and configuration. **Tags:** All-in-One Media Framework, Delphi, ActiveX, Windows, VCL, Capture **API:** TVFVideoCapture # Comprehensive TVFVideoCapture Installation Guide for Delphi Developers > Related products: [All-in-One Media Framework (Delphi / ActiveX)](https://www.visioforge.com/all-in-one-media-framework) ## Installation in Borland Delphi 6/7 The installation process for legacy Delphi 6/7 environments requires several specific steps to ensure proper integration of the TVFVideoCapture library. ### Step 1: Create a New Package Begin by creating a new package in your Delphi 6/7 development environment. ### Step 2: Configure Library Paths Add the TVFVideoCapture package folder (`Video Capture\Packages\Delphi `, which holds the precompiled `.dcu` units) to both the library and browsing path settings. This allows Delphi to locate the necessary component files. ### Step 3: Open the Library Package Navigate to and open the library package file to prepare for installation. ### Step 4: Install the Component Package Complete the installation by selecting the install option within the package interface. ### Architecture Limitations While TVFVideoCapture offers both x86 and x64 architecture support, Delphi 6/7 only supports x86 due to platform limitations. Developers using these versions will need to utilize the 32-bit implementation exclusively. ## Installation Process for Delphi 2005 and Later Versions Modern Delphi versions offer an improved installation workflow with enhanced capabilities. ### Step 1: Launch Delphi with Administrative Privileges Ensure you run your Delphi IDE with administrative rights to prevent permission-related installation issues. ### Step 2: Access Options Dialog Navigate to the Options menu to configure essential library settings. ### Step 3: Configure Source Directory Paths Add the TVFVideoCapture package folder (`Video Capture\Packages\Delphi `, which holds the precompiled `.dcu` units) to both the library and browsing path settings to ensure proper component discovery. ### Step 4: Open the Component Library Package Locate and open the library package file included with TVFVideoCapture. ### Step 5: Complete Package Installation Install the package through the IDE's package installation interface. ## Advanced Installation for Delphi 11 and Newer Releases The latest Delphi versions require a slightly different approach that leverages modern project structures. ### Step 1: Locate and Open the Package Project After installing the framework, navigate to the `Video Capture\Packages\Delphi ` folder in the installation directory and open the `VisioForge_VideoCapture_Package.dproj` package project. ### Step 2: Select the Appropriate Build Configuration Choose the Release build configuration to ensure optimal component performance. ### Step 3: Install the Component Package Complete the installation process through the IDE's package installation interface. ### Step 4: Verify Installation Success Confirm that the installation completed successfully before proceeding with development. ## Project Configuration Requirements and Best Practices ### Multi-Architecture Support TVFVideoCapture supports both x86 and x64 architectures, allowing you to develop applications for different platform targets. You can install both package versions simultaneously to support flexible deployment scenarios. ### Library Path Configuration For proper component functionality, ensure that you've configured the correct library folder path in your application project settings. This path should point to the location containing the `.dcu` files for your target architecture. To set this up: 1. Open your project options dialog 2. Navigate to the Library path section 3. Add the appropriate TVFVideoCapture library path 4. Save your project settings This configuration ensures that your application can locate all required component resources during both development and runtime. ## Troubleshooting Common Installation Issues When installing TVFVideoCapture, developers might encounter several known issues. Here are solutions to the most frequent problems: ### 64-bit Package Installation Problems If you're having difficulties installing the 64-bit package version, refer to our [detailed guide for resolving Delphi 64-bit package installation issues](../../../general/install-64bit/). ### Resource File (.otares) Installation Issues Some developers encounter problems related to `.otares` files during package installation. For a step-by-step resolution process, see our [troubleshooting guide for .otares installation problems](../../../general/install-otares/). ## Technical Support and Additional Resources For developers requiring additional assistance with the installation process or component implementation: - Contact our [technical support team](https://support.visioforge.com/) for personalized installation assistance - Visit our [GitHub repository](https://github.com/visioforge/) for additional code samples and implementation examples - Check our documentation for advanced usage scenarios and integration patterns Following this installation guide will ensure that you have a properly configured development environment for creating powerful multimedia applications with TVFVideoCapture in your Delphi projects. ---END OF PAGE--- ## Install TVFVideoCapture in Delphi, VB6, and C++ Builder **URL:** https://www.visioforge.com/help/docs/delphi/videocapture/install/ **Description:** Install TVFVideoCapture library in Delphi, Visual Studio, C++ Builder, and VB6 with step-by-step IDE setup and ActiveX integration. **Tags:** All-in-One Media Framework, Delphi, ActiveX, Windows, VCL, Capture **API:** TVFVideoCapture # TVFVideoCapture Installation Guide ## Installation 1. **Download the latest version of the VisioForge All-in-One Media Framework**: Navigate to the [product page](https://www.visioforge.com/all-in-one-media-framework) on our official website and download the most up-to-date version of the TVFVideoCapture library. Ensure that you select the appropriate version that matches your development environment requirements. 2. **Run the setup file**: After the download completes, locate the setup file in your download directory and execute it. This will launch the installation process. 3. **Follow the installation wizard instructions**: The setup wizard will guide you through the installation steps. Carefully read each prompt, accept the license agreement, choose the installation directory, and proceed by clicking "Next". 4. **Completion**: Upon successful installation, go to the installation folder. Here, you will find a variety of framework samples and detailed documentation designed to assist you in integrating and utilizing the library effectively within your projects. ### Delphi packages installation For detailed instructions on installing the TVFVideoCapture packages in your Delphi IDE, please refer to the following [Delphi installation guide](delphi/). ### ActiveX installation #### C++ Builder For [C++ Builder](builder/), the installation process involves importing the ActiveX control into your project. This straightforward process ensures that you can quickly start using the TVFVideoCapture library in your C++ Builder projects. #### Visual Basic 6 In [Visual Basic 6](visual-basic-6/), open your project and go to the "Project" menu. Select "Components" and click "Browse". Find `VisioForge_Video_Capture.ocx` in the `Redist` folder of the installation and add it to your project. The components will now be available in the toolbox for your VB6 applications. ### Visual Studio 2010 and later For [Visual Studio 2010 and newer](visual-studio/) versions, open your project in the IDE, right-click on the toolbox, and select "Choose Items". Navigate to the COM components tab, click "Browse", and select `VisioForge_Video_Capture.ocx` from the `Redist` folder (or `Redist\x64` for 64-bit) of the framework installation directory. This will add the components to your toolbox, allowing you to use them in your Visual Studio projects. ## Conclusion By following this comprehensive guide, you should be able to smoothly install and integrate the TVFVideoCapture library into your chosen development environment. Should you encounter any issues or require further assistance, please refer to the detailed documentation included in the framework or contact our support team. ---END OF PAGE--- ## Installing TVFVideoCapture in VB6 for Delphi Users **URL:** https://www.visioforge.com/help/docs/delphi/videocapture/install/visual-basic-6/ **Description:** Integrate TVFVideoCapture ActiveX control in Visual Basic 6 with x86 compatibility and full video capture feature access. **Tags:** All-in-One Media Framework, Delphi, ActiveX, Windows, VCL, Capture **API:** TVFVideoCapture # Integrating TVFVideoCapture with Visual Basic 6 ## Overview and Compatibility Microsoft Visual Basic 6 offers excellent compatibility with our TVFVideoCapture library through its ActiveX control interface. This integration empowers developers to significantly enhance their applications with advanced video capture capabilities while maintaining optimal performance characteristics. Due to the architecture of Visual Basic 6, which was developed during the early stages of Windows programming frameworks, the platform exclusively supports 32-bit applications. Consequently, only the x86 version of our TVFVideoCapture library is compatible with VB6 development environments. Despite this architectural limitation, our framework delivers exceptional performance within the 32-bit environment. The library provides full access to our comprehensive feature set, ensuring developers can implement sophisticated video capture solutions regardless of the 32-bit constraint. ## Detailed Installation Process The following step-by-step guide will walk you through the complete process of installing and configuring the TVFVideoCapture ActiveX control in your Visual Basic 6 development environment. ### Step 1: Create a New Project Environment Begin by launching Visual Basic 6 and creating a new standard project that will serve as the foundation for your video capture implementation. ### Step 2: Access the Components Dialog Navigate to the Project menu and select the "Components" option to open the component selection dialog. This interface allows you to browse and select from available ActiveX controls. ### Step 3: Select the TVFVideoCapture Component In the Components dialog, scroll through the available controls and locate the "VisioForge Video Capture" item. Check the box next to it to include this component in your toolbox. ### Step 4: Verify Successful Integration After adding the component, you should notice the new TVFVideoCapture control appearing in your VB6 toolbox. This confirms that the ActiveX control has been successfully integrated into your development environment. ## Implementation Considerations When implementing the TVFVideoCapture control in your VB6 application, consider the following best practices: - Initialize the control early in your application lifecycle - Configure capture parameters before starting the capture process - Implement proper error handling for device connectivity issues - Release resources when they are no longer needed ## Technical Support and Additional Resources --- For technical questions or implementation challenges, please contact our [support team](https://support.visioforge.com/) who specialize in assisting developers with integration requirements. For additional code examples and implementation patterns, visit our [GitHub repository](https://github.com/visioforge/) which contains numerous samples demonstrating optimal usage patterns. ---END OF PAGE--- ## Install TVFVideoCapture ActiveX Control in Visual Studio **URL:** https://www.visioforge.com/help/docs/delphi/videocapture/install/visual-studio/ **Description:** Install TVFVideoCapture ActiveX controls in Visual Studio 2010+ with C++ and managed code integration for video capture projects. **Tags:** All-in-One Media Framework, Delphi, ActiveX, Windows, VCL, Capture **API:** TVFVideoCapture # Installing TVFVideoCapture in Visual Studio 2010 and Later ## Overview of TVFVideoCapture Integration The TVFVideoCapture ActiveX control provides powerful video capture capabilities for your development projects. This guide walks you through the installation process in Visual Studio environments, with special considerations for Delphi developers. ## Installation Requirements Before beginning the installation process, ensure you have: - Visual Studio 2010 or a later version installed - Administrator rights on your development machine - Both x86 and x64 ActiveX controls registered (if applicable) ## Installation Process for Different Project Types You can implement the TVFVideoCapture ActiveX control directly in various project types. The integration approach differs slightly depending on your development environment: ### For C++ Projects In C++ projects, you can use the ActiveX control directly without additional wrappers or interfaces. ### For C#/VB.Net Projects When working with C# or Visual Basic .NET projects, Visual Studio automatically generates a custom wrapper assembly. This wrapper exposes the ActiveX API through managed code, making integration seamless. ## Step-by-Step Installation Guide Follow these detailed steps to install the TVFVideoCapture control in your Visual Studio environment: 1. Create a new project in your preferred language (C++, C#, or Visual Basic .NET) 2. Access the toolbox panel in your Visual Studio interface 1. Right-click on the toolbox and select "Choose toolbox items" from the context menu 1. In the dialog box that appears, locate and select the "VisioForge Video Capture" component 1. After selection, the control will be added to your toolbox for easy access 1. Add the control to your form by dragging it from the toolbox 2. For .NET projects, Visual Studio will automatically generate the necessary wrapper assembly ## Framework Samples and Resources For practical implementation examples, refer to the framework samples included with your installation package. These samples cover all supported programming languages and demonstrate various integration scenarios. ## Recommendations for .NET Developers While ActiveX integration is fully supported, .NET developers may benefit from using the native .NET version of the SDK. The native implementation offers: - Enhanced performance and stability - Direct integration with WinForms and WPF - MAUI control support for cross-platform development - More intuitive API design for .NET environments ## Additional Resources and Support Explore our extensive documentation for advanced configuration options and optimization techniques. Our development team continuously updates resources to address common implementation challenges. --- For technical assistance with this installation process, please contact our [support team](https://support.visioforge.com/). Additional code samples and implementation examples are available on our [GitHub repository](https://github.com/visioforge/). ---END OF PAGE--- ## Delphi MPEG-2 Video Capture with TV Tuner Hardware **URL:** https://www.visioforge.com/help/docs/delphi/videocapture/mpeg2-capture/ **Description:** Implement MPEG-2 capture in Delphi using TV tuner hardware encoders - device enumeration, format configuration, and optimized code examples. **Tags:** All-in-One Media Framework, Delphi, ActiveX, DirectShow, Windows, VCL, Capture, Encoding, TV Tuner, MPEG-2 # MPEG-2 Video Capture in Delphi Using TV Tuner Hardware Encoders This comprehensive tutorial demonstrates how to implement high-quality MPEG-2 video capture functionality in your Delphi applications by leveraging TV tuners with built-in hardware encoding capabilities. Hardware encoding significantly reduces CPU usage while maintaining excellent video quality. ## Overview of MPEG-2 Hardware Encoding MPEG-2 hardware encoders provide superior performance compared to software-based encoding solutions. They're particularly useful for developing professional video capture applications that require efficient processing and high-quality output. ## Enumerating Available MPEG-2 Hardware Encoders The first step is to identify all available MPEG-2 hardware encoders in the system. This code demonstrates how to populate a dropdown with detected devices: ``` // List all available MPEG-2 hardware encoders in the system // This helps users select the appropriate encoding device VideoCapture1.Special_Filters_Fill; for I := 0 to VideoCapture1.Special_Filters_GetCount(SF_Hardware_Video_Encoder) - 1 do cbMPEGEncoder.Items.Add(VideoCapture1.Special_Filters_GetItem(SF_Hardware_Video_Encoder, i)); ``` ``` // C++ MFC implementation for MPEG-2 encoder enumeration // Populates a combobox with all detected hardware encoders m_VideoCapture.Special_Filters_Fill(); for (int i = 0; i < m_VideoCapture.Special_Filters_GetCount(SF_Hardware_Video_Encoder); i++) { CString encoderName = m_VideoCapture.Special_Filters_GetItem(SF_Hardware_Video_Encoder, i); m_cbMPEGEncoder.AddString(encoderName); } ``` ``` ' VB6 implementation for finding hardware MPEG-2 encoders ' Lists all available encoders in a combobox control VideoCapture1.Special_Filters_Fill For i = 0 To VideoCapture1.Special_Filters_GetCount(SF_Hardware_Video_Encoder) - 1 cbMPEGEncoder.AddItem VideoCapture1.Special_Filters_GetItem(SF_Hardware_Video_Encoder, i) Next i ``` ## Selecting a Specific MPEG-2 Encoder After enumerating the available encoders, the next step is to select a specific encoder for use: ``` // Configure the component to use the selected MPEG-2 hardware encoder // This must be done before starting the capture process VideoCapture1.Video_CaptureDevice_InternalMPEGEncoder_Name := cbMPEGEncoder.Items[cbMPEGEncoder.ItemIndex]; ``` ``` // C++ MFC: Select and configure the chosen MPEG-2 hardware encoder // Retrieves the selected encoder name from the combobox int nIndex = m_cbMPEGEncoder.GetCurSel(); CString encoderName; m_cbMPEGEncoder.GetLBText(nIndex, encoderName); m_VideoCapture.Video_CaptureDevice_InternalMPEGEncoder_Name = encoderName; ``` ``` ' VB6: Set the selected encoder as the active MPEG-2 hardware encoder ' Must be called before initializing the capture graph VideoCapture1.Video_CaptureDevice_InternalMPEGEncoder_Name = cbMPEGEncoder.List(cbMPEGEncoder.ListIndex) ``` ## Configuring DirectStream MPEG Format for Output To properly capture MPEG-2 encoded video, you need to set the appropriate output format: ``` // Set the output format to DirectStream MPEG // This enables proper handling of hardware-encoded MPEG-2 streams VideoCapture1.OutputFormat := Format_DirectStream_MPEG; ``` ``` // C++ MFC: Configure the output format for MPEG-2 encoded content // DirectStream MPEG format preserves the hardware-encoded stream m_VideoCapture.OutputFormat = Format_DirectStream_MPEG; ``` ``` ' VB6: Set the proper output format for MPEG-2 hardware encoding ' DirectStream format ensures the encoded data is properly handled VideoCapture1.OutputFormat = Format_DirectStream_MPEG ``` ## Establishing Video Capture Mode Before starting the capture process, set the component to video capture mode: ``` // Configure the component for video capture operation // This prepares the internal DirectShow graph for recording VideoCapture1.Mode := Mode_Video_Capture; ``` ``` // C++ MFC: Set the component to video capture mode // Required before starting the MPEG-2 capture process m_VideoCapture.Mode = Mode_Video_Capture; ``` ``` ' VB6: Set video capture mode before starting recording ' This initializes the appropriate DirectShow filters VideoCapture1.Mode = Mode_Video_Capture ``` ## Initiating the MPEG-2 Capture Process Finally, start the capture process to begin recording MPEG-2 video: ``` // Begin the video capture process with the configured settings // The component will now start recording to the specified output VideoCapture1.Start; ``` ``` // C++ MFC: Start the MPEG-2 video capture process // Recording begins with the previously configured settings m_VideoCapture.Start(); ``` ``` ' VB6: Start the video capture with the current configuration ' The hardware encoder will now begin processing video data VideoCapture1.Start ``` ## Advanced MPEG-2 Capture Considerations When implementing MPEG-2 capture with hardware encoders, consider these additional factors: 1. Hardware encoders typically offer better performance than software-based solutions 2. Some TV tuners provide additional encoding parameters that can be customized 3. Buffer sizes may need adjustment for higher quality captures 4. Hardware encoders often handle video scaling and frame rate conversion internally ## Troubleshooting Common Issues If you encounter problems with MPEG-2 hardware encoding: 1. Verify that your TV tuner device supports hardware MPEG-2 encoding 2. Ensure proper driver installation for the capture device 3. Check that DirectX is properly installed and updated 4. Consider system resource availability, as some encoders require specific resources Please contact our dedicated support team for assistance with implementing this tutorial in your specific application. Visit our GitHub repository for additional code samples and implementation examples. ---END OF PAGE--- ## Implement WMV Network Streaming in Delphi and ActiveX **URL:** https://www.visioforge.com/help/docs/delphi/videocapture/network-streaming-wmv/ **Description:** Implement WMV network streaming in Delphi - configure profiles, manage client connections, set ports, and broadcast video with code examples. **Tags:** All-in-One Media Framework, Delphi, ActiveX, Windows, VCL, Capture, Streaming, Encoding, WMV # WMV Network Streaming Implementation Guide ## Overview This guide demonstrates how to implement network-based video broadcasting using Windows Media Video (WMV) format in your Delphi applications. The techniques shown here allow you to stream video content over networks while simultaneously capturing and saving the video to a file for archival purposes. ## Requirements Before implementing WMV network streaming, ensure that you have: - A supported video capture device connected to your system - Proper network access and permissions - A valid WMV profile file with encoder settings ## Implementation Steps ### Basic Configuration To enable WMV network streaming in your application, you'll need to configure several essential parameters: 1. Enable network streaming functionality 2. Specify a WMV profile file containing video encoding parameters 3. Set the maximum number of concurrent client connections 4. Define the network port for client connections ### Delphi Implementation Code ``` // Delphi code for configuring WMV network streaming // Enable the network streaming functionality VideoCapture1.Network_Streaming_Enabled := true; // Set the path to the WMV profile file containing encoder settings // This file defines video quality, bitrate, resolution, etc. VideoCapture1.Network_Streaming_WMV_Profile_FileName := edNetworkStreamingWMVProfile.Text; // Define maximum number of concurrent clients that can connect VideoCapture1.Network_Streaming_Maximum_Clients := StrToInt(edMaximumClients.Text); // Specify the network port that clients will use to connect VideoCapture1.Network_Streaming_Network_Port := StrToInt(edNetworkPort.Text); ``` ### C++ MFC Implementation ``` // C++ MFC implementation for WMV network streaming. // CEdit::GetWindowText takes a CString reference and writes into it (returns void), // so capture the value via a local CString and pass that to the COM setter. CString profile, maxClients, port; edNetworkStreamingWMVProfile.GetWindowText(profile); edMaximumClients.GetWindowText(maxClients); edNetworkPort.GetWindowText(port); // Enable streaming functionality m_VideoCapture.SetNetwork_Streaming_Enabled(true); // Set WMV profile path - contains encoding parameters m_VideoCapture.SetNetwork_Streaming_WMV_Profile_FileName(profile); // Define maximum concurrent client connections m_VideoCapture.SetNetwork_Streaming_Maximum_Clients(_ttoi(maxClients)); // Set the network port for client connections m_VideoCapture.SetNetwork_Streaming_Network_Port(_ttoi(port)); ``` ### VB6 Implementation ``` ' VB6 (ActiveX) implementation for WMV network streaming ' Enable network streaming capabilities VideoCapture1.Network_Streaming_Enabled = True ' Set the profile file containing video encoder settings VideoCapture1.Network_Streaming_WMV_Profile_FileName = txtNetworkStreamingWMVProfile.Text ' Define maximum number of clients allowed to connect simultaneously VideoCapture1.Network_Streaming_Maximum_Clients = CInt(txtMaximumClients.Text) ' Specify the network port for client connections VideoCapture1.Network_Streaming_Network_Port = CInt(txtNetworkPort.Text) ``` ## Client Connection Information After configuring the streaming parameters, your application can obtain the connection URL that clients will use to access the video stream: ``` // Get the URL that clients will use to connect to the stream // This URL can be shared with users who need to view the stream strStreamURL := VideoCapture1.Network_Streaming_URL; ``` This URL can be used with Windows Media Player or any other application that supports Windows Media streaming protocols. ## Best Practices For optimal streaming performance, consider the following recommendations: - Use appropriate bitrates based on your network capabilities - Monitor client connections to ensure system stability - Test your streaming configuration with various client applications - Consider network bandwidth limitations when setting quality parameters ## Troubleshooting If you encounter issues with your streaming implementation: - Verify network firewall settings allow traffic on your selected port - Ensure the WMV profile file exists and contains valid settings - Check that the maximum client count is appropriate for your server resources - Validate network connectivity between the server and potential clients --- Please get in touch with [support](https://support.visioforge.com/) if you have questions about this implementation. Visit our [GitHub](https://github.com/visioforge/) page for additional code samples and resources. ---END OF PAGE--- ## Resize and Crop Video in Delphi with TVFVideoCapture **URL:** https://www.visioforge.com/help/docs/delphi/videocapture/resize-crop/ **Description:** Implement video resizing and cropping in Delphi - real-time processing, aspect ratio handling, and performance optimization with code samples. **Tags:** All-in-One Media Framework, Delphi, ActiveX, Windows, VCL, Capture, Streaming **API:** TVFVideoCapture # Video Resizing and Cropping in Delphi TVFVideoCapture Video manipulation is a critical component of many modern applications. This guide provides detailed instructions for implementing real-time video resizing and cropping in your Delphi applications with minimal performance impact. ## Why Resize or Crop Video? Video resizing and cropping serve multiple purposes in development: - Optimize video for different display sizes - Reduce bandwidth requirements for streaming - Focus on specific regions of interest - Create uniform video dimensions across your application - Improve performance on resource-constrained devices ## Enabling Resize and Crop Functionality Before applying any transformations, you must enable the resize/crop functionality in the TVFVideoCapture component. ### Step 1: Enable the Feature ``` // Enable video resizing or cropping functionality VideoCapture1.Video_ResizeOrCrop_Enabled := true; ``` ``` // C++ MFC - Enable video transformation capabilities m_VideoCapture.SetVideo_ResizeOrCrop_Enabled(TRUE); ``` ``` ' VB6 - Activate resize/crop features VideoCapture1.Video_ResizeOrCrop_Enabled = True ``` ## Video Resizing Implementation Resizing allows you to change the dimensions of your video stream while maintaining visual quality. ### Setting New Dimensions ``` // Set the desired width and height for the resized video output VideoCapture1.Video_Resize_NewWidth := StrToInt(edResizeWidth.Text); VideoCapture1.Video_Resize_NewHeight := StrToInt(edResizeHeight.Text); ``` ``` // C++ MFC - Configure target dimensions for video resize m_VideoCapture.SetVideo_Resize_NewWidth(_ttoi(m_strResizeWidth)); m_VideoCapture.SetVideo_Resize_NewHeight(_ttoi(m_strResizeHeight)); ``` ``` ' VB6 - Define new video dimensions VideoCapture1.Video_Resize_NewWidth = CInt(txtResizeWidth.Text) VideoCapture1.Video_Resize_NewHeight = CInt(txtResizeHeight.Text) ``` ### Handling Aspect Ratio Changes When resizing video, you can choose between preserving the original aspect ratio (letterbox) or stretching the content to fit the new dimensions. ``` // Letterbox mode adds black borders to preserve aspect ratio // When false, the video will stretch to fit the new dimensions VideoCapture1.Video_Resize_LetterBox := cbResizeLetterbox.Checked; ``` ``` // C++ MFC - Configure aspect ratio handling method m_VideoCapture.SetVideo_Resize_LetterBox(m_bResizeLetterbox); ``` ``` ' VB6 - Set letterbox mode for aspect ratio preservation VideoCapture1.Video_Resize_LetterBox = chkResizeLetterbox.Value ``` ### Selecting Resize Algorithms Choose from multiple resize algorithms based on your quality requirements and performance constraints: ``` // Select the appropriate resize algorithm: // - NearestNeighbor: Fastest but lowest quality // - Bilinear: Good balance between speed and quality // - Bilinear_HQ: Enhanced bilinear with improved quality // - Bicubic: Better quality with moderate performance impact // - Bicubic_HQ: Highest quality with highest CPU usage case cbResizeMode.ItemIndex of 0: VideoCapture1.Video_Resize_Mode := rm_NearestNeighbor; 1: VideoCapture1.Video_Resize_Mode := rm_Bilinear; 2: VideoCapture1.Video_Resize_Mode := rm_Bilinear_HQ; 3: VideoCapture1.Video_Resize_Mode := rm_Bicubic; 4: VideoCapture1.Video_Resize_Mode := rm_Bicubic_HQ; end; ``` ``` // C++ MFC - Set the resize algorithm based on quality/performance needs switch(m_nResizeMode) { case 0: m_VideoCapture.SetVideo_Resize_Mode(rm_NearestNeighbor); break; // Fastest case 1: m_VideoCapture.SetVideo_Resize_Mode(rm_Bilinear); break; // Standard case 2: m_VideoCapture.SetVideo_Resize_Mode(rm_Bilinear_HQ); break; // Enhanced case 3: m_VideoCapture.SetVideo_Resize_Mode(rm_Bicubic); break; // High quality case 4: m_VideoCapture.SetVideo_Resize_Mode(rm_Bicubic_HQ); break; // Maximum quality } ``` ``` ' VB6 - Choose resize algorithm based on quality and performance needs Select Case cboResizeMode.ListIndex Case 0: VideoCapture1.Video_Resize_Mode = rm_NearestNeighbor ' Fastest, lower quality Case 1: VideoCapture1.Video_Resize_Mode = rm_Bilinear ' Balanced option Case 2: VideoCapture1.Video_Resize_Mode = rm_Bilinear_HQ ' Enhanced bilinear Case 3: VideoCapture1.Video_Resize_Mode = rm_Bicubic ' Better quality Case 4: VideoCapture1.Video_Resize_Mode = rm_Bicubic_HQ ' Highest quality End Select ``` ## Video Cropping Implementation Cropping allows you to select a specific region of interest from your video stream. ### Step 1: Enable Cropping As with resizing, you must first enable the feature: ``` // Enable video transformation capabilities before applying crop VideoCapture1.Video_ResizeOrCrop_Enabled := true; ``` ``` // C++ MFC - Activate video manipulation features m_VideoCapture.SetVideo_ResizeOrCrop_Enabled(TRUE); ``` ``` ' VB6 - Enable video transformation functionality VideoCapture1.Video_ResizeOrCrop_Enabled = True ``` ### Step 2: Define Crop Region Specify the boundaries of your crop region by defining the left, top, right, and bottom coordinates: ``` // Define the crop region coordinates in pixels // These values represent the distance from each edge of the original video VideoCapture1.Video_Crop_Left := StrToInt(edCropLeft.Text); VideoCapture1.Video_Crop_Top := StrToInt(edCropTop.Text); VideoCapture1.Video_Crop_Right := StrToInt(edCropRight.Text); VideoCapture1.Video_Crop_Bottom := StrToInt(edCropBottom.Text); ``` ``` // C++ MFC - Set the crop boundaries in pixels // Each value defines how many pixels to crop from the respective edge m_VideoCapture.SetVideo_Crop_Left(_ttoi(m_strCropLeft)); m_VideoCapture.SetVideo_Crop_Top(_ttoi(m_strCropTop)); m_VideoCapture.SetVideo_Crop_Right(_ttoi(m_strCropRight)); m_VideoCapture.SetVideo_Crop_Bottom(_ttoi(m_strCropBottom)); ``` ``` ' VB6 - Configure crop region boundaries ' Values represent pixel counts from each edge to exclude VideoCapture1.Video_Crop_Left = CInt(txtCropLeft.Text) VideoCapture1.Video_Crop_Top = CInt(txtCropTop.Text) VideoCapture1.Video_Crop_Right = CInt(txtCropRight.Text) VideoCapture1.Video_Crop_Bottom = CInt(txtCropBottom.Text) ``` ## Best Practices for Video Manipulation For optimal results when implementing video resizing and cropping: 1. **Test on target hardware** - Different resize algorithms have varying CPU requirements 2. **Consider your use case** - For real-time applications, favor performance over quality 3. **Maintain aspect ratios** - Unless specifically needed, preserve original proportions 4. **Combine operations judiciously** - Applying both resize and crop increases processing overhead 5. **Cache settings** - Avoid changing parameters frequently during capture ## Troubleshooting Common Issues - If performance is poor, try a faster resize algorithm - Ensure crop values don't exceed the dimensions of your video stream - When using letterbox mode, account for the black borders in your UI design - For best results, resize to dimensions that are multiples of 8 or 16 --- For additional code samples and implementation examples, visit our [GitHub](https://github.com/visioforge/) repository. Need technical assistance? Contact our support team for personalized guidance. ---END OF PAGE--- ## Delphi Screen Capture and Recording with TVFVideoCapture **URL:** https://www.visioforge.com/help/docs/delphi/videocapture/screen-capture/ **Description:** Implement screen recording in Delphi with TVFVideoCapture - capture regions, full screen, customize frame rates, track cursor with code examples. **Tags:** All-in-One Media Framework, Delphi, ActiveX, Windows, VCL, Capture, Screen Capture **API:** TVFVideoCapture # Screen Recording Implementation in Delphi ## Introduction to Screen Capture Functionality TVFVideoCapture provides powerful screen recording capabilities for Delphi developers. This guide walks through the implementation of screen capture features in your applications, allowing you to record specific regions or the entire screen with customizable settings. ## Configuring Screen Capture Area You can precisely control which portion of the screen to record by setting coordinate parameters. This is particularly useful when you want to focus on specific application windows or screen regions. ### Setting Specific Screen Coordinates Use these parameters to define the exact boundaries of your capture area: ``` // Define the top edge position of the capture rectangle (in pixels) VideoCapture1.Screen_Capture_Top := StrToInt(edScreenTop.Text); // Define the bottom edge position of the capture rectangle (in pixels) VideoCapture1.Screen_Capture_Bottom := StrToInt(edScreenBottom.Text); // Define the left edge position of the capture rectangle (in pixels) VideoCapture1.Screen_Capture_Left := StrToInt(edScreenLeft.Text); // Define the right edge position of the capture rectangle (in pixels) VideoCapture1.Screen_Capture_Right := StrToInt(edScreenRight.Text); ``` ``` // CEdit::GetWindowText(CString&) returns void and fills the buffer by reference, // so we must declare a CString first and then convert it to int via _ttoi // (the TCHAR-aware variant — required because CString is wide in Unicode MFC builds). CString sTop, sBottom, sLeft, sRight; m_edScreenTop.GetWindowText(sTop); m_edScreenBottom.GetWindowText(sBottom); m_edScreenLeft.GetWindowText(sLeft); m_edScreenRight.GetWindowText(sRight); // Define the top edge position of the capture rectangle (in pixels) m_VideoCapture.SetScreen_Capture_Top(_ttoi(sTop)); // Define the bottom edge position of the capture rectangle (in pixels) m_VideoCapture.SetScreen_Capture_Bottom(_ttoi(sBottom)); // Define the left edge position of the capture rectangle (in pixels) m_VideoCapture.SetScreen_Capture_Left(_ttoi(sLeft)); // Define the right edge position of the capture rectangle (in pixels) m_VideoCapture.SetScreen_Capture_Right(_ttoi(sRight)); ``` ``` ' Define the top edge position of the capture rectangle (in pixels) VideoCapture1.Screen_Capture_Top = CInt(edScreenTop.Text) ' Define the bottom edge position of the capture rectangle (in pixels) VideoCapture1.Screen_Capture_Bottom = CInt(edScreenBottom.Text) ' Define the left edge position of the capture rectangle (in pixels) VideoCapture1.Screen_Capture_Left = CInt(edScreenLeft.Text) ' Define the right edge position of the capture rectangle (in pixels) VideoCapture1.Screen_Capture_Right = CInt(edScreenRight.Text) ``` ### Capturing the Full Screen For complete screen recording, simply enable the full screen capture option: ``` // Enable full screen capture mode - will record the entire display VideoCapture1.Screen_Capture_FullScreen := true; ``` ``` // Enable full screen capture mode - will record the entire display m_VideoCapture.SetScreen_Capture_FullScreen(true); ``` ``` ' Enable full screen capture mode - will record the entire display VideoCapture1.Screen_Capture_FullScreen = True ``` ## Optimizing Frame Rate Settings The frame rate directly impacts both the quality and file size of your screen recordings. Higher frame rates produce smoother video but generate larger files. ``` // Set capture frame rate to 10 frames per second // Adjust this value based on your performance requirements VideoCapture1.Screen_Capture_FrameRate := 10; ``` ``` // Set capture frame rate to 10 frames per second // Adjust this value based on your performance requirements m_VideoCapture.SetScreen_Capture_FrameRate(10); ``` ``` ' Set capture frame rate to 10 frames per second ' Adjust this value based on your performance requirements VideoCapture1.Screen_Capture_FrameRate = 10 ``` ## Cursor Tracking Configuration For instructional videos or demonstrations, capturing the mouse cursor movement is essential: ``` // Enable mouse cursor capture in the recording // Set to false to hide cursor in the output video VideoCapture1.Screen_Capture_Grab_Mouse_Cursor := true; ``` ``` // Enable mouse cursor capture in the recording // Set to false to hide cursor in the output video m_VideoCapture.SetScreen_Capture_Grab_Mouse_Cursor(true); ``` ``` ' Enable mouse cursor capture in the recording ' Set to false to hide cursor in the output video VideoCapture1.Screen_Capture_Grab_Mouse_Cursor = True ``` ## Activating Screen Capture Mode After configuring all settings, set the component to screen capture mode to begin recording: ``` // Set component to screen capture operational mode // This activates all screen recording functionality VideoCapture1.Mode := Mode_Screen_Capture; ``` ``` // Set component to screen capture operational mode // This activates all screen recording functionality m_VideoCapture.SetMode(Mode_Screen_Capture); ``` ``` ' Set component to screen capture operational mode ' This activates all screen recording functionality VideoCapture1.Mode = Mode_Screen_Capture ``` ## Advanced Implementation Tips For optimal screen recording performance: - Consider system resources when selecting frame rates - Use region capture when possible to minimize processing load - Test different quality settings to balance file size and visual quality - Remember that cursor capture adds slight processing overhead --- For additional code samples and implementation examples, visit our [GitHub](https://github.com/visioforge/) repository. For technical assistance with implementation, please contact our [support team](https://support.visioforge.com/). ---END OF PAGE--- ## Select Video and Audio Capture Devices in Delphi and VB6 **URL:** https://www.visioforge.com/help/docs/delphi/videocapture/video-audio-sources/ **Description:** Select video and audio devices in Delphi - enumerate devices, configure formats, set frame rates with code examples for Delphi, C++, and VB6. **Tags:** All-in-One Media Framework, Delphi, ActiveX, Windows, VCL, Capture # Code sample - How to select video and audio capture devices? Delphi, C++ MFC and VB6 sample code ## Select video source ### Get a list of available video capture devices ``` for i := 0 to VideoCapture1.Video_CaptureDevices_GetCount - 1 do cbVideoInputDevice.Items.Add(VideoCapture1.Video_CaptureDevices_GetItem(i)); ``` ``` // C++ MFC for (int i = 0; i < m_VideoCapture.Video_CaptureDevices_GetCount(); i++) m_cbVideoInputDevice.AddString(m_VideoCapture.Video_CaptureDevices_GetItem(i)); ``` ``` ' VB6 For i = 0 To VideoCapture1.Video_CaptureDevices_GetCount - 1 cbVideoInputDevice.AddItem VideoCapture1.Video_CaptureDevices_GetItem(i) Next i ``` ### Select the video input device ``` VideoCapture1.Video_CaptureDevice := cbVideoInputDevice.Items[cbVideoInputDevice.ItemIndex]; ``` ``` // C++ MFC CString strDevice; m_cbVideoInputDevice.GetLBText(m_cbVideoInputDevice.GetCurSel(), strDevice); m_VideoCapture.put_Video_CaptureDevice(strDevice); ``` ``` ' VB6 VideoCapture1.Video_CaptureDevice = cbVideoInputDevice.Text ``` ### Get a list of available video formats ``` VideoCapture1.Video_CaptureDevice_Formats_Fill; for I := 0 to VideoCapture1.Video_CaptureDevice_Formats_GetCount - 1 do cbVideoInputFormat.Items.Add(VideoCapture1.Video_CaptureDevice_Formats_GetItem(i)); ``` ``` // C++ MFC m_VideoCapture.Video_CaptureDevice_Formats_Fill(); for (int i = 0; i < m_VideoCapture.Video_CaptureDevice_Formats_GetCount(); i++) m_cbVideoInputFormat.AddString(m_VideoCapture.Video_CaptureDevice_Formats_GetItem(i)); ``` ``` ' VB6 VideoCapture1.Video_CaptureDevice_Formats_Fill For i = 0 To VideoCapture1.Video_CaptureDevice_Formats_GetCount - 1 cbVideoInputFormat.AddItem VideoCapture1.Video_CaptureDevice_Formats_GetItem(i) Next i ``` ### Select video format ``` VideoCapture1.Video_CaptureFormat := cbVideoInputFormat.Items[cbVideoInputFormat.ItemIndex]; ``` ``` // C++ MFC CString strFormat; m_cbVideoInputFormat.GetLBText(m_cbVideoInputFormat.GetCurSel(), strFormat); m_VideoCapture.put_Video_CaptureFormat(strFormat); ``` ``` ' VB6 VideoCapture1.Video_CaptureFormat = cbVideoInputFormat.Text ``` or ### Automatically choose the best video format ``` VideoCapture1.Video_CaptureFormat_UseBest := cbUseBestVideoInputFormat.Checked; ``` ``` // C++ MFC m_VideoCapture.put_Video_CaptureFormat_UseBest(m_cbUseBestVideoInputFormat.GetCheck() == BST_CHECKED); ``` ``` ' VB6 VideoCapture1.Video_CaptureFormat_UseBest = cbUseBestVideoInputFormat.Value ``` ### Get a list of available frame rates ``` VideoCapture1.Video_CaptureDevice_FrameRates_Fill; for I := 0 to VideoCapture1.Video_CaptureDevice_FrameRates_GetCount - 1 do cbFrameRate.Items.Add(VideoCapture1.Video_CaptureDevice_FrameRates_GetItem(i)); ``` ``` // C++ MFC m_VideoCapture.Video_CaptureDevice_FrameRates_Fill(); for (int i = 0; i < m_VideoCapture.Video_CaptureDevice_FrameRates_GetCount(); i++) m_cbFrameRate.AddString(m_VideoCapture.Video_CaptureDevice_FrameRates_GetItem(i)); ``` ``` ' VB6 VideoCapture1.Video_CaptureDevice_FrameRates_Fill For i = 0 To VideoCapture1.Video_CaptureDevice_FrameRates_GetCount - 1 cbFrameRate.AddItem VideoCapture1.Video_CaptureDevice_FrameRates_GetItem(i) Next i ``` ### Select frame rate ``` VideoCapture1.Video_FrameRate := StrToFloat(cbFrameRate.Items[cbFrameRate.ItemIndex]); ``` ``` // C++ MFC CString strFrameRate; m_cbFrameRate.GetLBText(m_cbFrameRate.GetCurSel(), strFrameRate); m_VideoCapture.put_Video_FrameRate(_wtof(strFrameRate)); ``` ``` ' VB6 VideoCapture1.Video_FrameRate = CDbl(cbFrameRate.Text) ``` Select needed video input (configure crossbar) if needed. ## Select audio source ### Use video capture device as audio source ``` VideoCapture1.Video_CaptureDevice_IsAudioSource := true; ``` ``` // C++ MFC m_VideoCapture.put_Video_CaptureDevice_IsAudioSource(true); ``` ``` ' VB6 VideoCapture1.Video_CaptureDevice_IsAudioSource = True ``` or ### Get a list of available audio capture devices ``` for I := 0 to VideoCapture1.Audio_CaptureDevices_GetCount - 1 do cbAudioInputDevice.Items.Add(VideoCapture1.Audio_CaptureDevices_GetItem(i)); ``` ``` // C++ MFC for (int i = 0; i < m_VideoCapture.Audio_CaptureDevices_GetCount(); i++) m_cbAudioInputDevice.AddString(m_VideoCapture.Audio_CaptureDevices_GetItem(i)); ``` ``` ' VB6 For i = 0 To VideoCapture1.Audio_CaptureDevices_GetCount - 1 cbAudioInputDevice.AddItem VideoCapture1.Audio_CaptureDevices_GetItem(i) Next i ``` ### Select the audio input device ``` VideoCapture1.Audio_CaptureDevice := cbAudioInputDevice.Items[cbAudioInputDevice.ItemIndex]; ``` ``` // C++ MFC CString strAudioDevice; m_cbAudioInputDevice.GetLBText(m_cbAudioInputDevice.GetCurSel(), strAudioDevice); m_VideoCapture.put_Audio_CaptureDevice(strAudioDevice); ``` ``` ' VB6 VideoCapture1.Audio_CaptureDevice = cbAudioInputDevice.Text ``` ### Get a list of available audio formats ``` VideoCapture1.Audio_CaptureDevice_Formats_Fill; for I := 0 to VideoCapture1.Audio_CaptureDevice_Formats_GetCount - 1 do cbAudioInputFormat.Items.Add(VideoCapture1.Audio_CaptureDevice_Formats_GetItem(i)); ``` ``` // C++ MFC m_VideoCapture.Audio_CaptureDevice_Formats_Fill(); for (int i = 0; i < m_VideoCapture.Audio_CaptureDevice_Formats_GetCount(); i++) m_cbAudioInputFormat.AddString(m_VideoCapture.Audio_CaptureDevice_Formats_GetItem(i)); ``` ``` ' VB6 VideoCapture1.Audio_CaptureDevice_Formats_Fill For i = 0 To VideoCapture1.Audio_CaptureDevice_Formats_GetCount - 1 cbAudioInputFormat.AddItem VideoCapture1.Audio_CaptureDevice_Formats_GetItem(i) Next i ``` ### Select the format ``` VideoCapture1.Audio_CaptureFormat := cbAudioInputFormat.Items[cbAudioInputFormat.ItemIndex]; ``` ``` // C++ MFC CString strAudioFormat; m_cbAudioInputFormat.GetLBText(m_cbAudioInputFormat.GetCurSel(), strAudioFormat); m_VideoCapture.put_Audio_CaptureFormat(strAudioFormat); ``` ``` ' VB6 VideoCapture1.Audio_CaptureFormat = cbAudioInputFormat.Text ``` or ### Automatically choose the best audio format ``` VideoCapture1.Audio_CaptureFormat_UseBest := cbUseBestAudioInputFormat.Checked; ``` ``` // C++ MFC m_VideoCapture.put_Audio_CaptureFormat_UseBest(m_cbUseBestAudioInputFormat.GetCheck() == BST_CHECKED); ``` ``` ' VB6 VideoCapture1.Audio_CaptureFormat_UseBest = cbUseBestAudioInputFormat.Value ``` ### Get a list of available audio inputs (lines) ``` VideoCapture1.Audio_CaptureDevice_Lines_Fill; for I := 0 to VideoCapture1.Audio_CaptureDevice_Lines_GetCount - 1 do cbAudioInputLine.Items.Add(VideoCapture1.Audio_CaptureDevice_Lines_GetItem(i)); ``` ``` // C++ MFC m_VideoCapture.Audio_CaptureDevice_Lines_Fill(); for (int i = 0; i < m_VideoCapture.Audio_CaptureDevice_Lines_GetCount(); i++) m_cbAudioInputLine.AddString(m_VideoCapture.Audio_CaptureDevice_Lines_GetItem(i)); ``` ``` ' VB6 VideoCapture1.Audio_CaptureDevice_Lines_Fill For i = 0 To VideoCapture1.Audio_CaptureDevice_Lines_GetCount - 1 cbAudioInputLine.AddItem VideoCapture1.Audio_CaptureDevice_Lines_GetItem(i) Next i ``` ### Select audio input ``` VideoCapture1.Audio_CaptureLine := cbAudioInputLine.Items[cbAudioInputLine.ItemIndex]; ``` ``` // C++ MFC CString strAudioLine; m_cbAudioInputLine.GetLBText(m_cbAudioInputLine.GetCurSel(), strAudioLine); m_VideoCapture.put_Audio_CaptureLine(strAudioLine); ``` ``` ' VB6 VideoCapture1.Audio_CaptureLine = cbAudioInputLine.Text ``` --- Please get in touch with [support](https://support.visioforge.com/) to get help with this tutorial. Visit our [GitHub](https://github.com/visioforge/) page to get more code samples. ---END OF PAGE--- ## AVI Video Capture in Delphi Using TVFVideoCapture SDK **URL:** https://www.visioforge.com/help/docs/delphi/videocapture/video-capture-avi/ **Description:** Record video to AVI format in Delphi with TVFVideoCapture using codec selection, audio configuration, and complete implementation examples. **Tags:** All-in-One Media Framework, Delphi, ActiveX, C++, Windows, VCL, Capture, AVI **API:** TVFVideoCapture # Complete Guide to Video Capture to AVI Files in Delphi When developing multimedia applications in Delphi, video capture functionality is often a critical requirement. This guide explores how to implement high-quality video capture to AVI files using the TVFVideoCapture component in Delphi applications. We'll cover everything from setting up codecs to configuring audio parameters and starting the capture process. ## Understanding AVI Video Capture in Delphi The TVFVideoCapture component provides a powerful and flexible way to capture video directly to AVI format in Delphi applications. AVI (Audio Video Interleave) remains a popular video container format due to its broad compatibility and reliability for recording purposes. When implementing video capture in your Delphi application, you'll need to consider several key aspects: 1. Selecting appropriate video and audio codecs 2. Configuring audio parameters 3. Setting the output format and capture mode 4. Managing the capture process This guide provides detailed explanations and code samples for each of these steps. ## Working with Video and Audio Codecs ### Retrieving Available Codecs Before capturing video, you'll need to populate your application with the available video and audio codecs. The TVFVideoCapture component makes this straightforward: ``` procedure TMyForm.PopulateCodecLists; var I: Integer; begin // Clear existing items cbVideoCodecs.Items.Clear; cbAudioCodecs.Items.Clear; // Populate video codecs for I := 0 to VideoCapture1.Video_Codecs_GetCount - 1 do cbVideoCodecs.Items.Add(VideoCapture1.Video_Codecs_GetItem(i)); // Populate audio codecs for I := 0 to VideoCapture1.Audio_Codecs_GetCount - 1 do cbAudioCodecs.Items.Add(VideoCapture1.Audio_Codecs_GetItem(i)); end; ``` For developers using C++ MFC, the equivalent code would be: ``` void CMyDialog::PopulateCodecLists() { // Clear existing items m_VideoCodecsCombo.ResetContent(); m_AudioCodecsCombo.ResetContent(); // Populate video codecs for (int i = 0; i < m_VideoCapture.Video_Codecs_GetCount(); i++) { CString codecName = m_VideoCapture.Video_Codecs_GetItem(i); m_VideoCodecsCombo.AddString(codecName); } // Populate audio codecs for (int i = 0; i < m_VideoCapture.Audio_Codecs_GetCount(); i++) { CString codecName = m_VideoCapture.Audio_Codecs_GetItem(i); m_AudioCodecsCombo.AddString(codecName); } } ``` For VB6 developers, here's how to implement the same functionality: ``` Private Sub PopulateCodecLists() ' Clear existing items cboVideoCodecs.Clear cboAudioCodecs.Clear ' Populate video codecs Dim i As Integer For i = 0 To VideoCapture1.Video_Codecs_GetCount - 1 cboVideoCodecs.AddItem VideoCapture1.Video_Codecs_GetItem(i) Next i ' Populate audio codecs For i = 0 To VideoCapture1.Audio_Codecs_GetCount - 1 cboAudioCodecs.AddItem VideoCapture1.Audio_Codecs_GetItem(i) Next i End Sub ``` ### Selecting Codecs for Capture Once you've populated the lists, you'll need to let users select their preferred codecs and apply those selections to the capture component: ``` procedure TMyForm.ApplyCodecSelections; begin if cbVideoCodecs.ItemIndex >= 0 then VideoCapture1.Video_Codec := cbVideoCodecs.Items[cbVideoCodecs.ItemIndex]; if cbAudioCodecs.ItemIndex >= 0 then VideoCapture1.Audio_Codec := cbAudioCodecs.Items[cbAudioCodecs.ItemIndex]; end; ``` C++ MFC implementation: ``` void CMyDialog::ApplyCodecSelections() { int videoIndex = m_VideoCodecsCombo.GetCurSel(); if (videoIndex >= 0) { CString videoCodec; m_VideoCodecsCombo.GetLBText(videoIndex, videoCodec); m_VideoCapture.Video_Codec = videoCodec; } int audioIndex = m_AudioCodecsCombo.GetCurSel(); if (audioIndex >= 0) { CString audioCodec; m_AudioCodecsCombo.GetLBText(audioIndex, audioCodec); m_VideoCapture.Audio_Codec = audioCodec; } } ``` VB6 implementation: ``` Private Sub ApplyCodecSelections() If cboVideoCodecs.ListIndex >= 0 Then VideoCapture1.Video_Codec = cboVideoCodecs.Text End If If cboAudioCodecs.ListIndex >= 0 Then VideoCapture1.Audio_Codec = cboAudioCodecs.Text End If End Sub ``` ## Configuring Audio Parameters Quality audio capture requires proper configuration of three key parameters: 1. **Audio Channels**: Typically 1 (mono) or 2 (stereo) 2. **Bits Per Sample (BPS)**: Common values include 8, 16, or 24 bits 3. **Sample Rate**: Standard rates include 44100 Hz (CD quality) or 48000 Hz Here's how to apply these settings in Delphi: ``` procedure TMyForm.ConfigureAudioSettings; begin // Apply audio channel configuration (mono/stereo) VideoCapture1.Audio_Channels := StrToInt(cbChannels.Items[cbChannels.ItemIndex]); // Set bits per sample for audio quality VideoCapture1.Audio_BPS := StrToInt(cbBPS.Items[cbBPS.ItemIndex]); // Configure sample rate VideoCapture1.Audio_SampleRate := StrToInt(cbSampleRate.Items[cbSampleRate.ItemIndex]); end; ``` C++ MFC implementation: ``` void CMyDialog::ConfigureAudioSettings() { CString channelStr, bpsStr, sampleRateStr; // Get selected values from combo boxes m_ChannelsCombo.GetLBText(m_ChannelsCombo.GetCurSel(), channelStr); m_BpsCombo.GetLBText(m_BpsCombo.GetCurSel(), bpsStr); m_SampleRateCombo.GetLBText(m_SampleRateCombo.GetCurSel(), sampleRateStr); // Apply audio channel configuration m_VideoCapture.Audio_Channels = _ttoi(channelStr); // Set bits per sample m_VideoCapture.Audio_BPS = _ttoi(bpsStr); // Configure sample rate m_VideoCapture.Audio_SampleRate = _ttoi(sampleRateStr); } ``` VB6 implementation: ``` Private Sub ConfigureAudioSettings() ' Apply audio channel configuration VideoCapture1.Audio_Channels = CInt(cboChannels.Text) ' Set bits per sample VideoCapture1.Audio_BPS = CInt(cboBPS.Text) ' Configure sample rate VideoCapture1.Audio_SampleRate = CInt(cboSampleRate.Text) End Sub ``` ## Configuring Output Format and Capture Mode The next step is to configure the output format as AVI and set the appropriate capture mode: ``` procedure TMyForm.PrepareForCapture; begin // Set AVI as the output format VideoCapture1.OutputFormat := Format_AVI; // Configure video capture mode VideoCapture1.Mode := Mode_Video_Capture; end; ``` C++ MFC implementation: ``` void CMyDialog::PrepareForCapture() { // Set AVI as the output format m_VideoCapture.OutputFormat = Format_AVI; // Configure video capture mode m_VideoCapture.Mode = Mode_Video_Capture; } ``` VB6 implementation: ``` Private Sub PrepareForCapture() ' Set AVI as the output format VideoCapture1.OutputFormat = Format_AVI ' Configure video capture mode VideoCapture1.Mode = Mode_Video_Capture End Sub ``` ## Starting and Managing the Capture Process Once everything is configured, you can start the capture process: ``` procedure TMyForm.StartCapture; begin try // Set output filename VideoCapture1.Output_Filename := ExtractFilePath(Application.ExeName) + 'CapturedVideo.avi'; // Begin capture process VideoCapture1.Start; // Update UI to show capture in progress btnStart.Enabled := False; btnStop.Enabled := True; lblStatus.Caption := 'Recording...'; except on E: Exception do ShowMessage('Error starting capture: ' + E.Message); end; end; ``` C++ MFC implementation: ``` void CMyDialog::StartCapture() { try { TCHAR appPath[MAX_PATH]; GetModuleFileName(NULL, appPath, MAX_PATH); CString appDir = appPath; int pos = appDir.ReverseFind('\\'); if (pos != -1) { appDir = appDir.Left(pos + 1); } // Set output filename m_VideoCapture.Output_Filename = appDir + _T("CapturedVideo.avi"); // Begin capture process m_VideoCapture.Start(); // Update UI GetDlgItem(IDC_START_BUTTON)->EnableWindow(FALSE); GetDlgItem(IDC_STOP_BUTTON)->EnableWindow(TRUE); SetDlgItemText(IDC_STATUS_STATIC, _T("Recording...")); } catch (COleDispatchException* e) { CString errorMsg = _T("Error starting capture: "); errorMsg += e->m_strDescription; MessageBox(errorMsg, _T("Error"), MB_ICONERROR); e->Delete(); } } ``` VB6 implementation: ``` Private Sub StartCapture() On Error GoTo ErrorHandler ' Set output filename VideoCapture1.Output_Filename = App.Path & "\CapturedVideo.avi" ' Begin capture process VideoCapture1.Start ' Update UI btnStart.Enabled = False btnStop.Enabled = True lblStatus.Caption = "Recording..." Exit Sub ErrorHandler: MsgBox "Error starting capture: " & Err.Description, vbExclamation End Sub ``` ## Handling Capture Completion It's important to provide functionality to stop the capture process: ``` procedure TMyForm.StopCapture; begin try // Stop the capture process VideoCapture1.Stop; // Update UI btnStart.Enabled := True; btnStop.Enabled := False; lblStatus.Caption := 'Capture completed'; // Optionally open the captured file if FileExists(VideoCapture1.Output_Filename) and (MessageDlg('Open captured video?', mtConfirmation, [mbYes, mbNo], 0) = mrYes) then ShellExecute(0, 'open', PChar(VideoCapture1.Output_Filename), nil, nil, SW_SHOW); except on E: Exception do ShowMessage('Error stopping capture: ' + E.Message); end; end; ``` C++ MFC implementation: ``` void CMyDialog::StopCapture() { try { // Stop the capture process m_VideoCapture.Stop(); // Update UI GetDlgItem(IDC_START_BUTTON)->EnableWindow(TRUE); GetDlgItem(IDC_STOP_BUTTON)->EnableWindow(FALSE); SetDlgItemText(IDC_STATUS_STATIC, _T("Capture completed")); // Optionally open the captured file CString outputFile = m_VideoCapture.Output_Filename; if (PathFileExists(outputFile) && MessageBox(_T("Open captured video?"), _T("Confirmation"), MB_YESNO | MB_ICONQUESTION) == IDYES) { ShellExecute(NULL, _T("open"), outputFile, NULL, NULL, SW_SHOW); } } catch (COleDispatchException* e) { CString errorMsg = _T("Error stopping capture: "); errorMsg += e->m_strDescription; MessageBox(errorMsg, _T("Error"), MB_ICONERROR); e->Delete(); } } ``` VB6 implementation: ``` Private Sub StopCapture() On Error GoTo ErrorHandler ' Stop the capture process VideoCapture1.Stop ' Update UI btnStart.Enabled = True btnStop.Enabled = False lblStatus.Caption = "Capture completed" ' Optionally open the captured file If Dir(VideoCapture1.Output_Filename) <> "" Then If MsgBox("Open captured video?", vbQuestion + vbYesNo) = vbYes Then Shell "explorer.exe """ & VideoCapture1.Output_Filename & """", vbNormalFocus End If End If Exit Sub ErrorHandler: MsgBox "Error stopping capture: " & Err.Description, vbExclamation End Sub ``` ## Conclusion Implementing video capture to AVI files in Delphi applications using the TVFVideoCapture component is a straightforward process when you understand the key concepts. By following this guide, you can create robust multimedia applications with professional video capture functionality. The TVFVideoCapture component provides a wide range of additional features and customization options beyond what's covered in this guide, including video effects, overlays, and device property configuration. Remember to test your video capture implementation thoroughly with different codecs and audio configurations to ensure the best quality for your specific use case. --- For additional code samples and implementation guidance, visit our GitHub repository. If you need further assistance with this tutorial, our support team is available to help. ---END OF PAGE--- ## DV Video Capture in Delphi — Direct Stream and Recompressed **URL:** https://www.visioforge.com/help/docs/delphi/videocapture/video-capture-dv/ **Description:** Implement DV video capture in Delphi - compressed and uncompressed formats with step-by-step implementation and working code examples. **Tags:** All-in-One Media Framework, Delphi, ActiveX, Windows, VCL, Capture, Streaming # Video Capture to DV File Format: Implementation Guide Digital Video (DV) remains a reliable format for video capture applications, particularly when working with legacy systems or specific professional requirements. This guide explores how to implement DV video capture functionality in your Delphi applications, with additional C++ MFC and VB6 examples for cross-platform reference. ## Understanding DV Format Options DV format offers several advantages for video capture applications: - Consistent quality with minimal generation loss - Efficient storage for professional video content - Support for both PAL and NTSC standards - Compatibility with professional video editing software - Reliable audio synchronization When implementing DV video capture, developers have two primary approaches: 1. **Direct Stream Capture** - Raw DV data without recompression 2. **Recompressed DV** - Processed video with customizable settings Each approach serves different use cases depending on your application requirements. ## Direct Stream Capture Implementation Direct stream capture provides the highest quality by avoiding any recompression of the video signal. This method is ideal for archival purposes and professional video production where maintaining the original signal integrity is crucial. ### Configuring DV Type Settings The first step in implementing direct stream capture is setting the appropriate DV type configuration: #### Delphi ``` VideoCapture1.DV_Capture_Type2 := rbDVType2.Checked; ``` #### C++ MFC ``` m_videoCapture.put_DV_Capture_Type2(m_rbDVType2.GetCheck() == BST_CHECKED); ``` #### VB6 ``` VideoCapture1.DV_Capture_Type2 = rbDVType2.Value ``` The DV Type setting determines the specific format variation used for capture. Most modern applications use Type 2, which offers better compatibility with editing software. ### Setting Output Format for Direct Stream For direct stream capture, you must specify the DirectStream\_DV format: #### Delphi ``` VideoCapture1.OutputFormat := Format_DirectStream_DV; ``` #### C++ MFC ``` m_videoCapture.SetOutputFormat(Format_DirectStream_DV); ``` #### VB6 ``` VideoCapture1.OutputFormat = Format_DirectStream_DV ``` This ensures the video data is stored without additional processing or compression. ### Configuring Capture Mode Next, set the component to video capture mode: #### Delphi ``` VideoCapture1.Mode := Mode_Video_Capture; ``` #### C++ MFC ``` m_videoCapture.SetMode(Mode_Video_Capture); ``` #### VB6 ``` VideoCapture1.Mode = Mode_Video_Capture ``` This prepares the component for continuous video acquisition rather than single-frame capture. ### Initiating Direct Stream Capture With all settings in place, you can begin the capture process: #### Delphi ``` VideoCapture1.Start; ``` #### C++ MFC ``` m_videoCapture.Start(); ``` #### VB6 ``` VideoCapture1.Start ``` The component will now capture the video stream directly to the specified output location in DV format. ## Implementing DV Capture with Recompression In some scenarios, you may need to modify the DV stream during capture. This approach allows for customization of audio parameters and video format standards. ### Configuring Audio Parameters DV format supports multiple audio configurations. Set the channels and sample rate to match your requirements: #### Delphi ``` VideoCapture1.DV_Capture_Audio_Channels := StrToInt(cbDVChannels.Items[cbDVChannels.ItemIndex]); VideoCapture1.DV_Capture_Audio_SampleRate := StrToInt(cbDVSampleRate.Items[cbDVSampleRate.ItemIndex]); ``` #### C++ MFC ``` CString channelStr, sampleRateStr; m_cbDVChannels.GetLBText(m_cbDVChannels.GetCurSel(), channelStr); m_cbDVSampleRate.GetLBText(m_cbDVSampleRate.GetCurSel(), sampleRateStr); m_videoCapture.put_DV_Capture_Audio_Channels(_ttoi(channelStr)); m_videoCapture.put_DV_Capture_Audio_SampleRate(_ttoi(sampleRateStr)); ``` #### VB6 ``` VideoCapture1.DV_Capture_Audio_Channels = CInt(cbDVChannels.List(cbDVChannels.ListIndex)) VideoCapture1.DV_Capture_Audio_SampleRate = CInt(cbDVSampleRate.List(cbDVSampleRate.ListIndex)) ``` Standard DV audio options include: - Channels: 1 (mono) or 2 (stereo) - Sample rates: 32000 Hz, 44100 Hz, or 48000 Hz ### Setting Video Format Standard DV supports both PAL and NTSC standards. Select the appropriate standard for your target region: #### Delphi ``` if rbDVPAL.Checked then VideoCapture1.DV_Capture_Video_Format := DVF_PAL else VideoCapture1.DV_Capture_Video_Format := DVF_NTSC; ``` #### C++ MFC ``` if (m_rbDVPAL.GetCheck() == BST_CHECKED) m_videoCapture.put_DV_Capture_Video_Format(DVF_PAL); else m_videoCapture.put_DV_Capture_Video_Format(DVF_NTSC); ``` #### VB6 ``` If rbDVPAL.Value Then VideoCapture1.DV_Capture_Video_Format = DVF_PAL Else VideoCapture1.DV_Capture_Video_Format = DVF_NTSC End If ``` Remember that: - PAL: 720×576 resolution at 25 fps (used in Europe, Australia, parts of Asia) - NTSC: 720×480 resolution at 29.97 fps (used in North America, Japan, parts of South America) ### DV Type Selection As with direct streaming, specify the DV type for recompressed capture: #### Delphi ``` VideoCapture1.DV_Capture_Type2 := rbDVType2.Checked; ``` #### C++ MFC ``` m_videoCapture.put_DV_Capture_Type2(m_rbDVType2.GetCheck() == BST_CHECKED); ``` #### VB6 ``` VideoCapture1.DV_Capture_Type2 = rbDVType2.Value ``` ### Setting Output Format for Recompression For recompressed DV capture, specify the DV format rather than DirectStream\_DV: #### Delphi ``` VideoCapture1.OutputFormat := Format_DV; VideoCapture1.Mode := Mode_Video_Capture; ``` #### C++ MFC ``` m_videoCapture.SetOutputFormat(Format_DV); m_videoCapture.SetMode(Mode_Video_Capture); ``` #### VB6 ``` VideoCapture1.OutputFormat = Format_DV VideoCapture1.Mode = Mode_Video_Capture ``` This tells the component to process the stream through the DV codec during capture. ### Starting Recompressed Capture With all parameters configured, begin the capture process: #### Delphi ``` VideoCapture1.Start; ``` #### C++ MFC ``` m_videoCapture.Start(); ``` #### VB6 ``` VideoCapture1.Start ``` ## Best Practices for DV Capture Implementation When implementing DV capture in your applications, consider these recommendations: 1. **Pre-allocate sufficient disk space** - DV format requires approximately 13 GB per hour of footage 2. **Implement capture time limits** - DV files have a 4 GB size limit on some file systems 3. **Monitor system resources** - DV capture requires consistent CPU and disk performance 4. **Provide format selection UI** - Let users choose between direct stream and recompressed options 5. **Test with various camera models** - DV implementation can vary between manufacturers ## Error Handling Considerations Robust DV capture implementations should include error handling for these common scenarios: - Device disconnection during capture - Disk space exhaustion - Buffer overrun conditions - Invalid format settings - Codec compatibility issues ## Conclusion Implementing DV video capture in your Delphi, C++ MFC, or VB6 applications provides a solid foundation for professional video acquisition workflows. Whether you choose direct stream capture for maximum quality or recompressed capture for additional flexibility, the DV format offers reliable performance for specialized video applications. By following the implementation examples in this guide, you can integrate professional-grade video capture capabilities into your custom software solutions. --- Need additional assistance with your video capture implementation? Visit our [GitHub](https://github.com/visioforge/) page for more code samples or contact our [support team](https://support.visioforge.com/) for personalized guidance. ---END OF PAGE--- ## Video Capture to WMV Format in Delphi, C++ MFC and VB6 **URL:** https://www.visioforge.com/help/docs/delphi/videocapture/video-capture-wmv/ **Description:** Capture video to WMV format - external profiles, output configuration, and implementation for Delphi, C++ MFC, and VB6 with code examples. **Tags:** All-in-One Media Framework, Delphi, ActiveX, C++, Windows, VCL, Capture, Streaming, Encoding, WMV # Video Capture to Windows Media Video (WMV) Using External Profiles ## Introduction Capturing video to Windows Media Video (WMV) format is a common requirement in many software applications. This guide provides a detailed walkthrough of implementing video capture functionality using external WMV profiles in Delphi, C++ MFC, and VB6 applications. The WMV format remains popular due to its compatibility with Windows platforms and efficient compression algorithms that balance quality and file size. ## Understanding WMV and External Profiles Windows Media Video (WMV) is a compressed video file format developed by Microsoft as part of the Windows Media framework. When capturing video to WMV format, using external profiles allows for greater flexibility and customization of the output. External profiles contain pre-configured settings that define: - Video resolution - Bitrate - Frame rate - Compression quality - Audio settings - Other encoding parameters By leveraging external profiles, developers can quickly implement different quality presets without having to manually configure each parameter in code. ## Implementation Steps ### Step 1: Setting Up Your Environment Before implementing video capture functionality, ensure your development environment is properly configured: 1. Install the necessary video capture component 2. Add the component reference to your project 3. Design your user interface to include: 4. A file selector for choosing the WMV profile 5. Output file location selector 6. Video capture preview window 7. Start/Stop capture controls ### Step 2: Selecting a WMV Profile The first step in the implementation is to specify which WMV profile to use for encoding. This profile contains all the encoding parameters that will be applied to the captured video. > `WMV_Profile_Filename` expects the path to a `.prx` Windows Media profile (the encoding-parameters template) — NOT the path to the captured `.wmv` output file. Set the captured filename via `Output_Filename` (or the project's standard filename property). #### Delphi ``` // Pascal string literals use single quotes. VideoCapture1.WMV_Profile_Filename := 'C:\Profiles\HighQuality.prx'; ``` #### C++ MFC ``` m_videoCapture.SetWMVProfileFilename(_T("C:\\Profiles\\HighQuality.prx")); ``` #### VB6 ``` VideoCapture1.WMV_Profile_Filename = "C:\Profiles\HighQuality.prx" ``` ### Step 3: Configuring the Output Format Once the profile is selected, you need to configure the component to use WMV as the output format. This tells the capture component which encoder to use for processing the video stream. #### Delphi ``` VideoCapture1.OutputFormat := Format_WMV; ``` #### C++ MFC ``` m_videoCapture.SetOutputFormat(FORMAT_WMV); ``` #### VB6 ``` VideoCapture1.OutputFormat = FORMAT_WMV ``` ### Step 4: Setting the Capture Mode The capture component can operate in various modes, so it's important to explicitly set it to video capture mode. #### Delphi ``` VideoCapture1.Mode := Mode_Video_Capture; ``` #### C++ MFC ``` m_videoCapture.SetMode(MODE_VIDEO_CAPTURE); ``` #### VB6 ``` VideoCapture1.Mode = MODE_VIDEO_CAPTURE ``` This ensures that the component is configured for continuous video recording rather than other modes like snapshot capture or streaming. ### Step 5: Starting the Video Capture With all the configuration in place, the final step is to start the actual capture process. #### Delphi ``` VideoCapture1.Start; ``` #### C++ MFC ``` m_videoCapture.Start(); ``` #### VB6 ``` VideoCapture1.Start ``` This command begins the capture process using all the previously configured settings. ## Advanced Configuration Options ### Custom Output File Naming You can implement custom file naming for your captured video files: #### Delphi ``` VideoCapture1.Output_Filename := 'C:\Captures\Video_' + FormatDateTime('yyyymmdd_hhnnss', Now) + '.wmv'; ``` #### C++ MFC ``` CTime currentTime = CTime::GetCurrentTime(); CString fileName; fileName.Format(_T("C:\\Captures\\Video_%04d%02d%02d_%02d%02d%02d.wmv"), currentTime.GetYear(), currentTime.GetMonth(), currentTime.GetDay(), currentTime.GetHour(), currentTime.GetMinute(), currentTime.GetSecond()); m_videoCapture.SetOutputFilename(fileName); ``` #### VB6 ``` VideoCapture1.Output_Filename = "C:\Captures\Video_" & Format(Now, "yyyymmdd_hhnnss") & ".wmv" ``` These examples create a timestamped filename to ensure each captured file has a unique name. When designing your application, consider these best practices: 1. Always verify device availability before attempting capture 2. Provide feedback during long encoding operations 3. Include a preview window so users can see what's being captured 4. Implement a file size monitor for long recordings 5. Test with various WMV profiles to ensure compatibility ## Conclusion Implementing video capture to WMV format using external profiles provides flexibility and control over the capture process. The approach outlined in this guide works effectively in Delphi, C++ MFC, and VB6 development environments, allowing you to integrate professional-grade video capture capabilities into your applications. By using external profiles, you can quickly switch between different quality settings without changing your code, which is ideal for applications that need to adapt to different use cases or hardware capabilities. --- For additional code samples, visit our GitHub repository. If you need technical assistance with implementation, our support team is available to help. ---END OF PAGE--- ## Video Input Crossbar Selection in Delphi Applications **URL:** https://www.visioforge.com/help/docs/delphi/videocapture/video-input-crossbar/ **Description:** Select video input sources in Delphi with crossbar - configure composite, S-Video, HDMI inputs with step-by-step code examples for Delphi. **Tags:** All-in-One Media Framework, Delphi, ActiveX, Windows, VCL, Capture, Decoding, TV Tuner # Selecting Video Input Sources with Crossbar Technology ## Introduction to Video Input Selection When developing applications that capture video from external devices, you'll often need to handle multiple input sources. The crossbar is a crucial component in video capture systems that allows you to route different physical inputs (like composite, S-Video, HDMI) to your application. This guide walks you through the process of detecting, configuring, and selecting video inputs using the crossbar interface in Delphi, C++ MFC, and Visual Basic 6 applications. ## Understanding Crossbar Technology Crossbar technology functions as a routing matrix in video capture devices, enabling the connection between various inputs and outputs. Modern capture cards and TV tuners frequently incorporate crossbar functionality to facilitate switching between different video sources such as: - Composite video inputs - S-Video connections - Component video - HDMI inputs - TV tuner inputs - Digital video interfaces Properly configuring these connections programmatically is essential for applications that need to dynamically switch between different video sources. ## Implementation Steps Overview The implementation process for configuring crossbar connections in your application involves three main steps: 1. Initializing the crossbar interface and verifying its availability 2. Enumerating available video inputs for selection 3. Connecting the selected input to the video decoder output Let's examine each step in detail with sample code for Delphi, C++ MFC, and VB6 environments. ## Detailed Implementation Guide ### Step 1: Initialize the Crossbar Interface Before you can work with input selection, you need to initialize the crossbar interface and verify it's available on the current capture device. #### Delphi Implementation ``` // Initialize the crossbar interface CrossBarFound := VideoCapture1.Video_CaptureDevice_CrossBar_Init; // Check if crossbar functionality is available if CrossBarFound then ShowMessage('Crossbar functionality detected and initialized') else ShowMessage('No crossbar available on this capture device'); ``` #### C++ MFC Implementation ``` // Initialize the crossbar interface BOOL bCrossBarFound = m_videoCapture.Video_CaptureDevice_CrossBar_Init(); // Check if crossbar functionality is available if (bCrossBarFound) { AfxMessageBox(_T("Crossbar functionality detected and initialized")); } else { AfxMessageBox(_T("No crossbar available on this capture device")); } ``` #### VB6 Implementation ``` ' Initialize the crossbar interface Dim CrossBarFound As Boolean CrossBarFound = VideoCapture1.Video_CaptureDevice_CrossBar_Init() ' Check if crossbar functionality is available If CrossBarFound Then MsgBox "Crossbar functionality detected and initialized" Else MsgBox "No crossbar available on this capture device" End If ``` The initialization function returns a boolean value indicating whether the crossbar functionality is available on the current capture device. Not all capture devices support crossbar functionality, so this check is crucial. ### Step 2: Enumerate Available Video Inputs Once you've confirmed that the crossbar is available, the next step is to retrieve a list of available inputs for the "Video Decoder" output. This allows users to select from available physical connections. #### Delphi Implementation ``` // Variables declared at the procedure level so the snippet compiles on any Delphi 6+ IDE // (inline `var name: T := ...` requires Delphi 10.3 Rio or later). procedure TForm1.PopulateCrossBarInputs; var inputCount: Integer; inputName: String; i: Integer; begin // Clear any existing connections and UI elements VideoCapture1.Video_CaptureDevice_CrossBar_ClearConnections; cbCrossbarVideoInput.Clear; // Get count of available inputs for the "Video Decoder" output inputCount := VideoCapture1.Video_CaptureDevice_CrossBar_GetInputsForOutput_GetCount('Video Decoder'); // Populate UI with available inputs for i := 0 to inputCount - 1 do begin inputName := VideoCapture1.Video_CaptureDevice_CrossBar_GetInputsForOutput_GetItem('Video Decoder', i); cbCrossbarVideoInput.Items.Add(inputName); end; // Select the first item by default if available if cbCrossbarVideoInput.Items.Count > 0 then cbCrossbarVideoInput.ItemIndex := 0; end; ``` #### C++ MFC Implementation ``` // Clear any existing connections and UI elements m_videoCapture.Video_CaptureDevice_CrossBar_ClearConnections(); m_comboVideoInputs.ResetContent(); // Get count of available inputs for the "Video Decoder" output int inputCount = m_videoCapture.Video_CaptureDevice_CrossBar_GetInputsForOutput_GetCount(_T("Video Decoder")); // Populate UI with available inputs for (int i = 0; i < inputCount; i++) { CString inputName = m_videoCapture.Video_CaptureDevice_CrossBar_GetInputsForOutput_GetItem(_T("Video Decoder"), i); m_comboVideoInputs.AddString(inputName); } // Select the first item by default if available if (m_comboVideoInputs.GetCount() > 0) { m_comboVideoInputs.SetCurSel(0); } ``` #### VB6 Implementation ``` ' Clear any existing connections and UI elements VideoCapture1.Video_CaptureDevice_CrossBar_ClearConnections cboVideoInputs.Clear ' Get count of available inputs for the "Video Decoder" output Dim inputCount As Integer inputCount = VideoCapture1.Video_CaptureDevice_CrossBar_GetInputsForOutput_GetCount("Video Decoder") ' Populate UI with available inputs Dim i As Integer Dim inputName As String For i = 0 To inputCount - 1 inputName = VideoCapture1.Video_CaptureDevice_CrossBar_GetInputsForOutput_GetItem("Video Decoder", i) cboVideoInputs.AddItem inputName Next i ' Select the first item by default if available If cboVideoInputs.ListCount > 0 Then cboVideoInputs.ListIndex = 0 End If ``` Common input types you might encounter include: - Composite - S-Video - HDMI - Component - TV Tuner The exact list depends on your specific capture hardware capabilities. ### Step 3: Apply the Selected Input After the user selects their desired input source, you need to apply this selection by establishing a connection between the selected input and the video decoder output. #### Delphi Implementation ``` // Variables at procedure level — compatible with Delphi 6+ (avoids the inline `var` // shorthand introduced in Delphi 10.3 Rio). procedure TForm1.ApplySelectedCrossBarInput; var selectedInput: String; success: Boolean; begin // First clear any existing connections VideoCapture1.Video_CaptureDevice_CrossBar_ClearConnections; // Connect the selected input to the "Video Decoder" output // Parameters: input name, output name, automatic signal routing if cbCrossbarVideoInput.ItemIndex >= 0 then begin selectedInput := cbCrossbarVideoInput.Items[cbCrossbarVideoInput.ItemIndex]; success := VideoCapture1.Video_CaptureDevice_CrossBar_Connect(selectedInput, 'Video Decoder', true); if success then ShowMessage('Successfully connected ' + selectedInput + ' to Video Decoder') else ShowMessage('Failed to establish connection'); end; end; ``` #### C++ MFC Implementation ``` // First clear any existing connections m_videoCapture.Video_CaptureDevice_CrossBar_ClearConnections(); // Connect the selected input to the "Video Decoder" output // Parameters: input name, output name, automatic signal routing int selectedIndex = m_comboVideoInputs.GetCurSel(); if (selectedIndex >= 0) { CString selectedInput; m_comboVideoInputs.GetLBText(selectedIndex, selectedInput); BOOL success = m_videoCapture.Video_CaptureDevice_CrossBar_Connect( selectedInput, _T("Video Decoder"), TRUE); if (success) { CString msg; msg.Format(_T("Successfully connected %s to Video Decoder"), selectedInput); AfxMessageBox(msg); } else { AfxMessageBox(_T("Failed to establish connection")); } } ``` #### VB6 Implementation ``` ' First clear any existing connections VideoCapture1.Video_CaptureDevice_CrossBar_ClearConnections ' Connect the selected input to the "Video Decoder" output ' Parameters: input name, output name, automatic signal routing If cboVideoInputs.ListIndex >= 0 Then Dim selectedInput As String selectedInput = cboVideoInputs.Text Dim success As Boolean success = VideoCapture1.Video_CaptureDevice_CrossBar_Connect(selectedInput, "Video Decoder", True) If success Then MsgBox "Successfully connected " & selectedInput & " to Video Decoder" Else MsgBox "Failed to establish connection" End If End If ``` The third parameter (`true`) enables automatic signal routing, which helps handle complex connection scenarios where intermediate routing might be required. ## Best Practices for Crossbar Implementation For robust video input selection in your applications: 1. **Always initialize the crossbar first**: Check for availability before attempting operations 2. **Clear existing connections**: Before setting a new connection, clear any existing ones 3. **Handle missing crossbar gracefully**: Provide fallback options when crossbar functionality isn't available 4. **Validate selections**: Ensure a valid input is selected before attempting to establish connections 5. **Provide user feedback**: Inform users about successful or failed connection attempts ## Troubleshooting Common Issues If you encounter problems with crossbar connections: - Verify your capture device supports crossbar functionality - Check that input and output names match exactly what the device reports - Ensure proper device driver installation - Use debug logging to track connection attempts - Test with different input sources to isolate hardware-specific issues ## Conclusion Proper implementation of crossbar technology in your video capture applications gives users the flexibility to work with multiple input sources. By following the steps outlined in this guide, you can create a robust and user-friendly video input selection system for your applications regardless of whether you're developing in Delphi, C++ MFC, or Visual Basic 6. The code samples provided demonstrate how to initialize the crossbar, enumerate available inputs, and connect selected inputs to the video decoder output. With these fundamentals in place, you can build sophisticated video capture applications that support a wide range of input devices and connection types. --- For additional assistance with implementing this functionality, explore our other documentation pages and code samples repository for more advanced techniques and solutions. ---END OF PAGE--- ## Video Renderer Selection in Delphi — EVR, VMR9, and GDI **URL:** https://www.visioforge.com/help/docs/delphi/videocapture/video-renderer/ **Description:** Select optimal video renderers in Delphi - Video Renderer, VMR9, EVR with code examples for performance and hardware acceleration on Windows. **Tags:** All-in-One Media Framework, Delphi, ActiveX, Windows, VCL, Capture **API:** TVFVideoCapture # Video Renderer Selection Guide for TVFVideoCapture ## Overview of Available Renderers When developing video capture applications with TVFVideoCapture, selecting the appropriate video renderer significantly impacts performance and compatibility. This guide provides detailed implementation examples for the three available renderer options in Delphi, C++, and VB6 environments. ## Standard Video Renderer The standard Video Renderer utilizes GDI for drawing operations. This renderer option is primarily recommended for: - Legacy systems - Environments where Direct3D acceleration is unavailable - Maximum compatibility with older hardware ``` // Delphi VideoCapture1.Video_Renderer := VR_VideoRenderer; ``` ``` // C++ MFC m_VideoCapture.SetVideo_Renderer(VR_VideoRenderer); ``` ``` ' VB6 VideoCapture1.Video_Renderer = VR_VideoRenderer ``` ## Video Mixing Renderer 9 (VMR9) VMR9 represents a modern filtering solution capable of leveraging GPU capabilities for enhanced rendering. Key advantages include: - Hardware-accelerated video processing - Advanced deinterlacing options - Improved performance for high-resolution content ``` // Delphi VideoCapture1.Video_Renderer := VR_VMR9; ``` ``` // C++ MFC m_VideoCapture.SetVideo_Renderer(VR_VMR9); ``` ``` ' VB6 VideoCapture1.Video_Renderer = VR_VMR9 ``` ### Accessing Deinterlacing Modes VMR9 supports multiple deinterlacing techniques. The following code demonstrates how to retrieve available deinterlacing options: ``` // Delphi VideoCapture1.Video_Renderer_Deinterlace_Modes_Fill; for I := 0 to VideoCapture1.Video_Renderer_Deinterlace_Modes_GetCount - 1 do cbDeinterlaceModes.Items.Add(VideoCapture1.Video_Renderer_Deinterlace_Modes_GetItem(i)); ``` ``` // C++ MFC m_VideoCapture.Video_Renderer_Deinterlace_Modes_Fill(); for (int i = 0; i < m_VideoCapture.Video_Renderer_Deinterlace_Modes_GetCount(); i++) { m_DeinterlaceCombo.AddString(m_VideoCapture.Video_Renderer_Deinterlace_Modes_GetItem(i)); } ``` ``` ' VB6 VideoCapture1.Video_Renderer_Deinterlace_Modes_Fill For i = 0 To VideoCapture1.Video_Renderer_Deinterlace_Modes_GetCount - 1 cboDeinterlaceModes.AddItem VideoCapture1.Video_Renderer_Deinterlace_Modes_GetItem(i) Next i ``` ## Enhanced Video Renderer (EVR) EVR is the recommended renderer for modern Windows environments (Vista and later). This advanced renderer provides: - Superior video acceleration capabilities - Optimal performance on Windows 7/10/11 - Better resource utilization ``` // Delphi VideoCapture1.Video_Renderer := VR_EVR; ``` ``` // C++ MFC m_VideoCapture.SetVideo_Renderer(VR_EVR); ``` ``` ' VB6 VideoCapture1.Video_Renderer = VR_EVR ``` ## Managing Aspect Ratio and Display Options When displaying video content, you'll often need to handle aspect ratio differences between the source video and the display area. ### Stretching the Video Image To stretch the video to fill the entire display area: ``` // Delphi VideoCapture1.Screen_Stretch := true; VideoCapture1.Screen_Update; ``` ``` // C++ MFC m_VideoCapture.SetScreen_Stretch(true); m_VideoCapture.Screen_Update(); ``` ``` ' VB6 VideoCapture1.Screen_Stretch = True VideoCapture1.Screen_Update ``` ### Using Letterbox Mode (Black Borders) For preserving the original aspect ratio with black borders: ``` // Delphi VideoCapture1.Screen_Stretch := false; VideoCapture1.Screen_Update; ``` ``` // C++ MFC m_VideoCapture.SetScreen_Stretch(false); m_VideoCapture.Screen_Update(); ``` ``` ' VB6 VideoCapture1.Screen_Stretch = False VideoCapture1.Screen_Update ``` ## Performance Considerations When selecting a renderer for your application, consider these factors: 1. Target operating system version 2. Hardware capabilities of end-user systems 3. Video resolution and processing requirements 4. Compatibility needs for your deployment environment --- Please get in touch with [support](https://support.visioforge.com/) if you need technical assistance with this implementation. Visit our [GitHub](https://github.com/visioforge/) repository for additional code samples and resources. ---END OF PAGE--- ## TVFVideoEdit Changelog - Delphi Video Editing SDK Updates **URL:** https://www.visioforge.com/help/docs/delphi/videoedit/changelog/ **Description:** TVFVideoEdit version history from 2.1 to 10.0 with features, bug fixes, FFMPEG integration, Windows 8 support, and video effects updates. **Tags:** All-in-One Media Framework, Delphi, ActiveX, Windows, VCL, Streaming, Editing **API:** TVFVideoEdit # TVFVideoEdit Library: Complete Version History ## Version 10.0 - Latest Release ### Core Improvements - **Enhanced Media Compatibility**: Added dedicated MP3 splitter component to resolve playback issues with problematic MP3 files that fail with the default splitter - **Audio Processing Enhancements**: Significantly improved information extraction and metadata reading for Speex audio files - **Performance Optimization**: Fixed critical memory leak in FFMPEG source implementation for better resource management - **Expanded Format Support**: YUV2RGB filter now fully supports HDYC format for professional video workflows ## Version 8.7 - Engine Updates ### Technical Enhancements - **VLC Integration**: Updated VLC engine to latest stable release (libVLC 2.2.1.0) for improved codec support - **Decoding Capabilities**: Implemented latest FFMPEG engine version with expanded format compatibility ## Version 8.6 - Stability Improvements ### Bug Fixes & Additions - **Memory Management**: Resolved critical memory leak affecting long-running applications - **File Handling**: Fixed issues with incorrectly closed input and output files that caused resource locking - **WebM Support**: Added new high-performance WebM filters based on the official WebM project specifications ## Version 8.4 - Platform Expansion ### Development Environment Support - **Modern Delphi**: Added full Delphi XE8 integration and compatibility - **Architecture Expansion**: Introduced both Delphi and ActiveX 64-bit (x64) implementations ## Version 8.3.1 - Compatibility Update ### Development Tools - **IDE Support**: Added complete Delphi XE7 compatibility and integration ## Version 8.3 - Performance Release ### Core Improvements - **Decoder Update**: Substantially improved FFMPEG decoder implementation - **Stability**: Fixed multiple bugs affecting reliability and performance ## Version 8.0 - Major Engine Upgrade ### Key Features - **Playback Architecture**: Implemented VLC engine for enhanced video/audio file playback capabilities - **Reliability**: Resolved several critical bugs affecting performance ## Version 7.15 - Security Features ### Media Protection - **Content Security**: Added encrypted video file playback functionality - **Stability**: Implemented minor bug fixes for improved reliability ## Version 7.2 - Effects & Performance ### Visual Enhancements - **FFMPEG Implementation**: Updated FFMPEG decoder for better format support - **Video Effects**: Added professional pan/zoom video effect capabilities - **Reliability**: Fixed minor bugs for improved stability ## Version 7.0 - Windows 8 & FFMPEG ### Platform Support - **Operating System**: Added full Windows 8 RTM support - **Media Handling**: Integrated comprehensive FFMPEG decoding capabilities - **Visual Effects**: Substantially improved video effects processing quality ## Version 6.0 - Windows 8 Preview ### Platform Expansion - **Early Adoption**: Added Windows 8 Developer Preview compatibility - **Visual Processing**: Enhanced quality and performance of video effects ## Version 3.4 - Maintenance Release ### Stability Improvements - **Bug Fixes**: Resolved multiple issues affecting reliability ## Version 3.3 - Delphi XE2 Support ### Developer Tools - **IDE Compatibility**: Added full Delphi XE2 support and integration - **Stability**: Implemented various bug fixes for improved reliability ## Version 3.2 - Effects & Demos ### Enhanced Capabilities - **Visual Effects**: Significantly improved video effects processing - **Developer Resources**: Added additional demo applications for easier implementation ## Version 3.1 - Effects Upgrade ### Visual Processing - **Effects Engine**: Enhanced video effects processing capabilities - **Stability**: Fixed multiple bugs for improved reliability ## Version 3.0 - Feature Expansion ### Major Enhancements - **Effects System**: Substantially improved effects filter functionality - **Streaming**: Added MMS / WMV stream playback support - **Video Analysis**: Implemented motion detection capabilities - **Compositing**: Added professional chroma-key functionality - **Core Performance**: Significantly improved underlying engine ## Version 2.2 - Effects Update ### Visual Processing - **Effects Quality**: Enhanced effects filter implementation for better visual results ## Version 2.1 - Initial Effects ### First Implementations - **Visual Processing**: Introduced initial effects filter capabilities ---END OF PAGE--- ## Deploy TVFVideoEdit in Delphi and ActiveX Applications **URL:** https://www.visioforge.com/help/docs/delphi/videoedit/deployment/ **Description:** Deploy TVFVideoEdit in Delphi and ActiveX applications with automatic installers or manual setup for required components and dependencies. **Tags:** All-in-One Media Framework, Delphi, ActiveX, DirectShow, Windows, VCL, Encoding, Editing, IP Camera, MP4, WebM, H.264, AAC **API:** TVFVideoEdit # TVFVideoEdit Library Deployment Guide ## Introduction The TVFVideoEdit library provides powerful video editing capabilities for your Delphi and ActiveX applications. This guide explains how to properly deploy all necessary components to ensure your application functions correctly on end-user systems without requiring the full development framework. ## Deployment Options You have two primary methods for deploying the TVFVideoEdit library components: automatic installers or manual installation. Each approach has specific advantages depending on your distribution requirements. ### Automatic Silent Installers For streamlined deployment, we offer silent installer packages that handle all necessary component installation without user interaction: #### Required Base Package - **Base components** (always required): - [Delphi version](https://files.visioforge.com/redists_delphi/redist_video_edit_base_delphi.exe) - [ActiveX version](https://files.visioforge.com/redists_delphi/redist_video_edit_base_ax.exe) #### Optional Feature Packages - **FFMPEG package** (required for file and IP camera support (only for FFMPEG source engine)): - [x86 architecture](https://files.visioforge.com/redists_delphi/redist_video_edit_ffmpeg.exe) - **MP4 output package** (for MP4 video creation): - [x86 architecture](https://files.visioforge.com/redists_delphi/redist_video_edit_mp4.exe) ### Manual Installation Process For situations where you need precise control over component deployment, follow these detailed steps: 1. **Install Visual C++ Dependencies** 2. Install VC++ 2010 SP1 redistributable: - [x86 version](https://files.visioforge.com/shared/vcredist_2010_x86.exe) - [x64 version](https://files.visioforge.com/shared/vcredist_2010_x64.exe) 3. **Deploy Core Media Foundation Components** 4. Copy all MFP DLLs from the `Redist\Filters` directory to your application folder 5. **Register DirectShow Filters** 6. Copy and COM-register these essential DirectShow filters using [regsvr32.exe](https://support.microsoft.com/en-us/topic/how-to-use-the-regsvr32-tool-and-troubleshoot-regsvr32-error-messages-a98d960a-7392-e6fe-d90a-3f4e0cb543e5). 7. **Bitness:** the bare filename is the **x86 (32-bit)** filter; the matching **x64 (64-bit)** filter has the `_x64` suffix (for example `VisioForge_Video_Effects_Pro_x64.ax`). Both ship in the redistributable; deploy and register the variant that matches your application's target architecture. 64-bit applications must register the `_x64` variants. - `VisioForge_Audio_Effects_4.ax` - `VisioForge_Dump.ax` - `VisioForge_RGB2YUV.ax` - `VisioForge_Video_Effects_Pro.ax` - `VisioForge_Video_Mixer.ax` - `VisioForge_Video_Resize.ax` - `VisioForge_WavDest.ax` - `VisioForge_YUV2RGB.ax` - `VisioForge_FFMPEG_Source.ax` Screen-capture functionality (formerly delivered as `VisioForge_Screen_Capture.ax`) is now part of the base filters and does not require a separate registration step. 1. **Configure Path Settings** 2. Add the folder containing these filters to the system environment variable `PATH` if your application executable resides in a different directory ## Additional Components Installation ### FFMPEG Integration To enable advanced media format support: - Copy all files from the `Redist\FFMPEG` folder - Add this folder to the Windows system `PATH` variable - Register all .ax files from the `Redist\FFMPEG` folder ### VLC Support For extended format compatibility: - Copy all files from the `Redist\VLC` folder - COM-register the .ax file using regsvr32.exe - Create an environment variable named `VLC_PLUGIN_PATH` - Set its value to point to the `VLC\plugins` folder ### Audio Output Support For MP3 encoding capabilities: - Copy the lame.ax file from the `Redist\Formats` folder - Register the lame.ax file using regsvr32.exe ### WebM Format Support For WebM encoding and decoding: - Install the necessary free codecs available from the [xiph.org website](https://www.xiph.org/dshow/) ### Matroska Container Support For MKV format compatibility: - Install [Haali Matroska Splitter](https://haali.net/mkv/) for proper encoding and decoding ### MP4 H264/AAC Output - Modern Encoder For high-quality MP4 creation with modern codecs: - Copy `libmfxsw32.dll` / `libmfxsw64.dll` files - Register these DirectShow filters: - `VisioForge_H264_Encoder.ax` - `VisioForge_MP4_Muxer.ax` - `VisioForge_AAC_Encoder.ax` - `VisioForge_Video_Resize.ax` ### MP4 H264/AAC Output - Legacy Encoder For compatibility with older systems: - Copy `libmfxxp32.dll` / `libmfxxp64.dll` files - Register these DirectShow filters: - `VisioForge_H264_Encoder_XP.ax` - `VisioForge_MP4_Muxer_XP.ax` - `VisioForge_AAC_Encoder_XP.ax` - `VisioForge_Video_Resize.ax` ## Bulk Registration Utility To simplify the registration process for multiple DirectShow filters: - Place the `reg_special.exe` utility from the redistributable package into the folder containing your filters - Run it with administrator privileges to register all compatible filters in that directory ## Troubleshooting Tips Common issues during deployment often include: - Missing dependencies - Incorrect registration of COM components - Path configuration problems - Insufficient user permissions Ensure all required files are properly deployed and registered before launching your application. --- Please contact [our support team](https://support.visioforge.com/) if you encounter any issues with this deployment process. Visit our [GitHub repository](https://github.com/visioforge/) for additional code samples and implementation examples. ---END OF PAGE--- ## TVFVideoEdit - Video Editing SDK for Delphi and ActiveX **URL:** https://www.visioforge.com/help/docs/delphi/videoedit/ **Description:** Build video editing software in Delphi with TVFVideoEdit - supporting multiple formats, effects, transitions, timeline editing, and encryption. **Tags:** All-in-One Media Framework, Delphi, ActiveX, Windows, VCL, Editing **API:** TVFVideoEdit # TVFVideoEdit for Delphi / ActiveX Development ## Introduction to TVFVideoEdit The TVFVideoEdit library empowers Delphi developers to integrate sophisticated video editing functionality into their applications. This robust SDK provides a complete framework for handling diverse media operations while maintaining excellent performance and stability across projects of varying complexity. ## Core Capabilities ### Format Support TVFVideoEdit accommodates a wide array of video and audio formats, enabling seamless work with most industry-standard media types. This extensive compatibility ensures your application can process virtually any file users might import. ### Video Processing The library excels in fundamental video manipulation tasks, offering precise control over: - Resolution adjustment - Frame rate conversion - Aspect ratio modification - Color correction tools - Quality enhancement algorithms ### Effects and Transitions Enhance your application with: - Professional visual effects - Smooth transitions between clips - Custom animation capabilities - Real-time preview functionality - Text overlay with font control - Image compositing - Watermarking capabilities - Custom graphic insertion #### Audio Processing Create complete multimedia solutions with: - Volume normalization - Equalization tools - Audio effects application - Voice enhancement options ## Technical Advantages ### Output Flexibility Export finished projects in multiple formats with customizable quality settings to meet specific distribution requirements. ### Timeline Precision The timeline-based editing framework gives developers granular control over media positioning, transitions, and effects timing. ### Multi-Platform Compatibility Deploy your video editing solutions across different Windows environments with consistent performance and reliability. ### Distribution Rights TVFVideoEdit supports royalty-free distribution, making it a cost-effective solution for commercial software development. ## Resources for Developers Accelerate your development with these valuable resources: - [Product Information](https://www.visioforge.com/all-in-one-media-framework) - [API Documentation](https://api.visioforge.org/delphi/video_edit_sdk/index.html) - [Changelog](changelog/) - [Installation Guide](install/) - [Deployment Instructions](deployment/) - [License Agreement](../../eula/) ---END OF PAGE--- ## Install TVFVideoEdit ActiveX Control in C++ Builder **URL:** https://www.visioforge.com/help/docs/delphi/videoedit/install/builder/ **Description:** Import and configure TVFVideoEdit ActiveX components in C++ Builder 5/6, 2006, and newer versions with package and control setup. **Tags:** All-in-One Media Framework, Delphi, ActiveX, Windows, VCL, Editing **API:** TVFVideoEdit # Complete Guide to TVFVideoEdit Installation in C++ Builder > Related products: [VisioForge All-in-One Media Framework (Delphi / ActiveX)](https://www.visioforge.com/all-in-one-media-framework) ## Introduction to TVFVideoEdit for C++ Builder The TVFVideoEdit library provides powerful media processing capabilities for C++ Builder applications. This guide walks you through the installation process across different C++ Builder versions. Before you begin development, you'll need to properly install the ActiveX control into your IDE environment where it will be accessible through the component palette. ## Installation Process for Borland C++ Builder 5/6 ### Accessing the Import Menu Begin the installation process by navigating to the Component menu in your IDE: 1. Launch your Borland C++ Builder 5/6 environment 2. From the main menu, select **Component -> Import ActiveX Controls** ### Selecting the Video Edit Control In the Import ActiveX Control dialog: 1. Locate and select the **"VisioForge Video Edit Control"** from the available controls list 2. Click the **Install** button to begin the import process ### Confirming Installation The system will prompt you to confirm the installation: 1. A confirmation dialog will appear 2. Click the **Yes** button to proceed with the installation ### Verifying Successful Installation After installation completes: 1. The control will be added to your component palette 2. You can now use it in your C++ Builder projects ## Installation Guide for C++ Builder 2006 and Later Versions Modern versions of C++ Builder require a different installation approach using packages. ### Creating a New Package First, you'll need to create a package for the component: 1. Open C++ Builder 2006 or later 2. Select **File -> New -> Package** 3. This will create the foundation for adding the ActiveX control ### Importing the ActiveX Component Next, import the ActiveX control into your environment: 1. Navigate to **Component → Import Component** in the main menu 2. This opens the import wizard for adding new components ### Selecting Import Type In the import wizard: 1. Select the **Import ActiveX Control** radio button option 2. Click the **Next** button to proceed to component selection ### Choosing the Video Edit Control From the available ActiveX controls: 1. Find and select the **"VisioForge Video Edit Control"** from the list 2. Click **Next** to continue with the import process ### Configuring Output Location Specify where the component files should be stored: 1. Choose an appropriate package output folder for your development environment 2. Click **Next** to proceed with configuration ### Finalizing Component Import Complete the import process: 1. Select the **Add unit to…** radio button option 2. Click the **Finish** button to create the component wrapper ### Saving the Package Project After import completion: 1. The system will prompt you to save your package project 2. Choose an appropriate location and name for your package files ### Installing the Component Package To make the component available in the IDE: 1. Right-click on the package in the Project Manager 2. Select **Install** from the context menu 3. This compiles and registers the package with the IDE ### Verification and Usage Once installed: 1. The TVFVideoEdit control appears in your component palette 2. It's now ready to use in your C++ Builder applications 3. You can drag and drop it onto forms just like native components ## Additional Resources and Support ### Getting Help with Implementation If you encounter any issues during installation or implementation: 1. Our technical support team is available to assist 2. Contact [support](https://support.visioforge.com/) with specific questions 3. Provide details about your Builder version and installation environment ### Code Examples and Documentation To accelerate your development process: 1. Visit our [GitHub repository](https://github.com/visioforge/) for code samples 2. Find implementation examples for common media processing tasks 3. Access additional documentation on component features and usage ## Troubleshooting Common Installation Issues When installing the TVFVideoEdit component, developers may encounter several common issues: 1. **Missing Dependencies**: Ensure all required dependencies are installed 2. **Registration Problems**: Verify ActiveX registration status in Windows registry 3. **IDE Compatibility**: Check compatibility between component and Builder version 4. **Package Conflicts**: Resolve any conflicts with existing packages By following this detailed guide, you'll have TVFVideoEdit successfully integrated into your C++ Builder environment and ready for implementing advanced media functionality in your applications. ---END OF PAGE--- ## Install TVFVideoEdit in Delphi - Setup and Configuration **URL:** https://www.visioforge.com/help/docs/delphi/videoedit/install/delphi/ **Description:** Install TVFVideoEdit packages in Delphi 6/7, 2005+, and 11+ with library paths, package building, and troubleshooting configuration. **Tags:** All-in-One Media Framework, Delphi, ActiveX, Windows, VCL, Editing **API:** TVFVideoEdit # Install TVFVideoEdit in Delphi > Related products: [VisioForge All-in-One Media Framework (Delphi / ActiveX)](https://www.visioforge.com/all-in-one-media-framework) ## Installation Requirements Before beginning the installation process, ensure that you have: 1. Appropriate Delphi version installed and properly configured 2. Administrative rights for package installation 3. Downloaded the latest version of the TVFVideoEdit library ## Installing in Borland Delphi 6/7 ### Step 1: Configure Library Paths Begin by opening the "Options" window in your Delphi IDE. Navigate to the Library section and add the package folder (`Video Edit\Packages\Delphi `, which holds the precompiled `.dcu` units) to both the library and browsing paths. This ensures that Delphi can locate the necessary files. ### Step 2: Open and Install the Package Locate and open the main package file from the library. Install the package by clicking the Install button in the IDE. This registers the components with Delphi's component palette. ### Architecture Considerations The library includes both x86 and x64 architecture versions. However, for Delphi 6/7, you must use the x86 version as these Delphi versions do not support 64-bit development. ## Installing in Delphi 2005 and Later ### Step 1: Launch with Administrative Privileges For Delphi 2005 and later versions, launch the IDE with administrative rights to ensure proper installation permissions. ### Step 2: Configure Library Paths Open the Options window and navigate to the Library section. Add the package folder (`Video Edit\Packages\Delphi `, which holds the precompiled `.dcu` units) to both the library and browsing paths. ### Step 3: Install the Package Open the main package file `VisioForge_Video_Edit_Package.dpk` from the `Video Edit\Packages\Delphi ` folder. Click the Install button to register the components with Delphi's component palette. ### Architecture Support For Delphi 2005 and later versions, both x86 and x64 versions are available. You can utilize the 64-bit version if you need to develop 64-bit applications. Note that the IDE itself may require the x86 version for design-time operations. ## Installing in Delphi 11 and Later Modern Delphi versions feature a streamlined installation process: 1. Open the `VisioForge_Video_Edit_Package.dproj` package project located in the `Video Edit\Packages\Delphi ` folder after installation 2. Select the Release build configuration from the dropdown menu 3. Build and install the package using the IDE's build commands 4. The components will be registered and ready to use ## Project Configuration Best Practices You can install both x86 and x64 packages based on your project requirements. Ensure you've properly configured your application's library path settings: 1. Add the correct library folder path to your project options 2. Configure the path to properly locate `.dcu` files 3. Verify architecture compatibility between your project and the installed packages ## Troubleshooting Common Installation Issues If you encounter problems during installation, check these common issues: ### Delphi 64-bit Package Installation Problems Some specific issues can occur when installing 64-bit packages. See our [detailed troubleshooting guide](../../../general/install-64bit/) for solutions. ### Issues with .otares Files Installation problems related to `.otares` files are documented in our [dedicated troubleshooting page](../../../general/install-otares/). ## Additional Resources and Support For additional code examples and implementations, visit our [GitHub repository](https://github.com/visioforge/) where we maintain a collection of sample projects. If you need personalized assistance with installation or implementation, please contact our [technical support team](https://support.visioforge.com/) who can provide guidance specific to your development environment. --- For technical questions or installation assistance with this library, please reach out to our [development support team](https://support.visioforge.com/). Browse additional code samples and resources on our [GitHub](https://github.com/visioforge/) page. ---END OF PAGE--- ## Install TVFVideoEdit in Delphi, VB6, and C++ Builder **URL:** https://www.visioforge.com/help/docs/delphi/videoedit/install/ **Description:** Install TVFVideoEdit library in Delphi and ActiveX-compatible IDEs including MFC, VB6, and C++ Builder with package and control setup. **Tags:** All-in-One Media Framework, Delphi, ActiveX, Windows, VCL, Editing **API:** TVFVideoEdit # TVFVideoEdit library installation guide The library is available as a Delphi package exclusively for Delphi developers, offering tailored functionality and integration. Additionally, the ActiveX control version is versatile and can be used in MFC, VB6, or any other ActiveX-compatible IDEs, providing broad compatibility and flexibility for developers across different platforms. This ensures a robust and adaptable development experience regardless of your preferred environment. ## Installation 1. **Download the latest version of the All-in-One Media Framework**: Visit the [product page](https://www.visioforge.com/all-in-one-media-framework) and download the most recent version of the framework that is suitable for your needs. 2. **Run the setup file**: Once the download is complete, locate the setup file in your download directory and run it. This will start the installation process. 3. **Follow the installation wizard instructions**: The installation wizard will guide you through each step of the process. Carefully read and follow the prompts, accept the license agreement, select the installation directory, and continue by clicking the "Next" button. 4. **Completion**: After the installation is complete, navigate to the installation folder. Here, you will find various library samples and comprehensive documentation designed to assist you in getting started with integrating the library into your projects. ### Delphi packages installation For detailed instructions on installing the TVFVideoEdit packages in your Delphi IDE, please refer to the following [Delphi installation guide](delphi/). ### ActiveX installation #### C++ Builder For [C++ Builder](builder/), the installation process involves importing the ActiveX control into your project. This straightforward process ensures that you can quickly start using the TVFVideoEdit library in your C++ Builder projects. #### Visual Basic 6 In [Visual Basic 6](visual-basic-6/), open your project and go to the "Project" menu. Select "Components" item, then click "Browse" and find `VisioForge_Video_Edit.ocx` in the `Redist` folder of the installation. Add it to your project to make the components available in your toolbox. #### Visual Studio 2010 and later For [Visual Studio 2010 and newer](visual-studio/) versions, open your project in the IDE, right-click on the toolbox, and select "Choose Items". Navigate to the COM components tab, click "Browse", and select `VisioForge_Video_Edit.ocx` from the `Redist` folder (or `Redist\x64` for 64-bit) of the framework's installation directory. This will add the components to your toolbox, allowing their use in your Visual Studio projects. ## Conclusion By following this detailed guide, you can successfully install and integrate the TVFVideoEdit library into your preferred development environment. If you encounter any issues or need further assistance, please refer to the documentation provided with the framework or contact our support team for help. ---END OF PAGE--- ## Install TVFVideoEdit ActiveX Control in Visual Basic 6 **URL:** https://www.visioforge.com/help/docs/delphi/videoedit/install/visual-basic-6/ **Description:** Install TVFVideoEdit ActiveX control in Visual Basic 6 with x86 compatibility for video editing features in legacy applications. **Tags:** All-in-One Media Framework, Delphi, ActiveX, Windows, VCL, Editing **API:** TVFVideoEdit # Installing TVFVideoEdit ActiveX Control in Visual Basic 6 ## Introduction Visual Basic 6 remains a popular development environment for creating Windows applications. By leveraging our TVFVideoEdit library as an ActiveX control, developers can incorporate advanced video editing and processing capabilities into their VB6 applications without extensive coding. ## Technical Requirements and Limitations Microsoft Visual Basic 6 operates as a 32-bit development platform and cannot produce 64-bit applications. Due to this architectural constraint, only the x86 (32-bit) version of our library is compatible with VB6 projects. Despite this limitation, the 32-bit implementation delivers excellent performance and provides full access to the library's extensive feature set. ## Installation Process Follow these detailed steps to properly install the TVFVideoEdit ActiveX control in your Visual Basic 6 environment: ### Step 1: Create a New Project Begin by launching Visual Basic 6 and creating a new project: 1. Open Visual Basic 6 IDE 2. Select "New Project" from the File menu 3. Choose "Standard EXE" as the project type 4. Click "OK" to create the baseline project ### Step 2: Access Components Dialog Next, you need to register the ActiveX control within your development environment: 1. In the menu, navigate to "Project" 2. Select "Components" to open the components dialog ### Step 3: Select the TVFVideoEdit Control From the Components dialog: 1. Scroll through the available controls 2. Locate and check the box for "VisioForge Video Edit Control" 3. Click "OK" to confirm your selection ### Step 4: Verify Control Registration After successful registration: 1. The TVFVideoEdit control icon appears in your toolbox 2. This confirms the control is ready for use in your application ### Step 5: Implement the Control To begin using the control in your application: 1. Select the TVFVideoEdit control from the toolbox 2. Click and drag on your form to place an instance of the control 3. Size the control appropriately for your interface 4. Access properties and methods through the Properties window and code ## Advanced Implementation Tips - Set appropriate control properties before loading media files - Handle events for user interaction and processing notifications - Consider memory management when working with large video files - Test your application thoroughly with various media formats --- For technical questions or implementation challenges, contact our [support team](https://support.visioforge.com/). Access additional code examples and resources on our [GitHub repository](https://github.com/visioforge/). ---END OF PAGE--- ## Install TVFVideoEdit ActiveX Control in Visual Studio **URL:** https://www.visioforge.com/help/docs/delphi/videoedit/install/visual-studio/ **Description:** Install TVFVideoEdit ActiveX controls in Visual Studio 2010+ for C++, C#, and VB.NET projects with wrapper assembly configuration. **Tags:** Video Edit SDK, All-in-One Media Framework, Delphi, ActiveX, Windows, VCL, Editing **API:** TVFVideoEdit # Install TVFVideoEdit in Visual Studio ## Overview > Related products: [All-in-One Media Framework (Delphi / ActiveX)](https://www.visioforge.com/all-in-one-media-framework) TVFVideoEdit provides powerful video editing capabilities through ActiveX controls that integrate smoothly with various development environments. This guide walks you through the installation process specifically for Visual Studio 2010 and later versions. ## Compatibility Information The ActiveX control can be used directly in C++ projects without additional wrappers. For C# or VB.Net development, Visual Studio automatically creates a custom wrapper assembly that enables the ActiveX API in managed code environments. ## Prerequisites Before beginning the installation process, ensure you have: - Visual Studio 2010 or later installed on your development machine - Administrative privileges (required for ActiveX registration) - Both x86 and x64 ActiveX controls registered (Visual Studio might use x86 for the UI designer even when targeting x64) ## Step-by-Step Installation Guide ### Creating a New Project 1. Start Visual Studio and create a new project using C++, C#, or Visual Basic. 2. For this demonstration, we'll use a C# Windows Forms application, but the process applies similarly to VB.Net and C++ MFC projects. ### Adding the ActiveX Control to Your Toolbox 1. Right-click on the Toolbox panel in Visual Studio 2. Select the "Choose Items" option from the context menu that appears ### Selecting the Video Edit Control 1. In the Choose Toolbox Items dialog, locate the COM Components tab 2. Browse through the list or use the search functionality 3. Find and select the "VisioForge Video Edit Control" item 4. Click OK to add the control to your toolbox ### Implementing the Control in Your Form 1. Locate the newly added control in your toolbox 2. Click and drag it onto your form design surface 3. The control is now ready for implementation in your application ## Advanced Integration Options ### .NET Development Recommendations For developers working with .NET applications, we strongly recommend considering the native [.NET SDK](https://www.visioforge.com/video-edit-sdk-net) as an alternative to ActiveX integration. The .NET SDK offers several advantages: - Enhanced performance and stability - Native support for WinForms, WPF, and MAUI controls - Broader feature set and API capabilities - Simpler integration with modern development practices ## Troubleshooting Common Issues When integrating TVFVideoEdit, you might encounter these common challenges: - Registration issues: Ensure you have administrative privileges - Architecture mismatches: Verify both x86 and x64 versions are properly registered - Reference errors: Check that all required dependencies are included in your project ## Additional Resources If you encounter any difficulties following this tutorial or need specialized assistance with your implementation, our development team is available to provide technical guidance. - Access additional code samples on our [GitHub repository](https://github.com/visioforge/) - Contact our [technical support team](https://support.visioforge.com/) for personalized assistance ---END OF PAGE--- ## Register DirectShow Filters — regsvr32, C++, and C# Methods **URL:** https://www.visioforge.com/help/docs/directshow/deployment/filter-registration/ **Description:** Register VisioForge DirectShow filters using manual regsvr32, programmatic methods, and installer automation with troubleshooting tips. **Tags:** DirectShow, C++, Windows, Encoding, Mixing, MP4, H.264, AAC, C# **API:** FFMPEGSource, IBaseFilter # DirectShow Filter Registration Guide ## Overview DirectShow filters must be registered with Windows before they can be used in applications. This guide covers all registration methods for VisioForge DirectShow filters. --- ## Registration Methods ### Method 1: Automatic Registration (Installer) The recommended method for end-users is to use the official installer. **Available Installers**: - `visioforge_ffmpeg_source_filter_setup.exe` - FFMPEG Source Filter - `visioforge_vlc_source_filter_setup.exe` - VLC Source Filter - `visioforge_processing_filters_pack_setup.exe` - Processing Filters Pack - `visioforge_encoding_filters_pack_setup.exe` - Encoding Filters Pack - `visioforge_virtual_camera_sdk_setup.exe` - Virtual Camera SDK **Installation Steps**: 1. Run installer as Administrator 2. Follow installation wizard 3. Filters are automatically registered 4. No additional steps required --- ### Method 2: Manual Registration (regsvr32) For development and testing, you can manually register filters using Windows `regsvr32` utility. #### Registration Command ``` # Open Command Prompt as Administrator # Right-click Start → Command Prompt (Admin) # Register x86 (32-bit) filter regsvr32 "C:\Path\To\Filter.ax" # Register x64 (64-bit) filter regsvr32 "C:\Path\To\Filter_x64.ax" # Unregister filter regsvr32 /u "C:\Path\To\Filter.ax" ``` #### SDK-Specific Examples **FFMPEG Source Filter**: ``` # x86 regsvr32 "C:\Program Files (x86)\VisioForge\FFMPEG Source\VisioForge_FFMPEG_Source.ax" # x64 regsvr32 "C:\Program Files\VisioForge\FFMPEG Source\VisioForge_FFMPEG_Source_x64.ax" ``` **VLC Source Filter**: ``` # x86 only regsvr32 "C:\Program Files (x86)\VisioForge\VLC Source\VisioForge_VLC_Source.ax" ``` **Processing Filters Pack** (multiple filters): ``` # Video Effects regsvr32 "C:\Program Files\VisioForge\Processing Filters\VisioForge_Video_Effects_Pro.ax" regsvr32 "C:\Program Files\VisioForge\Processing Filters\VisioForge_Video_Effects_Pro_x64.ax" # Video Mixer regsvr32 "C:\Program Files\VisioForge\Processing Filters\VisioForge_Video_Mixer.ax" regsvr32 "C:\Program Files\VisioForge\Processing Filters\VisioForge_Video_Mixer_x64.ax" # Audio Enhancer regsvr32 "C:\Program Files\VisioForge\Processing Filters\VisioForge_Audio_Enhancer.ax" regsvr32 "C:\Program Files\VisioForge\Processing Filters\VisioForge_Audio_Enhancer_x64.ax" ``` **Encoding Filters Pack** (multiple filters): ``` # NVENC Encoder regsvr32 "C:\Program Files\VisioForge\Encoding Filters\VisioForge_NVENC.ax" regsvr32 "C:\Program Files\VisioForge\Encoding Filters\VisioForge_NVENC_x64.ax" # H.264 Encoder regsvr32 "C:\Program Files\VisioForge\Encoding Filters\VisioForge_H264_Encoder.ax" regsvr32 "C:\Program Files\VisioForge\Encoding Filters\VisioForge_H264_Encoder_x64.ax" # AAC Encoder regsvr32 "C:\Program Files\VisioForge\Encoding Filters\VisioForge_AAC_Encoder.ax" regsvr32 "C:\Program Files\VisioForge\Encoding Filters\VisioForge_AAC_Encoder_x64.ax" # MP4 Muxer regsvr32 "C:\Program Files\VisioForge\Encoding Filters\VisioForge_MP4_Muxer.ax" regsvr32 "C:\Program Files\VisioForge\Encoding Filters\VisioForge_MP4_Muxer_x64.ax" ``` **Virtual Camera SDK**: ``` # Virtual Camera Driver regsvr32 "C:\Program Files\VisioForge\Virtual Camera\VisioForge_Virtual_Camera.ax" regsvr32 "C:\Program Files\VisioForge\Virtual Camera\VisioForge_Virtual_Camera_x64.ax" # Push Source Filter regsvr32 "C:\Program Files\VisioForge\Virtual Camera\VisioForge_Push_Video_Source.ax" regsvr32 "C:\Program Files\VisioForge\Virtual Camera\VisioForge_Push_Video_Source_x64.ax" ``` --- ### Method 3: Programmatic Registration (C++) Register filters programmatically from your application code. #### Using LoadLibrary and DllRegisterServer ``` #include #include typedef HRESULT (STDAPICALLTYPE *LPFNDLLREGISTERSERVER)(); HRESULT RegisterFilter(const wchar_t* filterPath) { HMODULE hModule = LoadLibraryW(filterPath); if (!hModule) { DWORD error = GetLastError(); std::wcerr << L"Failed to load filter: " << filterPath << std::endl; std::wcerr << L"Error code: " << error << std::endl; return HRESULT_FROM_WIN32(error); } LPFNDLLREGISTERSERVER pfnDllRegisterServer = (LPFNDLLREGISTERSERVER)GetProcAddress(hModule, "DllRegisterServer"); if (!pfnDllRegisterServer) { FreeLibrary(hModule); return E_FAIL; } HRESULT hr = pfnDllRegisterServer(); FreeLibrary(hModule); if (SUCCEEDED(hr)) { std::wcout << L"Filter registered successfully: " << filterPath << std::endl; } else { std::wcerr << L"Registration failed with HRESULT: " << std::hex << hr << std::endl; } return hr; } HRESULT UnregisterFilter(const wchar_t* filterPath) { HMODULE hModule = LoadLibraryW(filterPath); if (!hModule) { return HRESULT_FROM_WIN32(GetLastError()); } typedef HRESULT (STDAPICALLTYPE *LPFNDLLUNREGISTERSERVER)(); LPFNDLLUNREGISTERSERVER pfnDllUnregisterServer = (LPFNDLLUNREGISTERSERVER)GetProcAddress(hModule, "DllUnregisterServer"); if (!pfnDllUnregisterServer) { FreeLibrary(hModule); return E_FAIL; } HRESULT hr = pfnDllUnregisterServer(); FreeLibrary(hModule); return hr; } // Usage int main() { const wchar_t* filterPath = L"C:\\Program Files\\VisioForge\\FFMPEG Source\\VisioForge_FFMPEG_Source_x64.ax"; HRESULT hr = RegisterFilter(filterPath); if (SUCCEEDED(hr)) { std::cout << "Filter registered successfully!" << std::endl; } else { std::cout << "Failed to register filter" << std::endl; } return 0; } ``` #### Using reg\_special.exe Utility VisioForge SDKs include a `reg_special.exe` utility for simplified registration: ``` #include #include HRESULT RegisterWithUtility(const wchar_t* filterPath) { // Build command line wchar_t cmdLine[MAX_PATH * 2]; swprintf_s(cmdLine, L"reg_special.exe /regserver \"%s\"", filterPath); // Execute registration utility SHELLEXECUTEINFO sei = { sizeof(sei) }; sei.lpVerb = L"runas"; // Run as administrator sei.lpFile = L"reg_special.exe"; sei.lpParameters = cmdLine; sei.nShow = SW_HIDE; sei.fMask = SEE_MASK_NOCLOSEPROCESS; if (!ShellExecuteEx(&sei)) { return HRESULT_FROM_WIN32(GetLastError()); } // Wait for completion WaitForSingleObject(sei.hProcess, INFINITE); DWORD exitCode; GetExitCodeProcess(sei.hProcess, &exitCode); CloseHandle(sei.hProcess); return (exitCode == 0) ? S_OK : E_FAIL; } ``` --- ### Method 4: Programmatic Registration (.NET/C#) Register filters from .NET applications using P/Invoke. ``` using System; using System.Runtime.InteropServices; using System.ComponentModel; public class FilterRegistration { [DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)] private static extern IntPtr LoadLibrary(string lpFileName); [DllImport("kernel32.dll", SetLastError = true)] private static extern bool FreeLibrary(IntPtr hModule); [DllImport("kernel32.dll", CharSet = CharSet.Ansi, SetLastError = true)] private static extern IntPtr GetProcAddress(IntPtr hModule, string lpProcName); [UnmanagedFunctionPointer(CallingConvention.StdCall)] private delegate int DllRegisterServerDelegate(); [UnmanagedFunctionPointer(CallingConvention.StdCall)] private delegate int DllUnregisterServerDelegate(); public static void RegisterFilter(string filterPath) { IntPtr hModule = LoadLibrary(filterPath); if (hModule == IntPtr.Zero) { throw new Win32Exception(Marshal.GetLastWin32Error(), $"Failed to load filter: {filterPath}"); } try { IntPtr procAddress = GetProcAddress(hModule, "DllRegisterServer"); if (procAddress == IntPtr.Zero) { throw new Exception("DllRegisterServer function not found"); } DllRegisterServerDelegate registerServer = Marshal.GetDelegateForFunctionPointer(procAddress); int result = registerServer(); if (result != 0) { throw new COMException($"Registration failed with HRESULT: 0x{result:X8}"); } Console.WriteLine($"Filter registered successfully: {filterPath}"); } finally { FreeLibrary(hModule); } } public static void UnregisterFilter(string filterPath) { IntPtr hModule = LoadLibrary(filterPath); if (hModule == IntPtr.Zero) { throw new Win32Exception(Marshal.GetLastWin32Error()); } try { IntPtr procAddress = GetProcAddress(hModule, "DllUnregisterServer"); if (procAddress == IntPtr.Zero) { throw new Exception("DllUnregisterServer function not found"); } DllUnregisterServerDelegate unregisterServer = Marshal.GetDelegateForFunctionPointer(procAddress); int result = unregisterServer(); if (result != 0) { throw new COMException($"Unregistration failed with HRESULT: 0x{result:X8}"); } Console.WriteLine($"Filter unregistered successfully: {filterPath}"); } finally { FreeLibrary(hModule); } } // Alternative: Use Process.Start with regsvr32 public static void RegisterFilterWithRegsvr32(string filterPath) { var startInfo = new System.Diagnostics.ProcessStartInfo { FileName = "regsvr32.exe", Arguments = $"/s \"{filterPath}\"", // /s = silent Verb = "runas", // Run as administrator UseShellExecute = true, CreateNoWindow = true }; using (var process = System.Diagnostics.Process.Start(startInfo)) { process.WaitForExit(); if (process.ExitCode != 0) { throw new Exception($"regsvr32 failed with exit code: {process.ExitCode}"); } } } } // Usage example class Program { static void Main(string[] args) { string filterPath = @"C:\Program Files\VisioForge\FFMPEG Source\VisioForge_FFMPEG_Source_x64.ax"; try { FilterRegistration.RegisterFilter(filterPath); Console.WriteLine("Filter registered successfully!"); } catch (Exception ex) { Console.WriteLine($"Error: {ex.Message}"); } } } ``` --- ## Registration Verification ### Method 1: Using GraphEdit/GraphStudioNext 1. Launch GraphEdit (Windows SDK) or GraphStudioNext 2. Click "Graph" → "Insert Filters" 3. Search for filter name (e.g., "FFMPEG Source", "VLC Source") 4. If filter appears in list, registration succeeded ### Method 2: Using Registry Editor ``` # Open Registry Editor regedit # Navigate to: HKEY_CLASSES_ROOT\CLSID\{GUID} # Example for FFMPEG Source: # HKEY_CLASSES_ROOT\CLSID\{1974D893-83E4-4F89-9908-795C524CC17E} ``` ### Method 3: Programmatic Verification (C++) ``` #include bool IsFilterRegistered(const CLSID& filterClsid) { IBaseFilter* pFilter = nullptr; HRESULT hr = CoCreateInstance(filterClsid, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void**)&pFilter); if (SUCCEEDED(hr) && pFilter) { pFilter->Release(); return true; } return false; } // Usage int main() { CoInitialize(NULL); // FFMPEG Source Filter CLSID CLSID ffmpegSourceClsid = { 0x1974D893, 0x83E4, 0x4F89, { 0x99, 0x08, 0x79, 0x5C, 0x52, 0x4C, 0xC1, 0x7E } }; if (IsFilterRegistered(ffmpegSourceClsid)) { std::cout << "FFMPEG Source filter is registered" << std::endl; } else { std::cout << "FFMPEG Source filter is NOT registered" << std::endl; } CoUninitialize(); return 0; } ``` ### Method 4: Programmatic Verification (.NET/C#) ## ``` using System; using System.Runtime.InteropServices; public static bool IsFilterRegistered(Guid clsid) { try { Type comType = Type.GetTypeFromCLSID(clsid, throwOnError: false); if (comType == null) return false; object instance = Activator.CreateInstance(comType); if (instance != null) { Marshal.ReleaseComObject(instance); return true; } } catch { return false; } return false; } // Usage Guid ffmpegSourceClsid = new Guid("1974D893-83E4-4F89-9908-795C524CC17E"); if (IsFilterRegistered(ffmpegSourceClsid)) { Console.WriteLine("FFMPEG Source filter is registered"); } ``` ## Troubleshooting ### Issue: "DllRegisterServer failed" or "Error 0x80004005" **Causes**: - Not running as Administrator - Missing dependencies (DLLs) - Wrong architecture (x86 vs x64) **Solutions**: 1. **Run as Administrator**: ``` # Right-click Command Prompt → Run as Administrator regsvr32 "C:\Path\To\Filter.ax" ``` 2. **Check Dependencies**: Use Dependency Walker or Dependencies.exe to check for missing DLLs: ``` # Download Dependencies from: https://github.com/lucasg/Dependencies Dependencies.exe "C:\Path\To\Filter.ax" ``` 3. **Verify Architecture**: ``` # For 32-bit application, register 32-bit filter regsvr32 "C:\Path\To\Filter.ax" # For 64-bit application, register 64-bit filter regsvr32 "C:\Path\To\Filter_x64.ax" ``` ### Issue: "The module was loaded but the entry-point was not found" **Cause**: File is not a valid DirectShow filter or is corrupted. **Solutions**: - Verify file integrity - Re-download or reinstall SDK - Check if file is a DirectShow filter (.ax extension) ### Issue: Filter registered but not found in applications **Causes**: - 32-bit/64-bit mismatch - Filter registered in wrong HKEY (per-user vs system-wide) **Solutions**: 1. **Match Application Architecture**: 2. 32-bit app needs 32-bit filter 3. 64-bit app needs 64-bit filter 4. **System-Wide Registration**: ``` # Run Command Prompt as Administrator # This registers system-wide (HKEY_LOCAL_MACHINE) regsvr32 "C:\Path\To\Filter.ax" ``` 5. **Check Both Registries**: 6. `HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID` 7. `HKEY_CURRENT_USER\SOFTWARE\Classes\CLSID` ### Issue: Access Denied **Cause**: Insufficient permissions. **Solution**: ``` # Always run as Administrator for filter registration # Right-click Command Prompt → Run as Administrator ``` ### Issue: Registration succeeds but filter doesn't work **Causes**: - Missing license key - Missing runtime dependencies - Incorrect installation path **Solutions**: 1. **Verify License**: 2. Check if trial license is expired 3. Ensure license key is properly activated 4. **Check Runtime Dependencies**: 5. FFMPEG Source: Requires FFmpeg DLLs (avcodec, avformat, etc.) 6. VLC Source: Requires VLC libraries (libvlc.dll, libvlccore.dll, plugins/) 7. NVENC: Requires NVIDIA GPU and drivers 8. Processing/Encoding: May require Visual C++ Redistributables 9. **Verify File Locations**: All dependent DLLs must be in same directory as .ax file or in system PATH. --- ## Registration-Free COM (Advanced) For xcopy deployment without registration, use registration-free COM with manifest files. ### Creating Manifest File **filter.manifest** (place next to .ax file): ``` ``` **application.exe.manifest** (place next to your .exe): ``` ``` **Limitations**: - More complex to set up - Requires manifest files - May not work with all DirectShow filters - System-registered filters take precedence --- ## Batch Registration Scripts ### Register All Filters (Batch Script) ``` @echo off echo Registering VisioForge DirectShow Filters... echo. REM Check for Administrator privileges net session >nul 2>&1 if %errorLevel% neq 0 ( echo ERROR: This script must be run as Administrator! pause exit /b 1 ) REM Set installation path set INSTALL_PATH=C:\Program Files\VisioForge REM Register FFMPEG Source echo Registering FFMPEG Source... regsvr32 /s "%INSTALL_PATH%\FFMPEG Source\VisioForge_FFMPEG_Source_x64.ax" if %errorLevel% equ 0 ( echo [OK] FFMPEG Source registered ) else ( echo [FAILED] FFMPEG Source registration failed ) REM Register VLC Source echo Registering VLC Source... regsvr32 /s "%INSTALL_PATH%\VLC Source\VisioForge_VLC_Source.ax" if %errorLevel% equ 0 ( echo [OK] VLC Source registered ) else ( echo [FAILED] VLC Source registration failed ) REM Register Processing Filters echo Registering Processing Filters... regsvr32 /s "%INSTALL_PATH%\Processing Filters\VisioForge_Video_Effects_Pro_x64.ax" regsvr32 /s "%INSTALL_PATH%\Processing Filters\VisioForge_Video_Mixer_x64.ax" regsvr32 /s "%INSTALL_PATH%\Processing Filters\VisioForge_Audio_Enhancer_x64.ax" echo [OK] Processing Filters registered REM Register Encoding Filters echo Registering Encoding Filters... regsvr32 /s "%INSTALL_PATH%\Encoding Filters\VisioForge_NVENC_x64.ax" regsvr32 /s "%INSTALL_PATH%\Encoding Filters\VisioForge_H264_Encoder_x64.ax" regsvr32 /s "%INSTALL_PATH%\Encoding Filters\VisioForge_AAC_Encoder_x64.ax" regsvr32 /s "%INSTALL_PATH%\Encoding Filters\VisioForge_MP4_Muxer_x64.ax" echo [OK] Encoding Filters registered echo. echo Registration complete! pause ``` ### Unregister All Filters ``` @echo off echo Unregistering VisioForge DirectShow Filters... echo. REM Check for Administrator privileges net session >nul 2>&1 if %errorLevel% neq 0 ( echo ERROR: This script must be run as Administrator! pause exit /b 1 ) set INSTALL_PATH=C:\Program Files\VisioForge REM Unregister all filters regsvr32 /s /u "%INSTALL_PATH%\FFMPEG Source\VisioForge_FFMPEG_Source_x64.ax" regsvr32 /s /u "%INSTALL_PATH%\VLC Source\VisioForge_VLC_Source.ax" regsvr32 /s /u "%INSTALL_PATH%\Processing Filters\VisioForge_Video_Effects_Pro_x64.ax" regsvr32 /s /u "%INSTALL_PATH%\Processing Filters\VisioForge_Video_Mixer_x64.ax" regsvr32 /s /u "%INSTALL_PATH%\Encoding Filters\VisioForge_NVENC_x64.ax" echo Unregistration complete! pause ``` --- ## See Also - [Redistributable Files](../redistributable-files/) - Complete file list for each SDK - [Installer Integration](../installer-integration/) - Creating custom installers - [Deployment Overview](../) - Main deployment guide ---END OF PAGE--- ## Deploy and Register DirectShow COM Filters on Windows **URL:** https://www.visioforge.com/help/docs/directshow/deployment/ **Description:** Deploy DirectShow filters with COM registration, WiX/NSIS/Inno Setup installer integration, redistributable files list, and troubleshooting tips. **Tags:** DirectShow, C++, Windows, Streaming # DirectShow SDKs - Deployment Guide ## Overview This comprehensive deployment guide covers everything you need to know about deploying VisioForge DirectShow SDKs in production environments. From filter registration to creating professional installers, this guide ensures your applications deploy smoothly. --- ## What's Covered ### Core Deployment Topics #### [Filter Registration](filter-registration/) Learn how to register DirectShow filters using multiple methods. **Topics**: - Manual registration with regsvr32 - Programmatic registration (C++, C#) - Batch scripts for automation - Verification techniques - Troubleshooting registration issues - Registration-free COM **When to Read**: Essential for all deployment scenarios --- #### [Redistributable Files](redistributable-files/) Complete reference of files to include in your deployment. **Topics**: - FFMPEG Source Filter files (~80-100MB) - VLC Source Filter files (~150-200MB) - Processing Filters Pack files (~20-180MB) - Encoding Filters Pack files (~40-300MB) - Virtual Camera SDK files (~15-35MB) - Dependencies and directory structures **When to Read**: Before creating installers or deployment packages --- #### [Installer Integration](installer-integration/) Create professional installers with WiX, NSIS, InstallShield, and Inno Setup. **Topics**: - WiX Toolset (MSI) - NSIS scripts - InstallShield projects - Inno Setup scripts - Custom actions for registration - Silent installation - Prerequisite bundling **When to Read**: When creating automated installation packages --- ## Quick Start ### Deployment Workflow Follow this recommended workflow for deploying DirectShow filters: ``` graph TD A[Identify Required SDKs] --> B[Collect Redistributable Files] B --> C[Choose Deployment Method] C --> D{Installation Method?} D -->|Manual| E[Create Batch Scripts] D -->|Installer| F[Create Installer Package] E --> G[Register Filters] F --> G G --> H[Test Deployment] H --> I{Works?} I -->|No| J[Troubleshoot] I -->|Yes| K[Deploy to Production] J --> H ``` ### Step-by-Step Quick Start #### Step 1: Identify Your SDKs Determine which SDKs your application uses: | SDK | Purpose | Key File | | --- | --- | --- | | **FFMPEG Source** | Media playback, streaming | VisioForge\_FFMPEG\_Source\_x64.ax | | **VLC Source** | Multi-track playback | VisioForge\_VLC\_Source.ax | | **Processing Filters** | Effects, mixing | VisioForge\_Video\_Effects\_Pro\_x64.ax | | **Encoding Filters** | Video encoding | VisioForge\_NVENC\_x64.ax | | **Virtual Camera** | Virtual devices | VisioForge\_Virtual\_Camera\_x64.ax | [View Complete File Lists →](redistributable-files/) --- #### Step 2: Collect Files Create deployment folder structure: ``` YourApp\ ├── YourApp.exe ├── YourApp.exe.config └── Filters\ ├── VisioForge_FFMPEG_Source_x64.ax ├── avcodec-58.dll ├── avformat-58.dll └── ... (other dependencies) ``` [View Directory Structures →](redistributable-files/#installation-directory-structure) --- #### Step 3: Choose Deployment Method | Method | Best For | Complexity | | --- | --- | --- | | **Batch Script** | Internal deployment, testing | Low | | **WiX (MSI)** | Enterprise, IT automation | Medium-High | | **NSIS** | Small installers, custom UI | Medium | | **InstallShield** | Commercial apps, advanced features | Medium | | **Inno Setup** | Simple installers, open-source | Low-Medium | [View Installer Comparisons →](#choosing-an-installer-technology) --- #### Step 4: Register Filters **Option A: Manual Registration (Development/Testing)** ``` @echo off cd /d "%~dp0Filters" regsvr32 /s VisioForge_FFMPEG_Source_x64.ax if %ERRORLEVEL% EQU 0 ( echo Registration successful ) else ( echo Registration failed ) ``` **Option B: Installer Custom Action (Production)** See [Installer Integration Guide](installer-integration/) for WiX, NSIS, and other examples. [View All Registration Methods →](filter-registration/) --- #### Step 5: Test Deployment **Verification Checklist**: - [ ] Install on clean test machine - [ ] Verify all files copied correctly - [ ] Check filter registration in registry - [ ] Test filter with GraphEdit/GraphStudioNext - [ ] Run application end-to-end test - [ ] Verify uninstall removes all components - [ ] Test on Windows 10 and Windows 11 - [ ] Test both x64 and x86 (if applicable) [View Testing Procedures →](#testing-deployments) --- ## Choosing an Installer Technology ### WiX Toolset **Pros**: - Industry-standard MSI format - Excellent for enterprise deployment - Group Policy support - Strong Windows Installer integration - Active community and documentation **Cons**: - XML-based syntax has learning curve - Requires compilation step - Less flexible UI than custom installers **Recommended For**: - Enterprise applications - IT-managed deployments - Applications requiring Group Policy deployment - Organizations with existing MSI infrastructure [View WiX Examples →](installer-integration/#wix-toolset-examples) --- ### NSIS **Pros**: - Very small installer size - Fast execution - Highly customizable UI - Simple scripting language - No external dependencies **Cons**: - Not MSI-based (may not suit all enterprises) - Less Windows Installer integration - Manual upgrade management **Recommended For**: - Consumer applications - Small to medium installers - Applications requiring custom UI - Portable application creation [View NSIS Examples →](installer-integration/#nsis-examples) --- ### InstallShield **Pros**: - Professional GUI designer - Comprehensive feature set - Visual Studio integration - Advanced prerequisite handling - Suite/bundle creation **Cons**: - Commercial license required (except Limited Edition) - Can be complex for simple installers - Larger learning curve **Recommended For**: - Commercial software products - Complex installation requirements - Professional installer appearance - Organizations with InstallShield expertise [View InstallShield Guide →](installer-integration/#installshield-integration) --- ### Inno Setup **Pros**: - Free and open-source - Easy to learn Pascal scripting - Good documentation - Unicode support - Active development **Cons**: - Not MSI-based - Fewer advanced features than commercial tools - Limited enterprise features **Recommended For**: - Open-source projects - Simple installers - Small applications - Budget-conscious deployments [View Inno Setup Examples →](installer-integration/#inno-setup-examples) --- ## Common Deployment Scenarios ### Scenario 1: Media Player Application **Requirements**: - FFMPEG Source Filter - Processing Filters (video effects) - User-friendly installer **Recommended Approach**: 1. Use **NSIS** or **Inno Setup** for consumer-friendly installer 2. Include Visual C++ Redistributable check 3. Register filters during installation 4. Create desktop shortcut 5. Associate media file types (optional) **Files to Deploy** (~100-150MB): - VisioForge\_FFMPEG\_Source\_x64.ax + FFmpeg DLLs - VisioForge\_Video\_Effects\_Pro\_x64.ax + dependencies [View Complete File List →](redistributable-files/#ffmpeg-source-filter) --- ### Scenario 2: Enterprise Video Processing **Requirements**: - FFMPEG Source + Encoding Filters - Silent installation support - MSI-based deployment - Group Policy deployment **Recommended Approach**: 1. Use **WiX Toolset** for MSI creation 2. Bundle Visual C++ Redistributable 3. Support silent installation parameters 4. Implement proper logging 5. Create deployment documentation **Example**: ``` msiexec /i EnterpriseVideoApp.msi /quiet /norestart /l*v install.log ``` [View WiX Bundle Examples →](installer-integration/#advanced-wix-self-extracting-bundle) --- ### Scenario 3: Virtual Camera Solution **Requirements**: - Virtual Camera SDK - Driver installation - System-level access **Recommended Approach**: 1. Use **WiX** or **InstallShield** for driver support 2. Require administrator privileges 3. Install virtual camera drivers 4. Register DirectShow filters 5. Provide clear installation instructions **Special Considerations**: - Drivers require digital signatures - May need system restart - Enhanced security warnings [View Virtual Camera Files →](redistributable-files/#virtual-camera-sdk) --- ### Scenario 4: Development SDK Redistribution **Requirements**: - Include filters with your SDK - Support both x86 and x64 - Flexible integration **Recommended Approach**: 1. Provide separate x86/x64 packages 2. Include registration batch scripts 3. Provide documentation for developers 4. Consider NuGet package distribution 5. Include header files and type libraries **Package Structure**: ``` YourSDK\ ├── bin\ │ ├── x86\ │ │ └── Filters\ │ └── x64\ │ └── Filters\ ├── docs\ ├── samples\ └── tools\ └── register_filters.bat ``` --- ## Prerequisites and Dependencies ### Visual C++ Redistributable **Required Version**: Visual C++ 2015-2022 Redistributable **Download Links**: - x64: - x86: **Detection Registry Keys**: ``` x64: HKLM\SOFTWARE\Microsoft\VisualStudio\14.0\VC\Runtimes\x64 x86: HKLM\SOFTWARE\Microsoft\VisualStudio\14.0\VC\Runtimes\x86 Value: "Installed" = 1 (DWORD) ``` **Installer Integration**: See [Bundling Dependencies](installer-integration/#bundling-dependencies) for WiX, NSIS, and other examples. --- ### .NET Requirements If your application uses .NET: - **.NET Framework 4.8** - For .NET Framework applications - **.NET 8.0 Runtime** - For modern .NET applications **Detection**: - .NET Framework: Check registry `HKLM\SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full` - .NET 8.0: Check for `dotnet --list-runtimes` --- ### Hardware Requirements (Optional) For hardware acceleration features: | Feature | Requirement | | --- | --- | | **NVENC Encoding** | NVIDIA GPU (GTX 600+) | | **QuickSync** | Intel CPU with integrated graphics | | **DXVA Decoding** | DirectX 11 compatible GPU | Document hardware requirements in your installer or documentation. --- ## Testing Deployments ### Test Environment Setup Create isolated test environments: 1. **Clean Windows 10 VM** - Test on fresh installation 2. **Clean Windows 11 VM** - Test latest OS 3. **Minimal Installation** - No Visual Studio or dev tools 4. **Different User Accounts** - Test standard user vs. admin ### Testing Checklist #### Installation Testing - [ ] Installer runs without errors - [ ] All files copied to correct locations - [ ] Filters registered successfully - [ ] Start menu shortcuts created - [ ] Registry entries created - [ ] Prerequisites detected/installed - [ ] User can launch application - [ ] Application functions correctly #### Uninstallation Testing - [ ] Uninstaller runs without errors - [ ] All files removed - [ ] Filters unregistered - [ ] Registry entries cleaned - [ ] Start menu shortcuts removed - [ ] No orphaned files remain #### Upgrade Testing - [ ] Upgrade from previous version works - [ ] User data preserved - [ ] Settings maintained - [ ] Old filters replaced with new versions #### Silent Installation Testing ``` REM Install silently MyAppSetup.exe /S REM Verify installation reg query "HKLM\SOFTWARE\MyApp" /v InstallDir REM Uninstall silently "%ProgramFiles%\MyApp\Uninstall.exe" /S ``` ### Automated Testing Script ``` # PowerShell deployment test script param( [string]$InstallerPath, [string]$FilterCLSID ) Write-Host "Testing installation..." -ForegroundColor Cyan # Install Start-Process $InstallerPath -ArgumentList "/S" -Wait # Verify filter registration $regPath = "HKLM:\SOFTWARE\Classes\CLSID\$FilterCLSID" if (Test-Path $regPath) { Write-Host "✓ Filter registered" -ForegroundColor Green } else { Write-Host "✗ Filter NOT registered" -ForegroundColor Red Exit 1 } # Test with GraphEdit $graphEdit = "C:\Program Files (x86)\Windows Kits\10\bin\*\x64\graphedt.exe" if (Test-Path $graphEdit) { Write-Host "✓ Testing with GraphEdit..." -ForegroundColor Cyan # Add GraphEdit automation here } # Uninstall $uninstaller = Get-ChildItem "C:\Program Files\MyApp\Uninstall.exe" -ErrorAction SilentlyContinue if ($uninstaller) { Start-Process $uninstaller.FullName -ArgumentList "/S" -Wait Write-Host "✓ Uninstall completed" -ForegroundColor Green } # Verify cleanup if (Test-Path $regPath) { Write-Host "✗ Filter still registered after uninstall" -ForegroundColor Red Exit 1 } else { Write-Host "✓ Filter unregistered successfully" -ForegroundColor Green } Write-Host "All tests passed!" -ForegroundColor Green ``` --- ## Architecture Considerations ### x86 vs x64 Deployment **x64 Applications**: - Use x64 filters only - Install to `C:\Program Files\YourApp` - Register in 64-bit registry view **x86 Applications**: - Use x86 filters only - Install to `C:\Program Files (x86)\YourApp` - Register in 32-bit registry view (regsvr32 handles automatically) **Mixed Applications**: - Include both x86 and x64 filters - Separate subdirectories: `Filters\x86` and `Filters\x64` - Conditional registration based on process architecture ### Registry Considerations **64-bit Windows Registry Views**: ``` HKLM\SOFTWARE\Classes\CLSID\{GUID} ← 64-bit view HKLM\SOFTWARE\Wow6432Node\Classes\CLSID\{GUID} ← 32-bit view ``` **Important**: regsvr32 automatically uses correct registry view: - `C:\Windows\System32\regsvr32.exe` → 64-bit registry - `C:\Windows\SysWOW64\regsvr32.exe` → 32-bit registry --- ## Security Considerations ### Code Signing **Recommended**: Sign all executables and installers with Authenticode certificate. ``` REM Sign installer with certificate signtool sign /f MyCert.pfx /p password /t https://timestamp.digicert.com MyAppSetup.exe ``` **Benefits**: - Removes SmartScreen warnings - Establishes trust with users - Required for kernel-mode drivers (Virtual Camera) ### Permission Requirements **Filter Registration Requires**: - Administrator privileges - Write access to HKLM registry - Write access to System32 (if registering there) **Best Practices**: - Always request elevation in installer manifest - Check privileges before registration - Provide clear error messages for permission issues ``` ``` --- ## Troubleshooting Common Issues ### Issue: Filter Registration Fails **Symptoms**: regsvr32 returns error, filter not in registry **Possible Causes**: 1. Missing dependencies (Visual C++ Runtime, DLLs) 2. Insufficient privileges 3. Corrupted filter file 4. Architecture mismatch **Solutions**: 1. Use Dependency Walker to check dependencies 2. Run installer as administrator 3. Verify file integrity (checksums) 4. Ensure x86 app uses x86 filter, x64 uses x64 filter [View Complete Troubleshooting →](filter-registration/#troubleshooting) --- ### Issue: Application Can't Find Filter **Symptoms**: Application fails to create filter graph, CLSID not found **Possible Causes**: 1. Filter not registered 2. Wrong CLSID used 3. 32-bit app looking for 64-bit filter **Solutions**: ``` // Verify filter registration programmatically HRESULT hr = CoCreateInstance(CLSID_FFMPEGSource, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void**)&pFilter); if (hr == REGDB_E_CLASSNOTREG) { // Filter not registered - prompt user } ``` --- ### Issue: Silent Installation Hangs **Symptoms**: Installer stops responding during silent install **Possible Causes**: 1. Waiting for user input 2. Reboot required 3. Prerequisite installation prompting **Solutions**: ``` # Add /norestart parameter msiexec /i MyApp.msi /quiet /norestart # NSIS: Check silent mode in script ${IfSilent} # Skip UI interactions ${EndIf} ``` --- ### Issue: Uninstall Leaves Files **Symptoms**: Application directory still exists after uninstall **Possible Causes**: 1. Files created after installation not tracked 2. Open file handles preventing deletion 3. Uninstall custom action not running **Solutions**: - Use Windows Installer RemoveFile table for dynamic files - Implement file cleanup in uninstall custom action - Ensure application not running during uninstall --- ## Best Practices Summary ### DO ✅ **Always** require administrator privileges for installation ✅ **Always** bundle or check for Visual C++ Redistributable ✅ **Always** test on clean machines before release ✅ **Always** implement proper uninstall ✅ **Always** log installation steps for troubleshooting ✅ **Always** verify filter registration after install ✅ **Do** support silent installation for enterprise deployments ✅ **Do** sign installers with Authenticode certificate ✅ **Do** provide clear error messages ✅ **Do** document system requirements ### DON'T ❌ **Never** register filters to System32 directory ❌ **Never** overwrite newer files with older versions ❌ **Never** fail installation if registration fails (warn instead) ❌ **Never** leave registry entries after uninstall ❌ **Never** require user to manually register filters ❌ **Don't** skip prerequisite checks ❌ **Don't** use hardcoded paths ❌ **Don't** forget to test upgrade scenarios ❌ **Don't** ignore HRESULT return values ❌ **Don't** deploy debug builds to production --- ## Deployment Checklist Use this checklist before releasing your installer: ### Pre-Release - [ ] All redistributable files identified - [ ] Correct architecture (x86/x64) selected - [ ] Dependencies documented - [ ] Installer created and tested - [ ] Silent installation tested - [ ] Uninstall tested completely - [ ] Code signing completed - [ ] Installation guide written - [ ] System requirements documented ### Testing - [ ] Tested on Windows 10 (21H2 or later) - [ ] Tested on Windows 11 - [ ] Tested on clean VM without dev tools - [ ] Tested with standard user account - [ ] Tested upgrade from previous version - [ ] Tested uninstall cleanup - [ ] Tested silent installation - [ ] Verified filter registration - [ ] Tested application functionality ### Documentation - [ ] Installation instructions written - [ ] Uninstallation instructions provided - [ ] Troubleshooting section included - [ ] System requirements listed - [ ] Support contact information provided --- ## Additional Resources ### Documentation - [Filter Registration Guide](filter-registration/) - Complete registration reference - [Redistributable Files](redistributable-files/) - All SDK files listed - [Installer Integration](installer-integration/) - WiX, NSIS, InstallShield examples ### External Resources - [DirectShow Registration (Microsoft)](https://learn.microsoft.com/en-us/windows/win32/directshow/how-to-register-directshow-filters) - [Windows Installer Best Practices](https://learn.microsoft.com/en-us/windows/win32/msi/windows-installer-best-practices) - [WiX Toolset](https://www.firegiant.com/wixtoolset/) - [NSIS](https://nsis.sourceforge.io/Main_Page) - [Inno Setup](https://jrsoftware.org/isinfo.php) ### Tools - **GraphEdit** - Filter testing (Windows SDK) - **GraphStudioNext** - Advanced filter testing - **Dependency Walker** - DLL dependency analysis - **Process Monitor** - Installation troubleshooting - **Registry Editor** - Registration verification --- ## Support For deployment assistance: 1. Check [Troubleshooting](#troubleshooting-common-issues) section 2. Review [Filter Registration](filter-registration/#troubleshooting) 3. Contact VisioForge support: [support@visioforge.com](mailto:support@visioforge.com) 4. Visit: ---END OF PAGE--- ## Deploy DirectShow Filters with WiX, NSIS, and Inno Setup **URL:** https://www.visioforge.com/help/docs/directshow/deployment/installer-integration/ **Description:** Step-by-step installer integration for VisioForge DirectShow filters. WiX, NSIS, Inno Setup, and InstallShield examples with COM registration custom actions. **Tags:** DirectShow, C++, Windows # Installer Integration Guide ## Overview This guide provides comprehensive instructions for integrating VisioForge DirectShow filters into Windows installers. It covers multiple installer technologies, custom actions for filter registration, dependency management, and best practices. --- ## Prerequisites Before creating an installer, ensure you understand: - [Redistributable Files](../redistributable-files/) - Files to include in installer - [Filter Registration](../filter-registration/) - Registration mechanisms - Target platform architecture (x86/x64) - Visual C++ Redistributable requirements --- ## Installer Technologies Overview ### WiX Toolset **Best For**: Enterprise applications, MSI-based deployments, IT automation **Advantages**: - XML-based declarative syntax - Native MSI support - Excellent Windows Installer integration - Group Policy deployment support - Active development and community **Requirements**: - WiX Toolset 3.x or 4.x - Visual Studio integration (optional) - .wixproj project files [View WiX Examples →](#wix-toolset-examples) --- ### NSIS (Nullsoft Scriptable Install System) **Best For**: Lightweight installers, custom UI, portable applications **Advantages**: - Small installer size - Highly customizable - Simple scripting language - No runtime dependencies - Fast execution **Requirements**: - NSIS 3.x compiler - .nsi script files [View NSIS Examples →](#nsis-examples) --- ### InstallShield **Best For**: Commercial applications, complex installations, advanced features **Advantages**: - Professional GUI designer - Built-in prerequisites detection - Multi-platform support - Suite/bundle creation - Visual Studio integration **Requirements**: - InstallShield Limited Edition (Visual Studio) or Professional - .ism project files [View InstallShield Guide →](#installshield-integration) --- ### Inno Setup **Best For**: Simple installers, small applications, freeware **Advantages**: - Free and open-source - Pascal scripting support - Unicode support - Good documentation - Active community **Requirements**: - Inno Setup 6.x compiler - .iss script files [View Inno Setup Examples →](#inno-setup-examples) --- ## WiX Toolset Examples ### Basic Filter Installation Create a complete WiX installer for a DirectShow filter with automatic registration. #### Product.wxs ``` NOT Installed Installed ``` #### Filters.wxs (Component Definition) ``` ``` #### VCRedist.wxs (Prerequisite Check) ``` ``` #### Building WiX Installer ``` # Using WiX 3.x command line candle.exe Product.wxs Filters.wxs VCRedist.wxs -ext WixUIExtension light.exe -out MyApp.msi Product.wixobj Filters.wixobj VCRedist.wixobj -ext WixUIExtension # Using WiX 4.x (newer syntax) wix build Product.wxs Filters.wxs VCRedist.wxs -ext WixToolset.UI.wixext -out MyApp.msi ``` --- ### Advanced WiX: Self-Extracting Bundle Create a bundle that includes Visual C++ Redistributable. #### Bundle.wxs ``` ``` Build bundle: ``` # WiX 3.x candle.exe Bundle.wxs -ext WixBalExtension light.exe -out MyAppSetup.exe Bundle.wixobj -ext WixBalExtension # WiX 4.x wix build Bundle.wxs -ext WixToolset.Bal.wixext -out MyAppSetup.exe ``` --- ### WiX: Custom C++ DLL for Registration For more control, create a custom action DLL. #### CustomActions.cpp ``` #include #include #include #pragma comment(lib, "msi.lib") // Forward declarations typedef HRESULT (STDAPICALLTYPE *LPFNDLLREGISTERSERVER)(); typedef HRESULT (STDAPICALLTYPE *LPFNDLLUNREGISTERSERVER)(); // Helper function to write to MSI log void LogMessage(MSIHANDLE hInstall, LPCTSTR message) { PMSIHANDLE hRecord = MsiCreateRecord(1); MsiRecordSetString(hRecord, 0, message); MsiProcessMessage(hInstall, INSTALLMESSAGE_INFO, hRecord); } // Custom action: Register DirectShow filters extern "C" __declspec(dllexport) UINT __stdcall RegisterDirectShowFilters(MSIHANDLE hInstall) { TCHAR installDir[MAX_PATH]; DWORD installDirSize = MAX_PATH; // Get INSTALLFOLDER property if (MsiGetProperty(hInstall, TEXT("INSTALLFOLDER"), installDir, &installDirSize) != ERROR_SUCCESS) { LogMessage(hInstall, TEXT("Failed to get INSTALLFOLDER property")); return ERROR_INSTALL_FAILURE; } LogMessage(hInstall, TEXT("Registering DirectShow filters...")); // Build path to filter TCHAR filterPath[MAX_PATH]; StringCchCopy(filterPath, MAX_PATH, installDir); StringCchCat(filterPath, MAX_PATH, TEXT("Filters\\VisioForge_FFMPEG_Source_x64.ax")); // Load filter DLL HMODULE hModule = LoadLibrary(filterPath); if (!hModule) { TCHAR errorMsg[512]; StringCchPrintf(errorMsg, 512, TEXT("Failed to load filter: %s (Error: %d)"), filterPath, GetLastError()); LogMessage(hInstall, errorMsg); return ERROR_INSTALL_FAILURE; } // Get DllRegisterServer function LPFNDLLREGISTERSERVER pfnRegister = (LPFNDLLREGISTERSERVER)GetProcAddress(hModule, "DllRegisterServer"); if (!pfnRegister) { LogMessage(hInstall, TEXT("DllRegisterServer not found in filter")); FreeLibrary(hModule); return ERROR_INSTALL_FAILURE; } // Register filter HRESULT hr = pfnRegister(); FreeLibrary(hModule); if (SUCCEEDED(hr)) { LogMessage(hInstall, TEXT("DirectShow filters registered successfully")); return ERROR_SUCCESS; } else { TCHAR errorMsg[256]; StringCchPrintf(errorMsg, 256, TEXT("Filter registration failed: HRESULT 0x%08X"), hr); LogMessage(hInstall, errorMsg); return ERROR_INSTALL_FAILURE; } } // Custom action: Unregister DirectShow filters extern "C" __declspec(dllexport) UINT __stdcall UnregisterDirectShowFilters(MSIHANDLE hInstall) { TCHAR installDir[MAX_PATH]; DWORD installDirSize = MAX_PATH; if (MsiGetProperty(hInstall, TEXT("INSTALLFOLDER"), installDir, &installDirSize) != ERROR_SUCCESS) { // Don't fail uninstall if we can't get the path return ERROR_SUCCESS; } LogMessage(hInstall, TEXT("Unregistering DirectShow filters...")); TCHAR filterPath[MAX_PATH]; StringCchCopy(filterPath, MAX_PATH, installDir); StringCchCat(filterPath, MAX_PATH, TEXT("Filters\\VisioForge_FFMPEG_Source_x64.ax")); HMODULE hModule = LoadLibrary(filterPath); if (!hModule) { // Filter may already be deleted, don't fail return ERROR_SUCCESS; } LPFNDLLUNREGISTERSERVER pfnUnregister = (LPFNDLLUNREGISTERSERVER)GetProcAddress(hModule, "DllUnregisterServer"); if (pfnUnregister) { pfnUnregister(); } FreeLibrary(hModule); LogMessage(hInstall, TEXT("DirectShow filters unregistered")); return ERROR_SUCCESS; } // DLL entry point BOOL APIENTRY DllMain(HMODULE hModule, DWORD reason, LPVOID reserved) { return TRUE; } ``` #### CustomActions.wxs ``` NOT Installed Installed ``` --- ## NSIS Examples ### Basic NSIS Installer Create a complete NSIS installer script. #### Installer.nsi ``` ; MyApp Installer with DirectShow Filters ; NSIS 3.x script ;-------------------------------- ; Includes !include "MUI2.nsh" !include "x64.nsh" ;-------------------------------- ; General Name "MyApp" OutFile "MyAppSetup.exe" Unicode True ; Default installation folder InstallDir "$PROGRAMFILES64\MyApp" ; Get installation folder from registry if available InstallDirRegKey HKLM "Software\MyApp" "InstallDir" ; Request application privileges RequestExecutionLevel admin ;-------------------------------- ; Interface Settings !define MUI_ABORTWARNING !define MUI_ICON "installer.ico" !define MUI_UNICON "uninstaller.ico" ;-------------------------------- ; Pages !insertmacro MUI_PAGE_LICENSE "License.txt" !insertmacro MUI_PAGE_COMPONENTS !insertmacro MUI_PAGE_DIRECTORY !insertmacro MUI_PAGE_INSTFILES !insertmacro MUI_PAGE_FINISH !insertmacro MUI_UNPAGE_CONFIRM !insertmacro MUI_UNPAGE_INSTFILES ;-------------------------------- ; Languages !insertmacro MUI_LANGUAGE "English" ;-------------------------------- ; Version Information VIProductVersion "1.0.0.0" VIAddVersionKey "ProductName" "MyApp" VIAddVersionKey "CompanyName" "Your Company" VIAddVersionKey "FileDescription" "MyApp Installer" VIAddVersionKey "FileVersion" "1.0.0.0" ;-------------------------------- ; Installer Sections Section "MyApp (required)" SecMain SectionIn RO ; Set output path SetOutPath "$INSTDIR" ; Install main application files File "MyApp.exe" File "MyApp.exe.config" ; Create Filters subdirectory CreateDirectory "$INSTDIR\Filters" SetOutPath "$INSTDIR\Filters" ; Install FFMPEG Source Filter File "Filters\VisioForge_FFMPEG_Source_x64.ax" File "Filters\avcodec-58.dll" File "Filters\avdevice-58.dll" File "Filters\avfilter-7.dll" File "Filters\avformat-58.dll" File "Filters\avutil-56.dll" File "Filters\swresample-3.dll" File "Filters\swscale-5.dll" ; Register DirectShow filter DetailPrint "Registering DirectShow filters..." ExecWait 'regsvr32 /s "$INSTDIR\Filters\VisioForge_FFMPEG_Source_x64.ax"' $0 ${If} $0 != 0 MessageBox MB_OK|MB_ICONEXCLAMATION "Filter registration failed. Code: $0" ${EndIf} ; Store installation folder WriteRegStr HKLM "Software\MyApp" "InstallDir" $INSTDIR ; Create uninstaller WriteUninstaller "$INSTDIR\Uninstall.exe" ; Create Start Menu shortcuts CreateDirectory "$SMPROGRAMS\MyApp" CreateShortcut "$SMPROGRAMS\MyApp\MyApp.lnk" "$INSTDIR\MyApp.exe" CreateShortcut "$SMPROGRAMS\MyApp\Uninstall.lnk" "$INSTDIR\Uninstall.exe" ; Add/Remove Programs entry WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\MyApp" "DisplayName" "MyApp" WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\MyApp" "UninstallString" "$INSTDIR\Uninstall.exe" WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\MyApp" "DisplayIcon" "$INSTDIR\MyApp.exe" WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\MyApp" "Publisher" "Your Company" WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\MyApp" "DisplayVersion" "1.0.0.0" WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\MyApp" "NoModify" 1 WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\MyApp" "NoRepair" 1 SectionEnd ;-------------------------------- ; Optional Sections Section "VLC Source Filter" SecVLC SetOutPath "$INSTDIR\Filters" ; Install VLC Source filter File "Filters\VisioForge_VLC_Source.ax" File "Filters\libvlc.dll" File "Filters\libvlccore.dll" ; Install VLC plugins directory SetOutPath "$INSTDIR\Filters\plugins" File /r "Filters\plugins\*.*" ; Register VLC Source filter DetailPrint "Registering VLC Source filter..." ExecWait 'regsvr32 /s "$INSTDIR\Filters\VisioForge_VLC_Source.ax"' SectionEnd ;-------------------------------- ; Section Descriptions !insertmacro MUI_FUNCTION_DESCRIPTION_BEGIN !insertmacro MUI_DESCRIPTION_TEXT ${SecMain} "Main application files and FFMPEG Source filter (required)" !insertmacro MUI_DESCRIPTION_TEXT ${SecVLC} "VLC Source filter for additional format support (optional)" !insertmacro MUI_FUNCTION_DESCRIPTION_END ;-------------------------------- ; Installer Functions Function .onInit ; Check if 64-bit Windows ${If} ${RunningX64} ; OK ${Else} MessageBox MB_OK|MB_ICONSTOP "This application requires 64-bit Windows." Abort ${EndIf} ; Check for Visual C++ Redistributable 2015-2022 ReadRegDWORD $0 HKLM "SOFTWARE\Microsoft\VisualStudio\14.0\VC\Runtimes\x64" "Installed" ${If} $0 != 1 MessageBox MB_YESNO|MB_ICONQUESTION "Visual C++ 2015-2022 Redistributable (x64) is required.$\n$\nDownload and install now?" IDYES download IDNO skip download: ExecShell "open" "https://aka.ms/vs/17/release/vc_redist.x64.exe" Abort skip: ${EndIf} FunctionEnd ;-------------------------------- ; Uninstaller Section Section "Uninstall" ; Unregister filters DetailPrint "Unregistering DirectShow filters..." ExecWait 'regsvr32 /s /u "$INSTDIR\Filters\VisioForge_FFMPEG_Source_x64.ax"' ExecWait 'regsvr32 /s /u "$INSTDIR\Filters\VisioForge_VLC_Source.ax"' ; Remove files Delete "$INSTDIR\MyApp.exe" Delete "$INSTDIR\MyApp.exe.config" Delete "$INSTDIR\Uninstall.exe" ; Remove Filters directory Delete "$INSTDIR\Filters\*.ax" Delete "$INSTDIR\Filters\*.dll" RMDir /r "$INSTDIR\Filters\plugins" RMDir "$INSTDIR\Filters" ; Remove installation directory RMDir "$INSTDIR" ; Remove Start Menu shortcuts Delete "$SMPROGRAMS\MyApp\MyApp.lnk" Delete "$SMPROGRAMS\MyApp\Uninstall.lnk" RMDir "$SMPROGRAMS\MyApp" ; Remove registry keys DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\MyApp" DeleteRegKey HKLM "Software\MyApp" SectionEnd ``` #### Building NSIS Installer ## ``` # Compile with NSIS makensis.exe Installer.nsi # Or use NSIS compiler GUI # File > Load Script > Select Installer.nsi > Test Installer ``` ### NSIS: Silent Installation Support Add silent installation parameters. ``` ; Add to .onInit function ; Check for silent mode ${GetParameters} $R0 ${GetOptions} $R0 "/S" $0 ${IfNot} ${Errors} ; Silent mode - skip prerequisite checks Goto silent_mode ${EndIf} ; Normal checks here... silent_mode: ; Continue with installation ; For silent uninstall, add to uninstaller: ; Run with: Uninstall.exe /S ``` --- ### NSIS: Custom Plugin for Registration Create a custom NSIS plugin for more control. #### FilterRegistration.cpp (NSIS Plugin) ``` #include #include "pluginapi.h" typedef HRESULT (STDAPICALLTYPE *LPFNDLLREGISTERSERVER)(); // Register filter function extern "C" void __declspec(dllexport) RegisterFilter( HWND hwndParent, int string_size, TCHAR *variables, stack_t **stacktop, extra_parameters *extra) { EXDLL_INIT(); // Pop filter path from stack TCHAR filterPath[MAX_PATH]; popstring(filterPath); // Load DLL HMODULE hModule = LoadLibrary(filterPath); if (!hModule) { pushstring(_T("ERROR")); return; } // Get registration function LPFNDLLREGISTERSERVER pfnRegister = (LPFNDLLREGISTERSERVER)GetProcAddress(hModule, "DllRegisterServer"); if (!pfnRegister) { FreeLibrary(hModule); pushstring(_T("ERROR")); return; } // Register HRESULT hr = pfnRegister(); FreeLibrary(hModule); pushstring(SUCCEEDED(hr) ? _T("OK") : _T("ERROR")); } BOOL WINAPI DllMain(HANDLE hInst, ULONG ul_reason_for_call, LPVOID lpReserved) { return TRUE; } ``` Usage in NSIS script: ``` ; Load plugin FilterRegistration::RegisterFilter "$INSTDIR\Filters\VisioForge_FFMPEG_Source_x64.ax" Pop $0 ${If} $0 == "ERROR" MessageBox MB_OK "Filter registration failed" ${EndIf} ``` --- ## InstallShield Integration ### Basic InstallShield Project Setup 1. **Create New Project**: 2. File > New Project 3. Select "Basic MSI Project" 4. Set project name and location 5. **Add Files**: 6. Application Files view 7. Add filter files to `[INSTALLDIR]\Filters` 8. Add application executables 9. **Add Custom Action**: #### Method 1: Using regsvr32 1. Go to **Behavior and Logic** > **Custom Actions** 2. Right-click **Install** > **New Custom Action** 3. Set properties: 4. Name: `Register DirectShow Filters` 5. Type: `Stored in the Directory Table` 6. Working Directory: `[INSTALLDIR]Filters` 7. Filename: `regsvr32.exe` 8. Command Line: `/s VisioForge_FFMPEG_Source_x64.ax` 9. Run: `Deferred Execution in System Context` 10. Condition: `NOT Installed` 11. For uninstall: 12. Name: `Unregister DirectShow Filters` 13. Command Line: `/s /u VisioForge_FFMPEG_Source_x64.ax` 14. Sequence: Before **RemoveFiles** 15. Condition: `Installed` #### Method 2: Using Custom DLL 1. Create C++ DLL with registration code (similar to WiX example above) 2. Add DLL to **Support Files** in InstallShield 3. Create custom action: 4. Type: `DLL from the installation` 5. DLL Name: `CustomActions.dll` 6. Function: `RegisterDirectShowFilters` ### InstallShield: Prerequisite Configuration 1. Go to **Redistributables** view 2. Add **Microsoft Visual C++ 2015-2022 Redistributable (x64)**: 3. Right-click > **Add Prerequisite** 4. Browse to `VC_redist.x64.exe` 5. Set: **Install Before This Application** --- ## Inno Setup Examples ### Basic Inno Setup Script #### Setup.iss ``` ; MyApp Setup Script for Inno Setup 6.x [Setup] AppName=MyApp AppVersion=1.0 DefaultDirName={autopf}\MyApp DefaultGroupName=MyApp UninstallDisplayIcon={app}\MyApp.exe Compression=lzma2 SolidCompression=yes OutputDir=Output OutputBaseFilename=MyAppSetup ArchitecturesInstallIn64BitMode=x64 PrivilegesRequired=admin MinVersion=10.0 [Files] ; Main application Source: "MyApp.exe"; DestDir: "{app}"; Flags: ignoreversion ; FFMPEG Source Filter Source: "Filters\VisioForge_FFMPEG_Source_x64.ax"; DestDir: "{app}\Filters"; Flags: ignoreversion regserver restartreplace uninsrestartdelete Source: "Filters\avcodec-58.dll"; DestDir: "{app}\Filters"; Flags: ignoreversion Source: "Filters\avdevice-58.dll"; DestDir: "{app}\Filters"; Flags: ignoreversion Source: "Filters\avfilter-7.dll"; DestDir: "{app}\Filters"; Flags: ignoreversion Source: "Filters\avformat-58.dll"; DestDir: "{app}\Filters"; Flags: ignoreversion Source: "Filters\avutil-56.dll"; DestDir: "{app}\Filters"; Flags: ignoreversion Source: "Filters\swresample-3.dll"; DestDir: "{app}\Filters"; Flags: ignoreversion Source: "Filters\swscale-5.dll"; DestDir: "{app}\Filters"; Flags: ignoreversion [Icons] Name: "{group}\MyApp"; Filename: "{app}\MyApp.exe" Name: "{group}\Uninstall MyApp"; Filename: "{uninstallexe}" [Run] ; Optionally launch application after install Filename: "{app}\MyApp.exe"; Description: "Launch MyApp"; Flags: nowait postinstall skipifsilent [Registry] Root: HKLM; Subkey: "Software\MyApp"; ValueType: string; ValueName: "InstallDir"; ValueData: "{app}"; Flags: uninsdeletekey [Code] // Check for Visual C++ Redistributable function InitializeSetup(): Boolean; var ResultCode: Integer; VCInstalled: Cardinal; begin Result := True; // Check if VC++ 2015-2022 is installed if not RegQueryDWordValue(HKLM, 'SOFTWARE\Microsoft\VisualStudio\14.0\VC\Runtimes\x64', 'Installed', VCInstalled) or (VCInstalled <> 1) then begin if MsgBox('Visual C++ 2015-2022 Redistributable (x64) is required.' + #13#10 + 'Download and install now?', mbConfirmation, MB_YESNO) = IDYES then begin ShellExec('open', 'https://aka.ms/vs/17/release/vc_redist.x64.exe', '', '', SW_SHOW, ewNoWait, ResultCode); Result := False; // Abort installation end; end; end; ``` #### Advanced Inno Setup: Custom Registration ## ``` [Files] ; Don't use regserver flag - we'll register manually Source: "Filters\VisioForge_FFMPEG_Source_x64.ax"; DestDir: "{app}\Filters"; Flags: ignoreversion [Code] // Import Windows API functions function LoadLibrary(lpFileName: String): THandle; external 'LoadLibraryW@kernel32.dll stdcall'; function FreeLibrary(hModule: THandle): Boolean; external 'FreeLibrary@kernel32.dll stdcall'; function GetProcAddress(hModule: THandle; lpProcName: AnsiString): Longword; external 'GetProcAddress@kernel32.dll stdcall'; type TDllRegisterServer = function: HRESULT; // Register DirectShow filter function RegisterDirectShowFilter(FilterPath: String): Boolean; var hModule: THandle; DllRegisterServer: TDllRegisterServer; RegisterFunc: Longword; hr: HRESULT; begin Result := False; hModule := LoadLibrary(FilterPath); if hModule = 0 then begin Log('Failed to load filter: ' + FilterPath); Exit; end; try RegisterFunc := GetProcAddress(hModule, 'DllRegisterServer'); if RegisterFunc = 0 then begin Log('DllRegisterServer not found'); Exit; end; @DllRegisterServer := Pointer(RegisterFunc); hr := DllRegisterServer(); Result := Succeeded(hr); if Result then Log('Filter registered successfully') else Log('Filter registration failed: ' + IntToHex(hr, 8)); finally FreeLibrary(hModule); end; end; // Called after installation procedure CurStepChanged(CurStep: TSetupStep); var FilterPath: String; begin if CurStep = ssPostInstall then begin FilterPath := ExpandConstant('{app}\Filters\VisioForge_FFMPEG_Source_x64.ax'); if not RegisterDirectShowFilter(FilterPath) then begin MsgBox('Warning: DirectShow filter registration failed.' + #13#10 + 'You may need to register it manually.', mbError, MB_OK); end; end; end; // Called before uninstallation procedure CurUninstallStepChanged(CurUninstallStep: TUninstallStep); var ResultCode: Integer; FilterPath: String; begin if CurUninstallStep = usUninstall then begin FilterPath := ExpandConstant('{app}\Filters\VisioForge_FFMPEG_Source_x64.ax'); // Unregister using regsvr32 Exec('regsvr32.exe', '/s /u "' + FilterPath + '"', '', SW_HIDE, ewWaitUntilTerminated, ResultCode); end; end; ``` ## Silent Installation ### Silent Installation Parameters #### MSI (WiX, InstallShield MSI) ``` # Silent install msiexec /i MyApp.msi /quiet /norestart # Silent install with log msiexec /i MyApp.msi /quiet /norestart /l*v install.log # Silent uninstall msiexec /x MyApp.msi /quiet /norestart # Silent install with custom install directory msiexec /i MyApp.msi /quiet INSTALLFOLDER="C:\CustomPath\MyApp" ``` #### NSIS ``` # Silent install MyAppSetup.exe /S # Silent install with custom directory MyAppSetup.exe /S /D=C:\CustomPath\MyApp # Silent uninstall Uninstall.exe /S ``` #### Inno Setup ``` # Silent install MyAppSetup.exe /SILENT # Very silent (no progress) MyAppSetup.exe /VERYSILENT # Silent with custom directory MyAppSetup.exe /SILENT /DIR="C:\CustomPath\MyApp" # Silent uninstall unins000.exe /SILENT ``` --- ## Bundling Dependencies ### Visual C++ Redistributable #### Option 1: Download Bootstrapper ``` ``` #### Option 2: Include Redistributable ``` ; NSIS Section "VC++ Redistributable" File "Prerequisites\VC_redist.x64.exe" ExecWait '"$INSTDIR\VC_redist.x64.exe" /install /quiet /norestart' Delete "$INSTDIR\VC_redist.x64.exe" SectionEnd ``` #### Option 3: Merge Modules (WiX) ## ``` ``` ## Best Practices ### Registration Timing 1. **Install Sequence**: ``` InstallFiles ↓ Register Filters (Custom Action) ↓ InstallFinalize ``` 1. **Uninstall Sequence**: ``` Unregister Filters (Custom Action) ↓ RemoveFiles ↓ UninstallFinalize ``` ### Error Handling **Always**: - Log registration attempts - Check HRESULT values - Provide user feedback on failure - Don't fail entire installation if registration fails - Allow manual registration post-install **Example error handling**: ``` HRESULT hr = RegisterFilter(filterPath); if (FAILED(hr)) { if (hr == REGDB_E_CLASSNOTREG) LogError("Class not registered - check dependencies"); else if (hr == E_ACCESSDENIED) LogError("Access denied - requires admin privileges"); else LogError("Registration failed with HRESULT: 0x%08X", hr); } ``` ### Rollback Support Ensure proper rollback if installation fails: ``` NOT Installed NOT Installed ``` ### Admin Privileges **Always require** admin/elevated privileges: ``` ``` ``` ; NSIS RequestExecutionLevel admin ``` ``` { Inno Setup } PrivilegesRequired=admin ``` ### Architecture Considerations ``` ``` ``` ; NSIS: Runtime architecture detection ${If} ${RunningX64} File "Filters\VisioForge_FFMPEG_Source_x64.ax" ${Else} File "Filters\VisioForge_FFMPEG_Source.ax" ${EndIf} ``` --- ## Testing Installation ### Manual Testing Checklist - [ ] Install on clean Windows 10/11 - [ ] Verify all files copied - [ ] Check filter registration (GraphEdit/GraphStudioNext) - [ ] Test application functionality - [ ] Uninstall completely - [ ] Verify no files remain - [ ] Check registry cleanup - [ ] Test upgrade scenario - [ ] Test repair functionality - [ ] Test silent installation - [ ] Test on different user accounts ### Automated Testing ## ``` # PowerShell test script $installerPath = ".\MyAppSetup.msi" $logPath = ".\install_test.log" # Install silently Start-Process msiexec.exe -ArgumentList "/i `"$installerPath`" /quiet /l*v `"$logPath`"" -Wait # Check if filter registered $filterCLSID = "{1974D893-83E4-4F89-9908-795C524CC17E}" $regPath = "HKLM:\SOFTWARE\Classes\CLSID\$filterCLSID" if (Test-Path $regPath) { Write-Host "Filter registered successfully" -ForegroundColor Green } else { Write-Host "Filter registration failed" -ForegroundColor Red Exit 1 } # Uninstall Start-Process msiexec.exe -ArgumentList "/x `"$installerPath`" /quiet" -Wait # Verify cleanup if (Test-Path $regPath) { Write-Host "Filter not unregistered" -ForegroundColor Red Exit 1 } else { Write-Host "Uninstall successful" -ForegroundColor Green } ``` ## Troubleshooting ### Common Issues #### Registration Fails with Access Denied **Cause**: Insufficient privileges **Solution**: ``` ``` #### Filter Works in Development but not After Install **Cause**: Missing dependencies or incorrect paths **Solution**: - Use Dependency Walker to check all DLL dependencies - Ensure all DLLs in same directory as filter - Check PATH environment variable #### Silent Install Hangs **Cause**: User interaction required **Solution**: ``` # Add /norestart parameter msiexec /i MyApp.msi /quiet /norestart ``` #### Uninstall Leaves Registry Entries **Cause**: Unregistration custom action not running **Solution**: ``` ``` --- ## See Also ### Documentation - [Filter Registration](../filter-registration/) - Manual registration methods - [Redistributable Files](../redistributable-files/) - Files to include in installer - [Deployment Overview](../) - Complete deployment guide ### External Resources - [WiX Toolset Documentation](https://docs.firegiant.com/wix/) - [NSIS Documentation](https://nsis.sourceforge.io/Docs/) - [Inno Setup Documentation](https://jrsoftware.org/ishelp/) - [Windows Installer (MSI) Documentation](https://learn.microsoft.com/en-us/windows/win32/Msi/windows-installer-portal) ---END OF PAGE--- ## DirectShow SDK Redistributable Files for Deployment **URL:** https://www.visioforge.com/help/docs/directshow/deployment/redistributable-files/ **Description:** Complete list of redistributable files for VisioForge DirectShow SDKs with dependencies, architecture files, and deployment requirements. **Tags:** DirectShow, C++, Windows, Streaming, Encoding, Decoding, Mixing, Screen Capture, WebM, H.264, MP3 # DirectShow SDKs - Redistributable Files Reference ## Overview This document provides a complete list of files required to redistribute each DirectShow SDK with your application. All files must be included in your installer or deployment package. --- ## FFMPEG Source Filter ### Core Files #### x86 (32-bit) **Filter**: - `VisioForge_FFMPEG_Source.ax` - Main DirectShow filter **FFmpeg Libraries** (required): - `avcodec-58.dll` - Video/audio codec library - `avdevice-58.dll` - Device handling - `avfilter-7.dll` - Audio/video filtering - `avformat-58.dll` - Container format handling - `avutil-56.dll` - Utility functions - `swresample-3.dll` - Audio resampling - `swscale-5.dll` - Video scaling and color conversion **Total Size**: ~80-100 MB #### x64 (64-bit) **Filter**: - `VisioForge_FFMPEG_Source_x64.ax` - Main DirectShow filter (64-bit) **FFmpeg Libraries** (required): - `avcodec-58.dll` - 64-bit version - `avdevice-58.dll` - 64-bit version - `avfilter-7.dll` - 64-bit version - `avformat-58.dll` - 64-bit version - `avutil-56.dll` - 64-bit version - `swresample-3.dll` - 64-bit version - `swscale-5.dll` - 64-bit version **Total Size**: ~90-110 MB ### Installation Directory Structure ``` YourApp\ ├── VisioForge_FFMPEG_Source.ax (x86) ├── VisioForge_FFMPEG_Source_x64.ax (x64) ├── avcodec-58.dll ├── avdevice-58.dll ├── avfilter-7.dll ├── avformat-58.dll ├── avutil-56.dll ├── swresample-3.dll └── swscale-5.dll ``` ### License Files - `license.rtf` - SDK license agreement (include in installer) ### Dependencies - **Visual C++ Redistributable 2015-2022** (x86 or x64) - Download: https://aka.ms/vs/17/release/vc\_redist.x64.exe --- ## VLC Source Filter ### Core Files #### x86 (32-bit) Only **Filter**: - `VisioForge_VLC_Source.ax` - Main DirectShow filter **VLC Libraries** (required): - `libvlc.dll` - VLC core library - `libvlccore.dll` - VLC core functionality **VLC Plugins Directory** (required): - `plugins\` - Complete VLC plugins folder (~100+ plugin DLLs) - `plugins\access\` - Input protocols - `plugins\audio_filter\` - Audio processing - `plugins\audio_mixer\` - Audio mixing - `plugins\audio_output\` - Audio output - `plugins\codec\` - Codecs - `plugins\control\` - Control interfaces - `plugins\demux\` - Demultiplexers - `plugins\misc\` - Miscellaneous - `plugins\packetizer\` - Packetizers - `plugins\services_discovery\` - Service discovery - `plugins\stream_filter\` - Stream filters - `plugins\stream_out\` - Stream output - `plugins\text_renderer\` - Text rendering - `plugins\video_chroma\` - Color conversion - `plugins\video_filter\` - Video filters - `plugins\video_output\` - Video output - `plugins\visualization\` - Visualizations **VLC Data Directories**: - `locale\` - Localization files (optional, ~50+ language folders) - `lua\` - Lua scripts for playlists and extensions - `hrtfs\` - HRTF audio files - `dodeca_and_7channel_3DSL_HRTF.sofa` **Total Size**: ~150-200 MB (with all plugins and locales) ### Installation Directory Structure ``` YourApp\ ├── VisioForge_VLC_Source.ax ├── libvlc.dll ├── libvlccore.dll ├── plugins\ │ ├── access\ │ ├── audio_filter\ │ ├── codec\ │ └── ... (all plugin directories) ├── locale\ (optional) ├── lua\ └── hrtfs\ ``` ### License Files - `license.rtf` - SDK license agreement ### Dependencies - **Visual C++ Redistributable 2015-2022** (x86) ### Important Notes - **All VLC plugins must be included** - Missing plugins will cause playback failures for certain formats - **Maintain directory structure** - VLC expects plugins in `plugins\` subdirectory - **No x64 version** - VLC Source Filter is 32-bit only --- ## Processing Filters Pack ### Core Filters #### x86 (32-bit) **Video Processing**: - `VisioForge_Video_Effects_Pro.ax` - Video effects filter (35+ effects) - `VisioForge_Video_Mixer.ax` - Multi-source video mixer - `VisioForge_Screen_Capture_DD.ax` - DirectDraw screen capture **Audio Processing**: - `VisioForge_Audio_Enhancer.ax` - Audio enhancement filter - `VisioForge_Audio_Effects_4.ax` - Audio effects (optional) - `VisioForge_Audio_Mixer.ax` - Audio mixer **Base Filters** (required): - `VisioForge_BaseFilters.ax` - Core base filter library - `VisioForge_AsyncEx.ax` - Async file reader (optional) **Helper Libraries**: - `VisioForge_MFP.dll` - Media Foundation helper - `VisioForge_MFPX.dll` - Extended MF functions #### x64 (64-bit) **Video Processing**: - `VisioForge_Video_Effects_Pro_x64.ax` - `VisioForge_Video_Mixer_x64.ax` - `VisioForge_Screen_Capture_DD_x64.ax` **Audio Processing**: - `VisioForge_Audio_Enhancer_x64.ax` - `VisioForge_Audio_Mixer_x64.ax` **Base Filters** (required): - `VisioForge_BaseFilters_x64.ax` - `VisioForge_AsyncEx_x64.ax` (optional) **Helper Libraries**: - `VisioForge_MFP64.dll` - `VisioForge_MFPX64.dll` ### LAV Filters (Optional but Recommended) LAV Filters provide additional codec support and are included with Processing Filters Pack. #### x86 **LAV Filters**: - `LAVSplitter.ax` - Source splitter - `LAVVideo.ax` - Video decoder - `LAVAudio.ax` - Audio decoder **FFmpeg Libraries for LAV**: - `avcodec-lav-58.dll` - `avformat-lav-58.dll` - `avfilter-lav-7.dll` - `avresample-lav-4.dll` - `avutil-lav-56.dll` - `swscale-lav-5.dll` **Additional Libraries**: - `libbluray.dll` - Blu-ray support - `IntelQuickSyncDecoder.dll` - Intel QuickSync hardware decoding **Manifest**: - `LAVFilters.Dependencies.manifest` **License**: - `COPYING` - LAV Filters license (LGPL) #### x64 Same files as x86 but 64-bit versions. ### Installation Directory Structure ``` YourApp\ ├── Filters\ │ ├── VisioForge_Video_Effects_Pro.ax │ ├── VisioForge_Video_Effects_Pro_x64.ax │ ├── VisioForge_Video_Mixer.ax │ ├── VisioForge_Video_Mixer_x64.ax │ ├── VisioForge_Audio_Enhancer.ax │ ├── VisioForge_Audio_Enhancer_x64.ax │ ├── VisioForge_BaseFilters.ax │ ├── VisioForge_BaseFilters_x64.ax │ ├── VisioForge_MFP.dll │ ├── VisioForge_MFP64.dll │ ├── VisioForge_MFPX.dll │ └── VisioForge_MFPX64.dll └── LAV\ ├── x86\ │ ├── LAVSplitter.ax │ ├── LAVVideo.ax │ ├── LAVAudio.ax │ ├── avcodec-lav-58.dll │ └── ... (other LAV files) └── x64\ ├── LAVSplitter.ax ├── LAVVideo.ax └── ... (other LAV files) ``` ### License Files - `license.rtf` - VisioForge SDK license - `VisioForge_AsyncEx_license.htm` - Async filter license - `VisioForge_Audio_Effects_4_note.txt` - Audio effects notes - `COPYING` - LAV Filters license (in LAV directory) ### Total Size - **Without LAV Filters**: ~20-30 MB - **With LAV Filters**: ~80-100 MB --- ## Encoding Filters Pack ### Core Filters #### x86 (32-bit) **Video Encoders**: - `VisioForge_NVENC.ax` - NVIDIA hardware encoder - `VisioForge_H264_Encoder.ax` - H.264 software encoder - `VisioForge_H264_Encoder_v9.ax` - H.264 encoder v9 - `VisioForge_H264_Decoder.ax` - H.264 decoder - `VisioForge_WebM_VP8_Encoder.ax` - VP8 encoder - `VisioForge_WebM_VP9_Encoder.ax` - VP9 encoder (in x64) - `VisioForge_WebM_VP8_Decoder.ax` - VP8 decoder - `VisioForge_WebM_VP9_Decoder.ax` - VP9 decoder **Audio Encoders**: - `VisioForge_AAC_Encoder.ax` - AAC encoder - `VisioForge_AAC_Encoder_v10.ax` - AAC encoder v10 - `VisioForge_LAME.ax` - MP3 encoder (LAME) - `VisioForge_WebM_Vorbis_Encoder.ax` - Vorbis encoder - `VisioForge_WebM_Vorbis_Decoder.ax` - Vorbis decoder **Muxers/Demuxers**: - `VisioForge_MP4_Muxer.ax` - MP4 container muxer - `VisioForge_MP4_Muxer_v10.ax` - MP4 muxer v10 - `VisioForge_MF_Mux.ax` - Media Foundation muxer - `VisioForge_WebM_Mux.ax` - WebM muxer - `VisioForge_WebM_Split.ax` - WebM splitter - `VisioForge_WebM_Source.ax` - WebM source - `VisioForge_WebM_Ogg_Source.ax` - Ogg source - `VisioForge_SSF_Muxer.ax` - SSF muxer **Network**: - `VisioForge_RTSP_Sink.ax` - RTSP sink - `VisioForge_RTSP_Source_Live555.ax` - RTSP source **Base Filters** (required): - `VisioForge_BaseFilters.ax` **Helper Libraries** (required): - `VisioForge_MFP.dll` - Media Foundation helper - `VisioForge_MFP64.dll` - 64-bit MF helper - `VisioForge_MFPX.dll` - Extended MF functions - `VisioForge_MFPX64.dll` - 64-bit extended MF - `VisioForge_MFT.dll` - Media Foundation Transform **Intel QuickSync** (optional): - `libmfxsw32.dll` - QuickSync software library - `libmfxxp32.dll` - QuickSync XP library #### x64 (64-bit) **Video Encoders**: - `VisioForge_NVENC_x64.ax` - `VisioForge_H264_Encoder_x64.ax` - `VisioForge_H264_Encoder_v9_x64.ax` - `VisioForge_H264_Decoder_x64.ax` - `VisioForge_WebM_VP8_Encoder_x64.ax` - `VisioForge_WebM_VP9_Encoder_x64.ax` - `VisioForge_WebM_VP8_Decoder_x64.ax` - `VisioForge_WebM_VP9_Decoder_x64.ax` **Audio Encoders**: - `VisioForge_AAC_Encoder_x64.ax` - `VisioForge_AAC_Encoder_v10_x64.ax` - `VisioForge_LAME_x64.ax` - `VisioForge_WebM_Vorbis_Encoder_x64.ax` - `VisioForge_WebM_Vorbis_Decoder_x64.ax` **Muxers/Demuxers**: - `VisioForge_MP4_Muxer_x64.ax` - `VisioForge_MP4_Muxer_v10_x64.ax` - `VisioForge_MF_Mux_x64.ax` - `VisioForge_WebM_Mux_x64.ax` - `VisioForge_WebM_Split_x64.ax` - `VisioForge_WebM_Source_x64.ax` - `VisioForge_WebM_Ogg_Source_x64.ax` - `VisioForge_SSF_Muxer_x64.ax` **Network**: - `VisioForge_RTSP_Sink_x64.ax` - `VisioForge_RTSP_Source_Live555_x64.ax` **Base Filters** (required): - `VisioForge_BaseFilters_x64.ax` **Helper Libraries** (same as x86): - `VisioForge_MFP64.dll` - `VisioForge_MFPX64.dll` - `VisioForge_MFT64.dll` **Intel QuickSync** (optional): - `libmfxsw64.dll` - `libmfxxp64.dll` ### FFMPEG Encoder The FFMPEG Encoder has its own set of FFmpeg libraries: #### x86 **Filter**: - `VisioForge_FFMPEG_Encoder.ax` **FFmpeg Libraries**: - `avcodec-58.dll` - `avdevice-58.dll` - `avfilter-7.dll` - `avformat-58.dll` - `avutil-56.dll` - `swresample-3.dll` - `swscale-5.dll` - `ffmedia.dll` - VisioForge FFmpeg wrapper **Info**: - `vfffmpeg_info.txt` - FFmpeg build information #### x64 Same files as x86 but 64-bit versions. ### Installation Directory Structure ``` YourApp\ ├── Filters\ │ ├── VisioForge_NVENC.ax │ ├── VisioForge_NVENC_x64.ax │ ├── VisioForge_H264_Encoder.ax │ ├── VisioForge_H264_Encoder_x64.ax │ ├── VisioForge_AAC_Encoder.ax │ ├── VisioForge_AAC_Encoder_x64.ax │ ├── VisioForge_MP4_Muxer.ax │ ├── VisioForge_MP4_Muxer_x64.ax │ ├── VisioForge_BaseFilters.ax │ ├── VisioForge_BaseFilters_x64.ax │ ├── VisioForge_MFP.dll │ ├── VisioForge_MFP64.dll │ ├── VisioForge_MFPX.dll │ ├── VisioForge_MFPX64.dll │ ├── VisioForge_MFT.dll │ ├── VisioForge_MFT64.dll │ ├── libmfxsw32.dll (QuickSync) │ ├── libmfxsw64.dll (QuickSync) │ └── ... (other filters) └── FFMPEG\ ├── x86\ │ ├── VisioForge_FFMPEG_Encoder.ax │ ├── avcodec-58.dll │ ├── avformat-58.dll │ ├── ffmedia.dll │ └── ... (other FFmpeg DLLs) └── x64\ ├── VisioForge_FFMPEG_Encoder_x64.ax └── ... (FFmpeg DLLs) ``` ### License Files - `license.rtf` - SDK license ### Total Size - **Core Filters Only**: ~40-60 MB - **With FFMPEG Encoder**: ~120-150 MB - **Complete Pack**: ~150-180 MB ### Hardware Requirements - **NVENC**: Requires NVIDIA GPU (GeForce GTX 600+ or Quadro K+) and drivers - **QuickSync**: Requires Intel CPU with integrated graphics (4th gen+) --- ## Virtual Camera SDK ### Core Files #### x86 (32-bit) **Virtual Camera Drivers**: - `VisioForge_Virtual_Camera.ax` - Virtual camera device driver - `VisioForge_Virtual_Audio_Card.ax` - Virtual audio device driver **Source Filters**: - `VisioForge_Push_Video_Source.ax` - Push source for streaming to virtual camera - `VisioForge_Screen_Capture_DD.ax` - DirectDraw screen capture **Processing** (included): - `VisioForge_Video_Effects_Pro.ax` - Video effects **Base Filters** (required): - `VisioForge_BaseFilters.ax` **Helper Libraries** (required): - `VisioForge_MFP.dll` - `VisioForge_MFPX.dll` **Runtime** (required): - `vcomp140.dll` - Visual C++ OpenMP runtime #### x64 (64-bit) **Virtual Camera Drivers**: - `VisioForge_Virtual_Camera_x64.ax` - `VisioForge_Virtual_Audio_Card_x64.ax` **Source Filters**: - `VisioForge_Push_Video_Source_x64.ax` - `VisioForge_Screen_Capture_DD_x64.ax` **Processing**: - `VisioForge_Video_Effects_Pro_x64.ax` **Base Filters** (required): - `VisioForge_BaseFilters_x64.ax` **Helper Libraries** (required): - `VisioForge_MFP64.dll` - `VisioForge_MFPX64.dll` ### Installation Directory Structure ``` YourApp\ ├── VisioForge_Virtual_Camera.ax ├── VisioForge_Virtual_Camera_x64.ax ├── VisioForge_Virtual_Audio_Card.ax ├── VisioForge_Virtual_Audio_Card_x64.ax ├── VisioForge_Push_Video_Source.ax ├── VisioForge_Push_Video_Source_x64.ax ├── VisioForge_Screen_Capture_DD.ax ├── VisioForge_Screen_Capture_DD_x64.ax ├── VisioForge_Video_Effects_Pro.ax ├── VisioForge_Video_Effects_Pro_x64.ax ├── VisioForge_BaseFilters.ax ├── VisioForge_BaseFilters_x64.ax ├── VisioForge_MFP.dll ├── VisioForge_MFP64.dll ├── VisioForge_MFPX.dll ├── VisioForge_MFPX64.dll └── vcomp140.dll ``` ### License Files - `license.rtf` - SDK license ### Total Size ~15-20 MB ### Important Notes - Virtual camera devices appear in video conferencing apps (Zoom, Teams, Skype, etc.) - Supports up to 4 virtual camera instances - Requires driver installation (included in installer) --- ## Common Dependencies ### Visual C++ Redistributables All SDKs require Visual C++ Redistributable 2015-2022. **Download Links**: - x86: https://aka.ms/vs/17/release/vc\_redist.x86.exe - x64: https://aka.ms/vs/17/release/vc\_redist.x64.exe **Installation Check** (programmatic): ``` // Check if VC++ Redistributable is installed bool IsVCRedistInstalled() { HKEY hKey; LONG result = RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\VisualStudio\\14.0\\VC\\Runtimes\\x64", 0, KEY_READ, &hKey); if (result == ERROR_SUCCESS) { RegCloseKey(hKey); return true; } return false; } ``` ### Registration Utility All SDKs include: - `reg_special.exe` - Custom registration utility This tool can be used instead of `regsvr32` for filter registration. --- ## Deployment Checklist ### Minimum Required Files For each SDK, you must include: 1. ✅ **Filter Files** - All .ax files for your architecture (x86/x64) 2. ✅ **Base Filters** - VisioForge\_BaseFilters.ax (if required by SDK) 3. ✅ **Helper DLLs** - VisioForge\_MFP*.dll, VisioForge\_MFPX*.dll 4. ✅ **Dependencies** - FFmpeg DLLs, VLC libraries, etc. 5. ✅ **License File** - license.rtf (display in installer) 6. ✅ **VC++ Redistributable** - Bundle or download in installer ### Optional Files - 📄 **LAV Filters** - Enhanced codec support (Processing Filters Pack) - 📄 **QuickSync DLLs** - Intel hardware encoding (Encoding Filters Pack) - 📄 **VLC Locale** - Multi-language support (VLC Source) - 📄 **Registration Utility** - reg\_special.exe (alternative to regsvr32) ### Architecture Considerations **32-bit Application**: - Include only x86 (.ax) files - No need for x64 versions **64-bit Application**: - Include only x64 (\_x64.ax) files - No need for x86 versions **AnyCPU/.NET Application**: - Include both x86 and x64 versions - Register both during installation - Application will use appropriate architecture at runtime --- ## File Size Summary | SDK | Minimum Size | With All Options | | --- | --- | --- | | **FFMPEG Source** | ~80 MB (x86) | ~190 MB (both arch) | | **VLC Source** | ~150 MB | ~200 MB (with locales) | | **Processing Filters** | ~20 MB | ~180 MB (with LAV) | | **Encoding Filters** | ~40 MB | ~300 MB (complete) | | **Virtual Camera** | ~15 MB | ~35 MB (both arch) | --- ## Testing Deployment Package Before releasing, verify all files are included: ``` @echo off echo Testing Filter Registration... REM Test each filter regsvr32 /s "VisioForge_FFMPEG_Source_x64.ax" if %errorLevel% neq 0 ( echo ERROR: FFMPEG Source failed to register echo Check if all FFmpeg DLLs are present exit /b 1 ) REM Test filter creation YourTestApp.exe echo All filters registered successfully! ``` --- ## See Also - [Filter Registration](../filter-registration/) - How to register filters - [Installer Integration](../installer-integration/) - Creating installers - [Deployment Overview](../) - Main deployment guide ---END OF PAGE--- ## FFmpeg Source Filter DirectShow Examples - C++, C#, VB.NET **URL:** https://www.visioforge.com/help/docs/directshow/ffmpeg-source-filters/examples/ **Description:** Build DirectShow graphs with FFmpeg Source Filter — file playback, hardware decoding, network streaming, and custom buffering in C++, C#, and VB.NET. **Tags:** DirectShow, C++, Windows, WinForms, Playback, Streaming, Decoding, RTSP, HLS, MP4, MKV, AVI, MOV, C#, VB.NET **API:** IFileSourceFilter, IFFMPEGSourceSettings, IBaseFilter, IVFRegister # Code Examples ## Overview This page provides practical code examples for using the FFMPEG Source Filter in DirectShow applications. Examples are provided in C++, C#, and VB.NET. ## Complete Working Samples **Official GitHub Repository**: All examples shown on this page are available as complete, working Visual Studio projects in our GitHub samples repository: 🔗 **[DirectShow Samples Repository](https://github.com/visioforge/directshow-samples)** ### FFMPEG Source Filter Samples - **[C# Sample](https://github.com/visioforge/directshow-samples/tree/master/FFMPEG%20Source%20Filter/dotnet/cs)** - Full-featured media player with all filter capabilities - **[VB.NET Sample](https://github.com/visioforge/directshow-samples/tree/master/FFMPEG%20Source%20Filter/dotnet/vbnet)** - VB.NET implementation - **[C++Builder Sample](https://github.com/visioforge/directshow-samples/tree/master/FFMPEG%20Source%20Filter/cpp_builder)** - C++ implementation Each sample includes: - Complete Visual Studio/C++Builder project files - Working code for playback, stream selection, and configuration - Hardware acceleration examples - Network streaming (RTSP/HLS) examples --- ## Prerequisites ### C++ Projects ``` #include #include #include "IFFMPEGSourceSettings.h" // From SDK #pragma comment(lib, "strmiids.lib") ``` ### C# Projects ``` using VisioForge.DirectShowAPI; using VisioForge.DirectShowLib; using System.Runtime.InteropServices; ``` **NuGet Packages**: - VisioForge.DirectShowAPI - MediaFoundationCore --- ## Example 1: Basic File Playback Play a local media file with default settings. ### C++ Implementation ``` #include #include #include "IFFMPEGSourceSettings.h" // CLSID for FFMPEG Source Filter DEFINE_GUID(CLSID_VFFFMPEGSource, 0x1974d893, 0x83e4, 0x4f89, 0x99, 0x8, 0x79, 0x5c, 0x52, 0x4c, 0xc1, 0x7e); HRESULT PlayFile(LPCWSTR filename, HWND hVideoWindow) { IGraphBuilder* pGraph = NULL; IMediaControl* pControl = NULL; IMediaEventEx* pEvent = NULL; IBaseFilter* pSourceFilter = NULL; IFileSourceFilter* pFileSource = NULL; IVideoWindow* pVideoWindow = NULL; HRESULT hr = S_OK; // Create Filter Graph hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void**)&pGraph); if (FAILED(hr)) return hr; // Create FFMPEG Source Filter hr = CoCreateInstance(CLSID_VFFFMPEGSource, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void**)&pSourceFilter); if (FAILED(hr)) goto cleanup; // Add filter to graph hr = pGraph->AddFilter(pSourceFilter, L"FFMPEG Source"); if (FAILED(hr)) goto cleanup; // Load file hr = pSourceFilter->QueryInterface(IID_IFileSourceFilter, (void**)&pFileSource); if (FAILED(hr)) goto cleanup; hr = pFileSource->Load(filename, NULL); if (FAILED(hr)) goto cleanup; // Render streams automatically hr = pGraph->QueryInterface(IID_IGraphBuilder, (void**)&pGraph); ICaptureGraphBuilder2* pBuild = NULL; hr = CoCreateInstance(CLSID_CaptureGraphBuilder2, NULL, CLSCTX_INPROC_SERVER, IID_ICaptureGraphBuilder2, (void**)&pBuild); if (SUCCEEDED(hr)) { hr = pBuild->SetFiltergraph(pGraph); // Render video stream hr = pBuild->RenderStream(NULL, &MEDIATYPE_Video, pSourceFilter, NULL, NULL); // Render audio stream hr = pBuild->RenderStream(NULL, &MEDIATYPE_Audio, pSourceFilter, NULL, NULL); pBuild->Release(); } // Set video window hr = pGraph->QueryInterface(IID_IVideoWindow, (void**)&pVideoWindow); if (SUCCEEDED(hr)) { pVideoWindow->put_Owner((OAHWND)hVideoWindow); pVideoWindow->put_WindowStyle(WS_CHILD | WS_CLIPSIBLINGS); RECT rc; GetClientRect(hVideoWindow, &rc); pVideoWindow->SetWindowPosition(0, 0, rc.right, rc.bottom); } // Get control interface hr = pGraph->QueryInterface(IID_IMediaControl, (void**)&pControl); if (FAILED(hr)) goto cleanup; // Run the graph hr = pControl->Run(); cleanup: if (pFileSource) pFileSource->Release(); if (pVideoWindow) pVideoWindow->Release(); if (pControl) pControl->Release(); if (pSourceFilter) pSourceFilter->Release(); if (pGraph) pGraph->Release(); return hr; } ``` ### C# Implementation ``` using System; using System.Runtime.InteropServices; using System.Windows.Forms; using VisioForge.DirectShowAPI; using VisioForge.DirectShowLib; public class FFMPEGSourceBasicExample { private IFilterGraph2 filterGraph; private IMediaControl mediaControl; private IVideoWindow videoWindow; private IBaseFilter sourceFilter; public void PlayFile(string filename, IntPtr videoWindowHandle) { try { // Create filter graph filterGraph = (IFilterGraph2)new FilterGraph(); mediaControl = (IMediaControl)filterGraph; videoWindow = (IVideoWindow)filterGraph; // Create and add FFMPEG Source filter sourceFilter = FilterGraphTools.AddFilterFromClsid( filterGraph, Consts.CLSID_VFFFMPEGSource, "FFMPEG Source"); // Load file var fileSource = sourceFilter as IFileSourceFilter; int hr = fileSource.Load(filename, null); DsError.ThrowExceptionForHR(hr); // Render streams ICaptureGraphBuilder2 captureGraph = (ICaptureGraphBuilder2)new CaptureGraphBuilder2(); hr = captureGraph.SetFiltergraph(filterGraph); DsError.ThrowExceptionForHR(hr); // Render video hr = captureGraph.RenderStream(null, MediaType.Video, sourceFilter, null, null); // Render audio hr = captureGraph.RenderStream(null, MediaType.Audio, sourceFilter, null, null); // Set video window videoWindow.put_Owner(videoWindowHandle); videoWindow.put_WindowStyle(WindowStyle.Child | WindowStyle.ClipSiblings); videoWindow.put_Visible(OABool.True); // Run graph mediaControl.Run(); Marshal.ReleaseComObject(captureGraph); } catch (Exception ex) { MessageBox.Show($"Error: {ex.Message}", "Playback Error"); } } public void Stop() { if (mediaControl != null) { mediaControl.Stop(); } if (videoWindow != null) { videoWindow.put_Visible(OABool.False); videoWindow.put_Owner(IntPtr.Zero); } FilterGraphTools.RemoveAllFilters(filterGraph); if (sourceFilter != null) Marshal.ReleaseComObject(sourceFilter); if (videoWindow != null) Marshal.ReleaseComObject(videoWindow); if (mediaControl != null) Marshal.ReleaseComObject(mediaControl); if (filterGraph != null) Marshal.ReleaseComObject(filterGraph); } } ``` ### VB.NET Implementation ``` Imports System.Runtime.InteropServices Imports VisioForge.DirectShowAPI Imports VisioForge.DirectShowLib Public Class FFMPEGSourceBasicExample Private filterGraph As IFilterGraph2 Private mediaControl As IMediaControl Private videoWindow As IVideoWindow Private sourceFilter As IBaseFilter Public Sub PlayFile(filename As String, videoWindowHandle As IntPtr) Try ' Create filter graph filterGraph = DirectCast(New FilterGraph(), IFilterGraph2) mediaControl = DirectCast(filterGraph, IMediaControl) videoWindow = DirectCast(filterGraph, IVideoWindow) ' Create and add FFMPEG Source filter sourceFilter = FilterGraphTools.AddFilterFromClsid( filterGraph, Consts.CLSID_VFFFMPEGSource, "FFMPEG Source") ' Load file Dim fileSource = DirectCast(sourceFilter, IFileSourceFilter) Dim hr As Integer = fileSource.Load(filename, Nothing) DsError.ThrowExceptionForHR(hr) ' Render streams Dim captureGraph As ICaptureGraphBuilder2 = DirectCast(New CaptureGraphBuilder2(), ICaptureGraphBuilder2) hr = captureGraph.SetFiltergraph(filterGraph) DsError.ThrowExceptionForHR(hr) ' Render video and audio captureGraph.RenderStream(Nothing, MediaType.Video, sourceFilter, Nothing, Nothing) captureGraph.RenderStream(Nothing, MediaType.Audio, sourceFilter, Nothing, Nothing) ' Set video window videoWindow.put_Owner(videoWindowHandle) videoWindow.put_WindowStyle(WindowStyle.Child Or WindowStyle.ClipSiblings) videoWindow.put_Visible(OABool.True) ' Run graph mediaControl.Run() Marshal.ReleaseComObject(captureGraph) Catch ex As Exception MessageBox.Show($"Error: {ex.Message}", "Playback Error") End Try End Sub Public Sub [Stop]() If mediaControl IsNot Nothing Then mediaControl.Stop() End If If videoWindow IsNot Nothing Then videoWindow.put_Visible(OABool.False) videoWindow.put_Owner(IntPtr.Zero) End If FilterGraphTools.RemoveAllFilters(filterGraph) If sourceFilter IsNot Nothing Then Marshal.ReleaseComObject(sourceFilter) If videoWindow IsNot Nothing Then Marshal.ReleaseComObject(videoWindow) If mediaControl IsNot Nothing Then Marshal.ReleaseComObject(mediaControl) If filterGraph IsNot Nothing Then Marshal.ReleaseComObject(filterGraph) End Sub End Class ``` --- ## Example 2: Hardware Acceleration Enable GPU decoding for better performance. ### C++ with Hardware Acceleration ``` HRESULT PlayFileWithGPU(LPCWSTR filename) { IBaseFilter* pSourceFilter = NULL; IFFMPEGSourceSettings* pSettings = NULL; // Create source filter HRESULT hr = CoCreateInstance(CLSID_VFFFMPEGSource, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void**)&pSourceFilter); if (FAILED(hr)) return hr; // Get configuration interface hr = pSourceFilter->QueryInterface(IID_IFFMPEGSourceSettings, (void**)&pSettings); if (FAILED(hr)) { pSourceFilter->Release(); return hr; } // Enable hardware acceleration (NVDEC/QuickSync/DXVA) hr = pSettings->SetHWAccelerationEnabled(TRUE); if (FAILED(hr)) { pSettings->Release(); pSourceFilter->Release(); return hr; } // Load file IFileSourceFilter* pFileSource = NULL; hr = pSourceFilter->QueryInterface(IID_IFileSourceFilter, (void**)&pFileSource); if (SUCCEEDED(hr)) { hr = pFileSource->Load(filename, NULL); pFileSource->Release(); } // Continue building graph... // (Add to graph, render streams, etc.) pSettings->Release(); pSourceFilter->Release(); return hr; } ``` ### C# with Hardware Acceleration ## ``` public void PlayFileWithHardwareAcceleration(string filename, IntPtr videoWindowHandle) { filterGraph = (IFilterGraph2)new FilterGraph(); // Create source filter sourceFilter = FilterGraphTools.AddFilterFromClsid( filterGraph, Consts.CLSID_VFFFMPEGSource, "FFMPEG Source"); // Configure hardware acceleration var settings = sourceFilter as IFFMPEGSourceSettings; if (settings != null) { // Enable GPU decoding int hr = settings.SetHWAccelerationEnabled(true); DsError.ThrowExceptionForHR(hr); } // Load file var fileSource = sourceFilter as IFileSourceFilter; fileSource.Load(filename, null); // Build and run graph... ICaptureGraphBuilder2 captureGraph = (ICaptureGraphBuilder2)new CaptureGraphBuilder2(); captureGraph.SetFiltergraph(filterGraph); captureGraph.RenderStream(null, MediaType.Video, sourceFilter, null, null); captureGraph.RenderStream(null, MediaType.Audio, sourceFilter, null, null); mediaControl = (IMediaControl)filterGraph; mediaControl.Run(); Marshal.ReleaseComObject(captureGraph); } ``` ## Example 3: Network Streaming (RTSP/HLS) Stream video from network sources. ### C# RTSP Streaming ``` public void PlayRTSPStream(string rtspUrl, IntPtr videoWindowHandle) { filterGraph = (IFilterGraph2)new FilterGraph(); sourceFilter = FilterGraphTools.AddFilterFromClsid( filterGraph, Consts.CLSID_VFFFMPEGSource, "FFMPEG Source"); // Configure for network streaming var settings = sourceFilter as IFFMPEGSourceSettings; if (settings != null) { // Set buffering mode for network streams settings.SetBufferingMode(FFMPEG_SOURCE_BUFFERING_MODE.FFMPEG_SOURCE_BUFFERING_MODE_ON); // Set connection timeout (in seconds) settings.SetLoadTimeOut(30); // Enable hardware decoding for performance settings.SetHWAccelerationEnabled(true); } // Load RTSP stream // Example: "rtsp://camera.example.com:554/stream" var fileSource = sourceFilter as IFileSourceFilter; int hr = fileSource.Load(rtspUrl, null); DsError.ThrowExceptionForHR(hr); // Build graph ICaptureGraphBuilder2 captureGraph = (ICaptureGraphBuilder2)new CaptureGraphBuilder2(); captureGraph.SetFiltergraph(filterGraph); captureGraph.RenderStream(null, MediaType.Video, sourceFilter, null, null); captureGraph.RenderStream(null, MediaType.Audio, sourceFilter, null, null); // Setup video window videoWindow = (IVideoWindow)filterGraph; videoWindow.put_Owner(videoWindowHandle); videoWindow.put_WindowStyle(WindowStyle.Child | WindowStyle.ClipSiblings); videoWindow.put_Visible(OABool.True); // Run mediaControl = (IMediaControl)filterGraph; mediaControl.Run(); Marshal.ReleaseComObject(captureGraph); } ``` ### C# HLS Streaming ``` public void PlayHLSStream(string hlsUrl, IntPtr videoWindowHandle) { filterGraph = (IFilterGraph2)new FilterGraph(); sourceFilter = FilterGraphTools.AddFilterFromClsid( filterGraph, Consts.CLSID_VFFFMPEGSource, "FFMPEG Source"); var settings = sourceFilter as IFFMPEGSourceSettings; if (settings != null) { // HLS streams benefit from buffering settings.SetBufferingMode(FFMPEG_SOURCE_BUFFERING_MODE.FFMPEG_SOURCE_BUFFERING_MODE_ON); // Longer timeout for HLS playlist loading settings.SetLoadTimeOut(60); // Hardware acceleration settings.SetHWAccelerationEnabled(true); } // Load HLS stream // Example: "https://example.com/stream/playlist.m3u8" var fileSource = sourceFilter as IFileSourceFilter; fileSource.Load(hlsUrl, null); // Build and run graph (same as RTSP example) ICaptureGraphBuilder2 captureGraph = (ICaptureGraphBuilder2)new CaptureGraphBuilder2(); captureGraph.SetFiltergraph(filterGraph); captureGraph.RenderStream(null, MediaType.Video, sourceFilter, null, null); captureGraph.RenderStream(null, MediaType.Audio, sourceFilter, null, null); videoWindow = (IVideoWindow)filterGraph; videoWindow.put_Owner(videoWindowHandle); videoWindow.put_WindowStyle(WindowStyle.Child | WindowStyle.ClipSiblings); mediaControl = (IMediaControl)filterGraph; mediaControl.Run(); Marshal.ReleaseComObject(captureGraph); } ``` --- ## Example 4: Custom FFmpeg Options Pass custom FFmpeg demuxer/decoder options. ### C# with Custom Options ``` public void PlayWithCustomOptions(string filename, IntPtr videoWindowHandle) { filterGraph = (IFilterGraph2)new FilterGraph(); sourceFilter = FilterGraphTools.AddFilterFromClsid( filterGraph, Consts.CLSID_VFFFMPEGSource, "FFMPEG Source"); var settings = sourceFilter as IFFMPEGSourceSettings; if (settings != null) { // Set custom FFmpeg options // Format: "key=value" for each option // Example 1: Set buffer size for network streams settings.SetCustomOption("buffer_size", "1024000"); // Example 2: Enable low latency mode settings.SetCustomOption("fflags", "nobuffer"); // Example 3: Set analyzer duration (microseconds) settings.SetCustomOption("analyzeduration", "1000000"); // Example 4: Set probe size settings.SetCustomOption("probesize", "5000000"); // Example 5: RTSP transport protocol settings.SetCustomOption("rtsp_transport", "tcp"); // Example 6: Set timeout (microseconds) settings.SetCustomOption("timeout", "5000000"); } // Load file var fileSource = sourceFilter as IFileSourceFilter; fileSource.Load(filename, null); // Build graph... ICaptureGraphBuilder2 captureGraph = (ICaptureGraphBuilder2)new CaptureGraphBuilder2(); captureGraph.SetFiltergraph(filterGraph); captureGraph.RenderStream(null, MediaType.Video, sourceFilter, null, null); captureGraph.RenderStream(null, MediaType.Audio, sourceFilter, null, null); mediaControl = (IMediaControl)filterGraph; mediaControl.Run(); Marshal.ReleaseComObject(captureGraph); } ``` ### Common FFmpeg Options ## ``` // Network streaming options settings.SetCustomOption("rtsp_transport", "tcp"); // Use TCP for RTSP settings.SetCustomOption("rtsp_flags", "prefer_tcp"); // Prefer TCP over UDP settings.SetCustomOption("timeout", "10000000"); // 10 second timeout settings.SetCustomOption("stimeout", "5000000"); // 5 second socket timeout // Buffer and probing options settings.SetCustomOption("buffer_size", "2097152"); // 2MB buffer settings.SetCustomOption("analyzeduration", "2000000"); // 2 seconds analysis settings.SetCustomOption("probesize", "10000000"); // 10MB probe size // Low latency options settings.SetCustomOption("fflags", "nobuffer"); // Disable buffering settings.SetCustomOption("flags", "low_delay"); // Low delay flag settings.SetCustomOption("framedrop", "1"); // Allow frame dropping // HTTP options settings.SetCustomOption("user_agent", "MyApp/1.0"); // Custom user agent settings.SetCustomOption("headers", "Authorization: Bearer token"); // Clear all custom options settings.ClearCustomOptions(); ``` ## Example 5: Buffering Mode Configuration Control buffering behavior for different scenarios. ### C# Buffering Examples ``` public enum BufferingScenario { LocalFile, NetworkStream, LowLatency } public void PlayWithBuffering(string source, BufferingScenario scenario, IntPtr videoWindowHandle) { filterGraph = (IFilterGraph2)new FilterGraph(); sourceFilter = FilterGraphTools.AddFilterFromClsid( filterGraph, Consts.CLSID_VFFFMPEGSource, "FFMPEG Source"); var settings = sourceFilter as IFFMPEGSourceSettings; if (settings != null) { switch (scenario) { case BufferingScenario.LocalFile: // Auto mode - let filter decide settings.SetBufferingMode( FFMPEG_SOURCE_BUFFERING_MODE.FFMPEG_SOURCE_BUFFERING_MODE_AUTO); break; case BufferingScenario.NetworkStream: // Enable buffering for smooth playback settings.SetBufferingMode( FFMPEG_SOURCE_BUFFERING_MODE.FFMPEG_SOURCE_BUFFERING_MODE_ON); settings.SetLoadTimeOut(30); // 30 second timeout break; case BufferingScenario.LowLatency: // Disable buffering for minimal latency settings.SetBufferingMode( FFMPEG_SOURCE_BUFFERING_MODE.FFMPEG_SOURCE_BUFFERING_MODE_OFF); settings.SetCustomOption("fflags", "nobuffer"); settings.SetCustomOption("flags", "low_delay"); break; } } // Load source var fileSource = sourceFilter as IFileSourceFilter; fileSource.Load(source, null); // Build and run graph... ICaptureGraphBuilder2 captureGraph = (ICaptureGraphBuilder2)new CaptureGraphBuilder2(); captureGraph.SetFiltergraph(filterGraph); captureGraph.RenderStream(null, MediaType.Video, sourceFilter, null, null); captureGraph.RenderStream(null, MediaType.Audio, sourceFilter, null, null); mediaControl = (IMediaControl)filterGraph; mediaControl.Run(); Marshal.ReleaseComObject(captureGraph); } ``` --- ## Example 6: Multi-Stream Selection Select specific video and audio tracks. ### C# Stream Selection ## ``` public void PlayWithStreamSelection(string filename, int videoStreamIndex, int audioStreamIndex, IntPtr videoWindowHandle) { filterGraph = (IFilterGraph2)new FilterGraph(); sourceFilter = FilterGraphTools.AddFilterFromClsid( filterGraph, Consts.CLSID_VFFFMPEGSource, "FFMPEG Source"); // Load file first var fileSource = sourceFilter as IFileSourceFilter; fileSource.Load(filename, null); // Get available streams var streamSelect = sourceFilter as IAMStreamSelect; if (streamSelect != null) { streamSelect.Count(out int streamCount); List videoStreams = new List(); List audioStreams = new List(); // Enumerate streams for (int i = 0; i < streamCount; i++) { streamSelect.Info(i, out AMMediaType mt, out _, out _, out _, out string name, out _, out _); if (mt.majorType == MediaType.Video) { videoStreams.Add(i); Console.WriteLine($"Video Stream {videoStreams.Count - 1}: {name}"); } else if (mt.majorType == MediaType.Audio) { audioStreams.Add(i); Console.WriteLine($"Audio Stream {audioStreams.Count - 1}: {name}"); } DsUtils.FreeAMMediaType(mt); } // Enable selected streams if (videoStreamIndex >= 0 && videoStreamIndex < videoStreams.Count) { streamSelect.Enable(videoStreams[videoStreamIndex], AMStreamSelectEnableFlags.Enable); } if (audioStreamIndex >= 0 && audioStreamIndex < audioStreams.Count) { streamSelect.Enable(audioStreams[audioStreamIndex], AMStreamSelectEnableFlags.Enable); } } // Build graph ICaptureGraphBuilder2 captureGraph = (ICaptureGraphBuilder2)new CaptureGraphBuilder2(); captureGraph.SetFiltergraph(filterGraph); captureGraph.RenderStream(null, MediaType.Video, sourceFilter, null, null); captureGraph.RenderStream(null, MediaType.Audio, sourceFilter, null, null); videoWindow = (IVideoWindow)filterGraph; videoWindow.put_Owner(videoWindowHandle); videoWindow.put_WindowStyle(WindowStyle.Child | WindowStyle.ClipSiblings); mediaControl = (IMediaControl)filterGraph; mediaControl.Run(); Marshal.ReleaseComObject(captureGraph); } ``` ## Example 7: Container Data Callback (e.g., SMPTE KLV metadata) Receive raw out-of-band data buffers carried in the container (such as SMPTE KLV metadata packets in MPEG-TS streams). The callback fires once per data packet and surfaces the packet bytes plus its presentation/end timestamps. ### C# Data Callback Implementation ``` // Real signature (per IFFmpegSourceSettings.h): // HRESULT (BYTE* buffer, int bufferLen, int dataType, LONGLONG startTime, LONGLONG stopTime) // dataType is a VF_DATA_TYPE enum: // 0 = unknown, 1 = SMPTE_KLV public delegate int FFMPEGDataCallbackDelegate( IntPtr buffer, int bufferLen, int dataType, long startTime, long stopTime); public class FFMPEGDataCallbackExample { private IFilterGraph2 filterGraph; private IBaseFilter sourceFilter; private FFMPEGDataCallbackDelegate dataCallback; public void PlayWithCallback(string filename, Action onPacket) { // Keep a managed reference to the delegate so the GC doesn't collect it // while native code holds a function pointer to it. this.dataCallback = (buffer, bufferLen, dataType, startTime, stopTime) => { byte[] managed = new byte[bufferLen]; Marshal.Copy(buffer, managed, 0, bufferLen); onPacket(managed, dataType, startTime, stopTime); return 0; // S_OK }; filterGraph = (IFilterGraph2)new FilterGraph(); sourceFilter = FilterGraphTools.AddFilterFromClsid( filterGraph, Consts.CLSID_VFFFMPEGSource, "FFMPEG Source"); var settings = sourceFilter as IFFMPEGSourceSettings; if (settings != null) { // Wire up the data callback settings.SetDataCallback(this.dataCallback); } // Load file var fileSource = sourceFilter as IFileSourceFilter; fileSource.Load(filename, null); // Build graph (without renderers if you only want callbacks) ICaptureGraphBuilder2 captureGraph = (ICaptureGraphBuilder2)new CaptureGraphBuilder2(); captureGraph.SetFiltergraph(filterGraph); // Render normally; the data callback fires alongside playback. captureGraph.RenderStream(null, MediaType.Video, sourceFilter, null, null); captureGraph.RenderStream(null, MediaType.Audio, sourceFilter, null, null); var mediaControl = (IMediaControl)filterGraph; mediaControl.Run(); Marshal.ReleaseComObject(captureGraph); } } // Usage: // example.PlayWithCallback("input.ts", (bytes, dataType, startTime, stopTime) => // { // const int VF_DATA_TYPE_SMPTE_KLV = 1; // if (dataType == VF_DATA_TYPE_SMPTE_KLV) // { // // Decode KLV metadata packet // Console.WriteLine($"KLV packet: {bytes.Length} bytes, {startTime}–{stopTime}"); // } // }); ``` --- ## Example 8: Timestamp Callback Monitor demuxer/stream timing per media type. ### C# Timestamp Callback ## ``` // Real signature (per IFFmpegSourceSettings.h): // HRESULT (int mediaType, __int64 demuxerStartTime, // __int64 streamStartTime, __int64 timestamp) // mediaType selects between audio and video streams. public delegate int FFMPEGTimestampCallbackDelegate( int mediaType, long demuxerStartTime, long streamStartTime, long timestamp); private FFMPEGTimestampCallbackDelegate timestampCallback; public void PlayWithTimestampCallback(string filename) { // Hold the delegate so it isn't GC'd while native code calls back. this.timestampCallback = (mediaType, demuxerStart, streamStart, timestamp) => { Console.WriteLine( $"mediaType={mediaType} demuxerStart={demuxerStart} " + $"streamStart={streamStart} timestamp={timestamp}"); return 0; // S_OK }; filterGraph = (IFilterGraph2)new FilterGraph(); sourceFilter = FilterGraphTools.AddFilterFromClsid( filterGraph, Consts.CLSID_VFFFMPEGSource, "FFMPEG Source"); var settings = sourceFilter as IFFMPEGSourceSettings; if (settings != null) { settings.SetTimestampCallback(this.timestampCallback); } // Load and play file... var fileSource = sourceFilter as IFileSourceFilter; fileSource.Load(filename, null); ICaptureGraphBuilder2 captureGraph = (ICaptureGraphBuilder2)new CaptureGraphBuilder2(); captureGraph.SetFiltergraph(filterGraph); captureGraph.RenderStream(null, MediaType.Video, sourceFilter, null, null); captureGraph.RenderStream(null, MediaType.Audio, sourceFilter, null, null); var mediaControl = (IMediaControl)filterGraph; mediaControl.Run(); Marshal.ReleaseComObject(captureGraph); } ``` ## Example 9: License Activation Activate purchased license. ### C# License Activation ``` public void PlayWithLicense(string filename, string licenseKey, IntPtr videoWindowHandle) { filterGraph = (IFilterGraph2)new FilterGraph(); sourceFilter = FilterGraphTools.AddFilterFromClsid( filterGraph, Consts.CLSID_VFFFMPEGSource, "FFMPEG Source"); // Activate license var registration = sourceFilter as IVFRegister; if (registration != null) { int hr = registration.SetLicenseKey(licenseKey); if (hr != 0) { throw new Exception("License activation failed"); } } // Configure and play... var settings = sourceFilter as IFFMPEGSourceSettings; if (settings != null) { settings.SetHWAccelerationEnabled(true); } var fileSource = sourceFilter as IFileSourceFilter; fileSource.Load(filename, null); ICaptureGraphBuilder2 captureGraph = (ICaptureGraphBuilder2)new CaptureGraphBuilder2(); captureGraph.SetFiltergraph(filterGraph); captureGraph.RenderStream(null, MediaType.Video, sourceFilter, null, null); captureGraph.RenderStream(null, MediaType.Audio, sourceFilter, null, null); videoWindow = (IVideoWindow)filterGraph; videoWindow.put_Owner(videoWindowHandle); videoWindow.put_WindowStyle(WindowStyle.Child | WindowStyle.ClipSiblings); mediaControl = (IMediaControl)filterGraph; mediaControl.Run(); Marshal.ReleaseComObject(captureGraph); } ``` --- ## Example 10: Complete Media Player Full-featured media player with all features. ### C# Complete Example ``` using System; using System.Runtime.InteropServices; using System.Windows.Forms; using VisioForge.DirectShowAPI; using VisioForge.DirectShowLib; public class FFMPEGMediaPlayer : IDisposable { private IFilterGraph2 filterGraph; private ICaptureGraphBuilder2 captureGraph; private IMediaControl mediaControl; private IMediaSeeking mediaSeeking; private IVideoWindow videoWindow; private IMediaEventEx mediaEventEx; private IBaseFilter sourceFilter; private const int WM_GRAPHNOTIFY = 0x8000 + 1; public event EventHandler PlaybackComplete; public void Initialize(IntPtr windowHandle, IntPtr notifyHandle) { // Create filter graph filterGraph = (IFilterGraph2)new FilterGraph(); captureGraph = (ICaptureGraphBuilder2)new CaptureGraphBuilder2(); mediaControl = (IMediaControl)filterGraph; mediaSeeking = (IMediaSeeking)filterGraph; videoWindow = (IVideoWindow)filterGraph; mediaEventEx = (IMediaEventEx)filterGraph; // Setup event notifications int hr = mediaEventEx.SetNotifyWindow(notifyHandle, WM_GRAPHNOTIFY, IntPtr.Zero); DsError.ThrowExceptionForHR(hr); // Attach capture graph hr = captureGraph.SetFiltergraph(filterGraph); DsError.ThrowExceptionForHR(hr); } public void LoadFile(string filename, bool enableGPU, bool enableBuffering, string licenseKey = null) { // Create source filter sourceFilter = FilterGraphTools.AddFilterFromClsid( filterGraph, Consts.CLSID_VFFFMPEGSource, "FFMPEG Source"); // Register license if provided if (!string.IsNullOrEmpty(licenseKey)) { var registration = sourceFilter as IVFRegister; registration?.SetLicenseKey(licenseKey); } // Configure filter var settings = sourceFilter as IFFMPEGSourceSettings; if (settings != null) { settings.SetHWAccelerationEnabled(enableGPU); if (enableBuffering) { settings.SetBufferingMode( FFMPEG_SOURCE_BUFFERING_MODE.FFMPEG_SOURCE_BUFFERING_MODE_ON); } else { settings.SetBufferingMode( FFMPEG_SOURCE_BUFFERING_MODE.FFMPEG_SOURCE_BUFFERING_MODE_AUTO); } settings.SetLoadTimeOut(30); } // Load file var fileSource = sourceFilter as IFileSourceFilter; int hr = fileSource.Load(filename, null); DsError.ThrowExceptionForHR(hr); // Render streams hr = captureGraph.RenderStream(null, MediaType.Video, sourceFilter, null, null); hr = captureGraph.RenderStream(null, MediaType.Audio, sourceFilter, null, null); } public void SetVideoWindow(IntPtr handle, int width, int height) { if (videoWindow != null) { videoWindow.put_Owner(handle); videoWindow.put_WindowStyle(WindowStyle.Child | WindowStyle.ClipSiblings); videoWindow.SetWindowPosition(0, 0, width, height); videoWindow.put_Visible(OABool.True); } } public void Play() { mediaControl?.Run(); } public void Pause() { mediaControl?.Pause(); } public void Stop() { mediaControl?.Stop(); } public void Seek(long timeInSeconds) { if (mediaSeeking != null) { long duration; mediaSeeking.GetDuration(out duration); long seekPos = timeInSeconds * 10000000; // Convert to 100-nanosecond units if (seekPos <= duration) { mediaSeeking.SetPositions(ref seekPos, AMSeekingSeekingFlags.AbsolutePositioning, IntPtr.Zero, AMSeekingSeekingFlags.NoPositioning); } } } public long GetPosition() { if (mediaSeeking != null) { mediaSeeking.GetCurrentPosition(out long position); return position / 10000000; // Convert to seconds } return 0; } public long GetDuration() { if (mediaSeeking != null) { mediaSeeking.GetDuration(out long duration); return duration / 10000000; // Convert to seconds } return 0; } public void HandleGraphEvent() { if (mediaEventEx != null) { while (mediaEventEx.GetEvent(out EventCode eventCode, out IntPtr param1, out IntPtr param2, 0) == 0) { mediaEventEx.FreeEventParams(eventCode, param1, param2); if (eventCode == EventCode.Complete) { PlaybackComplete?.Invoke(this, EventArgs.Empty); } } } } public void Dispose() { if (mediaControl != null) { mediaControl.Stop(); } if (mediaEventEx != null) { mediaEventEx.SetNotifyWindow(IntPtr.Zero, 0, IntPtr.Zero); } if (videoWindow != null) { videoWindow.put_Visible(OABool.False); videoWindow.put_Owner(IntPtr.Zero); } FilterGraphTools.RemoveAllFilters(filterGraph); if (sourceFilter != null) Marshal.ReleaseComObject(sourceFilter); if (videoWindow != null) Marshal.ReleaseComObject(videoWindow); if (mediaSeeking != null) Marshal.ReleaseComObject(mediaSeeking); if (mediaEventEx != null) Marshal.ReleaseComObject(mediaEventEx); if (captureGraph != null) Marshal.ReleaseComObject(captureGraph); if (mediaControl != null) Marshal.ReleaseComObject(mediaControl); if (filterGraph != null) Marshal.ReleaseComObject(filterGraph); } } ``` ### Usage Example ## ``` public partial class MainForm : Form { private FFMPEGMediaPlayer player; public MainForm() { InitializeComponent(); player = new FFMPEGMediaPlayer(); } private void btnLoad_Click(object sender, EventArgs e) { OpenFileDialog dlg = new OpenFileDialog(); dlg.Filter = "Video Files|*.mp4;*.mkv;*.avi;*.mov|All Files|*.*"; if (dlg.ShowDialog() == DialogResult.OK) { player.Initialize(panelVideo.Handle, this.Handle); player.LoadFile(dlg.FileName, enableGPU: true, enableBuffering: true); player.SetVideoWindow(panelVideo.Handle, panelVideo.Width, panelVideo.Height); player.PlaybackComplete += Player_PlaybackComplete; player.Play(); } } private void Player_PlaybackComplete(object sender, EventArgs e) { MessageBox.Show("Playback complete"); } protected override void WndProc(ref Message m) { if (m.Msg == 0x8000 + 1) // WM_GRAPHNOTIFY { player?.HandleGraphEvent(); } base.WndProc(ref m); } private void MainForm_FormClosing(object sender, FormClosingEventArgs e) { player?.Dispose(); } } ``` ## Troubleshooting ### Issue: "Class not registered" Error **Solution**: Ensure filter is registered: ``` regsvr32 VisioForge_FFMPEG_Source_x64.ax ``` ### Issue: Hardware Acceleration Not Working **Solution**: Check GPU support and drivers: ``` var settings = sourceFilter as IFFMPEGSourceSettings; bool isEnabled; settings.GetHWAccelerationEnabled(out isEnabled); Console.WriteLine($"HW Acceleration: {isEnabled}"); ``` ### Issue: Network Stream Connection Fails **Solution**: Increase timeout and use custom options: ``` settings.SetLoadTimeOut(60); settings.SetCustomOption("timeout", "30000000"); // 30 seconds settings.SetCustomOption("rtsp_transport", "tcp"); ``` --- ## See Also ### Documentation - [Interface Reference](../interface-reference/) - Complete API reference - [Deployment Guide](../../deployment/) - Filter deployment ### Code Samples - **[GitHub Samples Repository](https://github.com/visioforge/directshow-samples)** - Complete working examples - **[C# Sample Project](https://github.com/visioforge/directshow-samples/tree/master/FFMPEG%20Source%20Filter/dotnet/cs)** - Full-featured C# implementation - **[VB.NET Sample Project](https://github.com/visioforge/directshow-samples/tree/master/FFMPEG%20Source%20Filter/dotnet/vbnet)** - VB.NET implementation - **[C++ Sample Project](https://github.com/visioforge/directshow-samples/tree/master/FFMPEG%20Source%20Filter/cpp_builder)** - C++Builder implementation ### External Resources - [FFmpeg Documentation](https://ffmpeg.org/documentation.html) - [DirectShow Programming Guide](https://learn.microsoft.com/en-us/windows/win32/DirectShow/directshow) ### Support - [Technical Support](https://support.visioforge.com) - Get help from VisioForge team - [Discord Community](https://discord.com/invite/yvXUG56WCH) - Join our community ---END OF PAGE--- ## FFmpeg Source DirectShow Filter - 100+ Media Formats **URL:** https://www.visioforge.com/help/docs/directshow/ffmpeg-source-filters/ **Description:** DirectShow source filter powered by FFmpeg for decoding MP4, MKV, H.265, and 100+ formats with hardware acceleration. COM interface for C++, C#, and Delphi. **Tags:** DirectShow, C++, Windows, Streaming **API:** IBaseFilter, IFileSourceFilter, FFMPEGFilter, FileSource, IFFMPEGSourceSettings # FFMPEG Source DirectShow Filter ## Introduction The FFMPEG Source DirectShow filter enables developers to seamlessly integrate advanced media decoding and playback capabilities into any DirectShow-compatible application. This powerful component bridges the gap between complex multimedia formats and your software development needs, providing a robust foundation for building media-rich applications. --- ## Installation Before using the code samples and integrating the filter into your application, you must first install the FFMPEG Source DirectShow Filter from the [product page](https://www.visioforge.com/ffmpeg-source-directshow-filter). **Installation Steps**: 1. Download the SDK installer from the product page 2. Run the installer with administrative privileges 3. The installer will register the FFMPEG Source filter and deploy all necessary FFMPEG DLLs 4. Sample applications and source code will be available in the installation directory **Note**: The filter must be properly registered on the system before it can be used in your applications. The installer handles this automatically. --- ## Key Features and Capabilities Our filter comes bundled with all necessary FFMPEG DLLs and provides a feature-rich DirectShow filter interface that supports: - **Extensive Format Compatibility**: Handle a wide range of video and audio formats including MP4, MKV, AVI, MOV, WMV, FLV, and many others without additional codec installations - **Network Stream Support**: Connect to RTSP, RTMP, HTTP, UDP, and TCP streams for live media integration - **Multiple Stream Management**: Select between video and audio streams in multi-stream media files - **Advanced Seeking Capabilities**: Implement precise seeking functionality in your applications - **GPU Acceleration**: Utilize hardware acceleration for optimal performance ## Implementation Examples The SDK includes comprehensive sample applications for multiple development environments: ### Delphi Integration (Primary) ``` // Initialize the FFMPEG Source filter in Delphi using DSPack procedure TMainForm.InitializeFFMPEGSource; var FFMPEGFilter: IBaseFilter; FileSource: IFileSourceFilter; begin // Create FFMPEG Source filter instance // IMPORTANT: Ensure proper COM initialization before this call CoCreateInstance(CLSID_FFMPEGSource, nil, CLSCTX_INPROC_SERVER, IID_IBaseFilter, FFMPEGFilter); // Query for file source interface FFMPEGFilter.QueryInterface(IID_IFileSourceFilter, FileSource); // Load media file - can be local or network URL FileSource.Load('C:\media\sample.mp4', nil); // Add to filter graph for rendering FilterGraph.AddFilter(FFMPEGFilter, 'FFMPEG Source'); // Connect to appropriate renderers or processing filters // FilterGraph.RenderStream(...); end; ``` ### C# Integration (.NET) ``` using System; using System.Runtime.InteropServices; using VisioForge.DirectShowAPI; using VisioForge.DirectShowLib; // Initialize the FFMPEG Source filter in C# using DirectShowLib public class FFMPEGSourcePlayer { private IFilterGraph2 filterGraph; private ICaptureGraphBuilder2 captureGraph; private IMediaControl mediaControl; private IMediaSeeking mediaSeeking; private IMediaEventEx mediaEventEx; private IBaseFilter sourceFilter; private IBaseFilter videoRenderer; public void Initialize(string filename, IntPtr videoWindowHandle) { try { // Create the filter graph manager filterGraph = (IFilterGraph2)new FilterGraph(); captureGraph = (ICaptureGraphBuilder2)new CaptureGraphBuilder2(); mediaControl = (IMediaControl)filterGraph; mediaSeeking = (IMediaSeeking)filterGraph; mediaEventEx = (IMediaEventEx)filterGraph; // Attach the filter graph to the capture graph int hr = captureGraph.SetFiltergraph(filterGraph); DsError.ThrowExceptionForHR(hr); // Create the FFMPEG Source filter using the correct CLSID sourceFilter = FilterGraphTools.AddFilterFromClsid( filterGraph, Consts.CLSID_VFFFMPEGSource, "FFMPEG Source"); // Optional: Register purchased version // var reg = sourceFilter as IVFRegister; // reg?.SetLicenseKey("your-license-key-here"); // Configure filter settings var filterConfig = sourceFilter as IFFMPEGSourceSettings; if (filterConfig != null) { // Set buffering mode (AUTO, ON, or OFF) filterConfig.SetBufferingMode(FFMPEG_SOURCE_BUFFERING_MODE.FFMPEG_SOURCE_BUFFERING_MODE_AUTO); // Enable hardware acceleration (GPU decoding) filterConfig.SetHWAccelerationEnabled(true); // Set connection timeout (milliseconds) filterConfig.SetLoadTimeOut(30000); } // Load the media file or network stream var sourceFilterIntf = sourceFilter as IFileSourceFilter; hr = sourceFilterIntf.Load(filename, null); DsError.ThrowExceptionForHR(hr); // Create video renderer (EVR - Enhanced Video Renderer) Guid CLSID_EVR = new Guid("FA10746C-9B63-4B6C-BC49-FC300EA5F256"); videoRenderer = FilterGraphTools.AddFilterFromClsid(filterGraph, CLSID_EVR, "EVR"); // Configure EVR var evrConfig = videoRenderer as MediaFoundation.EVR.IEVRFilterConfig; evrConfig?.SetNumberOfStreams(1); // Set video window for rendering var getService = videoRenderer as MediaFoundation.IMFGetService; if (getService != null) { getService.GetService( MediaFoundation.MFServices.MR_VIDEO_RENDER_SERVICE, typeof(MediaFoundation.IMFVideoDisplayControl).GUID, out var videoDisplayControlObj); var videoDisplayControl = videoDisplayControlObj as MediaFoundation.IMFVideoDisplayControl; videoDisplayControl?.SetVideoWindow(videoWindowHandle); } // Render the streams hr = captureGraph.RenderStream(null, MediaType.Video, sourceFilter, null, videoRenderer); DsError.ThrowExceptionForHR(hr); hr = captureGraph.RenderStream(null, MediaType.Audio, sourceFilter, null, null); // Note: Audio rendering errors are not critical for video-only playback // Start playback hr = mediaControl.Run(); DsError.ThrowExceptionForHR(hr); } catch (Exception ex) { Console.WriteLine($"Error initializing FFMPEG Source: {ex.Message}"); Cleanup(); throw; } } public void Cleanup() { // Stop playback if (mediaControl != null) { mediaControl.StopWhenReady(); mediaControl.Stop(); } // Stop receiving events mediaEventEx?.SetNotifyWindow(IntPtr.Zero, 0, IntPtr.Zero); // Remove all filters FilterGraphTools.RemoveAllFilters(filterGraph); // Release DirectShow interfaces if (mediaControl != null) { Marshal.ReleaseComObject(mediaControl); mediaControl = null; } if (mediaSeeking != null) { Marshal.ReleaseComObject(mediaSeeking); mediaSeeking = null; } if (mediaEventEx != null) { Marshal.ReleaseComObject(mediaEventEx); mediaEventEx = null; } if (sourceFilter != null) { Marshal.ReleaseComObject(sourceFilter); sourceFilter = null; } if (videoRenderer != null) { Marshal.ReleaseComObject(videoRenderer); videoRenderer = null; } if (filterGraph != null) { Marshal.ReleaseComObject(filterGraph); filterGraph = null; } if (captureGraph != null) { Marshal.ReleaseComObject(captureGraph); captureGraph = null; } } } ``` **Key CLSIDs and GUIDs:** ``` // FFMPEG Source Filter CLSID — same value used across the C# / C++ samples and // the registry registration in ../deployment/filter-registration.md. public static readonly Guid CLSID_VFFFMPEGSource = new Guid("1974D893-83E4-4F89-9908-795C524CC17E"); // IFFMPEGSourceSettings interface — for the canonical IID see the interface header // (`IFFmpegSourceSettings.h` / `IFFmpegSourceSettings.cs`) linked from // [interface-reference.md](./interface-reference.md). The interface IID is distinct // from the filter CLSID above (a single GUID cannot serve as both). public interface IFFMPEGSourceSettings { /* ... */ } // IVFRegister Interface IID (for licensing) [Guid("59E82754-B531-4A8E-A94D-57C75F01DA30")] public interface IVFRegister { /* ... */ } ``` **Required NuGet Packages:** - `VisioForge.DirectShowAPI` - DirectShow wrapper library - `MediaFoundation.Net` - Media Foundation wrapper for EVR renderer **Stream Selection Example:** ``` // Select specific video or audio streams in multi-stream files var streamSelect = sourceFilter as IAMStreamSelect; if (streamSelect != null) { streamSelect.Count(out int streamCount); for (int i = 0; i < streamCount; i++) { streamSelect.Info(i, out var mediaType, out _, out _, out _, out var name, out _, out _); if (mediaType.majorType == MediaType.Video) { // Enable the first video stream streamSelect.Enable(i, AMStreamSelectEnableFlags.Enable); break; } } } ``` ### C++ Integration Example ``` // Initialize the FFMPEG Source filter in C++ using DirectShow HRESULT InitializeFFMPEGSource() { HRESULT hr = S_OK; IGraphBuilder* pGraph = NULL; IMediaControl* pControl = NULL; IBaseFilter* pFFMPEGSource = NULL; IFileSourceFilter* pFileSource = NULL; // Initialize COM CoInitialize(NULL); // Create the filter graph manager hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void**)&pGraph); if (FAILED(hr)) return hr; // Create the FFMPEG Source filter hr = CoCreateInstance(CLSID_FFMPEGSource, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void**)&pFFMPEGSource); if (FAILED(hr)) goto cleanup; // Add the filter to the graph hr = pGraph->AddFilter(pFFMPEGSource, L"FFMPEG Source"); if (FAILED(hr)) goto cleanup; // Get the IFileSourceFilter interface hr = pFFMPEGSource->QueryInterface(IID_IFileSourceFilter, (void**)&pFileSource); if (FAILED(hr)) goto cleanup; // Load the media file hr = pFileSource->Load(L"C:\\media\\sample.mp4", NULL); if (FAILED(hr)) goto cleanup; // Render the output pins of the FFMPEG Source filter hr = pGraph->Render(GetPin(pFFMPEGSource, PINDIR_OUTPUT, 0)); // Get the media control interface for playback control hr = pGraph->QueryInterface(IID_IMediaControl, (void**)&pControl); if (SUCCEEDED(hr)) { // Start playback hr = pControl->Run(); // ... handle playback as needed } cleanup: // Release interfaces if (pControl) pControl->Release(); if (pFileSource) pFileSource->Release(); if (pFFMPEGSource) pFFMPEGSource->Release(); if (pGraph) pGraph->Release(); return hr; } // Helper function to get pins from a filter IPin* GetPin(IBaseFilter* pFilter, PIN_DIRECTION PinDir, int nPin) { IEnumPins* pEnum = NULL; IPin* pPin = NULL; if (pFilter) { pFilter->EnumPins(&pEnum); if (pEnum) { while (pEnum->Next(1, &pPin, NULL) == S_OK) { PIN_DIRECTION PinDirThis; pPin->QueryDirection(&PinDirThis); if (PinDir == PinDirThis) { if (nPin == 0) break; nPin--; } pPin->Release(); pPin = NULL; } pEnum->Release(); } } return pPin; } ``` ## Integration with Processing Filters Enhance your media pipeline by connecting the FFMPEG Source filter with additional processing components: - Apply real-time video effects and transformations - Process audio streams for custom sound manipulation - Implement specialized media analysis features Our [Processing Filters pack](https://www.visioforge.com/processing-filters-pack) offers additional capabilities, or you can integrate with any standard DirectShow-compatible filters. ## Technical Specifications ### Supported DirectShow Interfaces The filter implements these standard DirectShow interfaces for maximum compatibility: - **IAMStreamSelect**: Select between multiple video and audio streams - **IAMStreamConfig**: Configure video and audio settings - **IFileSourceFilter**: Set filename or streaming URL - **IMediaSeeking**: Implement precise seeking functionality - **ISpecifyPropertyPages**: Access configuration through property pages ## Version History and Updates ### Version 15.0 - Enhanced FFMPEG libraries with latest codecs - Added GPU decoding support for improved performance - Optimized memory management for large files ### Version 12.0 - Updated FFMPEG libraries - Improved compatibility with Windows 10/11 ### Version 11.0 - Updated FFMPEG libraries - Fixed seeking issues with certain file formats ### Version 10.0 - Updated FFMPEG libraries - Added support for additional container formats ### Version 9.0 - Updated FFMPEG libraries - Performance optimizations ### Version 8.0 - Updated FFMPEG libraries - Improved error handling ### Version 7.0 - Initial release as an independent product - Core functionality established ## Additional Resources - Explore our [product page](https://www.visioforge.com/ffmpeg-source-directshow-filter) for detailed specifications - View our [End User License Agreement](../../eula/) for licensing details - Check our developer documentation for advanced implementation scenarios ---END OF PAGE--- ## FFmpeg Source DirectShow Filter Interface API Reference **URL:** https://www.visioforge.com/help/docs/directshow/ffmpeg-source-filters/interface-reference/ **Description:** IFFmpegSourceSettings interface with hardware acceleration, buffering modes, custom FFmpeg options, and callbacks for DirectShow. **Tags:** DirectShow, C++, Windows, Streaming, Decoding, RTSP, C# **API:** IFFmpegSourceSettings, IFileSourceFilter, IFFMPEGSourceSettings # IFFMPEGSourceSettings Interface Reference ## Overview The `IFFMPEGSourceSettings` interface provides advanced configuration options for the FFMPEG Source DirectShow filter. This interface enables developers to control hardware acceleration, buffering behavior, custom FFmpeg options, and various callbacks for media playback. > The .NET / C++ / Delphi headers spell this interface `IFFMPEGSourceSettings` (all uppercase `FFMPEG`). The legacy header file paths `IFFmpegSourceSettings.h` / `.cs` keep the historical mixed-case filename — but the symbol exposed by all three languages is the all-caps form. The two are equivalent identifiers in C#; this page uses the all-caps form consistently with examples.md / index.md. ## Interface Definition - **Interface Name**: `IFFMPEGSourceSettings` - **Filter CLSID it queries through**: `{1974D893-83E4-4F89-9908-795C524CC17E}` (the FFMPEG Source filter — the interface IID itself is distinct; consult the header). - **Inherits From**: `IUnknown` ### Interface Definition Files Complete interface definitions are available on GitHub: - **C# (.NET)**: [IFFmpegSourceSettings.cs](https://github.com/visioforge/directshow-samples/blob/main/Interfaces/dotnet/IFFmpegSourceSettings.cs) - **C++ Header**: [IFFmpegSourceSettings.h](https://github.com/visioforge/directshow-samples/blob/main/Interfaces/cpp/FFMPEG%20Source/IFFmpegSourceSettings.h) - **Delphi**: [VCFiltersAPI.pas](https://github.com/visioforge/directshow-samples/blob/main/Interfaces/delphi/VCFiltersAPI.pas) (search for `IFFMPEGSourceSettings`) All interface definitions include: - Complete method signatures with proper marshalling attributes - Callback delegate definitions - Enumeration types (buffering modes, media types) - Usage documentation and examples ## Methods Reference ### Hardware Acceleration #### GetHWAccelerationEnabled Retrieves the current hardware acceleration state. **Syntax (C++)**: ``` BOOL GetHWAccelerationEnabled(); ``` **Syntax (C#)**: ``` [PreserveSig] bool GetHWAccelerationEnabled(); ``` **Returns**: `TRUE` if hardware acceleration is enabled, `FALSE` otherwise. **Default**: `TRUE` --- #### SetHWAccelerationEnabled Enables or disables hardware video decoding acceleration. **Syntax (C++)**: ``` HRESULT SetHWAccelerationEnabled(BOOL enabled); ``` **Syntax (C#)**: ``` [PreserveSig] int SetHWAccelerationEnabled([MarshalAs(UnmanagedType.Bool)] bool enabled); ``` **Parameters**: - `enabled`: Set to `TRUE` to enable hardware acceleration, `FALSE` to disable. **Returns**: `S_OK` (0) on success, error code otherwise. **Usage Notes**: - Must be called **before** connecting downstream video filters - When enabled, the filter attempts to use hardware decoding (DXVA, NVDEC, QuickSync, etc.) - Falls back to software decoding if hardware acceleration is unavailable - Hardware acceleration significantly improves performance for H.264, H.265, VP9, and AV1 codecs **Example (C++)**: ``` IFFmpegSourceSettings* pSettings = nullptr; pFilter->QueryInterface(IID_IFFmpegSourceSettings, (void**)&pSettings); // Enable hardware acceleration pSettings->SetHWAccelerationEnabled(TRUE); pSettings->Release(); ``` **Example (C#)**: ``` var settings = filter as IFFmpegSourceSettings; if (settings != null) { // Enable hardware acceleration settings.SetHWAccelerationEnabled(true); } ``` --- ### Load Timeout Configuration #### GetLoadTimeOut Retrieves the current source loading timeout value. **Syntax (C++)**: ``` DWORD GetLoadTimeOut(); ``` **Syntax (C#)**: ``` [PreserveSig] uint GetLoadTimeOut(); ``` **Returns**: Timeout value in milliseconds. **Default**: `15000` (15 seconds) --- #### SetLoadTimeOut Sets the timeout duration for source loading operations. **Syntax (C++)**: ``` HRESULT SetLoadTimeOut(DWORD milliseconds); ``` **Syntax (C#)**: ``` [PreserveSig] int SetLoadTimeOut(uint milliseconds); ``` **Parameters**: - `milliseconds`: Timeout duration in milliseconds. **Returns**: `S_OK` (0) on success. **Usage Notes**: - Must be called **before** loading the source file/URL - Particularly important for network streams that may have slow connection times - Set higher values for slow network connections or large files - Set lower values to fail fast on unreachable sources **Example (C++)**: ``` // Set 30-second timeout for network streams pSettings->SetLoadTimeOut(30000); // Load RTSP stream IFileSourceFilter* pFileSource = nullptr; pFilter->QueryInterface(IID_IFileSourceFilter, (void**)&pFileSource); pFileSource->Load(L"rtsp://example.com/stream", nullptr); ``` --- ### Buffering Configuration #### GetBufferingMode Retrieves the current buffering mode. **Syntax (C++)**: ``` FFMPEG_SOURCE_BUFFERING_MODE GetBufferingMode(); ``` **Syntax (C#)**: ``` [PreserveSig] FFMPEG_SOURCE_BUFFERING_MODE GetBufferingMode(); ``` **Returns**: Current buffering mode (see enumeration below). **Default**: `FFMPEG_SOURCE_BUFFERING_MODE_AUTO` --- #### SetBufferingMode Sets the buffering mode for live sources. **Syntax (C++)**: ``` HRESULT SetBufferingMode(FFMPEG_SOURCE_BUFFERING_MODE mode); ``` **Syntax (C#)**: ``` [PreserveSig] int SetBufferingMode(FFMPEG_SOURCE_BUFFERING_MODE mode); ``` **Parameters**: - `mode`: Buffering mode to use. **Returns**: `S_OK` (0) on success. **Usage Notes**: - Must be called **before** loading the source - Affects latency and stability for live streams **Buffering Modes**: | Mode | Value | Description | Use Case | |------|-------|-------------|----------| | `FFMPEG_SOURCE_BUFFERING_MODE_AUTO` | 0 | Automatically detect if buffering is needed | Default - recommended for most scenarios | | `FFMPEG_SOURCE_BUFFERING_MODE_ON` | 1 | Force buffering enabled | Use for unstable network streams | | `FFMPEG_SOURCE_BUFFERING_MODE_OFF` | 2 | Force buffering disabled | Use for low-latency live streams | **Example (C++)**: ``` // Disable buffering for low-latency RTSP stream pSettings->SetBufferingMode(FFMPEG_SOURCE_BUFFERING_MODE_OFF); pSettings->SetLoadTimeOut(5000); // 5-second timeout ``` **Example (C#)**: ``` // Enable buffering for unstable network settings.SetBufferingMode(FFMPEG_SOURCE_BUFFERING_MODE.ON); ``` --- ### Custom FFmpeg Options #### SetCustomOption Sets a custom FFmpeg option for the demuxer or decoder. **Syntax (C++)**: ``` HRESULT SetCustomOption(LPSTR name, LPSTR value); ``` **Syntax (C#)**: ``` [PreserveSig] int SetCustomOption([MarshalAs(UnmanagedType.LPStr)] string name, [MarshalAs(UnmanagedType.LPStr)] string value); ``` **Parameters**: - `name`: Option name (ASCII string). - `value`: Option value (ASCII string). **Returns**: `S_OK` (0) on success. **Usage Notes**: - Must be called **before** loading the source - Allows passing any FFmpeg AVFormatContext or AVCodecContext option - Options are passed directly to FFmpeg libraries - Invalid options are ignored with a warning **Common Options**: | Option | Value | Description | | --- | --- | --- | | `rtsp_transport` | `tcp` or `udp` | Force RTSP transport protocol | | `timeout` | Microseconds | Network timeout for protocols | | `buffer_size` | Bytes | Input buffer size | | `analyzeduration` | Microseconds | Duration to analyze stream | | `probesize` | Bytes | Size of data to probe | | `fflags` | `nobuffer` | Disable buffering | | `threads` | Number | Decoder thread count | **Example (C++)**: ``` // Configure RTSP to use TCP transport pSettings->SetCustomOption("rtsp_transport", "tcp"); // Set network timeout to 5 seconds pSettings->SetCustomOption("timeout", "5000000"); // 5 seconds in microseconds // Increase probe size for better format detection pSettings->SetCustomOption("probesize", "10000000"); // 10MB ``` **Example (C#)**: ``` // Low-latency configuration settings.SetCustomOption("fflags", "nobuffer"); settings.SetCustomOption("flags", "low_delay"); settings.SetCustomOption("probesize", "32"); ``` --- #### ClearCustomOptions Clears all previously set custom options. **Syntax (C++)**: ``` HRESULT ClearCustomOptions(); ``` **Syntax (C#)**: ``` [PreserveSig] int ClearCustomOptions(); ``` **Returns**: `S_OK` (0) on success. **Usage Notes**: - Must be called **before** loading the source - Resets all custom options to FFmpeg defaults **Example (C++)**: ``` pSettings->ClearCustomOptions(); ``` --- ### Callback Configuration #### SetDataCallback Sets a callback function to receive decoded video/audio data. **Syntax (C++)**: ``` HRESULT SetDataCallback(FFMPEGDataCallbackDelegate callback); ``` **Syntax (C#)**: ``` [PreserveSig] int SetDataCallback([MarshalAs(UnmanagedType.FunctionPtr)] FFMPEGDataCallbackDelegate callback); ``` **Parameters**: - `callback`: Pointer to callback function. **Returns**: `S_OK` (0) on success. **Callback Signature (C++)**: ``` typedef HRESULT(_stdcall* FFMPEGDataCallbackDelegate) ( BYTE* buffer, // Pointer to data buffer int bufferLen, // Buffer length in bytes int dataType, // 0 = video, 1 = audio LONGLONG startTime, // Start timestamp (100-nanosecond units) LONGLONG stopTime // Stop timestamp (100-nanosecond units) ); ``` **Usage Notes**: - Callback is invoked for each decoded frame/audio sample - Called from filter's streaming thread - keep processing minimal - Buffer data is valid only during callback execution - Return `S_OK` from callback to continue processing **Example (C++)**: ``` HRESULT __stdcall DataCallback(BYTE* buffer, int bufferLen, int dataType, LONGLONG startTime, LONGLONG stopTime) { if (dataType == 0) // Video { // Process video frame ProcessVideoFrame(buffer, bufferLen, startTime); } else // Audio { // Process audio data ProcessAudioData(buffer, bufferLen); } return S_OK; } // Set callback pSettings->SetDataCallback(&DataCallback); ``` --- #### SetTimestampCallback Sets a callback function to receive timestamp information. **Syntax (C++)**: ``` HRESULT SetTimestampCallback(FFMPEGTimestampCallbackDelegate callback); ``` **Syntax (C#)**: ``` [PreserveSig] int SetTimestampCallback([MarshalAs(UnmanagedType.FunctionPtr)] FFMPEGTimestampCallbackDelegate callback); ``` **Parameters**: - `callback`: Pointer to callback function. **Returns**: `S_OK` (0) on success. **Callback Signature (C++)**: ``` typedef HRESULT(_stdcall* FFMPEGTimestampCallbackDelegate) ( int mediaType, // 0 = video, 1 = audio __int64 demuxerStartTime, // Demuxer start time __int64 streamStartTime, // Stream start time __int64 timestamp // Current timestamp ); ``` **Usage Notes**: - Useful for timestamp analysis and synchronization debugging - Called for each decoded frame/sample --- ### Audio Control #### SetAudioEnabled Enables or disables audio stream processing. **Syntax (C++)**: ``` HRESULT SetAudioEnabled(BOOL enabled); ``` **Syntax (C#)**: ``` [PreserveSig] int SetAudioEnabled([MarshalAs(UnmanagedType.Bool)] bool enabled); ``` **Parameters**: - `enabled`: Set to `TRUE` to enable audio, `FALSE` to disable. **Returns**: `S_OK` (0) on success. **Usage Notes**: - Must be called **before** loading the source - When disabled, audio streams are not decoded (saves CPU/memory) - Useful for video-only applications **Example (C++)**: ``` // Disable audio for video-only processing pSettings->SetAudioEnabled(FALSE); ``` ## Related Interfaces - **IFileSourceFilter** - Standard DirectShow interface for loading files/URLs - **IAMStreamSelect** - Select between multiple audio/video streams - **IMediaSeeking** - Seek to specific positions in the media - **IAMStreamConfig** - Configure video/audio format ## See Also ### Documentation - [FFMPEG Source Filter Overview](../) - Product overview and features - [Code Examples](../examples/) - Complete working code samples ### Interface Definitions - [C# Interface (.NET)](https://github.com/visioforge/directshow-samples/blob/main/Interfaces/dotnet/IFFmpegSourceSettings.cs) - Complete .NET interface definition - [C++ Interface Header](https://github.com/visioforge/directshow-samples/blob/main/Interfaces/cpp/FFMPEG%20Source/IFFmpegSourceSettings.h) - C++ header file - [Delphi Interface](https://github.com/visioforge/directshow-samples/blob/main/Interfaces/delphi/VCFiltersAPI.pas) - Delphi interface definition ### Working Samples - [GitHub Samples Repository](https://github.com/visioforge/directshow-samples) - Complete working examples for all platforms ### External Resources - [FFmpeg Documentation](https://ffmpeg.org/documentation.html) - FFmpeg library documentation - [DirectShow SDK](https://learn.microsoft.com/en-us/windows/win32/DirectShow/directshow) - Microsoft DirectShow documentation ---END OF PAGE--- ## DirectShow Encoding Codecs - H.264, H.265, AAC, and More **URL:** https://www.visioforge.com/help/docs/directshow/filters-enc/codecs-reference/ **Description:** DirectShow codec reference with H.264/H.265/VP8/VP9 video, AAC/MP3/Opus audio, and hardware acceleration (NVENC, QuickSync, AMF). **Tags:** DirectShow, C++, Windows, Streaming, Encoding, MKV, WebM, TS, H.264, H.265, VP8, VP9, MPEG-2, AAC, MP3, Opus, FLAC, Vorbis, Speex # Encoding Filters Pack - Codecs Reference ## Overview This document provides a comprehensive reference for all video and audio codecs supported by the DirectShow Encoding Filters Pack. The pack includes both software and hardware-accelerated encoders for professional media encoding. --- ## Video Codecs ### H.264/AVC (MPEG-4 Part 10) The most widely used video codec for streaming, broadcasting, and file storage. #### Encoder Options | Encoder Type | Description | Hardware Support | Performance | Quality | | --- | --- | --- | --- | --- | | **Software (x264)** | CPU-based H.264 encoder | None | Moderate | Excellent | | **NVENC** | NVIDIA GPU encoder | NVIDIA GPUs (Kepler+) | Very Fast | Good-Excellent | | **QuickSync** | Intel integrated graphics | Intel CPUs (2nd gen+) | Fast | Good | | **AMD AMF** | AMD GPU encoder | AMD GPUs (GCN+) | Fast | Good | | **Media Foundation** | Windows MF encoder | Various (OS-dependent) | Moderate | Good | | #### Profiles and Levels | | | | | | **Profiles**: | | | | | | - **Baseline** - Basic features, mobile devices | | | | | | - **Main** - Standard features, most applications | | | | | | - **High** - Advanced features, HD content, Blu-ray | | | | | | **Common Levels**: | | | | | | - **Level 3.0** - SD (720x480 @ 30 fps) | | | | | | - **Level 3.1** - 720p (1280x720 @ 30 fps) | | | | | | - **Level 4.0** - 1080p (1920x1080 @ 30 fps) | | | | | | - **Level 4.1** - 1080p @ 60 fps | | | | | | - **Level 5.0** - 4K (3840x2160 @ 30 fps) | | | | | | - **Level 5.1** - 4K @ 60 fps | | | | | | #### Rate Control Modes | | | | | | Mode | Description | Use Case | Bitrate Behavior | | | ------ | ------------- | ---------- | ------------------ | | | **CBR** | Constant Bitrate | Streaming, broadcasting | Fixed bitrate | | | **VBR** | Variable Bitrate | File storage | Varies based on complexity | | | **CQP** | Constant Quantization | High quality archival | Varies significantly | | | #### Recommended Settings | | | | | | **Streaming (1080p @ 30fps)**: | | | | | | - Bitrate: 4-6 Mbps | | | | | | - Profile: High | | | | | | - Level: 4.0 | | | | | | - GOP Size: 60 (2 seconds) | | | | | | - B-frames: 2 | | | | | | **Recording (1080p @ 60fps)**: | | | | | | - Bitrate: 8-12 Mbps | | | | | | - Profile: High | | | | | | - Level: 4.1 | | | | | | - GOP Size: 120 (2 seconds) | | | | | | - B-frames: 3 | | | | | | **Low Latency Streaming**: | | | | | | - Bitrate: 2-4 Mbps | | | | | | - Profile: Main | | | | | | - Level: 3.1 | | | | | | - GOP Size: 30 (1 second) | | | | | | - B-frames: 0 | | | | | | --- | | | | | ### H.265/HEVC (High Efficiency Video Coding) Next-generation codec offering 40-50% better compression than H.264. #### Encoder Options | Encoder Type | Description | Hardware Support | Performance | Quality | | --- | --- | --- | --- | --- | | **Software (x265)** | CPU-based HEVC encoder | None | Slow | Excellent | | **NVENC** | NVIDIA GPU encoder | NVIDIA GPUs (Maxwell+) | Fast | Good-Excellent | | **QuickSync** | Intel integrated graphics | Intel CPUs (6th gen+) | Fast | Good | | **AMD AMF** | AMD GPU encoder | AMD GPUs (Fiji+) | Fast | Good | #### Profiles and Tiers **Profiles**: - **Main** - 8-bit, 4:2:0, standard use - **Main 10** - 10-bit, HDR support - **Main Still Picture** - Single images **Tiers**: - **Main Tier** - Standard applications - **High Tier** - Professional/broadcast **Common Levels**: - **Level 3.1** - 720p @ 30 fps - **Level 4.0** - 1080p @ 30 fps - **Level 4.1** - 1080p @ 60 fps - **Level 5.0** - 4K @ 30 fps - **Level 5.1** - 4K @ 60 fps #### Recommended Settings **4K Streaming (2160p @ 30fps)**: - Bitrate: 15-20 Mbps - Profile: Main - Level: 5.0 - GOP Size: 60 - Tile Encoding: Enabled **1080p High Quality**: - Bitrate: 3-5 Mbps - Profile: Main or Main 10 - Level: 4.0 - GOP Size: 90 --- ### VP8 Google's open-source video codec, primarily for WebM containers. #### Features - **License**: Royalty-free, open source - **Container**: WebM (preferred), MKV - **Hardware Support**: Limited - **Quality**: Good at medium-high bitrates - **Complexity**: Moderate encoding time #### Recommended Settings **WebM Streaming (720p)**: - Bitrate: 1-2 Mbps - GOP Size: 120 - Quality: Good (0-63 scale, lower is better) - Threads: Auto --- ### VP9 Successor to VP8 with significantly improved compression efficiency. #### Features - **License**: Royalty-free, open source - **Container**: WebM (primary), MKV - **Hardware Support**: Recent GPUs (Intel, NVIDIA, AMD) - **Quality**: Comparable to H.265 - **Complexity**: Very high (software), moderate (hardware) #### Profiles - **Profile 0** - 8-bit, 4:2:0 (most common) - **Profile 1** - 8-bit, 4:2:2/4:4:4 - **Profile 2** - 10/12-bit, 4:2:0 - **Profile 3** - 10/12-bit, 4:2:2/4:4:4 #### Recommended Settings **YouTube/WebM (1080p @ 30fps)**: - Bitrate: 2-4 Mbps - Quality/Speed: 1 (fastest), 0 (slowest/best) - GOP Size: 60 - Tile Columns: 2 --- ### MPEG-2 Legacy codec still used for DVDs and broadcasting. #### Features - **License**: Requires license - **Container**: MPEG-PS, MPEG-TS, VOB - **Hardware Support**: Universal - **Quality**: Good but requires higher bitrates - **Use Cases**: DVD authoring, broadcasting #### Common Variants - **MPEG-2 DVD** - 4-8 Mbps, 720x480/720x576 - **MPEG-2 SVCD** - 2.5 Mbps, 480x480/480x576 - **MPEG-2 HD** - 15-25 Mbps, 1920x1080 #### Recommended Settings **DVD Video (NTSC)**: - Resolution: 720x480 - Bitrate: 6 Mbps - GOP Size: 15 (NTSC) or 12 (PAL) - Aspect Ratio: 16:9 or 4:3 --- ### MPEG-4 Part 2 Older MPEG-4 Visual codec (DivX/Xvid era). #### Features - **License**: Requires license - **Container**: AVI, MP4, MKV - **Quality**: Moderate - **Use Cases**: Legacy content, low-power devices #### Recommended Settings **Standard Definition**: - Resolution: 640x480 - Bitrate: 1-2 Mbps - GOP Size: 250 --- ## Audio Codecs ### AAC (Advanced Audio Coding) Industry-standard audio codec for most applications. #### Encoder Options | Encoder Type | Description | Quality | Performance | | --- | --- | --- | --- | | **FFmpeg AAC** | Software encoder | Good | Fast | | **Media Foundation AAC** | Windows built-in | Good | Fast | | **FAAC** | Open-source encoder | Moderate | Fast | | #### Profiles | | | | | - **AAC-LC (Low Complexity)** - Standard, most compatible | | | | | - **HE-AAC (High Efficiency)** - Better at low bitrates | | | | | - **HE-AAC v2** - Even better for very low bitrates | | | | | #### Recommended Bitrates | | | | | Quality | Stereo | 5.1 Surround | | | --------- | -------- | -------------- | | | **Low** | 64-96 kbps | 192 kbps | | | **Medium** | 128 kbps | 256 kbps | | | **High** | 192 kbps | 384 kbps | | | **Very High** | 256-320 kbps | 448-640 kbps | | | #### Sample Rates | | | | | - **44.1 kHz** - CD quality, music | | | | | - **48 kHz** - Professional audio, video | | | | | - **32 kHz** - Lower quality (voice) | | | | | --- | | | | ### MP3 (MPEG-1/2 Audio Layer III) Legacy but still widely used audio codec. #### Encoder Options - **LAME** - Excellent quality open-source encoder - **FFmpeg MP3** - Built-in encoder #### Bitrate Modes | Mode | Description | File Size | Quality | | --- | --- | --- | --- | | **CBR** | Constant Bitrate | Predictable | Consistent | | **VBR** | Variable Bitrate | Smaller | Better | | **ABR** | Average Bitrate | Balanced | Good | #### Recommended Settings **Music (High Quality)**: - Mode: VBR - Quality: V0-V2 (LAME scale) - Approximate Bitrate: 190-245 kbps - Sample Rate: 44.1 kHz **Podcast/Speech**: - Mode: CBR - Bitrate: 96-128 kbps - Sample Rate: 44.1 kHz **Low Bandwidth**: - Mode: VBR - Quality: V5-V6 - Approximate Bitrate: 120-150 kbps --- ### Vorbis Open-source alternative to MP3 and AAC. #### Features - **License**: Completely free, no patents - **Container**: OGG (primary), WebM, MKV - **Quality**: Excellent, especially at low-mid bitrates - **Compatibility**: Good but not universal #### Recommended Settings **Music (High Quality)**: - Quality: 6-8 (0-10 scale) - Approximate Bitrate: 192-256 kbps - Sample Rate: 44.1 kHz or 48 kHz **Streaming**: - Quality: 4-5 - Approximate Bitrate: 128-160 kbps --- ### Opus Modern, highly efficient codec for both speech and music. #### Features - **License**: Royalty-free, standardized (RFC 6716) - **Container**: WebM, MKV, OGG - **Latency**: Extremely low (5-66.5 ms) - **Bitrate Range**: 6-510 kbps - **Quality**: Superior to MP3, AAC, Vorbis #### Applications - **VoIP/Voice Chat**: 8-24 kbps - **Music Streaming**: 64-128 kbps - **High Fidelity**: 128-256 kbps #### Recommended Settings **Voice Chat**: - Bitrate: 16-24 kbps - Sample Rate: 16 kHz or 48 kHz - Application: VoIP **Music**: - Bitrate: 96-160 kbps - Sample Rate: 48 kHz - Application: Audio --- ### FLAC (Free Lossless Audio Codec) Lossless audio compression. #### Features - **License**: Open source, royalty-free - **Compression**: Typically 40-60% of original - **Quality**: Bit-perfect lossless - **Compatibility**: Good and improving #### Compression Levels - **Level 0** - Fastest, ~50% compression - **Level 5** - Default, ~55% compression - **Level 8** - Slowest, ~60% compression #### Recommended Settings **Archival**: - Compression Level: 5-8 - Sample Rate: Original (typically 44.1 or 48 kHz) - Bit Depth: Original (16 or 24-bit) **Streaming**: - Compression Level: 0-3 - Sample Rate: 44.1 or 48 kHz --- ### Speex Specialized codec for voice compression. #### Features - **License**: Open source (BSD) - **Purpose**: Speech compression (not music) - **Bitrate**: 2-44 kbps - **Quality**: Optimized for voice #### Modes - **Narrowband** (8 kHz) - Phone quality, 2.15-24.6 kbps - **Wideband** (16 kHz) - Better clarity, 4-44 kbps - **Ultra-wideband** (32 kHz) - Full speech spectrum #### Recommended Settings **VoIP**: - Mode: Wideband - Quality: 6-8 (0-10 scale) - Bitrate: ~15-20 kbps --- ## Hardware Acceleration Overview ### NVIDIA NVENC **Supported Codecs**: - H.264/AVC (all NVIDIA GPUs from Kepler generation) - H.265/HEVC (Maxwell generation and newer) **Generations**: - **Kepler** (GTX 600/700) - 1st gen, basic H.264 - **Maxwell** (GTX 900) - 2nd gen, HEVC support - **Pascal** (GTX 10XX) - 3rd gen, improved quality - **Turing/Ampere** (RTX 20XX/30XX) - 7th/8th gen, excellent quality **Performance**: Up to 8K @ 30 fps (GPU dependent) **Quality Settings**: - Preset: P1 (fastest) to P7 (slowest, best quality) - Recommended: P4-P6 for balanced quality/speed --- ### Intel QuickSync **Supported Codecs**: - H.264/AVC (2nd gen Core and newer) - H.265/HEVC (6th gen Core and newer) - VP9 (9th gen Core and newer) **Generations**: - **Sandy Bridge** (2nd gen) - H.264 support - **Skylake** (6th gen) - HEVC support - **Ice Lake** (10th gen mobile) - Improved quality - **Rocket Lake** (11th gen) - Enhanced features **Performance**: Up to 4K @ 60 fps **Quality**: Good, improving with each generation --- ### AMD AMF (Advanced Media Framework) **Supported Codecs**: - H.264/AVC (GCN 1.0 and newer) - H.265/HEVC (Fiji/Polaris and newer) **Generations**: - **GCN 1-4** (R7/R9, RX 400/500) - H.264 only - **Vega** (RX Vega) - HEVC support - **RDNA** (RX 5000/6000) - Improved quality **Performance**: Up to 4K @ 60 fps **Quality**: Good, competitive with QuickSync --- ## Codec Selection Guide ### For Streaming (Live) **Recommended**: H.264 (NVENC/QuickSync) - **Reason**: Universal compatibility, low latency, hardware acceleration - **Fallback**: H.264 (software) **Settings**: - 1080p @ 30fps: 4-6 Mbps - 720p @ 30fps: 2.5-4 Mbps - Low latency: Disable B-frames --- ### For Recording (High Quality) **Recommended**: H.265 (NVENC/QuickSync) or H.264 (software) - **Reason**: Best quality-to-size ratio - **Alternative**: HEVC software for maximum quality **Settings**: - 4K @ 30fps: 15-25 Mbps (HEVC) or 35-50 Mbps (H.264) - 1080p @ 60fps: 8-15 Mbps (HEVC) or 15-25 Mbps (H.264) --- ### For Web Delivery **Recommended**: VP9 or H.264 - **Reason**: Browser compatibility, royalty-free (VP9) **Settings**: - VP9: 1080p @ 2-4 Mbps - H.264: 1080p @ 4-6 Mbps --- ### For Audio **Music**: AAC (128-192 kbps) or Opus (96-160 kbps) **Voice**: Opus (16-32 kbps) or Speex (15-20 kbps) **Archival**: FLAC (lossless) **Podcast**: MP3 VBR (V4-V2, ~130-190 kbps) or AAC (128 kbps) --- ## Compatibility Matrix | Codec | MP4 | MKV | AVI | WebM | OGG | MPEG-TS | | --- | --- | --- | --- | --- | --- | --- | | **H.264** | ✓ | ✓ | ✓ | ✗ | ✗ | ✓ | | **H.265** | ✓ | ✓ | ✗ | ✗ | ✗ | ✓ | | **VP8** | ✗ | ✓ | ✗ | ✓ | ✗ | ✗ | | **VP9** | ✗ | ✓ | ✗ | ✓ | ✗ | ✗ | | **MPEG-2** | ✓ | ✓ | ✓ | ✗ | ✗ | ✓ | | **AAC** | ✓ | ✓ | ✗ | ✗ | ✗ | ✓ | | **MP3** | ✓ | ✓ | ✓ | ✗ | ✗ | ✓ | | **Vorbis** | ✗ | ✓ | ✗ | ✓ | ✓ | ✗ | | **Opus** | ✗ | ✓ | ✗ | ✓ | ✓ | ✗ | | **FLAC** | ✓ | ✓ | ✗ | ✓ | ✓ | ✗ | --- ## See Also - [Encoding Filters Pack Overview](../) - [Muxers Reference](../muxers-reference/) - [NVENC Interface Reference](../interfaces/nvenc/) - [Code Examples](../examples/) ---END OF PAGE--- ## DirectShow Encoding Filter Examples - C++, C#, VB.NET **URL:** https://www.visioforge.com/help/docs/directshow/filters-enc/examples/ **Description:** Code examples for DirectShow encoding — NVENC GPU, H.264/H.265 software, AAC/MP3/Opus audio, and MP4/MKV/WebM muxer configuration. **Tags:** DirectShow, C++, Windows, Streaming, Encoding, MP4, MKV, WebM, TS, H.264, H.265, VP9, AAC, MP3, Opus, FLAC, Vorbis, C# **API:** IBaseFilter, IFileSinkFilter, ProgressEventArgs # Encoding Filters Pack - Code Examples ## Overview This page provides practical code examples for encoding video and audio using the Encoding Filters Pack. Covers: - **NVENC Encoder** - NVIDIA hardware encoding (H.264/H.265) - **Software Encoders** - H.264, H.265, VP8, VP9, MPEG-2 - **Audio Encoders** - AAC, MP3, Opus, Vorbis, FLAC - **Muxers** - MP4, MKV, WebM, MPEG-TS, AVI --- ## Prerequisites ### C++ Projects ``` #include #include #include "INVEncConfig.h" // NVENC interface #pragma comment(lib, "strmiids.lib") ``` ### C# Projects ``` using VisioForge.DirectShowAPI; using VisioForge.DirectShowLib; using System.Runtime.InteropServices; ``` **NuGet Packages**: - VisioForge.DirectShowAPI - MediaFoundationCore --- ## NVENC Hardware Encoding Examples > **NVENC Preset and Profile GUIDs** — The `SetPreset(Guid)` and `SetProfile(Guid)` methods accept NVIDIA NVENC SDK GUID constants. Real presets: `NV_ENC_PRESET_DEFAULT_GUID`, `NV_ENC_PRESET_HP_GUID` (high performance), `NV_ENC_PRESET_HQ_GUID` (high quality), `NV_ENC_PRESET_LOW_LATENCY_DEFAULT_GUID`, `NV_ENC_PRESET_LOW_LATENCY_HQ_GUID`, `NV_ENC_PRESET_LOW_LATENCY_HP_GUID`, `NV_ENC_PRESET_LOSSLESS_DEFAULT_GUID`, `NV_ENC_PRESET_BD_GUID`. H.264 profiles: `NV_ENC_H264_PROFILE_BASELINE_GUID`, `NV_ENC_H264_PROFILE_MAIN_GUID`, `NV_ENC_H264_PROFILE_HIGH_GUID`. HEVC: `NV_ENC_HEVC_PROFILE_MAIN_GUID`. These GUIDs are defined in the NVIDIA NVENC SDK (`nvEncodeAPI.h`). ### Example 1: Basic NVENC H.264 Encoding Encode video with NVIDIA hardware acceleration. #### C# NVENC H.264 Encoding ``` using VisioForge.Core.Types.Output; // ... var nvenc = encoderFilter as INVEncConfig; if (nvenc != null) { nvenc.SetCodec(NVENCEncoder.H264); nvenc.SetRateControl(NVENCRateControlMode.CBR); nvenc.SetBitrate(5000000); // 5 Mbps nvenc.SetPreset(NV_ENC_PRESET_DEFAULT_GUID); // Balanced quality/speed nvenc.SetGOP(60); // Keyframe every 60 frames nvenc.SetBFrames(2); // B-frames nvenc.SetProfile(NV_ENC_H264_PROFILE_HIGH_GUID); nvenc.SetLevel(NVENCEncoderLevel.H264_41); // Level 4.1 } ``` #### C++ NVENC H.264 Encoding ``` hr = pEncoder->QueryInterface(IID_INVEncConfig, (void**)&pNVEnc); if (SUCCEEDED(hr)) { pNVEnc->SetCodec(0); // H264 pNVEnc->SetRateControl(2); // CBR pNVEnc->SetBitrate(5000000); // 5 Mbps pNVEnc->SetPreset(NV_ENC_PRESET_DEFAULT_GUID); // Balanced pNVEnc->SetGOP(60); // Keyframe interval pNVEnc->SetBFrames(2); // B-frames pNVEnc->SetProfile(NV_ENC_H264_PROFILE_HIGH_GUID); pNVEnc->SetLevel(41); // Level 4.1 pNVEnc->Release(); } ``` --- ### Example 2: NVENC H.265 (HEVC) Encoding Encode with H.265 for better compression. #### C# NVENC H.265 ## ``` public void EncodeH265(string inputFile, string outputFile) { var filterGraph = (IFilterGraph2)new FilterGraph(); // Add source filterGraph.AddSourceFilter(inputFile, "Source", out IBaseFilter sourceFilter); // Add NVENC encoder var encoderFilter = FilterGraphTools.AddFilterFromClsid( filterGraph, Consts.CLSID_VFNVENCEncoder, "NVENC Encoder"); var nvenc = encoderFilter as INVEncConfig; if (nvenc != null) { nvenc.SetCodec(NVENCEncoder.HEVC); nvenc.SetRateControl(NVENCRateControlMode.CONST_QP); nvenc.SetQp(23); // QP 23: good balance nvenc.SetPreset(NV_ENC_PRESET_HQ_GUID); // High quality nvenc.SetProfile(NV_ENC_HEVC_PROFILE_MAIN_GUID); nvenc.SetLevel(NVENCEncoderLevel.H264_41); // Level 4.1 nvenc.SetGOP(120); // 4 seconds at 30fps nvenc.SetBFrames(3); } // Add muxer var muxerFilter = FilterGraphTools.AddFilterFromClsid( filterGraph, Consts.CLSID_VFMP4Muxer, "MP4 Muxer"); var fileSink = muxerFilter as IFileSinkFilter; fileSink?.SetFileName(outputFile, null); // Connect and encode... ICaptureGraphBuilder2 captureGraph = (ICaptureGraphBuilder2)new CaptureGraphBuilder2(); captureGraph.SetFiltergraph(filterGraph); captureGraph.RenderStream(null, MediaType.Video, sourceFilter, encoderFilter, muxerFilter); var mediaControl = (IMediaControl)filterGraph; mediaControl.Run(); Marshal.ReleaseComObject(captureGraph); } ``` ### Example 3: NVENC Rate Control Modes Different rate control strategies for various use cases. #### C# Rate Control Examples ``` using VisioForge.Core.Types.Output; public void ConfigureRateControl(INVEncConfig nvenc, NVENCRateControlMode mode) { switch (mode) { case NVENCRateControlMode.CBR: nvenc.SetRateControl(NVENCRateControlMode.CBR); nvenc.SetBitrate(5000000); // 5 Mbps target nvenc.SetVbvBitrate(5000000); // Same as target for CBR nvenc.SetVbvSize(10000000); // 10 Mb buffer break; case NVENCRateControlMode.VBR: nvenc.SetRateControl(NVENCRateControlMode.VBR); nvenc.SetBitrate(5000000); // Average 5 Mbps nvenc.SetVbvBitrate(8000000); // Peak 8 Mbps nvenc.SetVbvSize(10000000); break; case NVENCRateControlMode.CONST_QP: nvenc.SetRateControl(NVENCRateControlMode.CONST_QP); nvenc.SetQp(23); // QP: lower = better quality break; } } ``` --- ### Example 4: NVENC Quality Presets Balance between speed and quality. #### C# Quality Presets ## ``` public void SetQualityPreset(INVEncConfig nvenc, string useCase) { switch (useCase.ToLower()) { case "realtime": nvenc.SetPreset(NV_ENC_PRESET_LOW_LATENCY_HP_GUID); nvenc.SetBFrames(0); break; case "fast": nvenc.SetPreset(NV_ENC_PRESET_LOW_LATENCY_DEFAULT_GUID); nvenc.SetBFrames(1); break; case "balanced": nvenc.SetPreset(NV_ENC_PRESET_DEFAULT_GUID); nvenc.SetBFrames(2); break; case "quality": nvenc.SetPreset(NV_ENC_PRESET_HQ_GUID); nvenc.SetBFrames(3); break; default: nvenc.SetPreset(NV_ENC_PRESET_DEFAULT_GUID); nvenc.SetBFrames(2); break; } } ``` ## Software Encoding Examples ### Example 5: Software H.264 Encoder Use CPU-based H.264 encoding. #### C# Software H.264 ``` public void EncodeSoftwareH264(string inputFile, string outputFile) { var filterGraph = (IFilterGraph2)new FilterGraph(); // Add source filterGraph.AddSourceFilter(inputFile, "Source", out IBaseFilter sourceFilter); // Add software H.264 encoder var encoderFilter = FilterGraphTools.AddFilterFromClsid( filterGraph, Consts.CLSID_VFH264Encoder, // Software encoder "H.264 Encoder"); // Configure encoder (if interface available) // var h264Config = encoderFilter as IH264EncoderConfig; // Configure bitrate, quality, etc. // Add muxer var muxerFilter = FilterGraphTools.AddFilterFromClsid( filterGraph, Consts.CLSID_VFMP4Muxer, "MP4 Muxer"); var fileSink = muxerFilter as IFileSinkFilter; fileSink?.SetFileName(outputFile, null); // Connect and encode ICaptureGraphBuilder2 captureGraph = (ICaptureGraphBuilder2)new CaptureGraphBuilder2(); captureGraph.SetFiltergraph(filterGraph); captureGraph.RenderStream(null, MediaType.Video, sourceFilter, encoderFilter, muxerFilter); var mediaControl = (IMediaControl)filterGraph; mediaControl.Run(); Marshal.ReleaseComObject(captureGraph); } ``` --- ## Audio Encoding Examples ### Example 6: AAC Audio Encoding Encode audio to AAC format. #### C# AAC Encoding ## ``` public void EncodeAACAudio(string inputFile, string outputFile) { var filterGraph = (IFilterGraph2)new FilterGraph(); // Add source filterGraph.AddSourceFilter(inputFile, "Source", out IBaseFilter sourceFilter); // Add video encoder (e.g., NVENC) var videoEncoderFilter = FilterGraphTools.AddFilterFromClsid( filterGraph, Consts.CLSID_VFNVENCEncoder, "NVENC Encoder"); var nvenc = videoEncoderFilter as INVEncConfig; if (nvenc != null) { nvenc.SetCodec(NVENCEncoder.H264); nvenc.SetRateControl(NVENCRateControlMode.CBR); nvenc.SetBitrate(5000000); nvenc.SetPreset(NV_ENC_PRESET_DEFAULT_GUID); } // Add AAC audio encoder var audioEncoderFilter = FilterGraphTools.AddFilterFromClsid( filterGraph, Consts.CLSID_VFAACEncoder, "AAC Encoder"); // Configure AAC (if interface available) // var aacConfig = audioEncoderFilter as IAACEncoderConfig; // aacConfig?.SetBitrate(192000); // 192 kbps // aacConfig?.SetProfile(AAC_PROFILE_LC); // Add muxer var muxerFilter = FilterGraphTools.AddFilterFromClsid( filterGraph, Consts.CLSID_VFMP4Muxer, "MP4 Muxer"); var fileSink = muxerFilter as IFileSinkFilter; fileSink?.SetFileName(outputFile, null); // Connect filters ICaptureGraphBuilder2 captureGraph = (ICaptureGraphBuilder2)new CaptureGraphBuilder2(); captureGraph.SetFiltergraph(filterGraph); // Video path captureGraph.RenderStream(null, MediaType.Video, sourceFilter, videoEncoderFilter, muxerFilter); // Audio path captureGraph.RenderStream(null, MediaType.Audio, sourceFilter, audioEncoderFilter, muxerFilter); // Run encoding var mediaControl = (IMediaControl)filterGraph; mediaControl.Run(); Marshal.ReleaseComObject(captureGraph); } ``` ### Example 7: Multiple Audio Codec Support Support for different audio codecs. #### C# Audio Codec Selection ``` public enum AudioCodec { AAC, MP3, Opus, Vorbis, FLAC } public IBaseFilter CreateAudioEncoder(IFilterGraph2 filterGraph, AudioCodec codec) { Guid encoderCLSID; string encoderName; switch (codec) { case AudioCodec.AAC: encoderCLSID = Consts.CLSID_VFAACEncoder; encoderName = "AAC Encoder"; break; case AudioCodec.MP3: encoderCLSID = Consts.CLSID_VFMP3Encoder; encoderName = "MP3 Encoder"; break; case AudioCodec.Opus: encoderCLSID = Consts.CLSID_VFOpusEncoder; encoderName = "Opus Encoder"; break; case AudioCodec.Vorbis: encoderCLSID = Consts.CLSID_VFVorbisEncoder; encoderName = "Vorbis Encoder"; break; case AudioCodec.FLAC: encoderCLSID = Consts.CLSID_VFFLACEncoder; encoderName = "FLAC Encoder"; break; default: throw new ArgumentException("Unsupported audio codec"); } return FilterGraphTools.AddFilterFromClsid(filterGraph, encoderCLSID, encoderName); } ``` --- ## Container Muxing Examples ### Example 8: MP4 Container Mux video and audio to MP4 format. #### C# MP4 Muxing ## ``` public void CreateMP4(string inputFile, string outputFile) { var filterGraph = (IFilterGraph2)new FilterGraph(); // Add source filterGraph.AddSourceFilter(inputFile, "Source", out IBaseFilter sourceFilter); // Add video encoder var videoEncoder = FilterGraphTools.AddFilterFromClsid( filterGraph, Consts.CLSID_VFNVENCEncoder, "NVENC Encoder"); // Add audio encoder var audioEncoder = FilterGraphTools.AddFilterFromClsid( filterGraph, Consts.CLSID_VFAACEncoder, "AAC Encoder"); // Add MP4 muxer var muxerFilter = FilterGraphTools.AddFilterFromClsid( filterGraph, Consts.CLSID_VFMP4Muxer, "MP4 Muxer"); // Set output file var fileSink = muxerFilter as IFileSinkFilter; fileSink?.SetFileName(outputFile, null); // Configure muxer (if needed) // var mp4Config = muxerFilter as IMP4MuxerConfig; // mp4Config?.SetFastStart(true); // Enable fast start for web // Connect filters ICaptureGraphBuilder2 captureGraph = (ICaptureGraphBuilder2)new CaptureGraphBuilder2(); captureGraph.SetFiltergraph(filterGraph); captureGraph.RenderStream(null, MediaType.Video, sourceFilter, videoEncoder, muxerFilter); captureGraph.RenderStream(null, MediaType.Audio, sourceFilter, audioEncoder, muxerFilter); var mediaControl = (IMediaControl)filterGraph; mediaControl.Run(); Marshal.ReleaseComObject(captureGraph); } ``` ### Example 9: MKV Container Create Matroska (MKV) files. #### C# MKV Muxing ``` public void CreateMKV(string inputFile, string outputFile) { var filterGraph = (IFilterGraph2)new FilterGraph(); // Add source filterGraph.AddSourceFilter(inputFile, "Source", out IBaseFilter sourceFilter); // Add encoders var videoEncoder = FilterGraphTools.AddFilterFromClsid( filterGraph, Consts.CLSID_VFNVENCEncoder, "NVENC Encoder"); var audioEncoder = FilterGraphTools.AddFilterFromClsid( filterGraph, Consts.CLSID_VFAACEncoder, "AAC Encoder"); // Add MKV muxer var muxerFilter = FilterGraphTools.AddFilterFromClsid( filterGraph, Consts.CLSID_VFMKVMuxer, "MKV Muxer"); var fileSink = muxerFilter as IFileSinkFilter; fileSink?.SetFileName(outputFile, null); // Connect and encode ICaptureGraphBuilder2 captureGraph = (ICaptureGraphBuilder2)new CaptureGraphBuilder2(); captureGraph.SetFiltergraph(filterGraph); captureGraph.RenderStream(null, MediaType.Video, sourceFilter, videoEncoder, muxerFilter); captureGraph.RenderStream(null, MediaType.Audio, sourceFilter, audioEncoder, muxerFilter); var mediaControl = (IMediaControl)filterGraph; mediaControl.Run(); Marshal.ReleaseComObject(captureGraph); } ``` --- ### Example 10: WebM Container Create WebM files for web delivery. #### C# WebM Muxing ## ``` public void CreateWebM(string inputFile, string outputFile) { var filterGraph = (IFilterGraph2)new FilterGraph(); // Add source filterGraph.AddSourceFilter(inputFile, "Source", out IBaseFilter sourceFilter); // Add VP9 video encoder (WebM standard) var videoEncoder = FilterGraphTools.AddFilterFromClsid( filterGraph, Consts.CLSID_VFVP9Encoder, "VP9 Encoder"); // Add Opus audio encoder (WebM standard) var audioEncoder = FilterGraphTools.AddFilterFromClsid( filterGraph, Consts.CLSID_VFOpusEncoder, "Opus Encoder"); // Add WebM muxer var muxerFilter = FilterGraphTools.AddFilterFromClsid( filterGraph, Consts.CLSID_VFWebMMuxer, "WebM Muxer"); var fileSink = muxerFilter as IFileSinkFilter; fileSink?.SetFileName(outputFile, null); // Connect and encode ICaptureGraphBuilder2 captureGraph = (ICaptureGraphBuilder2)new CaptureGraphBuilder2(); captureGraph.SetFiltergraph(filterGraph); captureGraph.RenderStream(null, MediaType.Video, sourceFilter, videoEncoder, muxerFilter); captureGraph.RenderStream(null, MediaType.Audio, sourceFilter, audioEncoder, muxerFilter); var mediaControl = (IMediaControl)filterGraph; mediaControl.Run(); Marshal.ReleaseComObject(captureGraph); } ``` ## Complete Encoding Pipeline ### Example 11: Full-Featured Encoder Complete encoding application with all features. #### C# Complete Encoder ``` using System; using System.Runtime.InteropServices; using VisioForge.DirectShowAPI; using VisioForge.DirectShowLib; public class CompleteEncoder : IDisposable { private IFilterGraph2 filterGraph; private ICaptureGraphBuilder2 captureGraph; private IMediaControl mediaControl; private IMediaEventEx mediaEventEx; private IMediaSeeking mediaSeeking; private const int WM_GRAPHNOTIFY = 0x8000 + 1; public event EventHandler EncodingComplete; public event EventHandler ProgressChanged; public class ProgressEventArgs : EventArgs { public long CurrentPosition { get; set; } public long Duration { get; set; } public double PercentComplete { get; set; } } public void Initialize(IntPtr notifyHandle) { filterGraph = (IFilterGraph2)new FilterGraph(); captureGraph = (ICaptureGraphBuilder2)new CaptureGraphBuilder2(); mediaControl = (IMediaControl)filterGraph; mediaEventEx = (IMediaEventEx)filterGraph; mediaSeeking = (IMediaSeeking)filterGraph; int hr = mediaEventEx.SetNotifyWindow(notifyHandle, WM_GRAPHNOTIFY, IntPtr.Zero); DsError.ThrowExceptionForHR(hr); hr = captureGraph.SetFiltergraph(filterGraph); DsError.ThrowExceptionForHR(hr); } public void ConfigureEncoding( string inputFile, string outputFile, VideoCodec videoCodec, AudioCodec audioCodec, ContainerFormat container, int videoBitrate = 5000000, int audioBitrate = 192000) { // Add source filterGraph.AddSourceFilter(inputFile, "Source", out IBaseFilter sourceFilter); // Create video encoder IBaseFilter videoEncoder = CreateVideoEncoder(videoCodec); ConfigureVideoEncoder(videoEncoder, videoCodec, videoBitrate); // Create audio encoder IBaseFilter audioEncoder = CreateAudioEncoder(audioCodec); ConfigureAudioEncoder(audioEncoder, audioCodec, audioBitrate); // Create muxer IBaseFilter muxer = CreateMuxer(container); // Set output file var fileSink = muxer as IFileSinkFilter; fileSink?.SetFileName(outputFile, null); // Connect pipeline int hr = captureGraph.RenderStream(null, MediaType.Video, sourceFilter, videoEncoder, muxer); hr = captureGraph.RenderStream(null, MediaType.Audio, sourceFilter, audioEncoder, muxer); } private IBaseFilter CreateVideoEncoder(VideoCodec codec) { Guid clsid; string name; switch (codec) { case VideoCodec.H264_NVENC: clsid = Consts.CLSID_VFNVENCEncoder; name = "NVENC H.264"; break; case VideoCodec.H265_NVENC: clsid = Consts.CLSID_VFNVENCEncoder; name = "NVENC H.265"; break; case VideoCodec.H264_Software: clsid = Consts.CLSID_VFH264Encoder; name = "Software H.264"; break; default: throw new ArgumentException("Unsupported video codec"); } return FilterGraphTools.AddFilterFromClsid(filterGraph, clsid, name); } private void ConfigureVideoEncoder(IBaseFilter encoder, VideoCodec codec, int bitrate) { if (codec == VideoCodec.H264_NVENC || codec == VideoCodec.H265_NVENC) { var nvenc = encoder as INVEncConfig; if (nvenc != null) { nvenc.SetCodec(codec == VideoCodec.H264_NVENC ? NVENCEncoder.H264 : NVENCEncoder.HEVC); nvenc.SetRateControl(NVENCRateControlMode.CBR); nvenc.SetBitrate(bitrate); nvenc.SetPreset(NV_ENC_PRESET_DEFAULT_GUID); nvenc.SetGOP(60); nvenc.SetBFrames(2); } } // Configure other encoders... } private IBaseFilter CreateAudioEncoder(AudioCodec codec) { Guid clsid; string name; switch (codec) { case AudioCodec.AAC: clsid = Consts.CLSID_VFAACEncoder; name = "AAC Encoder"; break; case AudioCodec.MP3: clsid = Consts.CLSID_VFMP3Encoder; name = "MP3 Encoder"; break; default: throw new ArgumentException("Unsupported audio codec"); } return FilterGraphTools.AddFilterFromClsid(filterGraph, clsid, name); } private void ConfigureAudioEncoder(IBaseFilter encoder, AudioCodec codec, int bitrate) { // Configure audio encoder based on codec type // (Interface-specific configuration) } private IBaseFilter CreateMuxer(ContainerFormat format) { Guid clsid; string name; switch (format) { case ContainerFormat.MP4: clsid = Consts.CLSID_VFMP4Muxer; name = "MP4 Muxer"; break; case ContainerFormat.MKV: clsid = Consts.CLSID_VFMKVMuxer; name = "MKV Muxer"; break; case ContainerFormat.WebM: clsid = Consts.CLSID_VFWebMMuxer; name = "WebM Muxer"; break; default: throw new ArgumentException("Unsupported container format"); } return FilterGraphTools.AddFilterFromClsid(filterGraph, clsid, name); } public void StartEncoding() { mediaControl?.Run(); } public void Stop() { mediaControl?.Stop(); } public double GetProgress() { if (mediaSeeking != null) { mediaSeeking.GetCurrentPosition(out long position); mediaSeeking.GetDuration(out long duration); if (duration > 0) { return (double)position / duration * 100.0; } } return 0.0; } public void HandleGraphEvent() { if (mediaEventEx != null) { while (mediaEventEx.GetEvent(out EventCode eventCode, out IntPtr param1, out IntPtr param2, 0) == 0) { mediaEventEx.FreeEventParams(eventCode, param1, param2); if (eventCode == EventCode.Complete) { EncodingComplete?.Invoke(this, EventArgs.Empty); } } } } public void Dispose() { if (mediaControl != null) { mediaControl.Stop(); } if (mediaEventEx != null) { mediaEventEx.SetNotifyWindow(IntPtr.Zero, 0, IntPtr.Zero); } FilterGraphTools.RemoveAllFilters(filterGraph); if (mediaEventEx != null) Marshal.ReleaseComObject(mediaEventEx); if (mediaSeeking != null) Marshal.ReleaseComObject(mediaSeeking); if (captureGraph != null) Marshal.ReleaseComObject(captureGraph); if (mediaControl != null) Marshal.ReleaseComObject(mediaControl); if (filterGraph != null) Marshal.ReleaseComObject(filterGraph); } } public enum VideoCodec { H264_NVENC, H265_NVENC, H264_Software, VP8, VP9 } public enum ContainerFormat { MP4, MKV, WebM, MPEG_TS, AVI } ``` --- ## Troubleshooting ### Issue: NVENC Not Available **Solution**: Check GPU compatibility: ``` var nvenc2 = encoder as INVEncConfig2; if (nvenc2 != null) { int hr = nvenc2.CheckNVENCAvailable(out bool available, out int status); if (hr != 0 || !available) { Console.WriteLine("NVENC not available - GPU may not support it"); // Fall back to software encoder } } ``` ### Issue: Encoding Too Slow **Solution**: Adjust quality preset: ``` // Use faster preset nvenc.SetPreset(NV_ENC_PRESET_LOW_LATENCY_HP_GUID); nvenc.SetBFrames(0); // Disable B-frames ``` ### Issue: Output File Size Too Large **Solution**: Adjust bitrate or use better codec: ``` // Lower bitrate nvenc.SetBitrate(2000000); // 2 Mbps instead of 5 // Or use H.265 for better compression nvenc.SetCodec(NVENCEncoder.HEVC); ``` --- ## See Also ### Documentation - [NVENC Interface](../interfaces/nvenc/) - Complete NVENC API - [Codecs Reference](../codecs-reference/) - All video/audio codecs - [Muxers Reference](../muxers-reference/) - Container formats ### External Resources - [NVIDIA NVENC Documentation](https://developer.nvidia.com/video-codec-sdk) - [H.264 Specification](https://www.itu.int/rec/T-REC-H.264) ---END OF PAGE--- ## DirectShow Encoding Filters — H.264, H.265, NVENC & More **URL:** https://www.visioforge.com/help/docs/directshow/filters-enc/ **Description:** DirectShow video/audio encoders with H.264, H.265, VP8, VP9, AAC, MP3, and GPU acceleration (NVENC, QuickSync, AMF) for Windows apps. **Tags:** DirectShow, C++, Windows, Streaming # DirectShow Encoding Filters Pack ## Introduction The DirectShow Encoding Filters Pack provides a powerful set of media encoding components designed specifically for software developers building professional multimedia applications. This toolkit enables seamless integration of high-performance encoding capabilities for both audio and video streams across a wide variety of popular formats. --- ## Installation Before using the code samples and integrating the filters into your application, you must first install the DirectShow Encoding Filters Pack from the [product page](https://www.visioforge.com/encoding-filters-pack). **Installation Steps**: 1. Download the Encoding Filters Pack installer from the product page 2. Run the installer with administrative privileges 3. The installer will register all encoding and muxing filters 4. Sample applications and source code will be available in the installation directory **Note**: All filters must be properly registered on the system before they can be used in your applications. The installer handles this automatically. --- ## Key Features ### Multi-Format Encoding Support The filters pack supports numerous industry-standard formats, including: - **MP4 container** with H264, HEVC, and AAC codecs - **MPEG-TS** streams - **MKV** (Matroska) containers - **WebM** format with VP8/VP9 video codecs - Multiple audio formats including **Vorbis**, **MP3**, **FLAC**, and **Opus** ### Hardware Acceleration Developers can leverage GPU acceleration for improved encoding performance: - **Intel** QuickSync technology - **AMD/ATI** hardware acceleration - **Nvidia** NVENC encoding support This hardware optimization dramatically improves encoding speeds while reducing CPU load in your applications. ### Flexible Implementation Options The pack includes: - Standalone H264/AAC encoders utilizing CPU resources - Specialized muxer components with integrated video and audio encoders - Options for both CPU and GPU-based encoding paths ## Technical Capabilities The filter components integrate seamlessly into DirectShow application pipelines, providing developers with: - High-quality video encoding at various bitrates and resolutions - Efficient audio compression with configurable quality settings - Advanced container format support with customizable parameters - DirectShow filter graph compatibility for straightforward implementation For detailed specifications and a comprehensive list of all supported video/audio encoders and output formats, please visit the [product page](https://www.visioforge.com/encoding-filters-pack). ## Version History ### 11.4 Release - Updated filter components to match current .Net SDK implementations - Enhanced AMD AMF H264/H265 encoders with latest optimizations - Improved Intel QuickSync H265 encoders for better performance - Refreshed sample applications with new coding examples ### 11.0 Release - Synchronized filters with current .Net SDK versions - Upgraded Nvidia NVENC H264/H265 encoders for better quality - Introduced new SSF muxer filter component ### 10.0 Release - Updated all filters to align with .Net SDK implementations - Enhanced Media Foundation encoders (H264, H265, AAC) - Added dedicated NVENC video encoder filter as CUDA encoder replacement ### 9.0 Release - Optimized MP4 container with H264/AAC output - Expanded WebM format support with VP9 encoding capabilities - Improved H265 encoder filter performance - Enhanced Intel QuickSync H264 encoders ### 8.6 Release - Implemented RTSP sink filter for streaming applications - Added RTMP sink filter in BETA status - Upgraded AAC encoder filter with quality improvements ### 8.5 Initial Release - First public release including filters from .Net SDKs - Core components: AAC encoder, H264 encoders (CPU/GPU) - Additional encoders: H265 (CPU/GPU), VP8, Vorbis - Container support: MP4 muxer, WebM muxer - Streaming capabilities: RTSP source, RTMP source --- ## Resources - [Product Page](https://www.visioforge.com/encoding-filters-pack) - Purchase, licensing, and product information - [Code Examples](https://github.com/visioforge/directshow-samples/tree/main/Encoding%20Filters%20Pack) - Sample applications and implementation examples --- ## See Also - [Codecs Reference](codecs-reference/) - Complete video and audio codec documentation - [Muxers Reference](muxers-reference/) - Container format specifications - [NVENC Interface](interfaces/nvenc/) - NVIDIA hardware encoder API - [Code Examples](examples/) - Practical encoding examples ---END OF PAGE--- ## AAC Encoder DirectShow Filter - COM Interface Reference **URL:** https://www.visioforge.com/help/docs/directshow/filters-enc/interfaces/aac/ **Description:** Configure AAC encoding in DirectShow with IMonogramAACEncoder and IVFAACEncoder interfaces. Bitrate, profile, sample rate, and channel settings for C++/C#. **Tags:** DirectShow, C++, Windows, Streaming, Encoding, Decoding, MP4, TS, AAC, MP3, C# **API:** IMonogramAACEncoder, IVFAACEncoder, AACConfig, VFAACEncoder, IBaseFilter # AAC Encoder Interface Reference ## Overview The AAC (Advanced Audio Coding) encoder DirectShow filters provide interfaces for high-quality audio encoding to the AAC format. AAC is the successor to MP3, offering better sound quality at the same bitrate and is the standard audio codec for MP4, M4A, and streaming applications. Two AAC encoder interfaces are available: - **IMonogramAACEncoder**: Simple configuration interface using a single configuration structure - **IVFAACEncoder**: Comprehensive interface with individual property methods for fine-grained control ## IMonogramAACEncoder Interface ### Overview The **IMonogramAACEncoder** interface provides a simple, structure-based configuration approach for AAC encoding. Configuration is performed using the `AACConfig` structure that contains all essential encoding parameters. **Interface GUID**: `{B2DE30C0-1441-4451-A0CE-A914FD561D7F}` **Inherits From**: `IUnknown` ### AACConfig Structure ``` /// /// AAC encoder configuration structure. /// public struct AACConfig { /// /// AAC version/profile (typically 2 for AAC-LC, 4 for AAC-HE) /// public int version; /// /// Object type / profile: /// 2 = AAC-LC (Low Complexity) - recommended for most uses /// 5 = AAC-HE (High Efficiency) /// 29 = AAC-HEv2 (High Efficiency version 2) /// public int object_type; /// /// Output format type (0 = Raw AAC, 1 = ADTS) /// public int output_type; /// /// Target bitrate in bits per second (e.g., 128000 for 128 kbps) /// public int bitrate; } ``` ### AACInfo Structure ``` /// /// AAC encoder runtime information. /// public struct AACInfo { /// /// Input sample rate in Hz (e.g., 44100, 48000) /// public int samplerate; /// /// Number of audio channels (1 = mono, 2 = stereo, 6 = 5.1, etc.) /// public int channels; /// /// AAC frame size in samples (typically 1024 for AAC-LC) /// public int frame_size; /// /// Total number of frames encoded /// public long frames_done; } ``` ### Interface Definitions #### C# Definition ``` using System; using System.Runtime.InteropServices; namespace VisioForge.DirectShowAPI { /// /// AAC encoder configuration structure. /// [StructLayout(LayoutKind.Sequential)] public struct AACConfig { public int version; public int object_type; public int output_type; public int bitrate; } /// /// AAC encoder runtime information. /// [StructLayout(LayoutKind.Sequential)] public struct AACInfo { public int samplerate; public int channels; public int frame_size; public long frames_done; } /// /// Monogram AAC encoder configuration interface. /// Provides structure-based configuration for AAC encoding. /// [ComImport] [Guid("B2DE30C0-1441-4451-A0CE-A914FD561D7F")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] public interface IMonogramAACEncoder { /// /// Gets the current AAC encoder configuration. /// /// Reference to AACConfig structure to receive current settings /// HRESULT (0 for success) [PreserveSig] int GetConfig(ref AACConfig config); /// /// Sets the AAC encoder configuration. /// /// Reference to AACConfig structure containing desired settings /// HRESULT (0 for success) [PreserveSig] int SetConfig(ref AACConfig config); } } ``` #### C++ Definition ``` #include // {B2DE30C0-1441-4451-A0CE-A914FD561D7F} DEFINE_GUID(IID_IMonogramAACEncoder, 0xb2de30c0, 0x1441, 0x4451, 0xa0, 0xce, 0xa9, 0x14, 0xfd, 0x56, 0x1d, 0x7f); /// /// AAC encoder configuration structure. /// struct AACConfig { int version; int object_type; int output_type; int bitrate; }; /// /// AAC encoder runtime information. /// struct AACInfo { int samplerate; int channels; int frame_size; __int64 frames_done; }; /// /// Monogram AAC encoder configuration interface. /// DECLARE_INTERFACE_(IMonogramAACEncoder, IUnknown) { /// /// Gets the current AAC encoder configuration. /// /// Pointer to AACConfig structure to receive settings /// S_OK for success STDMETHOD(GetConfig)(THIS_ AACConfig* config ) PURE; /// /// Sets the AAC encoder configuration. /// /// Pointer to AACConfig structure with desired settings /// S_OK for success STDMETHOD(SetConfig)(THIS_ const AACConfig* config ) PURE; }; ``` #### Delphi Definition ``` uses ActiveX, ComObj; const IID_IMonogramAACEncoder: TGUID = '{B2DE30C0-1441-4451-A0CE-A914FD561D7F}'; type /// /// AAC encoder configuration structure. /// TAACConfig = record version: Integer; object_type: Integer; output_type: Integer; bitrate: Integer; end; /// /// AAC encoder runtime information. /// TAACInfo = record samplerate: Integer; channels: Integer; frame_size: Integer; frames_done: Int64; end; /// /// Monogram AAC encoder configuration interface. /// IMonogramAACEncoder = interface(IUnknown) ['{B2DE30C0-1441-4451-A0CE-A914FD561D7F}'] /// /// Gets the current AAC encoder configuration. /// function GetConfig(var config: TAACConfig): HRESULT; stdcall; /// /// Sets the AAC encoder configuration. /// function SetConfig(const config: TAACConfig): HRESULT; stdcall; end; ``` --- ## IVFAACEncoder Interface ### Overview The **IVFAACEncoder** interface provides comprehensive, property-based configuration for AAC encoding with individual getter/setter methods for each parameter. This interface offers finer control and is easier to use for incremental configuration changes. **Interface GUID**: `{0BEF7533-39E6-42a5-863F-E087FAB5D84F}` **Inherits From**: `IUnknown` ### Interface Definitions #### C# Definition ``` using System; using System.Runtime.InteropServices; namespace VisioForge.DirectShowAPI { /// /// VisioForge AAC encoder configuration interface. /// Provides comprehensive property-based control over AAC encoding parameters. /// [ComImport] [Guid("0BEF7533-39E6-42a5-863F-E087FAB5D84F")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] public interface IVFAACEncoder { /// /// Forces a specific input sample rate. Set to 0 to accept any rate. /// /// Sample rate in Hz (e.g., 44100, 48000). 0 = any rate /// HRESULT (0 for success) [PreserveSig] int SetInputSampleRate(uint ulSampleRate); /// /// Gets the configured input sample rate. /// /// Receives sample rate in Hz. 0 if not fixed /// HRESULT (0 for success) [PreserveSig] int GetInputSampleRate(out uint pulSampleRate); /// /// Sets the number of input channels. /// /// Number of channels (1=mono, 2=stereo, 6=5.1, etc.) /// HRESULT (0 for success) [PreserveSig] int SetInputChannels(short nChannels); /// /// Gets the number of input channels. /// /// Receives the number of channels /// HRESULT (0 for success) [PreserveSig] int GetInputChannels(out short pnChannels); /// /// Sets the target bitrate. Set to -1 to use maximum bitrate. /// /// Bitrate in bits per second (e.g., 128000). -1 = maximum /// HRESULT (0 for success) [PreserveSig] int SetBitRate(uint ulBitRate); /// /// Gets the configured bitrate. /// /// Receives bitrate in bps. -1 if set to maximum /// HRESULT (0 for success) [PreserveSig] int GetBitRate(out uint pulBitRate); /// /// Sets the AAC profile type. /// /// Profile: 2=AAC-LC, 5=AAC-HE, 29=AAC-HEv2 /// HRESULT (0 for success) [PreserveSig] int SetProfile(uint uProfile); /// /// Gets the current AAC profile. /// /// Receives the profile type /// HRESULT (0 for success) [PreserveSig] int GetProfile(out uint puProfile); /// /// Sets the output format. /// /// Format: 0=Raw AAC, 1=ADTS /// HRESULT (0 for success) [PreserveSig] int SetOutputFormat(uint uFormat); /// /// Gets the output format. /// /// Receives the output format /// HRESULT (0 for success) [PreserveSig] int GetOutputFormat(out uint puFormat); /// /// Sets the time shift value for timestamp adjustment. /// /// Time shift in milliseconds /// HRESULT (0 for success) [PreserveSig] int SetTimeShift(int timeShift); /// /// Gets the time shift value. /// /// Receives the time shift in milliseconds /// HRESULT (0 for success) [PreserveSig] int GetTimeShift(out int ptimeShift); /// /// Enables or disables Low Frequency Effects (LFE) channel. /// /// 1 to enable LFE, 0 to disable /// HRESULT (0 for success) [PreserveSig] int SetLFE(uint lfe); /// /// Gets the LFE channel state. /// /// Receives LFE state (1=enabled, 0=disabled) /// HRESULT (0 for success) [PreserveSig] int GetLFE(out uint p); /// /// Enables or disables Temporal Noise Shaping (TNS). /// TNS improves encoding of transient sounds. /// /// 1 to enable TNS, 0 to disable /// HRESULT (0 for success) [PreserveSig] int SetTNS(uint tns); /// /// Gets the TNS state. /// /// Receives TNS state (1=enabled, 0=disabled) /// HRESULT (0 for success) [PreserveSig] int GetTNS(out uint p); /// /// Enables or disables Mid-Side stereo coding. /// Can improve compression for stereo audio. /// /// 1 to enable mid-side coding, 0 to disable /// HRESULT (0 for success) [PreserveSig] int SetMidSide(uint v); /// /// Gets the mid-side coding state. /// /// Receives mid-side state (1=enabled, 0=disabled) /// HRESULT (0 for success) [PreserveSig] int GetMidSide(out uint p); } } ``` #### C++ Definition ``` #include // {0BEF7533-39E6-42a5-863F-E087FAB5D84F} DEFINE_GUID(IID_IVFAACEncoder, 0x0bef7533, 0x39e6, 0x42a5, 0x86, 0x3f, 0xe0, 0x87, 0xfa, 0xb5, 0xd8, 0x4f); /// /// VisioForge AAC encoder configuration interface. /// DECLARE_INTERFACE_(IVFAACEncoder, IUnknown) { STDMETHOD(SetInputSampleRate)(THIS_ unsigned long ulSampleRate ) PURE; STDMETHOD(GetInputSampleRate)(THIS_ unsigned long* pulSampleRate ) PURE; STDMETHOD(SetInputChannels)(THIS_ short nChannels ) PURE; STDMETHOD(GetInputChannels)(THIS_ short* pnChannels ) PURE; STDMETHOD(SetBitRate)(THIS_ unsigned long ulBitRate ) PURE; STDMETHOD(GetBitRate)(THIS_ unsigned long* pulBitRate ) PURE; STDMETHOD(SetProfile)(THIS_ unsigned long uProfile ) PURE; STDMETHOD(GetProfile)(THIS_ unsigned long* puProfile ) PURE; STDMETHOD(SetOutputFormat)(THIS_ unsigned long uFormat ) PURE; STDMETHOD(GetOutputFormat)(THIS_ unsigned long* puFormat ) PURE; STDMETHOD(SetTimeShift)(THIS_ int timeShift ) PURE; STDMETHOD(GetTimeShift)(THIS_ int* ptimeShift ) PURE; STDMETHOD(SetLFE)(THIS_ unsigned long lfe ) PURE; STDMETHOD(GetLFE)(THIS_ unsigned long* p ) PURE; STDMETHOD(SetTNS)(THIS_ unsigned long tns ) PURE; STDMETHOD(GetTNS)(THIS_ unsigned long* p ) PURE; STDMETHOD(SetMidSide)(THIS_ unsigned long v ) PURE; STDMETHOD(GetMidSide)(THIS_ unsigned long* p ) PURE; }; ``` #### Delphi Definition ``` uses ActiveX, ComObj; const IID_IVFAACEncoder: TGUID = '{0BEF7533-39E6-42a5-863F-E087FAB5D84F}'; type /// /// VisioForge AAC encoder configuration interface. /// IVFAACEncoder = interface(IUnknown) ['{0BEF7533-39E6-42a5-863F-E087FAB5D84F}'] function SetInputSampleRate(ulSampleRate: Cardinal): HRESULT; stdcall; function GetInputSampleRate(out pulSampleRate: Cardinal): HRESULT; stdcall; function SetInputChannels(nChannels: SmallInt): HRESULT; stdcall; function GetInputChannels(out pnChannels: SmallInt): HRESULT; stdcall; function SetBitRate(ulBitRate: Cardinal): HRESULT; stdcall; function GetBitRate(out pulBitRate: Cardinal): HRESULT; stdcall; function SetProfile(uProfile: Cardinal): HRESULT; stdcall; function GetProfile(out puProfile: Cardinal): HRESULT; stdcall; function SetOutputFormat(uFormat: Cardinal): HRESULT; stdcall; function GetOutputFormat(out puFormat: Cardinal): HRESULT; stdcall; function SetTimeShift(timeShift: Integer): HRESULT; stdcall; function GetTimeShift(out ptimeShift: Integer): HRESULT; stdcall; function SetLFE(lfe: Cardinal): HRESULT; stdcall; function GetLFE(out p: Cardinal): HRESULT; stdcall; function SetTNS(tns: Cardinal): HRESULT; stdcall; function GetTNS(out p: Cardinal): HRESULT; stdcall; function SetMidSide(v: Cardinal): HRESULT; stdcall; function GetMidSide(out p: Cardinal): HRESULT; stdcall; end; ``` ## AAC Profiles and Configuration ### AAC Profiles **AAC-LC (Low Complexity) - Profile 2** (Recommended): - Best quality-to-bitrate ratio - Lowest computational complexity - Universal decoder support - Use for: Music, podcasts, video soundtracks - Bitrate range: 64-320 kbps **AAC-HE (High Efficiency) - Profile 5**: - Optimized for low bitrates - Uses Spectral Band Replication (SBR) - Better quality than AAC-LC at low bitrates (<= 64 kbps) - Use for: Streaming, voice, low-bitrate applications - Bitrate range: 32-80 kbps **AAC-HEv2 (High Efficiency version 2) - Profile 29**: - Further optimized for very low bitrates - Uses Parametric Stereo (PS) in addition to SBR - Best for mono/stereo at extremely low bitrates - Use for: Voice streaming, very low bandwidth - Bitrate range: 16-40 kbps ### Output Formats **Raw AAC (Format 0)**: - Pure AAC bitstream without container - Requires external container (MP4, M4A, MKV) - Use for: Muxing into MP4/M4A files - Smallest output size **ADTS (Audio Data Transport Stream) - Format 1**: - AAC with frame headers - Self-contained, can be played directly - Slightly larger than raw AAC - Use for: Standalone AAC files, streaming - Better error resilience ### Recommended Bitrates | Use Case | Channels | Profile | Bitrate | Notes | | --- | --- | --- | --- | --- | | Voice/Podcast (mono) | 1 | AAC-LC | 64-96 kbps | Clear speech | | Voice/Podcast (stereo) | 2 | AAC-LC | 96-128 kbps | High quality speech | | Music (stereo) standard | 2 | AAC-LC | 128-192 kbps | Good quality | | Music (stereo) high quality | 2 | AAC-LC | 256-320 kbps | Excellent quality | | Low-bandwidth streaming | 2 | AAC-HE | 48-64 kbps | Acceptable quality | | Very low bandwidth | 1-2 | AAC-HEv2 | 24-40 kbps | Basic quality | | 5.1 surround | 6 | AAC-LC | 384-512 kbps | Cinema quality | | ## Usage Examples | | | | | | ### C# Example - IMonogramAACEncoder (High Quality Music) | | | | | | ``` using System; using DirectShowLib; using VisioForge.DirectShowAPI; public class MonogramAACHighQuality { public void ConfigureHighQualityMusic(IBaseFilter audioEncoder) { // Query the Monogram AAC encoder interface var aacEncoder = audioEncoder as IMonogramAACEncoder; if (aacEncoder == null) { Console.WriteLine("Error: Filter does not support IMonogramAACEncoder"); return; } // Configure high quality stereo music encoding var config = new AACConfig { version = 2, // AAC version 2 object_type = 2, // AAC-LC profile output_type = 0, // Raw AAC (for MP4 muxing) bitrate = 192000 // 192 kbps }; int hr = aacEncoder.SetConfig(ref config); if (hr == 0) { Console.WriteLine("AAC encoder configured for high quality music:"); Console.WriteLine(" Profile: AAC-LC"); Console.WriteLine(" Bitrate: 192 kbps"); Console.WriteLine(" Output: Raw AAC for MP4 container"); } else { Console.WriteLine($"Error configuring AAC encoder: 0x{hr:X8}"); } } } ``` | | | | | | ### C# Example - IVFAACEncoder (Comprehensive Configuration) | | | | | | ``` public class VFAACHighQualityMusic { public void ConfigureComprehensive(IBaseFilter audioEncoder) { // Query the VisioForge AAC encoder interface var vfAacEncoder = audioEncoder as IVFAACEncoder; if (vfAacEncoder == null) { Console.WriteLine("Error: Filter does not support IVFAACEncoder"); return; } // Configure comprehensive stereo music encoding vfAacEncoder.SetInputSampleRate(48000); // 48 kHz vfAacEncoder.SetInputChannels(2); // Stereo vfAacEncoder.SetBitRate(256000); // 256 kbps vfAacEncoder.SetProfile(2); // AAC-LC vfAacEncoder.SetOutputFormat(0); // Raw AAC vfAacEncoder.SetTNS(1); // Enable TNS vfAacEncoder.SetMidSide(1); // Enable mid-side coding vfAacEncoder.SetLFE(0); // No LFE (stereo only) vfAacEncoder.SetTimeShift(0); // No time shift Console.WriteLine("VisioForge AAC encoder configured:"); // Verify configuration vfAacEncoder.GetBitRate(out uint bitrate); vfAacEncoder.GetProfile(out uint profile); vfAacEncoder.GetInputChannels(out short channels); Console.WriteLine($" Bitrate: {bitrate / 1000} kbps"); Console.WriteLine($" Profile: {(profile == 2 ? "AAC-LC" : profile.ToString())}"); Console.WriteLine($" Channels: {channels}"); } } ``` | | | | | | ### C# Example - Low Bitrate Streaming (AAC-HE) | | | | | | ``` public class VFAACLowBitrateStreaming { public void ConfigureLowBitrate(IBaseFilter audioEncoder) { var vfAacEncoder = audioEncoder as IVFAACEncoder; if (vfAacEncoder == null) return; // Configure for low-bitrate streaming vfAacEncoder.SetInputSampleRate(44100); // 44.1 kHz vfAacEncoder.SetInputChannels(2); // Stereo vfAacEncoder.SetBitRate(64000); // 64 kbps vfAacEncoder.SetProfile(5); // AAC-HE (High Efficiency) vfAacEncoder.SetOutputFormat(1); // ADTS for streaming vfAacEncoder.SetTNS(1); // Enable TNS vfAacEncoder.SetMidSide(1); // Enable mid-side vfAacEncoder.SetLFE(0); // No LFE Console.WriteLine("AAC-HE configured for low-bitrate streaming"); Console.WriteLine(" 64 kbps stereo with ADTS output"); } } ``` | | | | | | ### C# Example - Voice/Podcast Encoding | | | | | | ``` public class VFAACVoicePodcast { public void ConfigureVoicePodcast(IBaseFilter audioEncoder) { var vfAacEncoder = audioEncoder as IVFAACEncoder; if (vfAacEncoder == null) return; // Configure for voice/podcast (mono) vfAacEncoder.SetInputSampleRate(44100); // 44.1 kHz vfAacEncoder.SetInputChannels(1); // Mono vfAacEncoder.SetBitRate(80000); // 80 kbps vfAacEncoder.SetProfile(2); // AAC-LC vfAacEncoder.SetOutputFormat(0); // Raw AAC vfAacEncoder.SetTNS(1); // Enable TNS for speech vfAacEncoder.SetMidSide(0); // N/A for mono vfAacEncoder.SetLFE(0); // No LFE Console.WriteLine("AAC configured for voice/podcast"); Console.WriteLine(" 80 kbps mono AAC-LC"); } } ``` | | | | | | ### C++ Example - IMonogramAACEncoder | | | | | | ``` #include #include #include "IMonogramAACEncoder.h" void ConfigureMonogramAAC(IBaseFilter* pAudioEncoder) { IMonogramAACEncoder* pAACEncoder = NULL; HRESULT hr = S_OK; // Query the Monogram AAC encoder interface hr = pAudioEncoder->QueryInterface(IID_IMonogramAACEncoder, (void**)&pAACEncoder); if (FAILED(hr) || !pAACEncoder) { std::cout << "Error: Filter does not support IMonogramAACEncoder" << std::endl; return; } // Configure high quality music encoding AACConfig config; config.version = 2; // AAC version 2 config.object_type = 2; // AAC-LC config.output_type = 0; // Raw AAC config.bitrate = 192000; // 192 kbps hr = pAACEncoder->SetConfig(&config); if (SUCCEEDED(hr)) { std::cout << "AAC encoder configured for high quality music" << std::endl; std::cout << " Profile: AAC-LC" << std::endl; std::cout << " Bitrate: 192 kbps" << std::endl; } pAACEncoder->Release(); } ``` | | | | | | ### C++ Example - IVFAACEncoder | | | | | | ``` #include "IVFAACEncoder.h" void ConfigureVFAAC(IBaseFilter* pAudioEncoder) { IVFAACEncoder* pVFAACEncoder = NULL; HRESULT hr = pAudioEncoder->QueryInterface(IID_IVFAACEncoder, (void**)&pVFAACEncoder); if (SUCCEEDED(hr) && pVFAACEncoder) { // Configure comprehensive stereo encoding pVFAACEncoder->SetInputSampleRate(48000); // 48 kHz pVFAACEncoder->SetInputChannels(2); // Stereo pVFAACEncoder->SetBitRate(256000); // 256 kbps pVFAACEncoder->SetProfile(2); // AAC-LC pVFAACEncoder->SetOutputFormat(0); // Raw AAC pVFAACEncoder->SetTNS(1); // Enable TNS pVFAACEncoder->SetMidSide(1); // Enable mid-side pVFAACEncoder->SetLFE(0); // No LFE std::cout << "VisioForge AAC encoder configured" << std::endl; pVFAACEncoder->Release(); } } ``` | | | | | | ### Delphi Example - IMonogramAACEncoder | | | | | | ``` uses DirectShow9, ActiveX; procedure ConfigureMonogramAAC(AudioEncoder: IBaseFilter); var AACEncoder: IMonogramAACEncoder; Config: TAACConfig; hr: HRESULT; begin // Query the Monogram AAC encoder interface hr := AudioEncoder.QueryInterface(IID_IMonogramAACEncoder, AACEncoder); if Failed(hr) or (AACEncoder = nil) then begin WriteLn('Error: Filter does not support IMonogramAACEncoder'); Exit; end; try // Configure high quality music encoding Config.version := 2; // AAC version 2 Config.object_type := 2; // AAC-LC Config.output_type := 0; // Raw AAC Config.bitrate := 192000; // 192 kbps hr := AACEncoder.SetConfig(Config); if Succeeded(hr) then begin WriteLn('AAC encoder configured for high quality music'); WriteLn(' Profile: AAC-LC'); WriteLn(' Bitrate: 192 kbps'); end; finally AACEncoder := nil; end; end; ``` | | | | | | ### Delphi Example - IVFAACEncoder | | | | | | ``` procedure ConfigureVFAAC(AudioEncoder: IBaseFilter); var VFAACEncoder: IVFAACEncoder; begin if Succeeded(AudioEncoder.QueryInterface(IID_IVFAACEncoder, VFAACEncoder)) then begin try // Configure comprehensive stereo encoding VFAACEncoder.SetInputSampleRate(48000); // 48 kHz VFAACEncoder.SetInputChannels(2); // Stereo VFAACEncoder.SetBitRate(256000); // 256 kbps VFAACEncoder.SetProfile(2); // AAC-LC VFAACEncoder.SetOutputFormat(0); // Raw AAC VFAACEncoder.SetTNS(1); // Enable TNS VFAACEncoder.SetMidSide(1); // Enable mid-side VFAACEncoder.SetLFE(0); // No LFE WriteLn('VisioForge AAC encoder configured'); finally VFAACEncoder := nil; end; end; end; ``` | | | | | | ## Best Practices | | | | | | ### Profile Selection | | | | | | **Use AAC-LC (Profile 2) when**: | | | | | | - Encoding music or high-quality audio | | | | | | - Bitrate >= 96 kbps | | | | | | - Maximum decoder compatibility required | | | | | | - **Recommended for most scenarios** | | | | | | **Use AAC-HE (Profile 5) when**: | | | | | | - Bitrate constraints (32-80 kbps) | | | | | | - Streaming over limited bandwidth | | | | | | - Voice/speech content acceptable at lower quality | | | | | | - Mobile/web streaming applications | | | | | | **Use AAC-HEv2 (Profile 29) when**: | | | | | | - Extremely limited bandwidth (< 40 kbps) | | | | | | - Voice-only content | | | | | | - Mono or stereo only (not multichannel) | | | | | | ### Bitrate Guidelines | | | | | | **Mono Speech/Podcast**: | | | | | | - Minimum: 48-64 kbps (AAC-LC) | | | | | | - Recommended: 80-96 kbps (AAC-LC) | | | | | | - High quality: 128 kbps (AAC-LC) | | | | | | **Stereo Music**: | | | | | | - Minimum: 96-128 kbps (AAC-LC) | | | | | | - Recommended: 192-256 kbps (AAC-LC) | | | | | | - High quality: 256-320 kbps (AAC-LC) | | | | | | **Streaming Applications**: | | | | | | - Low bandwidth: 48-64 kbps (AAC-HE, stereo) | | | | | | - Standard bandwidth: 96-128 kbps (AAC-LC, stereo) | | | | | | - High bandwidth: 192-256 kbps (AAC-LC, stereo) | | | | | | ### Output Format Selection | | | | | | **Use Raw AAC (Format 0) when**: | | | | | | - Muxing into MP4, M4A, or MKV containers | | | | | | - Container provides framing and synchronization | | | | | | - **Recommended for most video/multimedia applications** | | | | | | **Use ADTS (Format 1) when**: | | | | | | - Creating standalone .aac files | | | | | | - Streaming without container | | | | | | - Better error recovery needed | | | | | | - Testing/debugging audio independently | | | | | | ### Feature Flags | | | | | | **Temporal Noise Shaping (TNS)**: | | | | | | - **Enable** for all encoding scenarios | | | | | | - Improves transient response | | | | | | - Better quality for percussive sounds | | | | | | - Minimal computational overhead | | | | | | **Mid-Side Stereo Coding**: | | | | | | - **Enable** for stereo music encoding | | | | | | - Improves compression efficiency | | | | | | - Better stereo imaging | | | | | | - No benefit for mono or uncorrelated stereo | | | | | | **Low Frequency Effects (LFE)**: | | | | | | - **Enable** only for 5.1/7.1 surround sound | | | | | | - Dedicated subwoofer channel (.1) | | | | | | - Disable for stereo/mono | | | | | | ## Troubleshooting | | | | | | ### Low Audio Quality | | | | | | **Symptoms**: Muffled sound, artifacts, poor clarity | | | | | | **Possible Causes**: | | | | | | 1. Bitrate too low for content | | | | | | 2. Wrong profile for bitrate | | | | | | 3. TNS disabled | | | | | | **Solutions**: | | | | | | - Increase bitrate to recommended levels (see tables above) | | | | | | - For low bitrates (<= 80 kbps), use AAC-HE instead of AAC-LC | | | | | | - Enable TNS: `SetTNS(1)` | | | | | | - For music, ensure bitrate >= 128 kbps with AAC-LC | | | | | | ### Encoder Initialization Failures | | | | | | **Symptoms**: SetConfig or Set methods return error codes | | | | | | **Possible Causes**: | | | | | | 1. Unsupported sample rate | | | | | | 2. Invalid bitrate for profile | | | | | | 3. Incompatible channel configuration | | | | | | **Solutions**: | | | | | | - Use standard sample rates: 44100, 48000 Hz | | | | | | - Verify bitrate is appropriate for profile | | | | | | - Check channel count matches source audio | | | | | | - For AAC-HE, keep bitrate <= 128 kbps | | | | | | ### File Won't Play | | | | | | **Symptoms**: AAC file doesn't play in media players | | | | | | **Possible Causes**: | | | | | | 1. Raw AAC without container | | | | | | 2. Unsupported profile | | | | | | 3. Corrupted stream | | | | | | **Solutions**: | | | | | | - Use ADTS output format (`SetOutputFormat(1)`) for standalone files | | | | | | - Use Raw AAC (`SetOutputFormat(0)`) only with MP4/M4A container | | | | | | - Verify player supports AAC profile (HE/HEv2 may not be supported on old players) | | | | | | - Ensure proper stream finalization in filter graph | | | | | | ### Compatibility Issues | | | | | | **Symptoms**: AAC plays on some devices but not others | | | | | | **Possible Causes**: | | | | | | 1. Advanced profile not supported (AAC-HE/HEv2) | | | | | | 2. Non-standard configuration | | | | | | **Solutions**: | | | | | | - Use AAC-LC (Profile 2) for maximum compatibility | | | | | | - Use standard sample rates (44100 or 48000 Hz) | | | | | | - Keep bitrates within recommended ranges | | | | | | - Avoid very low bitrates (< 64 kbps) for AAC-LC | | | | | | --- | | | | | ## See Also - [LAME MP3 Encoder Interface](../lame/) - [FLAC Encoder Interface](../flac/) - [Audio Codecs Reference](../../codecs-reference/) - [MP4 Muxer Interface](../mp4-muxer/) - [Encoding Filters Pack Overview](../../) ---END OF PAGE--- ## FFmpeg Encoder DirectShow Filter - MPEG, FLV, DVD Output **URL:** https://www.visioforge.com/help/docs/directshow/filters-enc/interfaces/ffmpeg/ **Description:** IVFFFMPEGEncoder COM interface for encoding to MPEG-1, MPEG-2, FLV, VCD, SVCD, DVD, and Transport Stream in DirectShow. Audio/video codec parameters for C++/C#. **Tags:** DirectShow, C++, Windows, Streaming, Encoding, MP4, FLV, TS, H.264, MPEG-2, AC-3, C# **API:** IVFFFMPEGEncoder, FFMPEGOutputSettings, IBaseFilter, CVFOutputSettings, TFFMPEGOutputSettings # FFMPEG Encoder Interface Reference ## Overview The **IVFFFMPEGEncoder** interface provides comprehensive configuration for encoding video and audio to various formats using the FFMPEG library. This powerful encoder supports multiple output formats including Flash Video (FLV), MPEG-1, MPEG-2, VCD, SVCD, DVD, and MPEG-2 Transport Stream. The encoder uses a structure-based configuration approach where all encoding parameters are set at once, providing a simple yet complete interface for professional video encoding to legacy and streaming formats. **Interface GUID**: `{17B8FF7D-A67F-45CE-B425-0E4F607D8C60}` **Filter CLSID**: `{554AB365-B293-4C1D-9245-E8DB01F027F7}` **Inherits From**: `IUnknown` ## Filter and Interface GUIDs ``` // FFMPEG Encoder Filter CLSID public static readonly Guid CLSID_FFMPEGEncoder = new Guid("554AB365-B293-4C1D-9245-E8DB01F027F7"); // IVFFFMPEGEncoder Interface IID public static readonly Guid IID_IVFFFMPEGEncoder = new Guid("17B8FF7D-A67F-45CE-B425-0E4F607D8C60"); ``` ## Output Formats ### VFFFMPEGDLLOutputFormat Enumeration ``` /// /// FFMPEG encoder output format options. /// public enum VFFFMPEGDLLOutputFormat { /// /// Flash Video (.flv) - Web streaming format /// FLV = 0, /// /// MPEG-1 (.mpg) - Standard MPEG-1 video /// MPEG1 = 1, /// /// MPEG-1 VCD - Video CD compliant format /// Resolution: 352x240 (NTSC) or 352x288 (PAL) /// Bitrate: 1150 kbps /// MPEG1VCD = 2, /// /// MPEG-2 (.mpg) - Standard MPEG-2 video /// MPEG2 = 3, /// /// MPEG-2 Transport Stream (.ts) - Broadcasting and streaming /// MPEG2TS = 4, /// /// MPEG-2 SVCD - Super Video CD compliant format /// Resolution: 480x480 (NTSC) or 480x576 (PAL) /// Bitrate: 2500 kbps /// MPEG2SVCD = 5, /// /// MPEG-2 DVD - DVD-Video compliant format /// Resolution: 720x480 (NTSC) or 720x576 (PAL) /// Bitrate: Up to 9800 kbps /// MPEG2DVD = 6 } ``` ### TV System Standards ``` /// /// Television system standards for video encoding. /// public enum VFFFMPEGDLLTVSystem { /// /// No specific TV system / Auto-detect /// None = 0, /// /// PAL (Phase Alternating Line) /// 25 fps, 576 lines /// Used in: Europe, Asia, Australia, Africa /// PAL = 1, /// /// NTSC (National Television System Committee) /// 29.97 fps, 480 lines /// Used in: North America, Japan, South Korea /// NTSC = 2, /// /// Film standard /// 24 fps /// Used for: Cinema, film transfers /// Film = 3 } ``` ## FFMPEGOutputSettings Structure ``` /// /// Complete configuration structure for FFMPEG encoder. /// Contains all audio, video, and output format settings. /// [StructLayout(LayoutKind.Sequential)] public struct FFMPEGOutputSettings { /// /// Output filename with path. /// [MarshalAs(UnmanagedType.LPWStr)] public string Filename; /// /// True if audio stream is included in output. /// [MarshalAs(UnmanagedType.Bool)] public bool AudioAvailable; /// /// Audio bitrate in bits per second (e.g., 128000 for 128 kbps). /// public int AudioBitrate; /// /// Audio sample rate in Hz (e.g., 44100, 48000). /// public int AudioSamplerate; /// /// Number of audio channels (1 = mono, 2 = stereo). /// public int AudioChannels; /// /// Video frame width in pixels. /// public int VideoWidth; /// /// Video frame height in pixels. /// public int VideoHeight; /// /// Display aspect ratio width (e.g., 16 for 16:9). /// public int AspectRatioW; /// /// Display aspect ratio height (e.g., 9 for 16:9). /// public int AspectRatioH; /// /// Video bitrate in bits per second (e.g., 5000000 for 5 Mbps). /// public int VideoBitrate; /// /// Maximum video bitrate for VBR encoding (bits per second). /// public int VideoMaxRate; /// /// Minimum video bitrate for VBR encoding (bits per second). /// public int VideoMinRate; /// /// Video buffer size in bits (affects latency and smoothness). /// public int VideoBufferSize; /// /// True to enable interlaced encoding (for broadcast TV). /// [MarshalAs(UnmanagedType.Bool)] public bool Interlace; /// /// GOP (Group of Pictures) size - keyframe interval. /// Typical: 12-15 for MPEG-2, 30-60 for web video. /// public int VideoGopSize; /// /// TV system standard (PAL, NTSC, Film, or None). /// [MarshalAs(UnmanagedType.I4)] public VFFFMPEGDLLTVSystem TVSystem; /// /// Output format (FLV, MPEG-1, MPEG-2, etc.). /// [MarshalAs(UnmanagedType.I4)] public VFFFMPEGDLLOutputFormat OutputFormat; } ``` ## Interface Definitions ### C# Definition ``` using System; using System.Runtime.InteropServices; namespace VisioForge.DirectShowAPI { /// /// FFMPEG encoder configuration interface. /// Provides comprehensive encoding to multiple formats using FFMPEG library. /// [ComImport] [Guid("17B8FF7D-A67F-45CE-B425-0E4F607D8C60")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] public interface IVFFFMPEGEncoder { /// /// Sets the complete FFMPEG encoder configuration. /// All encoding parameters must be set at once via this structure. /// /// Complete encoder settings structure [PreserveSig] void set_settings([In] FFMPEGOutputSettings settings); } } ``` ### C++ Definition ``` #include // {17B8FF7D-A67F-45CE-B425-0E4F607D8C60} DEFINE_GUID(IID_IVFFFMPEGEncoder, 0x17b8ff7d, 0xa67f, 0x45ce, 0xb4, 0x25, 0xe, 0x4f, 0x60, 0x7d, 0x8c, 0x60); // {554AB365-B293-4C1D-9245-E8DB01F027F7} DEFINE_GUID(CLSID_FFMPEGEncoder, 0x554ab365, 0xb293, 0x4c1d, 0x92, 0x45, 0xe8, 0xdb, 0x01, 0xf0, 0x27, 0xf7); /// /// Output format enumeration. /// enum FFOutputFormat { of_FLV = 0, of_MPEG1 = 1, of_MPEG1VCD = 2, of_MPEG2 = 3, of_MPEG2TS = 4, of_MPEG2SVCD = 5, of_MPEG2DVD = 6 }; /// /// TV system enumeration. /// enum video_tv_system_t { video_norm_unknown = 0, video_norm_pal = 1, video_norm_ntsc = 2, video_norm_film = 3 }; /// /// FFMPEG encoder output settings structure. /// struct CVFOutputSettings { wchar_t* filename; BOOL audioAvailable; int audioBitrate; int audioSamplerate; int audioChannels; int videoWidth; int videoHeight; int aspectRatioW; int aspectRatioH; int videoBitrate; int videoMaxRate; int videoMinRate; int videoBufferSize; BOOL interlace; int videoGopSize; int tvSystem; int outputFormat; }; /// /// FFMPEG encoder configuration interface. /// DECLARE_INTERFACE_(IVFFFMPEGEncoder, IUnknown) { /// /// Sets the complete FFMPEG encoder configuration. /// /// Complete encoder settings structure STDMETHOD(set_settings)(THIS_ CVFOutputSettings settings ) PURE; }; ``` ### Delphi Definition ``` uses ActiveX, ComObj; const IID_IVFFFMPEGEncoder: TGUID = '{17B8FF7D-A67F-45CE-B425-0E4F607D8C60}'; CLSID_FFMPEGEncoder: TGUID = '{554AB365-B293-4C1D-9245-E8DB01F027F7}'; type /// /// FFMPEG output format enumeration. /// TVFFFMPEGDLLOutputFormat = ( FLV, MPEG1, MPEG1VCD, MPEG2, MPEG2TS, MPEG2SVCD, MPEG2DVD ); /// /// TV system enumeration. Note: the `None` member can collide with the bare /// `None` identifier exposed by other Delphi units (e.g., RTL's `Variants`). /// Reference values via the enum's qualified name — /// `TVFFFMPEGDLLTVSystem.None` — to avoid ambiguity in real code. /// TVFFFMPEGDLLTVSystem = ( None, PAL, NTSC, Film ); /// /// FFMPEG encoder output settings structure. /// TFFMPEGOutputSettings = record Filename: PWideChar; AudioAvailable: BOOL; AudioBitrate: Integer; AudioSamplerate: Integer; AudioChannels: Integer; VideoWidth: Integer; VideoHeight: Integer; AspectRatioW: Integer; AspectRatioH: Integer; VideoBitrate: Integer; VideoMaxRate: Integer; VideoMinRate: Integer; VideoBufferSize: Integer; Interlace: BOOL; VideoGopSize: Integer; TVSystem: Integer; OutputFormat: Integer; end; /// /// FFMPEG encoder configuration interface. /// IVFFFMPEGEncoder = interface(IUnknown) ['{17B8FF7D-A67F-45CE-B425-0E4F607D8C60}'] /// /// Sets the complete FFMPEG encoder configuration. /// procedure set_settings(const settings: TFFMPEGOutputSettings); stdcall; end; ``` ## Output Format Specifications ### FLV (Flash Video) **Format**: Adobe Flash Video (.flv) **Use Cases**: Web streaming, legacy Flash content **Typical Settings**: - Resolution: 640x480, 854x480, 1280x720 - Video Bitrate: 500-2500 kbps - Audio: MP3, 64-128 kbps, 44100 Hz - GOP: 30-60 frames ### MPEG-1 **Format**: MPEG-1 video (.mpg) **Use Cases**: Basic video, legacy systems, web **Typical Settings**: - Resolution: 352x240 (NTSC), 352x288 (PAL) - Video Bitrate: 1150 kbps - Audio: MPEG Layer 2, 224 kbps, 44100 Hz - GOP: 12-15 frames ### MPEG-1 VCD (Video CD) **Format**: Video CD compliant MPEG-1 (.mpg) **Use Cases**: VCD authoring, disc distribution **Required Settings**: - Resolution: 352x240 (NTSC), 352x288 (PAL) - Video Bitrate: 1150 kbps (fixed) - Audio: MPEG Layer 2, 224 kbps, 44100 Hz - GOP: 12 frames (NTSC), 15 frames (PAL) - TV System: Must match (NTSC or PAL) ### MPEG-2 **Format**: MPEG-2 video (.mpg) **Use Cases**: DVD authoring, broadcast, high quality **Typical Settings**: - Resolution: 720x480 (NTSC), 720x576 (PAL) - Video Bitrate: 4000-9800 kbps - Audio: MPEG Layer 2 or AC-3, 192-448 kbps - GOP: 12-15 frames ### MPEG-2 TS (Transport Stream) **Format**: MPEG-2 Transport Stream (.ts) **Use Cases**: Broadcasting, streaming, Blu-ray **Typical Settings**: - Resolution: 720x480, 1280x720, 1920x1080 - Video Bitrate: 3000-15000 kbps - Audio: MPEG Layer 2 or AC-3 - GOP: 12-30 frames - Better error resilience than MPEG-2 PS ### MPEG-2 SVCD (Super Video CD) **Format**: Super Video CD compliant MPEG-2 (.mpg) **Use Cases**: SVCD authoring, disc distribution **Required Settings**: - Resolution: 480x480 (NTSC), 480x576 (PAL) - Video Bitrate: 2500 kbps (typical) - Audio: MPEG Layer 2, 224 kbps, 44100 Hz - GOP: 12-15 frames - TV System: Must match (NTSC or PAL) ### MPEG-2 DVD (DVD-Video) **Format**: DVD-Video compliant MPEG-2 (.mpg) **Use Cases**: DVD authoring, professional distribution **Required Settings**: - Resolution: 720x480 (NTSC), 720x576 (PAL) - Video Bitrate: 4000-9800 kbps - Audio: AC-3 or PCM, up to 448 kbps - GOP: 12 frames (NTSC), 15 frames (PAL) - TV System: Must match (NTSC or PAL) - Interlaced: Typically enabled for broadcast ## Usage Examples ### C# Example - DVD-Quality MPEG-2 (NTSC) ``` using System; using DirectShowLib; using VisioForge.DirectShowAPI; public class FFMPEGDVDEncoder { public void ConfigureDVDNTSC(IBaseFilter ffmpegEncoder) { // Query the FFMPEG encoder interface var encoder = ffmpegEncoder as IVFFFMPEGEncoder; if (encoder == null) { Console.WriteLine("Error: Filter does not support IVFFFMPEGEncoder"); return; } // Configure DVD-compliant MPEG-2 encoding (NTSC) var settings = new FFMPEGOutputSettings { // Output file Filename = "C:\\output\\movie.mpg", // Audio settings AudioAvailable = true, AudioBitrate = 224000, // 224 kbps AudioSamplerate = 48000, // 48 kHz for DVD AudioChannels = 2, // Stereo // Video settings - DVD NTSC specs VideoWidth = 720, VideoHeight = 480, AspectRatioW = 16, AspectRatioH = 9, VideoBitrate = 6000000, // 6 Mbps VideoMaxRate = 9800000, // 9.8 Mbps max for DVD VideoMinRate = 0, VideoBufferSize = 1835008, // Standard DVD buffer Interlace = true, // DVD is interlaced VideoGopSize = 12, // 12 frames for NTSC // Format settings TVSystem = VFFFMPEGDLLTVSystem.NTSC, OutputFormat = VFFFMPEGDLLOutputFormat.MPEG2DVD }; encoder.set_settings(settings); Console.WriteLine("FFMPEG encoder configured for DVD NTSC:"); Console.WriteLine(" Resolution: 720x480 (16:9)"); Console.WriteLine(" Video: 6 Mbps MPEG-2, interlaced"); Console.WriteLine(" Audio: 224 kbps, 48 kHz stereo"); Console.WriteLine(" GOP: 12 frames"); } } ``` ### C# Example - Web Streaming FLV ``` public class FFMPEGWebStreaming { public void ConfigureFLV(IBaseFilter ffmpegEncoder) { var encoder = ffmpegEncoder as IVFFFMPEGEncoder; if (encoder == null) return; // Configure Flash Video for web streaming var settings = new FFMPEGOutputSettings { Filename = "C:\\output\\video.flv", // Audio settings AudioAvailable = true, AudioBitrate = 96000, // 96 kbps AudioSamplerate = 44100, AudioChannels = 2, // Video settings - 720p web streaming VideoWidth = 1280, VideoHeight = 720, AspectRatioW = 16, AspectRatioH = 9, VideoBitrate = 2000000, // 2 Mbps VideoMaxRate = 2500000, // 2.5 Mbps max VideoMinRate = 1500000, // 1.5 Mbps min VideoBufferSize = 2000000, Interlace = false, // Progressive for web VideoGopSize = 60, // 2 seconds at 30fps TVSystem = VFFFMPEGDLLTVSystem.None, OutputFormat = VFFFMPEGDLLOutputFormat.FLV }; encoder.set_settings(settings); Console.WriteLine("FFMPEG encoder configured for FLV web streaming:"); Console.WriteLine(" 720p @ 2 Mbps, progressive"); } } ``` ### C# Example - VCD Compliant MPEG-1 (PAL) ``` public class FFMPEGVCDEncoder { public void ConfigureVCDPAL(IBaseFilter ffmpegEncoder) { var encoder = ffmpegEncoder as IVFFFMPEGEncoder; if (encoder == null) return; // Configure VCD-compliant MPEG-1 (PAL) var settings = new FFMPEGOutputSettings { Filename = "C:\\output\\vcd.mpg", // Audio settings - VCD spec AudioAvailable = true, AudioBitrate = 224000, // 224 kbps required AudioSamplerate = 44100, // 44.1 kHz required AudioChannels = 2, // Video settings - VCD PAL specs VideoWidth = 352, VideoHeight = 288, // PAL resolution AspectRatioW = 4, AspectRatioH = 3, VideoBitrate = 1150000, // 1150 kbps required VideoMaxRate = 1150000, VideoMinRate = 1150000, VideoBufferSize = 327680, // VCD buffer size Interlace = false, VideoGopSize = 15, // 15 frames for PAL TVSystem = VFFFMPEGDLLTVSystem.PAL, OutputFormat = VFFFMPEGDLLOutputFormat.MPEG1VCD }; encoder.set_settings(settings); Console.WriteLine("FFMPEG encoder configured for VCD PAL:"); Console.WriteLine(" 352x288 @ 1150 kbps"); } } ``` ### C# Example - MPEG-2 Transport Stream ``` public class FFMPEGMPEG2TS { public void ConfigureMPEG2TS(IBaseFilter ffmpegEncoder) { var encoder = ffmpegEncoder as IVFFFMPEGEncoder; if (encoder == null) return; // Configure MPEG-2 Transport Stream for broadcasting var settings = new FFMPEGOutputSettings { Filename = "C:\\output\\stream.ts", // Audio settings AudioAvailable = true, AudioBitrate = 192000, AudioSamplerate = 48000, AudioChannels = 2, // Video settings - 1080i HD broadcast VideoWidth = 1920, VideoHeight = 1080, AspectRatioW = 16, AspectRatioH = 9, VideoBitrate = 12000000, // 12 Mbps VideoMaxRate = 15000000, // 15 Mbps max VideoMinRate = 8000000, // 8 Mbps min VideoBufferSize = 8000000, Interlace = true, // Broadcast is interlaced VideoGopSize = 15, TVSystem = VFFFMPEGDLLTVSystem.NTSC, OutputFormat = VFFFMPEGDLLOutputFormat.MPEG2TS }; encoder.set_settings(settings); Console.WriteLine("FFMPEG encoder configured for MPEG-2 TS:"); Console.WriteLine(" 1080i HD broadcast stream"); } } ``` ### C++ Example - DVD NTSC ``` #include #include #include "InterfaceDefine.h" void ConfigureFFMPEGDVD(IBaseFilter* pFFMPEGEncoder) { IVFFFMPEGEncoder* pEncoder = NULL; HRESULT hr = S_OK; // Query the FFMPEG encoder interface hr = pFFMPEGEncoder->QueryInterface(IID_IVFFFMPEGEncoder, (void**)&pEncoder); if (FAILED(hr) || !pEncoder) { std::cout << "Error: Filter does not support IVFFFMPEGEncoder" << std::endl; return; } // Configure DVD-compliant MPEG-2 encoding (NTSC) CVFOutputSettings settings; ZeroMemory(&settings, sizeof(settings)); settings.filename = L"C:\\output\\movie.mpg"; // Audio settings settings.audioAvailable = TRUE; settings.audioBitrate = 224000; settings.audioSamplerate = 48000; settings.audioChannels = 2; // Video settings - DVD NTSC specs settings.videoWidth = 720; settings.videoHeight = 480; settings.aspectRatioW = 16; settings.aspectRatioH = 9; settings.videoBitrate = 6000000; settings.videoMaxRate = 9800000; settings.videoMinRate = 0; settings.videoBufferSize = 1835008; settings.interlace = TRUE; settings.videoGopSize = 12; settings.tvSystem = video_norm_ntsc; settings.outputFormat = of_MPEG2DVD; pEncoder->set_settings(settings); std::cout << "FFMPEG encoder configured for DVD NTSC" << std::endl; pEncoder->Release(); } ``` ### C++ Example - FLV Web Streaming ``` void ConfigureFFMPEGFLV(IBaseFilter* pFFMPEGEncoder) { IVFFFMPEGEncoder* pEncoder = NULL; HRESULT hr = pFFMPEGEncoder->QueryInterface(IID_IVFFFMPEGEncoder, (void**)&pEncoder); if (SUCCEEDED(hr) && pEncoder) { CVFOutputSettings settings; ZeroMemory(&settings, sizeof(settings)); settings.filename = L"C:\\output\\video.flv"; // Audio settings settings.audioAvailable = TRUE; settings.audioBitrate = 96000; settings.audioSamplerate = 44100; settings.audioChannels = 2; // Video settings - 720p web settings.videoWidth = 1280; settings.videoHeight = 720; settings.aspectRatioW = 16; settings.aspectRatioH = 9; settings.videoBitrate = 2000000; settings.videoMaxRate = 2500000; settings.videoMinRate = 1500000; settings.videoBufferSize = 2000000; settings.interlace = FALSE; settings.videoGopSize = 60; settings.tvSystem = video_norm_unknown; settings.outputFormat = of_FLV; pEncoder->set_settings(settings); std::cout << "FFMPEG FLV encoder configured" << std::endl; pEncoder->Release(); } } ``` ### Delphi Example - DVD PAL ``` uses DirectShow9, ActiveX; procedure ConfigureFFMPEGDVDPAL(FFMPEGEncoder: IBaseFilter); var Encoder: IVFFFMPEGEncoder; Settings: TFFMPEGOutputSettings; hr: HRESULT; begin hr := FFMPEGEncoder.QueryInterface(IID_IVFFFMPEGEncoder, Encoder); if Failed(hr) or (Encoder = nil) then begin WriteLn('Error: Filter does not support IVFFFMPEGEncoder'); Exit; end; try ZeroMemory(@Settings, SizeOf(Settings)); Settings.Filename := 'C:\output\movie.mpg'; // Audio settings Settings.AudioAvailable := True; Settings.AudioBitrate := 224000; Settings.AudioSamplerate := 48000; Settings.AudioChannels := 2; // Video settings - DVD PAL specs Settings.VideoWidth := 720; Settings.VideoHeight := 576; Settings.AspectRatioW := 16; Settings.AspectRatioH := 9; Settings.VideoBitrate := 6000000; Settings.VideoMaxRate := 9800000; Settings.VideoMinRate := 0; Settings.VideoBufferSize := 1835008; Settings.Interlace := True; Settings.VideoGopSize := 15; Settings.TVSystem := Ord(PAL); Settings.OutputFormat := Ord(MPEG2DVD); Encoder.set_settings(Settings); WriteLn('FFMPEG encoder configured for DVD PAL'); finally Encoder := nil; end; end; ``` ## Best Practices ### Format-Specific Recommendations **For DVD Authoring (MPEG2DVD)**: - Always match TV system to target region (NTSC for Americas/Japan, PAL for Europe/Asia) - Use 720x480 for NTSC, 720x576 for PAL - Enable interlacing for broadcast compatibility - GOP: 12 frames (NTSC), 15 frames (PAL) - Video bitrate: 4-9.8 Mbps - Audio: 48 kHz, 224-448 kbps **For VCD/SVCD (MPEG1VCD, MPEG2SVCD)**: - Strictly follow format specifications (resolution, bitrate) - Match TV system to target region - Use exact specified bitrates for best compatibility - Test on target hardware (standalone VCD/SVCD players) **For Web Streaming (FLV)**: - Use progressive (non-interlaced) encoding - Lower bitrates for broader reach (500-2500 kbps) - GOP: 30-60 frames for seek points every 1-2 seconds - Consider modern alternatives (MP4/H.264) for better quality **For Broadcasting (MPEG2TS)**: - Transport Stream has better error resilience - Use for live streaming and broadcast applications - Higher bitrates acceptable (10-15 Mbps for HD) - Match interlacing to broadcast standard ### Resolution and Aspect Ratio **Standard Resolutions by Format**: | Format | NTSC Resolution | PAL Resolution | Aspect Ratio | | --- | --- | --- | --- | | VCD | 352x240 | 352x288 | 4:3 | | SVCD | 480x480 | 480x576 | 4:3 or 16:9 | | DVD | 720x480 | 720x576 | 4:3 or 16:9 | | FLV/MPEG-2 | Any | Any | Any | **Aspect Ratio Settings**: - 4:3 standard: `AspectRatioW = 4, AspectRatioH = 3` - 16:9 widescreen: `AspectRatioW = 16, AspectRatioH = 9` - Ensure display aspect ratio matches pixel aspect ratio ### GOP Size Guidelines **VCD/SVCD/DVD**: - NTSC: 12 frames (0.4 seconds at 29.97 fps) - PAL: 15 frames (0.6 seconds at 25 fps) - Required for format compliance **Web Streaming**: - 30-60 frames (1-2 seconds) - Shorter GOP: Better seeking, larger file - Longer GOP: Smaller file, slower seeking **Broadcast**: - 12-15 frames for high quality - Match to TV system standard ### Bitrate Configuration **VBR (Variable Bitrate)**: - Set `VideoBitrate` (average), `VideoMinRate`, `VideoMaxRate` - Better quality for same average bitrate - Use for file-based encoding **CBR (Constant Bitrate)**: - Set all three bitrates to the same value - Predictable file size and bandwidth - Use for streaming and broadcasting ### Audio Settings **Sample Rates**: - 44100 Hz: CD quality, VCD/SVCD - 48000 Hz: DVD, professional broadcast - Match source when possible **Bitrates**: - Mono speech: 64-96 kbps - Stereo music: 128-224 kbps - DVD audio: 192-448 kbps ## Troubleshooting ### Encoder Initialization Fails **Symptoms**: `set_settings` call fails or crashes **Possible Causes**: 1. Invalid filename or path 2. Incorrect format specifications 3. Unsupported resolution/bitrate combination **Solutions**: - Ensure output directory exists and is writable - Verify resolution matches format requirements - Check bitrate is within format limits - For VCD/SVCD/DVD, strictly follow specifications ### Output File Won't Play **Symptoms**: Encoded file doesn't play or has errors **Possible Causes**: 1. Format specifications not met 2. Wrong TV system for format 3. Interlacing mismatch 4. GOP size issues **Solutions**: - For DVD/VCD/SVCD: Use exact specification parameters - Match TV system to target region - Enable interlacing for DVD/broadcast - Use standard GOP sizes (12 for NTSC, 15 for PAL) ### Poor Video Quality **Symptoms**: Blocky, blurry, or artifact-laden video **Possible Causes**: 1. Bitrate too low for resolution 2. Incorrect GOP size 3. Bitrate range too restrictive **Solutions**: - Increase video bitrate (see format recommendations) - For VBR, widen min/max bitrate range - Use appropriate GOP size for format - Ensure resolution matches format specifications ### A/V Sync Issues **Symptoms**: Audio and video drift out of sync **Possible Causes**: 1. Incorrect sample rate 2. Wrong frame rate for TV system 3. Buffer size issues **Solutions**: - Use 48000 Hz for DVD, 44100 Hz for VCD - Ensure TV system matches source frame rate - Increase `VideoBufferSize` for complex content - Verify source audio/video are synchronized ### DVD/VCD Won't Play on Hardware **Symptoms**: File plays on computer but not on standalone player **Possible Causes**: 1. Format specifications not strictly followed 2. Wrong TV system 3. Non-compliant GOP size or bitrate **Solutions**: - **Critical**: Use exact format specifications - VCD: 352x240/288, 1150 kbps, GOP 12/15 - DVD: 720x480/576, max 9.8 Mbps, GOP 12/15 - Match TV system to player region - Enable interlacing for DVD - Test with software DVD/VCD player first ### Large File Sizes **Symptoms**: Output files larger than expected **Possible Causes**: 1. Bitrate too high 2. CBR instead of VBR 3. Small GOP size **Solutions**: - Reduce video bitrate - Use VBR with appropriate min/max range - Increase GOP size (for non-DVD/VCD formats) - Consider more efficient formats (H.264/MP4 instead of MPEG-2) --- ## See Also - [H.264 Encoder Interface](../h264/) - [Video Codecs Reference](../../codecs-reference/) - [MP4 Muxer Interface](../mp4-muxer/) - [Encoding Filters Pack Overview](../../) ---END OF PAGE--- ## FLAC Lossless Audio Encoder DirectShow Filter Interface **URL:** https://www.visioforge.com/help/docs/directshow/filters-enc/interfaces/flac/ **Description:** FLAC encoder DirectShow interface with encoding levels, LPC configuration, block sizes, and compression for lossless audio encoding. **Tags:** DirectShow, C++, Windows, Encoding, Decoding, MP3, FLAC, C# **API:** FLACEncoder, IFLACEncodeSettings, IBaseFilter, AudioEncoder, FLACArchivalEncoder # FLAC Encoder Interface Reference ## Overview The **IFLACEncodeSettings** interface provides complete control over FLAC (Free Lossless Audio Codec) audio encoding parameters in DirectShow filter graphs. FLAC is a lossless audio compression format that reduces file size without any loss in audio quality, making it ideal for archival, professional audio production, and high-fidelity music distribution. This interface allows developers to configure encoding quality levels, Linear Predictive Coding (LPC) parameters, block sizes, mid-side stereo coding, and Rice partition orders to achieve optimal compression efficiency for different types of audio content. **Interface GUID**: `{A6096781-2A65-4540-A536-011235D0A5FE}` **Inherits From**: `IUnknown` ## Interface Definitions ### C# Definition ``` using System; using System.Runtime.InteropServices; namespace VisioForge.DirectShowAPI { /// /// FLAC (Free Lossless Audio Codec) encoder configuration interface. /// Provides comprehensive control over FLAC encoding parameters for lossless audio compression. /// [ComImport] [Guid("A6096781-2A65-4540-A536-011235D0A5FE")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] public interface IFLACEncodeSettings { /// /// Checks if encoding settings can be modified at the current time. /// /// True if settings can be modified, false otherwise [PreserveSig] [return: MarshalAs(UnmanagedType.Bool)] bool canModifySettings(); /// /// Sets the FLAC encoding level (compression quality). /// /// Encoding level (0-8, where 8 is highest compression, slowest) /// True if successful, false otherwise [PreserveSig] [return: MarshalAs(UnmanagedType.Bool)] bool setEncodingLevel(uint inLevel); /// /// Sets the Linear Predictive Coding (LPC) order. /// Higher values provide better compression but slower encoding. /// /// LPC order (typically 0-32) /// True if successful, false otherwise [PreserveSig] [return: MarshalAs(UnmanagedType.Bool)] bool setLPCOrder(uint inLPCOrder); /// /// Sets the audio block size for encoding. /// Larger blocks can provide better compression but increase latency. /// /// Block size in samples (typically 192-4608) /// True if successful, false otherwise [PreserveSig] [return: MarshalAs(UnmanagedType.Bool)] bool setBlockSize(uint inBlockSize); /// /// Enables or disables mid-side stereo coding for 2-channel audio. /// Can improve compression for stereo audio with correlated channels. /// /// True to enable mid-side coding, false to disable /// True if successful, false otherwise /// Only applicable for 2-channel (stereo) audio [PreserveSig] [return: MarshalAs(UnmanagedType.Bool)] bool useMidSideCoding([In, MarshalAs(UnmanagedType.Bool)] bool inUseMidSideCoding); /// /// Enables or disables adaptive mid-side stereo coding. /// Automatically decides whether to use mid-side coding on a per-block basis. /// Overrides useMidSideCoding and is generally faster. /// /// True to enable adaptive mid-side coding, false to disable /// True if successful, false otherwise /// Only for 2-channel audio. Overrides useMidSideCoding setting. Generally provides better performance. [PreserveSig] [return: MarshalAs(UnmanagedType.Bool)] bool useAdaptiveMidSideCoding([In, MarshalAs(UnmanagedType.Bool)] bool inUseAdaptiveMidSideCoding); /// /// Enables or disables exhaustive model search for best compression. /// Significantly slower but can provide better compression ratios. /// /// True to enable exhaustive search, false to disable /// True if successful, false otherwise [PreserveSig] [return: MarshalAs(UnmanagedType.Bool)] bool useExhaustiveModelSearch([In, MarshalAs(UnmanagedType.Bool)] bool inUseExhaustiveModelSearch); /// /// Sets the Rice partition order range for entropy coding. /// Controls the trade-off between compression efficiency and encoding speed. /// /// Minimum Rice partition order /// Maximum Rice partition order /// True if successful, false otherwise [PreserveSig] [return: MarshalAs(UnmanagedType.Bool)] bool setRicePartitionOrder(uint inMin, uint inMax); /// /// Gets the current encoding level setting. /// /// Current encoding level (0-8) [PreserveSig] int encoderLevel(); /// /// Gets the current Linear Predictive Coding (LPC) order. /// /// Current LPC order [PreserveSig] uint LPCOrder(); /// /// Gets the current block size setting. /// /// Current block size in samples [PreserveSig] uint blockSize(); /// /// Gets the minimum Rice partition order. /// /// Minimum Rice partition order [PreserveSig] uint riceMin(); /// /// Gets the maximum Rice partition order. /// /// Maximum Rice partition order [PreserveSig] uint riceMax(); /// /// Checks if mid-side stereo coding is enabled. /// /// True if mid-side coding is enabled, false otherwise [PreserveSig] [return: MarshalAs(UnmanagedType.Bool)] bool isUsingMidSideCoding(); /// /// Checks if adaptive mid-side stereo coding is enabled. /// /// True if adaptive mid-side coding is enabled, false otherwise [PreserveSig] [return: MarshalAs(UnmanagedType.Bool)] bool isUsingAdaptiveMidSideCoding(); /// /// Checks if exhaustive model search is enabled. /// /// True if exhaustive model search is enabled, false otherwise [PreserveSig] [return: MarshalAs(UnmanagedType.Bool)] bool isUsingExhaustiveModel(); } } ``` ### C++ Definition ``` #include // {A6096781-2A65-4540-A536-011235D0A5FE} DEFINE_GUID(IID_IFLACEncodeSettings, 0xa6096781, 0x2a65, 0x4540, 0xa5, 0x36, 0x01, 0x12, 0x35, 0xd0, 0xa5, 0xfe); /// /// FLAC (Free Lossless Audio Codec) encoder configuration interface. /// Provides comprehensive control over FLAC encoding parameters for lossless audio compression. /// DECLARE_INTERFACE_(IFLACEncodeSettings, IUnknown) { /// /// Checks if encoding settings can be modified at the current time. /// /// TRUE if settings can be modified, FALSE otherwise STDMETHOD_(BOOL, canModifySettings)(THIS) PURE; /// /// Sets the FLAC encoding level (compression quality). /// /// Encoding level (0-8, where 8 is highest compression, slowest) /// TRUE if successful, FALSE otherwise STDMETHOD_(BOOL, setEncodingLevel)(THIS_ unsigned long inLevel ) PURE; /// /// Sets the Linear Predictive Coding (LPC) order. /// Higher values provide better compression but slower encoding. /// /// LPC order (typically 0-32) /// TRUE if successful, FALSE otherwise STDMETHOD_(BOOL, setLPCOrder)(THIS_ unsigned long inLPCOrder ) PURE; /// /// Sets the audio block size for encoding. /// Larger blocks can provide better compression but increase latency. /// /// Block size in samples (typically 192-4608) /// TRUE if successful, FALSE otherwise STDMETHOD_(BOOL, setBlockSize)(THIS_ unsigned long inBlockSize ) PURE; /// /// Enables or disables mid-side stereo coding for 2-channel audio. /// Can improve compression for stereo audio with correlated channels. /// /// TRUE to enable mid-side coding, FALSE to disable /// TRUE if successful, FALSE otherwise /// Only applicable for 2-channel (stereo) audio STDMETHOD_(BOOL, useMidSideCoding)(THIS_ BOOL inUseMidSideCoding ) PURE; /// /// Enables or disables adaptive mid-side stereo coding. /// Automatically decides whether to use mid-side coding on a per-block basis. /// Overrides useMidSideCoding and is generally faster. /// /// TRUE to enable adaptive mid-side coding, FALSE to disable /// TRUE if successful, FALSE otherwise /// Only for 2-channel audio. Overrides useMidSideCoding setting. Generally provides better performance. STDMETHOD_(BOOL, useAdaptiveMidSideCoding)(THIS_ BOOL inUseAdaptiveMidSideCoding ) PURE; /// /// Enables or disables exhaustive model search for best compression. /// Significantly slower but can provide better compression ratios. /// /// TRUE to enable exhaustive search, FALSE to disable /// TRUE if successful, FALSE otherwise STDMETHOD_(BOOL, useExhaustiveModelSearch)(THIS_ BOOL inUseExhaustiveModelSearch ) PURE; /// /// Sets the Rice partition order range for entropy coding. /// Controls the trade-off between compression efficiency and encoding speed. /// /// Minimum Rice partition order /// Maximum Rice partition order /// TRUE if successful, FALSE otherwise STDMETHOD_(BOOL, setRicePartitionOrder)(THIS_ unsigned long inMin, unsigned long inMax ) PURE; /// /// Gets the current encoding level setting. /// /// Current encoding level (0-8) STDMETHOD_(int, encoderLevel)(THIS) PURE; /// /// Gets the current Linear Predictive Coding (LPC) order. /// /// Current LPC order STDMETHOD_(unsigned long, LPCOrder)(THIS) PURE; /// /// Gets the current block size setting. /// /// Current block size in samples STDMETHOD_(unsigned long, blockSize)(THIS) PURE; /// /// Gets the minimum Rice partition order. /// /// Minimum Rice partition order STDMETHOD_(unsigned long, riceMin)(THIS) PURE; /// /// Gets the maximum Rice partition order. /// /// Maximum Rice partition order STDMETHOD_(unsigned long, riceMax)(THIS) PURE; /// /// Checks if mid-side stereo coding is enabled. /// /// TRUE if mid-side coding is enabled, FALSE otherwise STDMETHOD_(BOOL, isUsingMidSideCoding)(THIS) PURE; /// /// Checks if adaptive mid-side stereo coding is enabled. /// /// TRUE if adaptive mid-side coding is enabled, FALSE otherwise STDMETHOD_(BOOL, isUsingAdaptiveMidSideCoding)(THIS) PURE; /// /// Checks if exhaustive model search is enabled. /// /// TRUE if exhaustive model search is enabled, FALSE otherwise STDMETHOD_(BOOL, isUsingExhaustiveModel)(THIS) PURE; }; ``` ### Delphi Definition ``` uses ActiveX, ComObj; const IID_IFLACEncodeSettings: TGUID = '{A6096781-2A65-4540-A536-011235D0A5FE}'; type /// /// FLAC (Free Lossless Audio Codec) encoder configuration interface. /// Provides comprehensive control over FLAC encoding parameters for lossless audio compression. /// IFLACEncodeSettings = interface(IUnknown) ['{A6096781-2A65-4540-A536-011235D0A5FE}'] /// /// Checks if encoding settings can be modified at the current time. /// /// True if settings can be modified, false otherwise function canModifySettings: BOOL; stdcall; /// /// Sets the FLAC encoding level (compression quality). /// /// Encoding level (0-8, where 8 is highest compression, slowest) /// True if successful, false otherwise function setEncodingLevel(inLevel: Cardinal): BOOL; stdcall; /// /// Sets the Linear Predictive Coding (LPC) order. /// Higher values provide better compression but slower encoding. /// /// LPC order (typically 0-32) /// True if successful, false otherwise function setLPCOrder(inLPCOrder: Cardinal): BOOL; stdcall; /// /// Sets the audio block size for encoding. /// Larger blocks can provide better compression but increase latency. /// /// Block size in samples (typically 192-4608) /// True if successful, false otherwise function setBlockSize(inBlockSize: Cardinal): BOOL; stdcall; /// /// Enables or disables mid-side stereo coding for 2-channel audio. /// Can improve compression for stereo audio with correlated channels. /// /// True to enable mid-side coding, false to disable /// True if successful, false otherwise /// Only applicable for 2-channel (stereo) audio function useMidSideCoding(inUseMidSideCoding: BOOL): BOOL; stdcall; /// /// Enables or disables adaptive mid-side stereo coding. /// Automatically decides whether to use mid-side coding on a per-block basis. /// Overrides useMidSideCoding and is generally faster. /// /// True to enable adaptive mid-side coding, false to disable /// True if successful, false otherwise /// Only for 2-channel audio. Overrides useMidSideCoding setting. Generally provides better performance. function useAdaptiveMidSideCoding(inUseAdaptiveMidSideCoding: BOOL): BOOL; stdcall; /// /// Enables or disables exhaustive model search for best compression. /// Significantly slower but can provide better compression ratios. /// /// True to enable exhaustive search, false to disable /// True if successful, false otherwise function useExhaustiveModelSearch(inUseExhaustiveModelSearch: BOOL): BOOL; stdcall; /// /// Sets the Rice partition order range for entropy coding. /// Controls the trade-off between compression efficiency and encoding speed. /// /// Minimum Rice partition order /// Maximum Rice partition order /// True if successful, false otherwise function setRicePartitionOrder(inMin: Cardinal; inMax: Cardinal): BOOL; stdcall; /// /// Gets the current encoding level setting. /// /// Current encoding level (0-8) function encoderLevel: Integer; stdcall; /// /// Gets the current Linear Predictive Coding (LPC) order. /// /// Current LPC order function LPCOrder: Cardinal; stdcall; /// /// Gets the current block size setting. /// /// Current block size in samples function blockSize: Cardinal; stdcall; /// /// Gets the minimum Rice partition order. /// /// Minimum Rice partition order function riceMin: Cardinal; stdcall; /// /// Gets the maximum Rice partition order. /// /// Maximum Rice partition order function riceMax: Cardinal; stdcall; /// /// Checks if mid-side stereo coding is enabled. /// /// True if mid-side coding is enabled, false otherwise function isUsingMidSideCoding: BOOL; stdcall; /// /// Checks if adaptive mid-side stereo coding is enabled. /// /// True if adaptive mid-side coding is enabled, false otherwise function isUsingAdaptiveMidSideCoding: BOOL; stdcall; /// /// Checks if exhaustive model search is enabled. /// /// True if exhaustive model search is enabled, false otherwise function isUsingExhaustiveModel: BOOL; stdcall; end; ``` ## Method Reference ### Configuration Check #### canModifySettings Checks if encoding settings can be modified at the current time. This is useful to verify the encoder is in a state where configuration changes are allowed (typically before the filter graph starts running). **Returns**: `true` if settings can be modified, `false` otherwise **Example Usage**: ``` if (flacEncoder.canModifySettings()) { // Safe to modify encoder settings flacEncoder.setEncodingLevel(5); } ``` ### Encoding Configuration Methods #### setEncodingLevel Sets the FLAC encoding level, which controls the compression quality and encoding speed trade-off. **Parameters**: - `inLevel` - Encoding level (0-8): - 0 = Fastest encoding, lowest compression - 5 = Balanced (recommended for most uses) - 8 = Slowest encoding, highest compression **Returns**: `true` if successful, `false` otherwise **Recommended Values**: - **Fast archival**: Level 3-5 - **High-quality archival**: Level 6-8 - **Real-time encoding**: Level 0-2 #### setLPCOrder Sets the Linear Predictive Coding (LPC) order, which affects compression efficiency and encoding speed. **Parameters**: - `inLPCOrder` - LPC order value (typically 0-32) - 0 = No LPC (fastest) - 12 = Default for most audio - 32 = Maximum compression (slowest) **Returns**: `true` if successful, `false` otherwise **Note**: Higher LPC orders provide better compression but significantly increase encoding time. #### setBlockSize Sets the audio block size for encoding. The block size affects both compression efficiency and latency. **Parameters**: - `inBlockSize` - Block size in samples - Common values: 192, 576, 1152, 2304, 4608 - Default is typically 4096 for 44.1kHz audio **Returns**: `true` if successful, `false` otherwise **Recommendations**: - **Low latency**: 192-1152 samples - **Standard archival**: 4096 samples - **Maximum compression**: 4608 samples #### useMidSideCoding Enables or disables mid-side stereo coding for 2-channel audio. Mid-side coding can improve compression for stereo audio where the left and right channels are highly correlated. **Parameters**: - `inUseMidSideCoding` - `true` to enable, `false` to disable **Returns**: `true` if successful, `false` otherwise **Note**: Only applicable for 2-channel (stereo) audio. Most music benefits from mid-side coding. #### useAdaptiveMidSideCoding Enables or disables adaptive mid-side stereo coding. This mode automatically decides whether to use mid-side coding on a per-block basis, providing better compression than fixed mid-side coding. **Parameters**: - `inUseAdaptiveMidSideCoding` - `true` to enable, `false` to disable **Returns**: `true` if successful, `false` otherwise **Note**: - Only for 2-channel audio - Overrides `useMidSideCoding` setting - Generally provides better performance than fixed mid-side coding - Recommended for most stereo encoding scenarios #### useExhaustiveModelSearch Enables or disables exhaustive model search for finding the best compression predictor. **Parameters**: - `inUseExhaustiveModelSearch` - `true` to enable, `false` to disable **Returns**: `true` if successful, `false` otherwise **Warning**: Exhaustive search significantly slows down encoding (often 2-4x slower) but can provide marginally better compression (typically 1-3% file size reduction). **Recommended**: Only enable for archival of critical audio where encoding time is not a concern. #### setRicePartitionOrder Sets the Rice partition order range for entropy coding. Rice coding is the final compression stage in FLAC. **Parameters**: - `inMin` - Minimum Rice partition order (typically 0-2) - `inMax` - Maximum Rice partition order (typically 3-8) **Returns**: `true` if successful, `false` otherwise **Typical Values**: - Fast encoding: min=0, max=3 - Standard encoding: min=0, max=6 - Maximum compression: min=0, max=8 ### Status Query Methods #### encoderLevel Gets the current encoding level setting. **Returns**: Current encoding level (0-8) #### LPCOrder Gets the current Linear Predictive Coding (LPC) order. **Returns**: Current LPC order value #### blockSize Gets the current block size setting. **Returns**: Current block size in samples #### riceMin Gets the minimum Rice partition order. **Returns**: Minimum Rice partition order #### riceMax Gets the maximum Rice partition order. **Returns**: Maximum Rice partition order #### isUsingMidSideCoding Checks if fixed mid-side stereo coding is enabled. **Returns**: `true` if mid-side coding is enabled, `false` otherwise #### isUsingAdaptiveMidSideCoding Checks if adaptive mid-side stereo coding is enabled. **Returns**: `true` if adaptive mid-side coding is enabled, `false` otherwise #### isUsingExhaustiveModel Checks if exhaustive model search is enabled. **Returns**: `true` if exhaustive model search is enabled, `false` otherwise ## Usage Examples ### C# Example - High Quality Archival ``` using System; using DirectShowLib; using VisioForge.DirectShowAPI; public class FLACArchivalEncoder { public void ConfigureHighQualityArchival(IBaseFilter audioEncoder) { // Query the FLAC encoder interface var flacEncoder = audioEncoder as IFLACEncodeSettings; if (flacEncoder == null) { Console.WriteLine("Error: Filter does not support IFLACEncodeSettings"); return; } // Check if we can modify settings if (!flacEncoder.canModifySettings()) { Console.WriteLine("Warning: Cannot modify encoder settings at this time"); return; } // High quality archival settings flacEncoder.setEncodingLevel(8); // Maximum compression flacEncoder.setLPCOrder(12); // Good LPC order for music flacEncoder.setBlockSize(4096); // Standard block size for 44.1kHz flacEncoder.useAdaptiveMidSideCoding(true); // Adaptive mid-side for stereo flacEncoder.useExhaustiveModelSearch(true); // Best possible compression flacEncoder.setRicePartitionOrder(0, 8); // Maximum Rice partition range Console.WriteLine("FLAC encoder configured for high-quality archival:"); Console.WriteLine($" Encoding Level: {flacEncoder.encoderLevel()}"); Console.WriteLine($" LPC Order: {flacEncoder.LPCOrder()}"); Console.WriteLine($" Block Size: {flacEncoder.blockSize()}"); Console.WriteLine($" Adaptive Mid-Side: {flacEncoder.isUsingAdaptiveMidSideCoding()}"); Console.WriteLine($" Exhaustive Search: {flacEncoder.isUsingExhaustiveModel()}"); Console.WriteLine($" Rice Partition: {flacEncoder.riceMin()}-{flacEncoder.riceMax()}"); } } ``` ### C# Example - Fast Real-Time Encoding ``` public class FLACRealTimeEncoder { public void ConfigureFastEncoding(IBaseFilter audioEncoder) { var flacEncoder = audioEncoder as IFLACEncodeSettings; if (flacEncoder == null || !flacEncoder.canModifySettings()) return; // Fast encoding settings for real-time use flacEncoder.setEncodingLevel(2); // Fast encoding flacEncoder.setLPCOrder(8); // Lower LPC for speed flacEncoder.setBlockSize(1152); // Smaller blocks for lower latency flacEncoder.useAdaptiveMidSideCoding(true); // Still good compression flacEncoder.useExhaustiveModelSearch(false); // Disable for speed flacEncoder.setRicePartitionOrder(0, 4); // Reduced Rice partition range Console.WriteLine("FLAC encoder configured for fast real-time encoding"); Console.WriteLine($" Encoding Level: {flacEncoder.encoderLevel()}"); Console.WriteLine($" LPC Order: {flacEncoder.LPCOrder()}"); Console.WriteLine($" Block Size: {flacEncoder.blockSize()} (lower latency)"); } } ``` ### C# Example - Balanced Music Encoding ``` public class FLACMusicEncoder { public void ConfigureBalancedMusic(IBaseFilter audioEncoder) { var flacEncoder = audioEncoder as IFLACEncodeSettings; if (flacEncoder == null || !flacEncoder.canModifySettings()) return; // Balanced settings for music encoding (good compression, reasonable speed) flacEncoder.setEncodingLevel(5); // Balanced compression flacEncoder.setLPCOrder(12); // Standard LPC for music flacEncoder.setBlockSize(4096); // Optimal for 44.1kHz flacEncoder.useAdaptiveMidSideCoding(true); // Adaptive mid-side flacEncoder.useExhaustiveModelSearch(false); // Not needed for music flacEncoder.setRicePartitionOrder(0, 6); // Good Rice partition range Console.WriteLine("FLAC encoder configured for balanced music encoding"); } } ``` ### C++ Example - High Quality Archival ``` #include #include #include "IFLACEncodeSettings.h" void ConfigureHighQualityFLAC(IBaseFilter* pAudioEncoder) { IFLACEncodeSettings* pFLACEncoder = NULL; HRESULT hr = S_OK; // Query the FLAC encoder interface hr = pAudioEncoder->QueryInterface(IID_IFLACEncodeSettings, (void**)&pFLACEncoder); if (FAILED(hr) || !pFLACEncoder) { std::cout << "Error: Filter does not support IFLACEncodeSettings" << std::endl; return; } // Check if we can modify settings if (!pFLACEncoder->canModifySettings()) { std::cout << "Warning: Cannot modify encoder settings" << std::endl; pFLACEncoder->Release(); return; } // Configure high quality archival settings pFLACEncoder->setEncodingLevel(8); // Maximum compression pFLACEncoder->setLPCOrder(12); // Good LPC order pFLACEncoder->setBlockSize(4096); // Standard block size pFLACEncoder->useAdaptiveMidSideCoding(TRUE); // Adaptive mid-side pFLACEncoder->useExhaustiveModelSearch(TRUE); // Best compression pFLACEncoder->setRicePartitionOrder(0, 8); // Maximum range // Display configuration std::cout << "FLAC encoder configured for high-quality archival:" << std::endl; std::cout << " Encoding Level: " << pFLACEncoder->encoderLevel() << std::endl; std::cout << " LPC Order: " << pFLACEncoder->LPCOrder() << std::endl; std::cout << " Block Size: " << pFLACEncoder->blockSize() << std::endl; std::cout << " Adaptive Mid-Side: " << (pFLACEncoder->isUsingAdaptiveMidSideCoding() ? "Yes" : "No") << std::endl; std::cout << " Exhaustive Search: " << (pFLACEncoder->isUsingExhaustiveModel() ? "Yes" : "No") << std::endl; pFLACEncoder->Release(); } ``` ### C++ Example - Fast Real-Time Encoding ``` void ConfigureFastFLAC(IBaseFilter* pAudioEncoder) { IFLACEncodeSettings* pFLACEncoder = NULL; HRESULT hr = pAudioEncoder->QueryInterface(IID_IFLACEncodeSettings, (void**)&pFLACEncoder); if (SUCCEEDED(hr) && pFLACEncoder) { if (pFLACEncoder->canModifySettings()) { // Fast encoding configuration pFLACEncoder->setEncodingLevel(2); // Fast pFLACEncoder->setLPCOrder(8); // Lower LPC pFLACEncoder->setBlockSize(1152); // Smaller blocks pFLACEncoder->useAdaptiveMidSideCoding(TRUE); // Still good pFLACEncoder->useExhaustiveModelSearch(FALSE); // Disabled for speed pFLACEncoder->setRicePartitionOrder(0, 4); // Reduced range std::cout << "FLAC encoder configured for fast real-time encoding" << std::endl; } pFLACEncoder->Release(); } } ``` ### Delphi Example - High Quality Archival ``` uses DirectShow9, ActiveX; procedure ConfigureHighQualityFLAC(AudioEncoder: IBaseFilter); var FLACEncoder: IFLACEncodeSettings; hr: HRESULT; begin // Query the FLAC encoder interface hr := AudioEncoder.QueryInterface(IID_IFLACEncodeSettings, FLACEncoder); if Failed(hr) or (FLACEncoder = nil) then begin WriteLn('Error: Filter does not support IFLACEncodeSettings'); Exit; end; try // Check if we can modify settings if not FLACEncoder.canModifySettings then begin WriteLn('Warning: Cannot modify encoder settings'); Exit; end; // Configure high quality archival settings FLACEncoder.setEncodingLevel(8); // Maximum compression FLACEncoder.setLPCOrder(12); // Good LPC order FLACEncoder.setBlockSize(4096); // Standard block size FLACEncoder.useAdaptiveMidSideCoding(True); // Adaptive mid-side FLACEncoder.useExhaustiveModelSearch(True); // Best compression FLACEncoder.setRicePartitionOrder(0, 8); // Maximum range // Display configuration WriteLn('FLAC encoder configured for high-quality archival:'); WriteLn(' Encoding Level: ', FLACEncoder.encoderLevel); WriteLn(' LPC Order: ', FLACEncoder.LPCOrder); WriteLn(' Block Size: ', FLACEncoder.blockSize); WriteLn(' Adaptive Mid-Side: ', FLACEncoder.isUsingAdaptiveMidSideCoding); WriteLn(' Exhaustive Search: ', FLACEncoder.isUsingExhaustiveModel); finally FLACEncoder := nil; end; end; ``` ### Delphi Example - Balanced Music Encoding ``` procedure ConfigureBalancedMusicFLAC(AudioEncoder: IBaseFilter); var FLACEncoder: IFLACEncodeSettings; begin if Succeeded(AudioEncoder.QueryInterface(IID_IFLACEncodeSettings, FLACEncoder)) then begin try if FLACEncoder.canModifySettings then begin // Balanced settings for music FLACEncoder.setEncodingLevel(5); // Balanced FLACEncoder.setLPCOrder(12); // Standard for music FLACEncoder.setBlockSize(4096); // Optimal FLACEncoder.useAdaptiveMidSideCoding(True); // Adaptive FLACEncoder.useExhaustiveModelSearch(False); // Not needed FLACEncoder.setRicePartitionOrder(0, 6); // Good range WriteLn('FLAC encoder configured for balanced music encoding'); end; finally FLACEncoder := nil; end; end; end; ``` ## Best Practices ### Encoding Level Selection **Level 0-2**: Fast encoding, suitable for real-time applications - Use when encoding speed is critical - Typical compression: 50-55% of original size **Level 3-5**: Balanced encoding (recommended for most uses) - Good balance between speed and compression - Typical compression: 45-50% of original size - **Level 5 is recommended** for general-purpose archival **Level 6-8**: Maximum compression, slower encoding - Use for long-term archival where storage space is critical - Typical compression: 40-45% of original size - Encoding can be 2-5x slower than level 5 ### Mid-Side Stereo Coding - **Always enable** `useAdaptiveMidSideCoding` for stereo audio - Adaptive mode automatically determines when mid-side coding helps - Provides better compression than fixed mid-side mode - No significant performance penalty ### LPC Order Recommendations **Music and General Audio**: - Use LPC order 12 for most music encoding - Higher orders (16-32) provide minimal benefit for music - Lower orders (8) are suitable for speech **Classical and High-Dynamic Range**: - Consider LPC order 16-32 for orchestral recordings - Provides better prediction for complex harmonic content ### Block Size Selection **Sample Rate Considerations**: - 44.1kHz: 4096 samples (default, ~93ms) - 48kHz: 4608 samples (~96ms) - 96kHz: 4608-8192 samples **Latency Requirements**: - Real-time: 192-1152 samples - Standard archival: 4096 samples - Maximum compression: 4608 samples ### Exhaustive Model Search **When to Enable**: - Critical archival projects where every byte counts - Unlimited encoding time available - File size reduction is paramount **When to Disable** (recommended for most users): - Real-time or near-real-time encoding - Large batch encoding projects - Compression improvement is typically <3% - Encoding time increases 2-4x ### Rice Partition Order **Fast Encoding**: `setRicePartitionOrder(0, 3)` **Standard Encoding**: `setRicePartitionOrder(0, 6)` (recommended) **Maximum Compression**: `setRicePartitionOrder(0, 8)` ## Troubleshooting ### Settings Cannot Be Modified **Symptom**: `canModifySettings()` returns `false` **Causes**: 1. Filter graph is already running 2. Encoder is actively processing audio 3. Filter is in an incorrect state **Solutions**: - Stop the filter graph before modifying settings - Configure encoder before connecting filter pins - Query settings before starting playback/capture ### Poor Compression Ratio **Symptom**: FLAC files are larger than expected **Possible Causes**: 1. Low encoding level (0-2) 2. Source audio is already compressed (MP3, AAC) 3. Source audio has high noise floor 4. Inappropriate block size for sample rate **Solutions**: - Increase encoding level to 5-8 - **Never re-encode already compressed audio** - FLAC cannot improve quality - Use noise reduction on source audio before encoding - Adjust block size to match sample rate (see recommendations above) ### Encoding Too Slow **Symptom**: Real-time encoding cannot keep up with audio stream **Solutions**: 1. Reduce encoding level to 0-3 2. Disable exhaustive model search 3. Reduce LPC order to 8 4. Reduce Rice partition max to 4 5. Use smaller block sizes (1152 or less) ### Audio Pops or Clicks in Encoded Output **Symptom**: Audible artifacts in encoded FLAC files **Possible Causes**: 1. Encoder cannot process fast enough (buffer underruns) 2. Incompatible block size with sample rate 3. Hardware performance issues **Solutions**: - Reduce encoding complexity (lower level, disable exhaustive search) - Use standard block sizes for the sample rate - Increase DirectShow buffer sizes - Reduce system load during encoding ### Stereo Encoding Issues **Symptom**: Stereo audio sounds incorrect or mono **Check**: - Verify input is actually stereo (2 channels) - Mid-side coding only works with stereo input - Check if adaptive mid-side is enabled for best results - Verify filter graph audio format (use GraphEdit to inspect) ## Technical Notes ### FLAC Encoding Process FLAC encoding involves several stages: 1. **Blocking**: Audio divided into blocks 2. **Prediction**: LPC analysis predicts sample values 3. **Mid-Side Coding**: Optional stereo decorrelation (for 2-channel audio) 4. **Residual Encoding**: Rice coding compresses prediction errors 5. **Frame Assembly**: Blocks assembled into FLAC frames ### Performance Characteristics **CPU Usage by Setting**: - Encoding Level: ~10% increase per level - LPC Order: ~5% increase per 4 orders - Exhaustive Search: 200-400% increase - Mid-Side Coding: ~2-5% increase **Memory Requirements**: - Minimal: ~512KB working memory - Larger blocks require more memory - No significant dependency on audio duration ### Compatibility FLAC files encoded with any settings combination are compatible with all FLAC decoders. Higher compression settings only affect encoding time and file size, not decoder compatibility or playback quality. --- ## See Also - [LAME MP3 Encoder Interface](../lame/) - [Audio Codecs Reference](../../codecs-reference/) - [Encoding Filters Pack Overview](../../) ---END OF PAGE--- ## H.264 DirectShow Encoder Filter - COM Interface API **URL:** https://www.visioforge.com/help/docs/directshow/filters-enc/interfaces/h264/ **Description:** Configure H.264/AVC encoding in DirectShow — bitrate control (CBR/VBR), profiles (Baseline/Main/High), GOP structure, and rate control. IH264Encoder reference. **Tags:** DirectShow, C++, Windows, Streaming, Encoding, Decoding, H.264, C# **API:** H264Encoder, IH264Encoder, IBaseFilter, VideoEncoder, H264HighQualityEncoder # H.264 Encoder Interface Reference ## Overview The **IH264Encoder** interface provides comprehensive control over H.264/AVC (Advanced Video Coding) video encoding in DirectShow filter graphs. H.264 is the industry-standard video compression format used for broadcast, streaming, and distribution applications. This interface allows developers to configure encoding profiles, bitrate control, Group of Pictures (GOP) structure, macroblock encoding modes, and advanced timing parameters for optimal video quality and file size in various scenarios including streaming, broadcast, and archival. **Interface GUID**: `{09FA2EA3-4773-41a8-90DC-9499D4061E9F}` **Inherits From**: `IUnknown` ## Interface Definitions ### C# Definition ``` using System; using System.Runtime.InteropServices; namespace VisioForge.DirectShowAPI { /// /// H.264/AVC (Advanced Video Coding) encoder configuration interface. /// Provides comprehensive control over H.264 encoding parameters including /// bitrate control, profile/level settings, GOP structure, and rate control modes. /// [ComImport] [Guid("09FA2EA3-4773-41a8-90DC-9499D4061E9F")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] public interface IH264Encoder { /// /// Gets the target bitrate for encoding. /// /// Receives the bitrate in bits per second (bps) /// HRESULT (0 for success) [PreserveSig] int get_Bitrate([Out] out int plValue); /// /// Sets the target bitrate for encoding. /// /// Bitrate in bits per second (bps). Typical range: 500,000 to 50,000,000 /// HRESULT (0 for success) [PreserveSig] int put_Bitrate([In] int lValue); /// /// Gets the rate control mode. /// /// Receives the rate control mode (0=CBR, 1=VBR) /// HRESULT (0 for success) [PreserveSig] int get_RateControl([Out] out int pValue); /// /// Sets the rate control mode. /// /// Rate control mode: 0 = CBR (Constant Bitrate), 1 = VBR (Variable Bitrate) /// HRESULT (0 for success) [PreserveSig] int put_RateControl([In] int value); /// /// Gets the macroblock encoding mode. /// /// Receives the MB encoding mode /// HRESULT (0 for success) [PreserveSig] int get_MbEncoding([Out] out int pValue); /// /// Sets the macroblock encoding mode (affects encoding complexity and quality). /// /// MB encoding mode value /// HRESULT (0 for success) [PreserveSig] int put_MbEncoding([In] int value); /// /// Gets the GOP (Group of Pictures) enable state. /// /// Receives true if GOP is enabled, false otherwise /// HRESULT (0 for success) [PreserveSig] int get_GOP([Out] [MarshalAs(UnmanagedType.Bool)] out bool pValue); /// /// Enables or disables GOP (Group of Pictures) structure. /// /// True to enable GOP, false to disable (all I-frames) /// HRESULT (0 for success) [PreserveSig] int put_GOP([In] [MarshalAs(UnmanagedType.Bool)] bool value); /// /// Gets the auto-bitrate adjustment state. /// /// Receives true if auto-bitrate is enabled, false otherwise /// HRESULT (0 for success) [PreserveSig] int get_AutoBitrate([Out] [MarshalAs(UnmanagedType.Bool)] out bool pValue); /// /// Enables or disables automatic bitrate adjustment. /// When enabled, the encoder automatically adjusts bitrate based on content complexity. /// /// True to enable auto-bitrate, false for fixed bitrate /// HRESULT (0 for success) [PreserveSig] int put_AutoBitrate([In] [MarshalAs(UnmanagedType.Bool)] bool value); /// /// Gets the H.264 profile. /// /// Receives the profile value /// HRESULT (0 for success) [PreserveSig] int get_Profile([Out] out int pValue); /// /// Sets the H.264 profile (Baseline, Main, High, etc.). /// /// Profile value: 66=Baseline, 77=Main, 100=High /// HRESULT (0 for success) [PreserveSig] int put_Profile([In] int value); /// /// Gets the H.264 level. /// /// Receives the level value /// HRESULT (0 for success) [PreserveSig] int get_Level([Out] out int pValue); /// /// Sets the H.264 level (constrains resolution, bitrate, and frame rate). /// /// Level value: 10=Level 1.0, 11=Level 1.1, ..., 51=Level 5.1 /// HRESULT (0 for success) [PreserveSig] int put_Level([In] int value); /// /// Gets the usage mode (quality/speed trade-off). /// /// Receives the usage mode value /// HRESULT (0 for success) [PreserveSig] int get_Usage([Out] out int pValue); /// /// Sets the usage mode to optimize for quality vs. speed. /// /// Usage mode: 0=Quality, 1=Balanced, 2=Speed /// HRESULT (0 for success) [PreserveSig] int put_Usage([In] int value); /// /// Gets the sequential timing mode. /// /// Receives the sequential timing value /// HRESULT (0 for success) [PreserveSig] int get_SequentialTiming([Out] out int pValue); /// /// Sets the sequential timing mode for frame processing. /// /// Sequential timing mode value /// HRESULT (0 for success) [PreserveSig] int put_SequentialTiming([In] int value); /// /// Gets the slice intervals for IDR and P frames. /// /// Receives the IDR frame interval /// Receives the P frame interval /// HRESULT (0 for success) [PreserveSig] int get_SliceIntervals([Out] out int piIDR, [Out] out int piP); /// /// Sets the slice intervals for IDR (Instantaneous Decoder Refresh) and P frames. /// IDR frames are full keyframes, P frames are predicted frames. /// /// IDR frame interval (every N frames). Typical: 30-300 /// P frame interval. Typical: 1-3 /// HRESULT (0 for success) [PreserveSig] int put_SliceIntervals([In] ref int piIDR, [In] ref int piP); /// /// Gets the maximum bitrate for VBR encoding. /// /// Receives the maximum bitrate in bps /// HRESULT (0 for success) [PreserveSig] int get_MaxBitrate([Out] out int plValue); /// /// Sets the maximum bitrate for Variable Bitrate (VBR) encoding. /// Only applicable when rate control is set to VBR. /// /// Maximum bitrate in bits per second (bps) /// HRESULT (0 for success) [PreserveSig] int put_MaxBitrate([In] int lValue); /// /// Gets the minimum bitrate for VBR encoding. /// /// Receives the minimum bitrate in bps /// HRESULT (0 for success) [PreserveSig] int get_MinBitrate([Out] out int plValue); /// /// Sets the minimum bitrate for Variable Bitrate (VBR) encoding. /// Only applicable when rate control is set to VBR. /// /// Minimum bitrate in bits per second (bps) /// HRESULT (0 for success) [PreserveSig] int put_MinBitrate([In] int lValue); } } ``` ### C++ Definition ``` #include // {09FA2EA3-4773-41a8-90DC-9499D4061E9F} DEFINE_GUID(IID_IH264Encoder, 0x09fa2ea3, 0x4773, 0x41a8, 0x90, 0xdc, 0x94, 0x99, 0xd4, 0x06, 0x1e, 0x9f); /// /// H.264/AVC (Advanced Video Coding) encoder configuration interface. /// Provides comprehensive control over H.264 encoding parameters. /// DECLARE_INTERFACE_(IH264Encoder, IUnknown) { /// /// Gets the target bitrate for encoding. /// /// Pointer to receive bitrate in bits per second (bps) /// S_OK for success STDMETHOD(get_Bitrate)(THIS_ long* plValue ) PURE; /// /// Sets the target bitrate for encoding. /// /// Bitrate in bits per second (bps) /// S_OK for success STDMETHOD(put_Bitrate)(THIS_ long lValue ) PURE; /// /// Gets the rate control mode. /// /// Pointer to receive rate control mode /// S_OK for success STDMETHOD(get_RateControl)(THIS_ int* pValue ) PURE; /// /// Sets the rate control mode. /// /// Rate control mode: 0 = CBR, 1 = VBR /// S_OK for success STDMETHOD(put_RateControl)(THIS_ int value ) PURE; /// /// Gets the macroblock encoding mode. /// /// Pointer to receive MB encoding mode /// S_OK for success STDMETHOD(get_MbEncoding)(THIS_ int* pValue ) PURE; /// /// Sets the macroblock encoding mode. /// /// MB encoding mode value /// S_OK for success STDMETHOD(put_MbEncoding)(THIS_ int value ) PURE; /// /// Gets the GOP enable state. /// /// Pointer to receive GOP enabled state /// S_OK for success STDMETHOD(get_GOP)(THIS_ BOOL* pValue ) PURE; /// /// Enables or disables GOP structure. /// /// TRUE to enable GOP, FALSE to disable /// S_OK for success STDMETHOD(put_GOP)(THIS_ BOOL value ) PURE; /// /// Gets the auto-bitrate adjustment state. /// /// Pointer to receive auto-bitrate state /// S_OK for success STDMETHOD(get_AutoBitrate)(THIS_ BOOL* pValue ) PURE; /// /// Enables or disables automatic bitrate adjustment. /// /// TRUE to enable auto-bitrate, FALSE for fixed /// S_OK for success STDMETHOD(put_AutoBitrate)(THIS_ BOOL value ) PURE; /// /// Gets the H.264 profile. /// /// Pointer to receive profile value /// S_OK for success STDMETHOD(get_Profile)(THIS_ int* pValue ) PURE; /// /// Sets the H.264 profile. /// /// Profile value: 66=Baseline, 77=Main, 100=High /// S_OK for success STDMETHOD(put_Profile)(THIS_ int value ) PURE; /// /// Gets the H.264 level. /// /// Pointer to receive level value /// S_OK for success STDMETHOD(get_Level)(THIS_ int* pValue ) PURE; /// /// Sets the H.264 level. /// /// Level value: 10-51 /// S_OK for success STDMETHOD(put_Level)(THIS_ int value ) PURE; /// /// Gets the usage mode. /// /// Pointer to receive usage mode /// S_OK for success STDMETHOD(get_Usage)(THIS_ int* pValue ) PURE; /// /// Sets the usage mode. /// /// Usage mode: 0=Quality, 1=Balanced, 2=Speed /// S_OK for success STDMETHOD(put_Usage)(THIS_ int value ) PURE; /// /// Gets the sequential timing mode. /// /// Pointer to receive sequential timing value /// S_OK for success STDMETHOD(get_SequentialTiming)(THIS_ int* pValue ) PURE; /// /// Sets the sequential timing mode. /// /// Sequential timing mode value /// S_OK for success STDMETHOD(put_SequentialTiming)(THIS_ int value ) PURE; /// /// Gets the slice intervals. /// /// Pointer to receive IDR frame interval /// Pointer to receive P frame interval /// S_OK for success STDMETHOD(get_SliceIntervals)(THIS_ int* piIDR, int* piP ) PURE; /// /// Sets the slice intervals. /// /// Pointer to IDR frame interval /// Pointer to P frame interval /// S_OK for success STDMETHOD(put_SliceIntervals)(THIS_ int* piIDR, int* piP ) PURE; /// /// Gets the maximum bitrate. /// /// Pointer to receive maximum bitrate in bps /// S_OK for success STDMETHOD(get_MaxBitrate)(THIS_ long* plValue ) PURE; /// /// Sets the maximum bitrate for VBR encoding. /// /// Maximum bitrate in bps /// S_OK for success STDMETHOD(put_MaxBitrate)(THIS_ long lValue ) PURE; /// /// Gets the minimum bitrate. /// /// Pointer to receive minimum bitrate in bps /// S_OK for success STDMETHOD(get_MinBitrate)(THIS_ long* plValue ) PURE; /// /// Sets the minimum bitrate for VBR encoding. /// /// Minimum bitrate in bps /// S_OK for success STDMETHOD(put_MinBitrate)(THIS_ long lValue ) PURE; }; ``` ### Delphi Definition ``` uses ActiveX, ComObj; const IID_IH264Encoder: TGUID = '{09FA2EA3-4773-41a8-90DC-9499D4061E9F}'; type /// /// H.264/AVC encoder configuration interface. /// IH264Encoder = interface(IUnknown) ['{09FA2EA3-4773-41a8-90DC-9499D4061E9F}'] /// /// Gets the target bitrate for encoding. /// function get_Bitrate(out plValue: Integer): HRESULT; stdcall; /// /// Sets the target bitrate for encoding. /// function put_Bitrate(lValue: Integer): HRESULT; stdcall; /// /// Gets the rate control mode. /// function get_RateControl(out pValue: Integer): HRESULT; stdcall; /// /// Sets the rate control mode (0=CBR, 1=VBR). /// function put_RateControl(value: Integer): HRESULT; stdcall; /// /// Gets the macroblock encoding mode. /// function get_MbEncoding(out pValue: Integer): HRESULT; stdcall; /// /// Sets the macroblock encoding mode. /// function put_MbEncoding(value: Integer): HRESULT; stdcall; /// /// Gets the GOP enable state. /// function get_GOP(out pValue: BOOL): HRESULT; stdcall; /// /// Enables or disables GOP structure. /// function put_GOP(value: BOOL): HRESULT; stdcall; /// /// Gets the auto-bitrate adjustment state. /// function get_AutoBitrate(out pValue: BOOL): HRESULT; stdcall; /// /// Enables or disables automatic bitrate adjustment. /// function put_AutoBitrate(value: BOOL): HRESULT; stdcall; /// /// Gets the H.264 profile. /// function get_Profile(out pValue: Integer): HRESULT; stdcall; /// /// Sets the H.264 profile (66=Baseline, 77=Main, 100=High). /// function put_Profile(value: Integer): HRESULT; stdcall; /// /// Gets the H.264 level. /// function get_Level(out pValue: Integer): HRESULT; stdcall; /// /// Sets the H.264 level (10-51). /// function put_Level(value: Integer): HRESULT; stdcall; /// /// Gets the usage mode. /// function get_Usage(out pValue: Integer): HRESULT; stdcall; /// /// Sets the usage mode (0=Quality, 1=Balanced, 2=Speed). /// function put_Usage(value: Integer): HRESULT; stdcall; /// /// Gets the sequential timing mode. /// function get_SequentialTiming(out pValue: Integer): HRESULT; stdcall; /// /// Sets the sequential timing mode. /// function put_SequentialTiming(value: Integer): HRESULT; stdcall; /// /// Gets the slice intervals. /// function get_SliceIntervals(out piIDR: Integer; out piP: Integer): HRESULT; stdcall; /// /// Sets the slice intervals for IDR and P frames. /// function put_SliceIntervals(var piIDR: Integer; var piP: Integer): HRESULT; stdcall; /// /// Gets the maximum bitrate. /// function get_MaxBitrate(out plValue: Integer): HRESULT; stdcall; /// /// Sets the maximum bitrate for VBR encoding. /// function put_MaxBitrate(lValue: Integer): HRESULT; stdcall; /// /// Gets the minimum bitrate. /// function get_MinBitrate(out plValue: Integer): HRESULT; stdcall; /// /// Sets the minimum bitrate for VBR encoding. /// function put_MinBitrate(lValue: Integer): HRESULT; stdcall; end; ``` ## H.264 Profiles and Levels ### Profiles H.264 profiles define the features and capabilities available for encoding: **Profile 66 - Baseline Profile**: - Lowest complexity, best decoder compatibility - No B-frames, no CABAC entropy coding - Used for: Video conferencing, mobile devices, web streaming - Compatibility: All H.264 decoders **Profile 77 - Main Profile**: - Medium complexity, good compression - Supports B-frames, CABAC entropy coding - Used for: Standard definition broadcast, streaming services - Better compression than Baseline **Profile 100 - High Profile**: - Highest quality, best compression - Advanced features including 8x8 transforms - Used for: Blu-ray, HDTV broadcast, high-quality streaming - Recommended for most professional applications **Profile 110 - High 10 Profile**: - 10-bit color depth support - Used for: Professional production, HDR content **Profile 122 - High 4:2:2 Profile**: - 4:2:2 chroma subsampling - Used for: Professional editing, broadcast production ### Levels H.264 levels constrain maximum resolution, frame rate, and bitrate: | Level | Max Resolution | Max Frame Rate | Max Bitrate | Typical Use Case | | --- | --- | --- | --- | --- | | 1.0 (10) | 176x144 | 15 fps | 64 Kbps | Mobile, low res | | 3.0 (30) | 720x576 | 30 fps | 10 Mbps | SD broadcast | | 3.1 (31) | 1280x720 | 30 fps | 14 Mbps | 720p HD | | 4.0 (40) | 1920x1080 | 30 fps | 20 Mbps | 1080p HD | | 4.1 (41) | 1920x1080 | 30 fps | 50 Mbps | 1080p HD high bitrate | | 5.0 (50) | 2560x1920 | 30 fps | 135 Mbps | 2K, professional | | 5.1 (51) | 4096x2304 | 30 fps | 240 Mbps | 4K UHD | | 5.2 (52) | 4096x2304 | 60 fps | 480 Mbps | 4K UHD 60fps | **Auto-Selection**: Set level to 0 for automatic selection based on resolution and frame rate. ## Rate Control Modes ### Constant Bitrate (CBR) - Mode 0 **Characteristics**: - Maintains consistent bitrate throughout encoding - Predictable file size and network bandwidth usage - Quality varies based on scene complexity **Use Cases**: - Live streaming (RTMP, HLS, DASH) - Video conferencing - Broadcast transmission - Network-constrained scenarios **Configuration**: ``` h264Encoder.put_RateControl(0); // CBR mode h264Encoder.put_Bitrate(5000000); // 5 Mbps fixed ``` ### Variable Bitrate (VBR) - Mode 1 **Characteristics**: - Allocates more bits to complex scenes, fewer to simple scenes - Better overall quality for the same average bitrate - File size and bitrate fluctuate **Use Cases**: - File-based encoding for storage - VOD (Video On Demand) content - Archival and distribution - When quality is more important than consistent bandwidth **Configuration**: ``` h264Encoder.put_RateControl(1); // VBR mode h264Encoder.put_Bitrate(5000000); // 5 Mbps target h264Encoder.put_MinBitrate(3000000); // 3 Mbps minimum h264Encoder.put_MaxBitrate(8000000); // 8 Mbps maximum ``` ## Method Reference ### Bitrate Configuration #### get\_Bitrate / put\_Bitrate Gets or sets the target bitrate for encoding in bits per second. **Typical Values**: - **360p (SD)**: 500,000 - 1,500,000 bps (0.5-1.5 Mbps) - **720p (HD)**: 2,500,000 - 5,000,000 bps (2.5-5 Mbps) - **1080p (Full HD)**: 5,000,000 - 15,000,000 bps (5-15 Mbps) - **4K (UHD)**: 20,000,000 - 50,000,000 bps (20-50 Mbps) **Example**: ``` h264Encoder.put_Bitrate(5000000); // 5 Mbps for 1080p ``` #### get\_MaxBitrate / put\_MaxBitrate Gets or sets the maximum bitrate for VBR encoding. Only applicable when rate control is set to VBR (mode 1). **Recommendation**: Set MaxBitrate to 1.5-2x the target bitrate for VBR encoding. #### get\_MinBitrate / put\_MinBitrate Gets or sets the minimum bitrate for VBR encoding. Only applicable for VBR mode. **Recommendation**: Set MinBitrate to 0.5-0.7x the target bitrate for VBR encoding. ### Rate Control Methods #### get\_RateControl / put\_RateControl Gets or sets the rate control mode: - **0**: Constant Bitrate (CBR) - **1**: Variable Bitrate (VBR) #### get\_AutoBitrate / put\_AutoBitrate Enables or disables automatic bitrate adjustment based on content complexity. **When enabled**: Encoder automatically adjusts bitrate within configured constraints based on scene complexity, motion, and detail. **Recommended**: Enable for VBR mode, disable for CBR mode. ### Profile and Level Configuration #### get\_Profile / put\_Profile Gets or sets the H.264 profile: - **66**: Baseline Profile - **77**: Main Profile - **100**: High Profile - **110**: High 10 Profile - **122**: High 4:2:2 Profile **Recommendation**: Use High Profile (100) for most applications. Use Baseline (66) only for maximum compatibility with old devices. #### get\_Level / put\_Level Gets or sets the H.264 level (10 = Level 1.0, 11 = Level 1.1, ..., 51 = Level 5.1, 52 = Level 5.2). **Auto-Selection**: Set to 0 for automatic level selection based on resolution and frame rate. ### GOP (Group of Pictures) Configuration #### get\_GOP / put\_GOP Enables or disables GOP structure: - **true**: Normal GOP with I/P/B frames - **false**: All I-frames (intra-only encoding) **All I-frames mode**: - Higher bitrate required - Better editing capability (every frame is a keyframe) - No temporal compression - Use for: Production/editing workflows **Normal GOP mode** (recommended): - Efficient compression with I/P/B frame structure - Lower bitrate for same quality - Use for: Distribution, streaming, archival ### Slice Interval Configuration #### get\_SliceIntervals / put\_SliceIntervals Gets or sets the slice intervals for IDR (Instantaneous Decoder Refresh) frames and P frames. **Parameters**: - `piIDR`: IDR frame interval (keyframe every N frames) - `piP`: P frame interval **Typical Values**: - **Streaming (low latency)**: IDR=30-60 (1-2 seconds at 30fps), P=1 - **Standard encoding**: IDR=120-300 (4-10 seconds), P=1-3 - **Long-form video**: IDR=300+ (10+ seconds), P=3 **IDR Frame Interval**: - Lower values (30-60): Better seeking, higher bitrate overhead, faster error recovery - Higher values (240-600): Lower bitrate overhead, slower seeking, slower error recovery **Example**: ``` int idr = 120; // Keyframe every 120 frames (4 seconds at 30fps) int p = 1; // P frame every frame h264Encoder.put_SliceIntervals(ref idr, ref p); ``` ### Advanced Configuration #### get\_Usage / put\_Usage Sets the encoding usage mode (quality vs. speed trade-off): - **0**: Quality Mode - Slower encoding, best quality - **1**: Balanced Mode - Good quality, reasonable speed - **2**: Speed Mode - Fast encoding, lower quality **Recommendation**: - Use Quality Mode (0) for file-based encoding - Use Balanced Mode (1) for most real-time applications - Use Speed Mode (2) only when encoding performance is critical #### get\_MbEncoding / put\_MbEncoding Configures macroblock encoding mode, affecting encoding complexity and compression efficiency. **Note**: Specific values are encoder-dependent. Consult encoder documentation for supported modes. #### get\_SequentialTiming / put\_SequentialTiming Configures sequential timing mode for frame processing. **Note**: Implementation-specific. Affects frame ordering and presentation timing. ## Usage Examples ### C# Example - High Quality 1080p Encoding ``` using System; using DirectShowLib; using VisioForge.DirectShowAPI; public class H264HighQualityEncoder { public void ConfigureHighQuality1080p(IBaseFilter videoEncoder) { // Query the H.264 encoder interface var h264Encoder = videoEncoder as IH264Encoder; if (h264Encoder == null) { Console.WriteLine("Error: Filter does not support IH264Encoder"); return; } // High quality 1080p settings h264Encoder.put_Profile(100); // High Profile h264Encoder.put_Level(41); // Level 4.1 (1080p @ 30fps) h264Encoder.put_RateControl(1); // VBR mode h264Encoder.put_Bitrate(10000000); // 10 Mbps target h264Encoder.put_MinBitrate(6000000); // 6 Mbps minimum h264Encoder.put_MaxBitrate(15000000); // 15 Mbps maximum h264Encoder.put_Usage(0); // Quality mode h264Encoder.put_GOP(true); // Enable GOP structure h264Encoder.put_AutoBitrate(true); // Auto bitrate adjustment // Set keyframe interval: 120 frames (4 seconds at 30fps) int idr = 120; int p = 1; h264Encoder.put_SliceIntervals(ref idr, ref p); Console.WriteLine("H.264 encoder configured for high-quality 1080p:"); h264Encoder.get_Bitrate(out int bitrate); h264Encoder.get_Profile(out int profile); h264Encoder.get_Level(out int level); Console.WriteLine($" Bitrate: {bitrate / 1000000.0:F1} Mbps"); Console.WriteLine($" Profile: {profile} (High)"); Console.WriteLine($" Level: {level / 10.0:F1}"); } } ``` ### C# Example - Live Streaming Configuration ``` public class H264LiveStreamingEncoder { public void ConfigureLiveStreaming720p(IBaseFilter videoEncoder) { var h264Encoder = videoEncoder as IH264Encoder; if (h264Encoder == null) return; // Live streaming 720p settings h264Encoder.put_Profile(77); // Main Profile (good compatibility) h264Encoder.put_Level(31); // Level 3.1 (720p @ 30fps) h264Encoder.put_RateControl(0); // CBR mode for streaming h264Encoder.put_Bitrate(3500000); // 3.5 Mbps constant h264Encoder.put_Usage(1); // Balanced mode h264Encoder.put_GOP(true); // Enable GOP h264Encoder.put_AutoBitrate(false); // Fixed bitrate for streaming // Low latency: keyframe every 2 seconds int idr = 60; // 2 seconds at 30fps int p = 1; h264Encoder.put_SliceIntervals(ref idr, ref p); Console.WriteLine("H.264 encoder configured for live streaming"); Console.WriteLine(" 720p @ 3.5 Mbps CBR"); Console.WriteLine(" Keyframe interval: 2 seconds"); } } ``` ### C# Example - Fast Encoding for Recording ``` public class H264FastRecording { public void ConfigureFastRecording(IBaseFilter videoEncoder) { var h264Encoder = videoEncoder as IH264Encoder; if (h264Encoder == null) return; // Fast recording settings h264Encoder.put_Profile(66); // Baseline (fastest encoding) h264Encoder.put_Level(40); // Level 4.0 (1080p @ 30fps) h264Encoder.put_RateControl(0); // CBR mode h264Encoder.put_Bitrate(8000000); // 8 Mbps h264Encoder.put_Usage(2); // Speed mode (fast encoding) h264Encoder.put_GOP(true); // Enable GOP h264Encoder.put_AutoBitrate(false); // Fixed bitrate // Longer keyframe interval for faster encoding int idr = 300; // 10 seconds at 30fps int p = 1; h264Encoder.put_SliceIntervals(ref idr, ref p); Console.WriteLine("H.264 encoder configured for fast recording"); } } ``` ### C++ Example - High Quality Configuration ``` #include #include #include "IH264Encoder.h" void ConfigureH264HighQuality(IBaseFilter* pVideoEncoder) { IH264Encoder* pH264Encoder = NULL; HRESULT hr = S_OK; // Query the H.264 encoder interface hr = pVideoEncoder->QueryInterface(IID_IH264Encoder, (void**)&pH264Encoder); if (FAILED(hr) || !pH264Encoder) { std::cout << "Error: Filter does not support IH264Encoder" << std::endl; return; } // Configure high quality 1080p encoding pH264Encoder->put_Profile(100); // High Profile pH264Encoder->put_Level(41); // Level 4.1 pH264Encoder->put_RateControl(1); // VBR mode pH264Encoder->put_Bitrate(10000000); // 10 Mbps pH264Encoder->put_MinBitrate(6000000); // 6 Mbps min pH264Encoder->put_MaxBitrate(15000000); // 15 Mbps max pH264Encoder->put_Usage(0); // Quality mode pH264Encoder->put_GOP(TRUE); // Enable GOP pH264Encoder->put_AutoBitrate(TRUE); // Auto bitrate // Set keyframe interval int idr = 120; int p = 1; pH264Encoder->put_SliceIntervals(&idr, &p); // Display configuration long bitrate; pH264Encoder->get_Bitrate(&bitrate); std::cout << "H.264 encoder configured:" << std::endl; std::cout << " Bitrate: " << (bitrate / 1000000.0) << " Mbps" << std::endl; pH264Encoder->Release(); } ``` ### C++ Example - Live Streaming ``` void ConfigureH264LiveStreaming(IBaseFilter* pVideoEncoder) { IH264Encoder* pH264Encoder = NULL; HRESULT hr = pVideoEncoder->QueryInterface(IID_IH264Encoder, (void**)&pH264Encoder); if (SUCCEEDED(hr) && pH264Encoder) { // Live streaming configuration pH264Encoder->put_Profile(77); // Main Profile pH264Encoder->put_Level(31); // Level 3.1 (720p) pH264Encoder->put_RateControl(0); // CBR for streaming pH264Encoder->put_Bitrate(3500000); // 3.5 Mbps pH264Encoder->put_Usage(1); // Balanced mode pH264Encoder->put_GOP(TRUE); // Enable GOP pH264Encoder->put_AutoBitrate(FALSE); // Fixed bitrate // Low latency keyframes int idr = 60; // 2 seconds int p = 1; pH264Encoder->put_SliceIntervals(&idr, &p); std::cout << "H.264 live streaming configured" << std::endl; pH264Encoder->Release(); } } ``` ### Delphi Example - High Quality Encoding ``` uses DirectShow9, ActiveX; procedure ConfigureH264HighQuality(VideoEncoder: IBaseFilter); var H264Encoder: IH264Encoder; IDR, P: Integer; Bitrate: Integer; hr: HRESULT; begin // Query the H.264 encoder interface hr := VideoEncoder.QueryInterface(IID_IH264Encoder, H264Encoder); if Failed(hr) or (H264Encoder = nil) then begin WriteLn('Error: Filter does not support IH264Encoder'); Exit; end; try // Configure high quality 1080p encoding H264Encoder.put_Profile(100); // High Profile H264Encoder.put_Level(41); // Level 4.1 H264Encoder.put_RateControl(1); // VBR mode H264Encoder.put_Bitrate(10000000); // 10 Mbps H264Encoder.put_MinBitrate(6000000); // 6 Mbps minimum H264Encoder.put_MaxBitrate(15000000); // 15 Mbps maximum H264Encoder.put_Usage(0); // Quality mode H264Encoder.put_GOP(True); // Enable GOP H264Encoder.put_AutoBitrate(True); // Auto bitrate // Set keyframe interval IDR := 120; P := 1; H264Encoder.put_SliceIntervals(IDR, P); // Display configuration H264Encoder.get_Bitrate(Bitrate); WriteLn('H.264 encoder configured for high quality:'); WriteLn(' Bitrate: ', Bitrate / 1000000:0:1, ' Mbps'); finally H264Encoder := nil; end; end; ``` ### Delphi Example - Live Streaming ``` procedure ConfigureH264LiveStreaming(VideoEncoder: IBaseFilter); var H264Encoder: IH264Encoder; IDR, P: Integer; begin if Succeeded(VideoEncoder.QueryInterface(IID_IH264Encoder, H264Encoder)) then begin try // Live streaming configuration H264Encoder.put_Profile(77); // Main Profile H264Encoder.put_Level(31); // Level 3.1 (720p) H264Encoder.put_RateControl(0); // CBR mode H264Encoder.put_Bitrate(3500000); // 3.5 Mbps H264Encoder.put_Usage(1); // Balanced mode H264Encoder.put_GOP(True); // Enable GOP H264Encoder.put_AutoBitrate(False); // Fixed bitrate // Low latency keyframes IDR := 60; // 2 seconds at 30fps P := 1; H264Encoder.put_SliceIntervals(IDR, P); WriteLn('H.264 live streaming configured'); finally H264Encoder := nil; end; end; end; ``` ## Best Practices ### Bitrate Selection Guidelines **Resolution-Based Recommendations**: | Resolution | CBR (Streaming) | VBR Target | VBR Min-Max | | --- | --- | --- | --- | | 360p (SD) | 0.8 Mbps | 1 Mbps | 0.5 - 1.5 Mbps | | 480p (SD) | 1.5 Mbps | 2 Mbps | 1 - 3 Mbps | | 720p (HD) | 3 Mbps | 4 Mbps | 2.5 - 6 Mbps | | 1080p (Full HD) | 6 Mbps | 8 Mbps | 5 - 12 Mbps | | 1440p (2K) | 12 Mbps | 16 Mbps | 10 - 24 Mbps | | 2160p (4K UHD) | 25 Mbps | 35 Mbps | 20 - 50 Mbps | **Content Type Adjustments**: - **Low motion** (presentations, talking head): Use 60-70% of recommended bitrate - **Medium motion** (standard video): Use recommended bitrate - **High motion** (sports, action): Use 120-150% of recommended bitrate ### Profile Selection **Use Baseline Profile (66) when**: - Maximum device compatibility required - Targeting old mobile devices or web browsers - Real-time encoding performance is critical **Use Main Profile (77) when**: - Good balance between quality and compatibility needed - Live streaming to mixed audiences - Standard broadcast applications **Use High Profile (100) when** (recommended): - Best quality is required - Modern device compatibility is acceptable (post-2010 devices) - File-based encoding for distribution - **Most production scenarios** ### GOP Structure Recommendations **Streaming Applications**: - IDR interval: 60-120 frames (2-4 seconds at 30fps) - Shorter intervals: Better seeking, faster error recovery, slightly higher bitrate - Longer intervals: Lower bitrate overhead, but slower seeking **File-Based Encoding**: - IDR interval: 240-300 frames (8-10 seconds at 30fps) - Balance between file size and seeking capability **Low-Latency Applications** (video conferencing): - IDR interval: 30-60 frames (1-2 seconds at 30fps) - Short intervals reduce lag from dropped frames **All-Intra Encoding** (editing workflows): - Disable GOP (`put_GOP(false)`) - Every frame is a keyframe - Higher bitrate required (typically 3-5x normal encoding) - Perfect frame-accurate editing ### Usage Mode Selection **Quality Mode (0)**: - Slowest encoding, best quality - Use for: File-based encoding, archival, VOD content - Not suitable for real-time encoding on slower hardware **Balanced Mode (1)** (recommended): - Good quality, reasonable performance - Use for: Most real-time applications, live streaming - Best choice for general-purpose encoding **Speed Mode (2)**: - Fastest encoding, lower quality - Use for: High-resolution real-time encoding on limited hardware - Screen recording, surveillance applications ## Troubleshooting ### Low Video Quality **Symptoms**: Blocky artifacts, blurring, loss of detail **Possible Causes**: 1. Bitrate too low for resolution 2. Wrong profile selection 3. GOP interval too long 4. Usage mode set to Speed instead of Quality **Solutions**: - Increase bitrate to recommended levels (see table above) - Switch to High Profile (100) for better compression - Shorten IDR interval to 120-180 frames - Use Balanced (1) or Quality (0) usage mode - For VBR, increase minimum bitrate ### Encoding Too Slow / Cannot Keep Up **Symptoms**: Dropped frames, encoding slower than real-time **Solutions**: 1. Switch to Baseline Profile (66) for faster encoding 2. Set Usage mode to Speed (2) 3. Reduce bitrate to lower computational requirements 4. Increase IDR interval (longer GOP = less processing) 5. Consider hardware encoder (NVENC, QuickSync) instead ### Large File Sizes **Symptoms**: Files larger than expected **Possible Causes**: 1. Bitrate too high for target quality 2. CBR mode with conservative bitrate setting 3. GOP disabled (all I-frames) 4. Wrong level setting **Solutions**: - Switch from CBR to VBR for variable content - Enable GOP structure (`put_GOP(true)`) - Reduce target bitrate - Adjust min/max bitrate range for VBR - Use High Profile (100) for better compression ### Streaming Compatibility Issues **Symptoms**: Video plays on some devices but not others **Possible Causes**: 1. Profile too advanced (High Profile not supported on old devices) 2. Level too high for device capabilities 3. Incorrect slice configuration **Solutions**: - Use Main Profile (77) or Baseline Profile (66) for maximum compatibility - Set level to 0 for automatic selection - Test on target devices - Verify player/device H.264 capabilities ### Seeking Issues / Slow Scrubbing **Symptoms**: Slow or inaccurate seeking in encoded video **Cause**: IDR interval too long (keyframes too far apart) **Solutions**: - Reduce IDR interval to 60-120 frames (2-4 seconds) - For editing workflows, consider all-intra encoding (`put_GOP(false)`) - Shorter IDR intervals improve seeking at cost of slightly higher bitrate --- ## See Also - [NVENC Encoder Interface](../nvenc/) - NVIDIA hardware H.264/HEVC encoding - [Video Codecs Reference](../../codecs-reference/) - [Encoding Filters Pack Overview](../../) - [MP4 Muxer Interface](../mp4-muxer/) ---END OF PAGE--- ## LAME MP3 Encoder Settings via DirectShow COM Interface **URL:** https://www.visioforge.com/help/docs/directshow/filters-enc/interfaces/lame/ **Description:** IAudioEncoderProperties interface for LAME MP3 encoding with variable and constant bitrate modes and quality configuration. **Tags:** DirectShow, C++, Windows, Streaming, Encoding, MP3, C# **API:** IBaseFilter, AudioEncoder # LAME MP3 Encoder Interface Reference ## Overview The `IAudioEncoderProperties` interface provides comprehensive control over LAME MP3 audio encoding. LAME (LAME Ain't an MP3 Encoder) is a high-quality MP3 encoder that produces excellent audio quality with efficient compression. This interface allows configuration of bitrate, quality, variable bitrate (VBR) settings, and various encoding flags for optimal MP3 output. ## Interface Definition - **Interface Name**: `IAudioEncoderProperties` - **GUID**: `{595EB9D1-F454-41AD-A1FA-EC232AD9DA52}` - **Inherits From**: `IUnknown` ## Interface Definitions ### C# Definition ``` using System; using System.Runtime.InteropServices; namespace VisioForge.DirectShowAPI { /// /// LAME MP3 encoder interface. /// /// /// Configuring MPEG audio encoder parameters with unspecified /// input stream type may lead to misbehavior and confusing /// results. In most cases the specified parameters will be /// overridden by defaults for the input media type. /// To achieve proper results use this interface on the /// audio encoder filter with input pin connected to a valid source. /// [ComImport] [System.Security.SuppressUnmanagedCodeSecurity] [Guid("595EB9D1-F454-41AD-A1FA-EC232AD9DA52")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] public interface IAudioEncoderProperties { // PES Output Control [PreserveSig] int get_PESOutputEnabled(out int dwEnabled); [PreserveSig] int set_PESOutputEnabled([In] int dwEnabled); // Bitrate Configuration [PreserveSig] int get_Bitrate(out int dwBitrate); [PreserveSig] int set_Bitrate([In] int dwBitrate); // Variable Bitrate (VBR) [PreserveSig] int get_Variable(out int dwVariable); [PreserveSig] int set_Variable([In] int dwVariable); [PreserveSig] int get_VariableMin(out int dwmin); [PreserveSig] int set_VariableMin([In] int dwmin); [PreserveSig] int get_VariableMax(out int dwmax); [PreserveSig] int set_VariableMax([In] int dwmax); // Quality Settings [PreserveSig] int get_Quality(out int dwQuality); [PreserveSig] int set_Quality([In] int dwQuality); [PreserveSig] int get_VariableQ(out int dwVBRq); [PreserveSig] int set_VariableQ([In] int dwVBRq); // Source Information [PreserveSig] int get_SourceSampleRate(out int dwSampleRate); [PreserveSig] int get_SourceChannels(out int dwChannels); // Output Configuration [PreserveSig] int get_SampleRate(out int dwSampleRate); [PreserveSig] int set_SampleRate([In] int dwSampleRate); [PreserveSig] int get_ChannelMode(out int dwChannelMode); [PreserveSig] int set_ChannelMode([In] int dwChannelMode); // Flags [PreserveSig] int get_CRCFlag(out int dwFlag); [PreserveSig] int set_CRCFlag([In] int dwFlag); [PreserveSig] int get_OriginalFlag(out int dwFlag); [PreserveSig] int set_OriginalFlag([In] int dwFlag); [PreserveSig] int get_CopyrightFlag(out int dwFlag); [PreserveSig] int set_CopyrightFlag([In] int dwFlag); [PreserveSig] int get_EnforceVBRmin(out int dwFlag); [PreserveSig] int set_EnforceVBRmin([In] int dwFlag); [PreserveSig] int get_VoiceMode(out int dwFlag); [PreserveSig] int set_VoiceMode([In] int dwFlag); [PreserveSig] int get_KeepAllFreq(out int dwFlag); [PreserveSig] int set_KeepAllFreq([In] int dwFlag); [PreserveSig] int get_StrictISO(out int dwFlag); [PreserveSig] int set_StrictISO([In] int dwFlag); [PreserveSig] int get_NoShortBlock(out int dwDisable); [PreserveSig] int set_NoShortBlock([In] int dwDisable); [PreserveSig] int get_XingTag(out int dwXingTag); [PreserveSig] int set_XingTag([In] int dwXingTag); [PreserveSig] int get_ForceMS(out int dwFlag); [PreserveSig] int set_ForceMS([In] int dwFlag); [PreserveSig] int get_ModeFixed(out int dwFlag); [PreserveSig] int set_ModeFixed([In] int dwFlag); // Configuration Management // pcBlock is a BYTE[] buffer in C++; use LPArray with SizeParamIndex=1 // so the marshaler reads pdwSize bytes back from native code. [PreserveSig] int get_ParameterBlockSize( [Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] byte[] pcBlock, out int pdwSize); [PreserveSig] int set_ParameterBlockSize( [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] byte[] pcBlock, [In] int dwSize); [PreserveSig] int DefaultAudioEncoderProperties(); [PreserveSig] int LoadAudioEncoderPropertiesFromRegistry(); [PreserveSig] int SaveAudioEncoderPropertiesToRegistry(); [PreserveSig] int InputTypeDefined(); } } ``` ### C++ Definition ``` #include // {595EB9D1-F454-41AD-A1FA-EC232AD9DA52} static const GUID IID_IAudioEncoderProperties = { 0x595eb9d1, 0xf454, 0x41ad, { 0xa1, 0xfa, 0xec, 0x23, 0x2a, 0xd9, 0xda, 0x52 } }; DECLARE_INTERFACE_(IAudioEncoderProperties, IUnknown) { // PES Output STDMETHOD(get_PESOutputEnabled)(THIS_ int* dwEnabled) PURE; STDMETHOD(set_PESOutputEnabled)(THIS_ int dwEnabled) PURE; // Bitrate STDMETHOD(get_Bitrate)(THIS_ int* dwBitrate) PURE; STDMETHOD(set_Bitrate)(THIS_ int dwBitrate) PURE; // Variable Bitrate STDMETHOD(get_Variable)(THIS_ int* dwVariable) PURE; STDMETHOD(set_Variable)(THIS_ int dwVariable) PURE; STDMETHOD(get_VariableMin)(THIS_ int* dwmin) PURE; STDMETHOD(set_VariableMin)(THIS_ int dwmin) PURE; STDMETHOD(get_VariableMax)(THIS_ int* dwmax) PURE; STDMETHOD(set_VariableMax)(THIS_ int dwmax) PURE; // Quality STDMETHOD(get_Quality)(THIS_ int* dwQuality) PURE; STDMETHOD(set_Quality)(THIS_ int dwQuality) PURE; STDMETHOD(get_VariableQ)(THIS_ int* dwVBRq) PURE; STDMETHOD(set_VariableQ)(THIS_ int dwVBRq) PURE; // Source Information STDMETHOD(get_SourceSampleRate)(THIS_ int* dwSampleRate) PURE; STDMETHOD(get_SourceChannels)(THIS_ int* dwChannels) PURE; // Output Configuration STDMETHOD(get_SampleRate)(THIS_ int* dwSampleRate) PURE; STDMETHOD(set_SampleRate)(THIS_ int dwSampleRate) PURE; STDMETHOD(get_ChannelMode)(THIS_ int* dwChannelMode) PURE; STDMETHOD(set_ChannelMode)(THIS_ int dwChannelMode) PURE; // Flags STDMETHOD(get_CRCFlag)(THIS_ int* dwFlag) PURE; STDMETHOD(set_CRCFlag)(THIS_ int dwFlag) PURE; STDMETHOD(get_OriginalFlag)(THIS_ int* dwFlag) PURE; STDMETHOD(set_OriginalFlag)(THIS_ int dwFlag) PURE; STDMETHOD(get_CopyrightFlag)(THIS_ int* dwFlag) PURE; STDMETHOD(set_CopyrightFlag)(THIS_ int dwFlag) PURE; STDMETHOD(get_EnforceVBRmin)(THIS_ int* dwFlag) PURE; STDMETHOD(set_EnforceVBRmin)(THIS_ int dwFlag) PURE; STDMETHOD(get_VoiceMode)(THIS_ int* dwFlag) PURE; STDMETHOD(set_VoiceMode)(THIS_ int dwFlag) PURE; STDMETHOD(get_KeepAllFreq)(THIS_ int* dwFlag) PURE; STDMETHOD(set_KeepAllFreq)(THIS_ int dwFlag) PURE; STDMETHOD(get_StrictISO)(THIS_ int* dwFlag) PURE; STDMETHOD(set_StrictISO)(THIS_ int dwFlag) PURE; STDMETHOD(get_NoShortBlock)(THIS_ int* dwDisable) PURE; STDMETHOD(set_NoShortBlock)(THIS_ int dwDisable) PURE; STDMETHOD(get_XingTag)(THIS_ int* dwXingTag) PURE; STDMETHOD(set_XingTag)(THIS_ int dwXingTag) PURE; STDMETHOD(get_ForceMS)(THIS_ int* dwFlag) PURE; STDMETHOD(set_ForceMS)(THIS_ int dwFlag) PURE; STDMETHOD(get_ModeFixed)(THIS_ int* dwFlag) PURE; STDMETHOD(set_ModeFixed)(THIS_ int dwFlag) PURE; // Configuration Management STDMETHOD(get_ParameterBlockSize)(THIS_ byte* pcBlock, int* pdwSize) PURE; STDMETHOD(set_ParameterBlockSize)(THIS_ byte* pcBlock, int dwSize) PURE; STDMETHOD(DefaultAudioEncoderProperties)(THIS) PURE; STDMETHOD(LoadAudioEncoderPropertiesFromRegistry)(THIS) PURE; STDMETHOD(SaveAudioEncoderPropertiesToRegistry)(THIS) PURE; STDMETHOD(InputTypeDefined)(THIS) PURE; }; ``` ### Delphi Definition ``` uses ActiveX, ComObj; const IID_IAudioEncoderProperties: TGUID = '{595EB9D1-F454-41AD-A1FA-EC232AD9DA52}'; type IAudioEncoderProperties = interface(IUnknown) ['{595EB9D1-F454-41AD-A1FA-EC232AD9DA52}'] // PES Output function get_PESOutputEnabled(out dwEnabled: Integer): HRESULT; stdcall; function set_PESOutputEnabled(dwEnabled: Integer): HRESULT; stdcall; // Bitrate function get_Bitrate(out dwBitrate: Integer): HRESULT; stdcall; function set_Bitrate(dwBitrate: Integer): HRESULT; stdcall; // Variable Bitrate function get_Variable(out dwVariable: Integer): HRESULT; stdcall; function set_Variable(dwVariable: Integer): HRESULT; stdcall; function get_VariableMin(out dwmin: Integer): HRESULT; stdcall; function set_VariableMin(dwmin: Integer): HRESULT; stdcall; function get_VariableMax(out dwmax: Integer): HRESULT; stdcall; function set_VariableMax(dwmax: Integer): HRESULT; stdcall; // Quality function get_Quality(out dwQuality: Integer): HRESULT; stdcall; function set_Quality(dwQuality: Integer): HRESULT; stdcall; function get_VariableQ(out dwVBRq: Integer): HRESULT; stdcall; function set_VariableQ(dwVBRq: Integer): HRESULT; stdcall; // Source Information function get_SourceSampleRate(out dwSampleRate: Integer): HRESULT; stdcall; function get_SourceChannels(out dwChannels: Integer): HRESULT; stdcall; // Output Configuration function get_SampleRate(out dwSampleRate: Integer): HRESULT; stdcall; function set_SampleRate(dwSampleRate: Integer): HRESULT; stdcall; function get_ChannelMode(out dwChannelMode: Integer): HRESULT; stdcall; function set_ChannelMode(dwChannelMode: Integer): HRESULT; stdcall; // Flags function get_CRCFlag(out dwFlag: Integer): HRESULT; stdcall; function set_CRCFlag(dwFlag: Integer): HRESULT; stdcall; function get_OriginalFlag(out dwFlag: Integer): HRESULT; stdcall; function set_OriginalFlag(dwFlag: Integer): HRESULT; stdcall; function get_CopyrightFlag(out dwFlag: Integer): HRESULT; stdcall; function set_CopyrightFlag(dwFlag: Integer): HRESULT; stdcall; function get_EnforceVBRmin(out dwFlag: Integer): HRESULT; stdcall; function set_EnforceVBRmin(dwFlag: Integer): HRESULT; stdcall; function get_VoiceMode(out dwFlag: Integer): HRESULT; stdcall; function set_VoiceMode(dwFlag: Integer): HRESULT; stdcall; function get_KeepAllFreq(out dwFlag: Integer): HRESULT; stdcall; function set_KeepAllFreq(dwFlag: Integer): HRESULT; stdcall; function get_StrictISO(out dwFlag: Integer): HRESULT; stdcall; function set_StrictISO(dwFlag: Integer): HRESULT; stdcall; function get_NoShortBlock(out dwDisable: Integer): HRESULT; stdcall; function set_NoShortBlock(dwDisable: Integer): HRESULT; stdcall; function get_XingTag(out dwXingTag: Integer): HRESULT; stdcall; function set_XingTag(dwXingTag: Integer): HRESULT; stdcall; function get_ForceMS(out dwFlag: Integer): HRESULT; stdcall; function set_ForceMS(dwFlag: Integer): HRESULT; stdcall; function get_ModeFixed(out dwFlag: Integer): HRESULT; stdcall; function set_ModeFixed(dwFlag: Integer): HRESULT; stdcall; // Configuration Management function get_ParameterBlockSize(out pcBlock: Byte; out pdwSize: Integer): HRESULT; stdcall; function set_ParameterBlockSize(pcBlock: Byte; dwSize: Integer): HRESULT; stdcall; function DefaultAudioEncoderProperties: HRESULT; stdcall; function LoadAudioEncoderPropertiesFromRegistry: HRESULT; stdcall; function SaveAudioEncoderPropertiesToRegistry: HRESULT; stdcall; function InputTypeDefined: HRESULT; stdcall; end; ``` --- ## Methods Reference ### Bitrate Configuration #### set\_Bitrate / get\_Bitrate Sets or retrieves the target compression bitrate in Kbits/s. **Parameters**: - `dwBitrate`: Bitrate in kilobits per second **Common MP3 Bitrates**: - **320 kbps** - Highest quality, near-transparent - **256 kbps** - Very high quality - **192 kbps** - High quality (recommended for music) - **128 kbps** - Standard quality (acceptable for most content) - **96 kbps** - Lower quality, smaller files - **64 kbps** - Voice/podcast quality **Example (C#)**: ``` var lame = audioEncoder as IAudioEncoderProperties; if (lame != null) { // Set high quality 192 kbps lame.set_Bitrate(192); } ``` --- ### Variable Bitrate (VBR) #### set\_Variable / get\_Variable Enables or disables variable bitrate mode. **Parameters**: - `dwVariable`: 1 to enable VBR, 0 to disable (CBR mode) **Usage Notes**: - VBR provides better quality-to-size ratio than CBR - VBR allocates more bits to complex audio passages - CBR provides predictable file sizes - VBR is recommended for music archival #### set\_VariableMin / get\_VariableMin Sets the minimum bitrate for VBR mode. **Parameters**: - `dwmin`: Minimum bitrate in kbps #### set\_VariableMax / get\_VariableMax Sets the maximum bitrate for VBR mode. **Parameters**: - `dwmax`: Maximum bitrate in kbps **Example (C#)**: ``` // Enable VBR with 128-256 kbps range lame.set_Variable(1); lame.set_VariableMin(128); lame.set_VariableMax(256); lame.set_VariableQ(4); // VBR quality level ``` --- ### Quality Settings #### set\_Quality / get\_Quality Sets the encoding quality for CBR mode. **Parameters**: - `dwQuality`: Quality level (0-9) - **0** - Highest quality (slowest) - **2** - Near-highest quality (recommended) - **5** - Good quality/speed balance - **7** - Faster encoding, lower quality - **9** - Lowest quality (fastest) **Example (C++)**: ``` IAudioEncoderProperties* pLame = nullptr; pFilter->QueryInterface(IID_IAudioEncoderProperties, (void**)&pLame); // High quality CBR encoding pLame->set_Bitrate(192); pLame->set_Quality(2); pLame->Release(); ``` #### set\_VariableQ / get\_VariableQ Sets the quality level for VBR mode. **Parameters**: - `dwVBRq`: VBR quality (0-9) - **0** - Highest quality (~245 kbps) - **2** - Very high quality (~190 kbps) - **4** - High quality (~165 kbps) - recommended - **6** - Medium quality (~130 kbps) - **9** - Lowest quality (~65 kbps) --- ### Channel Mode #### set\_ChannelMode / get\_ChannelMode Sets the stereo encoding mode. **Parameters**: - `dwChannelMode`: Channel mode value - **0** - Stereo - **1** - Joint Stereo (recommended) - **2** - Dual Channel - **3** - Mono **Usage Notes**: - Joint Stereo provides best quality at lower bitrates - Use Stereo for critical listening at high bitrates - Mono reduces file size for speech/podcasts **Example (C#)**: ``` // Joint stereo for music at 192 kbps lame.set_ChannelMode(1); lame.set_Bitrate(192); ``` --- ### Encoding Flags #### set\_CRCFlag / get\_CRCFlag Enables CRC error protection. **Parameters**: - `dwFlag`: 1 to enable, 0 to disable **Usage**: Adds error detection, minimal size increase (~0.2%) #### set\_CopyrightFlag / get\_CopyrightFlag Sets the copyright flag in MP3 header. **Parameters**: - `dwFlag`: 1 if copyrighted, 0 otherwise #### set\_OriginalFlag / get\_OriginalFlag Sets the original/copy flag. **Parameters**: - `dwFlag`: 1 for original, 0 for copy #### set\_VoiceMode / get\_VoiceMode Optimizes encoding for voice content. **Parameters**: - `dwFlag`: 1 to enable voice optimization **Usage**: Improves quality for speech at lower bitrates **Example (C#)**: ``` // Optimize for podcast/voice content lame.set_VoiceMode(1); lame.set_Bitrate(64); lame.set_ChannelMode(3); // Mono ``` #### set\_XingTag / get\_XingTag Adds Xing VBR tag for accurate seeking. **Parameters**: - `dwFlag`: 1 to add tag (recommended for VBR) **Usage**: Essential for VBR files to enable proper seeking --- ## Configuration Management ### SaveAudioEncoderPropertiesToRegistry Saves the current encoder configuration to the registry. **Usage Notes**: - Must be called after changing properties - Settings persist between sessions - Requires appropriate registry permissions ### LoadAudioEncoderPropertiesFromRegistry Loads encoder configuration from the registry. ### DefaultAudioEncoderProperties Resets all encoder properties to default values based on input stream type. ### InputTypeDefined Checks if the input format has been specified. **Returns**: - `S_OK` - Input type is defined, encoder can be configured - `E_FAIL` - Input type not specified, configuration may fail --- ## Complete Examples ### Example 1: High Quality Music Encoding (C#) ``` using VisioForge.DirectShowAPI; public void ConfigureHighQualityMP3(IBaseFilter audioEncoder) { var lame = audioEncoder as IAudioEncoderProperties; if (lame == null) return; // Check if input is connected if (lame.InputTypeDefined() != 0) { Console.WriteLine("Warning: Input not connected, using defaults"); } // High quality VBR settings lame.set_Variable(1); // Enable VBR lame.set_VariableQ(2); // Very high quality lame.set_VariableMin(192); // Min 192 kbps lame.set_VariableMax(320); // Max 320 kbps // Joint stereo for efficiency lame.set_ChannelMode(1); // Quality flags lame.set_XingTag(1); // Add VBR tag lame.set_OriginalFlag(1); // Mark as original lame.set_CopyrightFlag(1); // Set copyright // Save settings lame.SaveAudioEncoderPropertiesToRegistry(); } ``` ### Example 2: Podcast/Voice Encoding (C++) ``` #include "LAME.h" HRESULT ConfigurePodcastMP3(IBaseFilter* pAudioEncoder) { HRESULT hr; IAudioEncoderProperties* pLame = nullptr; hr = pAudioEncoder->QueryInterface(IID_IAudioEncoderProperties, (void**)&pLame); if (FAILED(hr)) return hr; // Voice-optimized settings pLame->set_VoiceMode(1); // Voice optimization pLame->set_Bitrate(64); // 64 kbps for speech pLame->set_Quality(5); // Balanced quality pLame->set_ChannelMode(3); // Mono // Disable VBR for predictable file size pLame->set_Variable(0); // Add Xing tag for compatibility pLame->set_XingTag(1); // Save configuration pLame->SaveAudioEncoderPropertiesToRegistry(); pLame->Release(); return S_OK; } ``` ### Example 3: Standard Music Encoding (Delphi) ## ``` procedure ConfigureStandardMP3(AudioEncoder: IBaseFilter); var Lame: IAudioEncoderProperties; hr: HRESULT; begin if Succeeded(AudioEncoder.QueryInterface(IID_IAudioEncoderProperties, Lame)) then begin // Standard VBR music settings Lame.set_Variable(1); // Enable VBR Lame.set_VariableQ(4); // High quality (~165 kbps avg) Lame.set_VariableMin(128); // Min 128 kbps Lame.set_VariableMax(256); // Max 256 kbps // Joint stereo Lame.set_ChannelMode(1); // Essential flags Lame.set_XingTag(1); // VBR tag for seeking // Save to registry Lame.SaveAudioEncoderPropertiesToRegistry; Lame := nil; end; end; ``` ## Best Practices ### Quality Recommendations 1. **Music Archival**: VBR Q0-Q2 (245-190 kbps average) 2. **Music Distribution**: VBR Q4 (165 kbps) or CBR 192 kbps 3. **Streaming**: CBR 128 kbps 4. **Podcasts/Speech**: CBR 64 kbps mono with voice mode ### Performance Tips 1. **Use Joint Stereo** at bitrates below 192 kbps 2. **Enable VBR** for better quality-to-size ratio 3. **Add Xing Tag** for VBR files 4. **Use Voice Mode** for speech content at <96 kbps ### Configuration Workflow 1. Connect input pin before configuring 2. Check `InputTypeDefined()` before setting properties 3. Configure all desired properties 4. Call `SaveAudioEncoderPropertiesToRegistry()` 5. Verify settings with get methods --- ## Troubleshooting ### Issue: Settings Not Applied **Solution**: ``` // Ensure input is connected first if (lame.InputTypeDefined() == 0) { // Configure settings lame.set_Bitrate(192); lame.SaveAudioEncoderPropertiesToRegistry(); } else { // Connect input first, then configure } ``` ### Issue: Poor Quality Output **Solutions**: - Increase VBR quality: `set_VariableQ(2)` or lower - Increase CBR bitrate: `set_Bitrate(192)` or higher - Use better quality setting: `set_Quality(2)` - Disable voice mode for music: `set_VoiceMode(0)` ### Issue: Large File Sizes **Solutions**: ``` // Use VBR instead of high CBR pLame->set_Variable(1); pLame->set_VariableQ(4); // ~165 kbps average pLame->set_VariableMax(192); // Cap maximum bitrate ``` --- ## See Also - [Encoding Filters Pack Overview](../../) - [Audio Codecs Reference](../../codecs-reference/) - [AAC Encoder](../aac/) - [FLAC Encoder](../flac/) ---END OF PAGE--- ## MP4 Muxer DirectShow Filter - Timing and Live Streaming **URL:** https://www.visioforge.com/help/docs/directshow/filters-enc/interfaces/mp4-muxer/ **Description:** MP4 muxer DirectShow interfaces with threading configuration, timing correction, and live streaming options for MP4 container output. **Tags:** DirectShow, C++, Windows, Streaming, Encoding, MP4, C# **API:** MP4V10Flags, IBaseFilter, MP4MuxerStandardConfig, MP4MuxerDeterministicConfig, MP4V10LiveStreamingConfig # MP4 Muxer Interface Reference ## Overview The MP4 muxer DirectShow filters provide interfaces for configuring MP4 (MPEG-4 Part 14) container output. These interfaces allow developers to control threading behavior, timing correction, and special handling for live streaming scenarios. Two muxer interfaces are available: - **IMP4MuxerConfig**: Basic MP4 muxer configuration for threading and timing - **IMP4V10MuxerConfig**: Advanced configuration for version 10 muxer with timing flags and live streaming control ## IMP4MuxerConfig Interface ### Overview The **IMP4MuxerConfig** interface provides basic configuration for MP4 multiplexing, controlling single-threaded operation and timing correction behavior. **Interface GUID**: `{99DC9BE5-0AFA-45d4-8370-AB021FB07CF4}` **Inherits From**: `IUnknown` ### Interface Definitions #### C# Definition ``` using System; using System.Runtime.InteropServices; namespace VisioForge.DirectShowAPI { /// /// MP4 muxer configuration interface. /// Controls threading and timing behavior for MP4 container creation. /// [ComImport] [Guid("99DC9BE5-0AFA-45d4-8370-AB021FB07CF4")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] public interface IMP4MuxerConfig { /// /// Gets the single-thread processing state. /// /// Receives true if single-threaded mode is enabled, false otherwise /// HRESULT (0 for success) [PreserveSig] int get_SingleThread([Out] [MarshalAs(UnmanagedType.Bool)] out bool pValue); /// /// Enables or disables single-threaded processing. /// When enabled, all muxer operations run on a single thread for deterministic behavior. /// /// True to enable single-threaded mode, false for multi-threaded /// HRESULT (0 for success) [PreserveSig] int put_SingleThread([In] [MarshalAs(UnmanagedType.Bool)] bool value); /// /// Gets the timing correction state. /// /// Receives true if timing correction is enabled, false otherwise /// HRESULT (0 for success) [PreserveSig] int get_CorrectTiming([Out] [MarshalAs(UnmanagedType.Bool)] out bool pValue); /// /// Enables or disables timing correction. /// When enabled, the muxer adjusts timestamps to correct timing drift and inconsistencies. /// /// True to enable timing correction, false to disable /// HRESULT (0 for success) [PreserveSig] int put_CorrectTiming([In] [MarshalAs(UnmanagedType.Bool)] bool value); } } ``` #### C++ Definition ``` #include // {99DC9BE5-0AFA-45d4-8370-AB021FB07CF4} DEFINE_GUID(IID_IMP4MuxerConfig, 0x99dc9be5, 0x0afa, 0x45d4, 0x83, 0x70, 0xab, 0x02, 0x1f, 0xb0, 0x7c, 0xf4); /// /// MP4 muxer configuration interface. /// Controls threading and timing behavior. /// DECLARE_INTERFACE_(IMP4MuxerConfig, IUnknown) { /// /// Gets the single-thread processing state. /// /// Pointer to receive single-thread enabled state /// S_OK for success STDMETHOD(get_SingleThread)(THIS_ BOOL* pValue ) PURE; /// /// Enables or disables single-threaded processing. /// /// TRUE to enable single-threaded mode, FALSE for multi-threaded /// S_OK for success STDMETHOD(put_SingleThread)(THIS_ BOOL value ) PURE; /// /// Gets the timing correction state. /// /// Pointer to receive timing correction enabled state /// S_OK for success STDMETHOD(get_CorrectTiming)(THIS_ BOOL* pValue ) PURE; /// /// Enables or disables timing correction. /// /// TRUE to enable timing correction, FALSE to disable /// S_OK for success STDMETHOD(put_CorrectTiming)(THIS_ BOOL value ) PURE; }; ``` #### Delphi Definition ``` uses ActiveX, ComObj; const IID_IMP4MuxerConfig: TGUID = '{99DC9BE5-0AFA-45d4-8370-AB021FB07CF4}'; type /// /// MP4 muxer configuration interface. /// IMP4MuxerConfig = interface(IUnknown) ['{99DC9BE5-0AFA-45d4-8370-AB021FB07CF4}'] /// /// Gets the single-thread processing state. /// function get_SingleThread(out pValue: BOOL): HRESULT; stdcall; /// /// Enables or disables single-threaded processing. /// function put_SingleThread(value: BOOL): HRESULT; stdcall; /// /// Gets the timing correction state. /// function get_CorrectTiming(out pValue: BOOL): HRESULT; stdcall; /// /// Enables or disables timing correction. /// function put_CorrectTiming(value: BOOL): HRESULT; stdcall; end; ``` ### Method Reference #### get\_SingleThread / put\_SingleThread Controls whether the muxer processes data using a single thread or multiple threads. **Single-Threaded Mode (enabled)**: - All muxing operations run on one thread - Deterministic, predictable behavior - Easier debugging and troubleshooting - Slightly lower performance on multi-core systems - **Recommended for**: Scenarios requiring consistent, reproducible output **Multi-Threaded Mode (disabled)**: - Muxer can use multiple threads for processing - Better performance on multi-core processors - Non-deterministic operation order - **Recommended for**: High-performance encoding with multiple streams **Default**: Typically multi-threaded (false) **Example**: ``` // Enable single-threaded mode for consistent output mp4Muxer.put_SingleThread(true); ``` #### get\_CorrectTiming / put\_CorrectTiming Enables or disables automatic timestamp correction for audio and video streams. **Timing Correction Enabled (true)**: - Muxer automatically adjusts timestamps to correct drift - Fixes timing inconsistencies from source filters - Ensures proper A/V synchronization - Adds small processing overhead - **Recommended for**: Most scenarios, especially with live sources **Timing Correction Disabled (false)**: - Timestamps passed through without modification - Assumes source filters provide accurate timestamps - Slightly better performance - **Use only when**: Source provides guaranteed accurate timestamps **Default**: Typically enabled (true) **Example**: ``` // Enable timing correction for A/V sync mp4Muxer.put_CorrectTiming(true); ``` --- ## IMP4V10MuxerConfig Interface ### Overview The **IMP4V10MuxerConfig** interface provides advanced configuration for the version 10 MP4 muxer, including timing override flags and live streaming control. **Interface GUID**: `{9E26CE8B-6708-4535-AAA4-23F9A97C7937}` **Inherits From**: `IUnknown` ### MP4V10Flags Enumeration ``` /// /// MP4 v10 muxer configuration flags. /// [Flags] public enum MP4V10Flags { /// /// No special flags. /// None = 0, /// /// Time override mode - allows manual timestamp control. /// TimeOverride = 0x00000001, /// /// Time adjust mode - enables automatic timestamp adjustment. /// TimeAdjust = 0x00000002 } ``` ### Interface Definitions #### C# Definition ``` using System; using System.Runtime.InteropServices; namespace VisioForge.DirectShowAPI { /// /// MP4 v10 muxer flags. /// [Flags] public enum MP4V10Flags { /// /// Default - no special flags. /// None = 0, /// /// Time override - allows manual timestamp control. /// TimeOverride = 0x00000001, /// /// Time adjust - enables automatic timestamp adjustment. /// TimeAdjust = 0x00000002 } /// /// MP4 version 10 muxer configuration interface. /// Provides advanced timing control and live streaming options. /// [ComImport] [Guid("9E26CE8B-6708-4535-AAA4-23F9A97C7937")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] public interface IMP4V10MuxerConfig { /// /// Sets the muxer configuration flags. /// /// Combination of MP4V10Flags values /// HRESULT (0 for success) [PreserveSig] int SetFlags([In] uint value); /// /// Gets the current muxer configuration flags. /// /// Receives the current flags /// HRESULT (0 for success) [PreserveSig] int GetFlags([Out] out uint pValue); /// /// Disables live streaming optimizations. /// When disabled, muxer uses standard file-based output mode. /// /// True to disable live mode, false to enable /// HRESULT (0 for success) [PreserveSig] int SetLiveDisabled([MarshalAs(UnmanagedType.Bool)] bool liveDisabled); } } ``` #### C++ Definition ``` #include // {9E26CE8B-6708-4535-AAA4-23F9A97C7937} DEFINE_GUID(IID_IMP4V10MuxerConfig, 0x9e26ce8b, 0x6708, 0x4535, 0xaa, 0xa4, 0x23, 0xf9, 0xa9, 0x7c, 0x79, 0x37); /// /// MP4 v10 muxer flags. /// enum MP4V10Flags { MP4V10_NONE = 0, MP4V10_TIME_OVERRIDE = 0x00000001, MP4V10_TIME_ADJUST = 0x00000002 }; /// /// MP4 version 10 muxer configuration interface. /// Provides advanced timing control and live streaming options. /// DECLARE_INTERFACE_(IMP4V10MuxerConfig, IUnknown) { /// /// Sets the muxer configuration flags. /// /// Combination of MP4V10Flags values /// S_OK for success STDMETHOD(SetFlags)(THIS_ unsigned long value ) PURE; /// /// Gets the current muxer configuration flags. /// /// Pointer to receive current flags /// S_OK for success STDMETHOD(GetFlags)(THIS_ unsigned long* pValue ) PURE; /// /// Disables live streaming optimizations. /// /// TRUE to disable live mode, FALSE to enable /// S_OK for success STDMETHOD(SetLiveDisabled)(THIS_ BOOL liveDisabled ) PURE; }; ``` #### Delphi Definition ``` uses ActiveX, ComObj; const IID_IMP4V10MuxerConfig: TGUID = '{9E26CE8B-6708-4535-AAA4-23F9A97C7937}'; // MP4V10Flags constants MP4V10_NONE = 0; MP4V10_TIME_OVERRIDE = $00000001; MP4V10_TIME_ADJUST = $00000002; type /// /// MP4 version 10 muxer configuration interface. /// IMP4V10MuxerConfig = interface(IUnknown) ['{9E26CE8B-6708-4535-AAA4-23F9A97C7937}'] /// /// Sets the muxer configuration flags. /// function SetFlags(value: Cardinal): HRESULT; stdcall; /// /// Gets the current muxer configuration flags. /// function GetFlags(out pValue: Cardinal): HRESULT; stdcall; /// /// Disables live streaming optimizations. /// function SetLiveDisabled(liveDisabled: BOOL): HRESULT; stdcall; end; ``` ### Method Reference #### SetFlags / GetFlags Sets or retrieves the muxer configuration flags that control timing behavior. **MP4V10Flags Values**: **None (0)**: - Standard operation - Default timestamp handling - No special timing modifications **TimeOverride (0x00000001)**: - Enables manual timestamp override - Allows application to control timestamps directly - Disables automatic timestamp generation - **Use when**: Application needs full control over timing **TimeAdjust (0x00000002)**: - Enables automatic timestamp adjustment - Muxer corrects timing drift and irregularities - Similar to IMP4MuxerConfig::CorrectTiming - **Use for**: Sources with inconsistent timestamps **Combining Flags**: ``` // Enable both time override and adjust uint flags = (uint)(MP4V10Flags.TimeOverride | MP4V10Flags.TimeAdjust); mp4V10Muxer.SetFlags(flags); ``` #### SetLiveDisabled Controls whether the muxer operates in live streaming mode or file-based mode. **Live Mode Enabled** (liveDisabled = false): - Optimized for live/real-time streaming - Minimal buffering - Lower latency - Progressive MP4 output (can be played while being written) - **Use for**: Live streaming to file, network streaming output **Live Mode Disabled** (liveDisabled = true): - Standard file-based muxing - Can perform multi-pass optimization - Complete MP4 structure written at end - May require seeking in output file - **Use for**: File-based encoding, post-processing scenarios **Example**: ``` // Enable file-based mode (disable live optimizations) mp4V10Muxer.SetLiveDisabled(true); ``` ## Usage Examples ### C# Example - Standard MP4 File Creation ``` using System; using DirectShowLib; using VisioForge.DirectShowAPI; public class MP4MuxerStandardConfig { public void ConfigureStandardMP4(IBaseFilter mp4Muxer) { // Query the standard MP4 muxer interface var muxerConfig = mp4Muxer as IMP4MuxerConfig; if (muxerConfig == null) { Console.WriteLine("Error: Filter does not support IMP4MuxerConfig"); return; } // Configure for standard file-based encoding muxerConfig.put_SingleThread(false); // Multi-threaded for performance muxerConfig.put_CorrectTiming(true); // Enable timing correction Console.WriteLine("MP4 muxer configured for standard file creation"); // Verify configuration muxerConfig.get_SingleThread(out bool singleThread); muxerConfig.get_CorrectTiming(out bool correctTiming); Console.WriteLine($" Single-threaded: {singleThread}"); Console.WriteLine($" Timing correction: {correctTiming}"); } } ``` ### C# Example - Deterministic Output ``` public class MP4MuxerDeterministicConfig { public void ConfigureDeterministicMP4(IBaseFilter mp4Muxer) { var muxerConfig = mp4Muxer as IMP4MuxerConfig; if (muxerConfig == null) return; // Configure for deterministic, reproducible output muxerConfig.put_SingleThread(true); // Single-threaded for consistency muxerConfig.put_CorrectTiming(true); // Enable timing correction Console.WriteLine("MP4 muxer configured for deterministic output"); Console.WriteLine(" Suitable for regression testing and validation"); } } ``` ### C# Example - Live Streaming to File (MP4 V10) ``` public class MP4V10LiveStreamingConfig { public void ConfigureLiveStreaming(IBaseFilter mp4V10Muxer) { // Query the MP4 v10 muxer interface var muxerV10Config = mp4V10Muxer as IMP4V10MuxerConfig; if (muxerV10Config == null) { Console.WriteLine("Error: Filter does not support IMP4V10MuxerConfig"); return; } // Configure for live streaming to file muxerV10Config.SetLiveDisabled(false); // Enable live mode // Enable timing adjustment for live sources uint flags = (uint)MP4V10Flags.TimeAdjust; muxerV10Config.SetFlags(flags); Console.WriteLine("MP4 v10 muxer configured for live streaming"); // Verify configuration muxerV10Config.GetFlags(out uint currentFlags); Console.WriteLine($" Flags: 0x{currentFlags:X8}"); Console.WriteLine($" Time Adjust: {((currentFlags & (uint)MP4V10Flags.TimeAdjust) != 0)}"); } } ``` ### C# Example - Manual Timestamp Control (MP4 V10) ``` public class MP4V10ManualTimestampConfig { public void ConfigureManualTimestamps(IBaseFilter mp4V10Muxer) { var muxerV10Config = mp4V10Muxer as IMP4V10MuxerConfig; if (muxerV10Config == null) return; // Configure for manual timestamp control muxerV10Config.SetLiveDisabled(true); // Disable live mode // Enable time override for manual control uint flags = (uint)MP4V10Flags.TimeOverride; muxerV10Config.SetFlags(flags); Console.WriteLine("MP4 v10 muxer configured for manual timestamp control"); Console.WriteLine(" Application must provide accurate timestamps"); } } ``` ### C++ Example - Standard Configuration ``` #include #include #include "IMP4MuxerConfig.h" void ConfigureMP4Muxer(IBaseFilter* pMp4Muxer) { IMP4MuxerConfig* pMuxerConfig = NULL; HRESULT hr = S_OK; // Query the MP4 muxer interface hr = pMp4Muxer->QueryInterface(IID_IMP4MuxerConfig, (void**)&pMuxerConfig); if (FAILED(hr) || !pMuxerConfig) { std::cout << "Error: Filter does not support IMP4MuxerConfig" << std::endl; return; } // Configure muxer pMuxerConfig->put_SingleThread(FALSE); // Multi-threaded pMuxerConfig->put_CorrectTiming(TRUE); // Enable timing correction // Verify configuration BOOL singleThread, correctTiming; pMuxerConfig->get_SingleThread(&singleThread); pMuxerConfig->get_CorrectTiming(&correctTiming); std::cout << "MP4 muxer configured:" << std::endl; std::cout << " Single-threaded: " << (singleThread ? "Yes" : "No") << std::endl; std::cout << " Timing correction: " << (correctTiming ? "Yes" : "No") << std::endl; pMuxerConfig->Release(); } ``` ### C++ Example - Live Streaming (MP4 V10) ``` #include "IMP4V10MuxerConfig.h" void ConfigureMP4V10LiveStreaming(IBaseFilter* pMp4V10Muxer) { IMP4V10MuxerConfig* pMuxerV10Config = NULL; HRESULT hr = pMp4V10Muxer->QueryInterface(IID_IMP4V10MuxerConfig, (void**)&pMuxerV10Config); if (SUCCEEDED(hr) && pMuxerV10Config) { // Configure for live streaming pMuxerV10Config->SetLiveDisabled(FALSE); // Enable live mode // Enable timing adjustment unsigned long flags = MP4V10_TIME_ADJUST; pMuxerV10Config->SetFlags(flags); std::cout << "MP4 v10 muxer configured for live streaming" << std::endl; pMuxerV10Config->Release(); } } ``` ### Delphi Example - Standard Configuration ``` uses DirectShow9, ActiveX; procedure ConfigureMP4Muxer(Mp4Muxer: IBaseFilter); var MuxerConfig: IMP4MuxerConfig; SingleThread, CorrectTiming: BOOL; hr: HRESULT; begin // Query the MP4 muxer interface hr := Mp4Muxer.QueryInterface(IID_IMP4MuxerConfig, MuxerConfig); if Failed(hr) or (MuxerConfig = nil) then begin WriteLn('Error: Filter does not support IMP4MuxerConfig'); Exit; end; try // Configure muxer MuxerConfig.put_SingleThread(False); // Multi-threaded MuxerConfig.put_CorrectTiming(True); // Enable timing correction // Verify configuration MuxerConfig.get_SingleThread(SingleThread); MuxerConfig.get_CorrectTiming(CorrectTiming); WriteLn('MP4 muxer configured:'); WriteLn(' Single-threaded: ', SingleThread); WriteLn(' Timing correction: ', CorrectTiming); finally MuxerConfig := nil; end; end; ``` ### Delphi Example - Live Streaming (MP4 V10) ``` procedure ConfigureMP4V10LiveStreaming(Mp4V10Muxer: IBaseFilter); var MuxerV10Config: IMP4V10MuxerConfig; Flags: Cardinal; begin if Succeeded(Mp4V10Muxer.QueryInterface(IID_IMP4V10MuxerConfig, MuxerV10Config)) then begin try // Configure for live streaming MuxerV10Config.SetLiveDisabled(False); // Enable live mode // Enable timing adjustment Flags := MP4V10_TIME_ADJUST; MuxerV10Config.SetFlags(Flags); WriteLn('MP4 v10 muxer configured for live streaming'); finally MuxerV10Config := nil; end; end; end; ``` ## Best Practices ### When to Use IMP4MuxerConfig **Use IMP4MuxerConfig when**: - You need basic muxer configuration - Working with standard MP4 output - Simple timing correction is sufficient - Don't need advanced live streaming features **Typical Configuration**: ``` mp4Muxer.put_SingleThread(false); // Multi-threaded for performance mp4Muxer.put_CorrectTiming(true); // Enable timing correction ``` ### When to Use IMP4V10MuxerConfig **Use IMP4V10MuxerConfig when**: - Need advanced timing control - Working with live streaming scenarios - Require manual timestamp override - Need progressive MP4 output **Live Streaming Configuration**: ``` mp4V10Muxer.SetLiveDisabled(false); // Enable live mode mp4V10Muxer.SetFlags((uint)MP4V10Flags.TimeAdjust); // Auto timing adjustment ``` ### Single-Threaded vs Multi-Threaded **Use Single-Threaded Mode when**: - Debugging muxer behavior - Need deterministic, reproducible output - Running automated tests - Troubleshooting timing issues **Use Multi-Threaded Mode when**: - Performance is critical - Encoding high-resolution video (1080p+) - System has multiple CPU cores available - Standard production encoding ### Timing Correction **Always Enable Timing Correction when**: - Working with live sources (cameras, capture devices) - Sources may have timestamp inconsistencies - Combining multiple streams (audio + video) - Need reliable A/V synchronization **Can Disable Timing Correction when**: - Source provides guaranteed accurate timestamps - File-based encoding with pre-validated timestamps - Performance is absolutely critical - Using manual timestamp control (TimeOverride flag) ### Live Streaming Optimization **Enable Live Mode** (SetLiveDisabled = false) **when**: - Encoding for real-time streaming - Output needs to be playable while being written - Creating progressive MP4 files - Low latency is important **Disable Live Mode** (SetLiveDisabled = true) **when**: - Creating files for post-processing - Need complete MP4 structure at end - Can perform multi-pass optimization - Output file will only be played after completion ## Troubleshooting ### Audio/Video Sync Issues **Symptoms**: Audio and video drift out of sync over time **Solutions**: 1. Enable timing correction: `put_CorrectTiming(true)` 2. For v10 muxer, use TimeAdjust flag: `SetFlags((uint)MP4V10Flags.TimeAdjust)` 3. Verify source filters provide accurate timestamps 4. Check that audio and video sample rates are correct ### File Cannot Be Played While Recording **Symptom**: MP4 file only playable after encoding completes **Cause**: Live mode is disabled **Solution**: - Use IMP4V10MuxerConfig interface - Enable live mode: `SetLiveDisabled(false)` - This creates progressive MP4 files playable during encoding ### Inconsistent File Output **Symptoms**: Same input produces different output files **Cause**: Multi-threaded operation with race conditions **Solutions**: 1. Enable single-threaded mode: `put_SingleThread(true)` 2. Enable timing correction: `put_CorrectTiming(true)` 3. Use TimeAdjust flag for v10 muxer ### Performance Issues **Symptoms**: Encoding slower than expected, high CPU usage **Possible Causes**: 1. Single-threaded mode on multi-core system 2. Excessive timing correction overhead **Solutions**: - Disable single-threaded mode: `put_SingleThread(false)` - If sources have accurate timestamps, can try disabling timing correction - Ensure video encoder (not muxer) is the performance bottleneck - Consider hardware encoding (NVENC, QuickSync) ### Corrupted MP4 Files **Symptoms**: MP4 file won't play or has errors **Possible Causes**: 1. Timing correction disabled with poor timestamps 2. Incorrect live mode setting for use case 3. Muxer stopped before proper finalization **Solutions**: - Enable timing correction for live sources - Match live mode setting to use case (live vs file-based) - Ensure proper filter graph shutdown and stream finalization - Verify all streams end properly (send EC\_COMPLETE event) --- ## See Also - [H.264 Encoder Interface](../h264/) - [AAC Encoder Interfaces](../aac/) - [Muxers Reference](../../muxers-reference/) - [Encoding Filters Pack Overview](../../) ---END OF PAGE--- ## NVIDIA NVENC Hardware Encoder Settings for DirectShow **URL:** https://www.visioforge.com/help/docs/directshow/filters-enc/interfaces/nvenc/ **Description:** Configure NVIDIA NVENC hardware encoding in DirectShow with INVEncConfig COM interface. H.264/H.265 codec settings, presets, and GPU selection for C++/C#. **Tags:** DirectShow, C++, Windows, Streaming, Encoding, H.264, H.265, C# **API:** IBaseFilter # INVEncConfig Interface Reference ## Overview The `INVEncConfig` interface provides comprehensive control over NVIDIA NVENC hardware video encoding. This interface extends the standard DirectShow `IAMVideoCompression` interface with NVENC-specific configuration options for H.264 and H.265 encoding. NVENC is NVIDIA's dedicated hardware encoder available on GeForce, Quadro, and Tesla GPUs, offering high-performance video encoding with minimal CPU usage. ## Filter and Interface GUIDs - **Filter CLSID**: `CLSID_NVEncoder` `{6EEC9161-7276-430B-A197-0D4C3BCC87E5}` - **Interface**: `INVEncConfig` **GUID**: `{9A2AC42C-3E3D-4E6A-84E5-D097292D496B}` **Inherits From**: `IAMVideoCompression` **Header File**: `Intf.h` (C++) - **Interface**: `INVEncConfig2` **GUID**: `{2A741FB6-6DE1-460B-8FCA-76DB478C9357}` **Inherits From**: `IUnknown` **Header File**: `Intf2.h` (C++) ## Interface Definitions ### C++ Definition (INVEncConfig) ``` #include // {9A2AC42C-3E3D-4E6A-84E5-D097292D496B} static const GUID IID_INVEncConfig = { 0x9a2ac42c, 0x3e3d, 0x4e6a, { 0x84, 0xe5, 0xd0, 0x97, 0x29, 0x2d, 0x49, 0x6b } }; // {6EEC9161-7276-430B-A197-0D4C3BCC87E5} static const GUID CLSID_NVEncoder = { 0x6eec9161, 0x7276, 0x430b, { 0xa1, 0x97, 0xd, 0x4c, 0x3b, 0xcc, 0x87, 0xe5 } }; MIDL_INTERFACE("9A2AC42C-3E3D-4E6A-84E5-D097292D496B") INVEncConfig : public IAMVideoCompression { public: virtual HRESULT STDMETHODCALLTYPE SetDeviceType(int v) = 0; virtual HRESULT STDMETHODCALLTYPE GetDeviceType(int *v) = 0; virtual HRESULT STDMETHODCALLTYPE SetPictureStructure(int v) = 0; virtual HRESULT STDMETHODCALLTYPE GetPictureStructure(int *v) = 0; virtual HRESULT STDMETHODCALLTYPE SetNumBuffers(int v) = 0; virtual HRESULT STDMETHODCALLTYPE GetNumBuffers(int *v) = 0; virtual HRESULT STDMETHODCALLTYPE SetRateControl(int v) = 0; virtual HRESULT STDMETHODCALLTYPE GetRateControl(int *v) = 0; virtual HRESULT STDMETHODCALLTYPE SetPreset(GUID v) = 0; virtual HRESULT STDMETHODCALLTYPE GetPreset(GUID *v) = 0; virtual HRESULT STDMETHODCALLTYPE SetQp(int v) = 0; virtual HRESULT STDMETHODCALLTYPE GetQp(int *v) = 0; virtual HRESULT STDMETHODCALLTYPE SetBFrames(int v) = 0; virtual HRESULT STDMETHODCALLTYPE GetBFrames(int *v) = 0; virtual HRESULT STDMETHODCALLTYPE SetGOP(int v) = 0; virtual HRESULT STDMETHODCALLTYPE GetGOP(int *v) = 0; virtual HRESULT STDMETHODCALLTYPE SetBitrate(int v) = 0; virtual HRESULT STDMETHODCALLTYPE GetBitrate(int *v) = 0; virtual HRESULT STDMETHODCALLTYPE SetVbvBitrate(int v) = 0; virtual HRESULT STDMETHODCALLTYPE GetVbvBitrate(int *v) = 0; virtual HRESULT STDMETHODCALLTYPE SetVbvSize(int v) = 0; virtual HRESULT STDMETHODCALLTYPE GetVbvSize(int *v) = 0; virtual HRESULT STDMETHODCALLTYPE SetProfile(GUID v) = 0; virtual HRESULT STDMETHODCALLTYPE GetProfile(GUID *v) = 0; virtual HRESULT STDMETHODCALLTYPE SetLevel(int v) = 0; virtual HRESULT STDMETHODCALLTYPE GetLevel(int *v) = 0; virtual HRESULT STDMETHODCALLTYPE SetCodec(int v) = 0; virtual HRESULT STDMETHODCALLTYPE GetCodec(int *v) = 0; }; ``` ### C# Definition (INVEncConfig) ``` using System; using System.Runtime.InteropServices; using DirectShowLib; namespace VisioForge.DirectShowAPI { /// /// NVENC encoder configuration interface. /// Provides hardware-accelerated H.264/H.265 encoding on NVIDIA GPUs. /// [ComImport] [System.Security.SuppressUnmanagedCodeSecurity] [Guid("9A2AC42C-3E3D-4E6A-84E5-D097292D496B")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] public interface INVEncConfig { // Note: Also inherits IAMVideoCompression methods // (put_KeyFrameRate, get_KeyFrameRate, put_PFramesPerKeyFrame, etc.) /// Sets the CUDA device index for encoding. /// Device index (0 for first GPU, 1 for second, etc.) [PreserveSig] int SetDeviceType(int v); /// Gets the CUDA device index. [PreserveSig] int GetDeviceType(out int v); /// Sets picture structure (progressive or interlaced). /// 0 = Progressive, 1 = Interlaced [PreserveSig] int SetPictureStructure(int v); /// Gets picture structure. [PreserveSig] int GetPictureStructure(out int v); /// Sets number of encoding buffers. /// Buffer count (typically 4-8) [PreserveSig] int SetNumBuffers(int v); /// Gets number of encoding buffers. [PreserveSig] int GetNumBuffers(out int v); /// Sets rate control mode. /// 0 = CQP, 1 = VBR, 2 = CBR [PreserveSig] int SetRateControl(int v); /// Gets rate control mode. [PreserveSig] int GetRateControl(out int v); /// Sets encoding preset. /// Preset GUID (P1-P7) [PreserveSig] int SetPreset(Guid v); /// Gets encoding preset. [PreserveSig] int GetPreset(out Guid v); /// Sets quantization parameter for CQP mode. /// QP value (0-51, lower = higher quality) [PreserveSig] int SetQp(int v); /// Gets quantization parameter. [PreserveSig] int GetQp(out int v); /// Sets number of B-frames. /// B-frame count (0-4) [PreserveSig] int SetBFrames(int v); /// Gets number of B-frames. [PreserveSig] int GetBFrames(out int v); /// Sets GOP (Group of Pictures) size. /// GOP size in frames [PreserveSig] int SetGOP(int v); /// Gets GOP size. [PreserveSig] int GetGOP(out int v); /// Sets target bitrate. /// Bitrate in bits per second [PreserveSig] int SetBitrate(int v); /// Gets target bitrate. [PreserveSig] int GetBitrate(out int v); /// Sets VBV buffer bitrate. /// VBV bitrate in bps [PreserveSig] int SetVbvBitrate(int v); /// Gets VBV buffer bitrate. [PreserveSig] int GetVbvBitrate(out int v); /// Sets VBV buffer size. /// VBV size in bits [PreserveSig] int SetVbvSize(int v); /// Gets VBV buffer size. [PreserveSig] int GetVbvSize(out int v); /// Sets encoding profile. /// Profile GUID (Baseline, Main, High, etc.) [PreserveSig] int SetProfile(Guid v); /// Gets encoding profile. [PreserveSig] int GetProfile(out Guid v); /// Sets profile level. /// Level value (30, 31, 40, 41, 50, 51, etc.) [PreserveSig] int SetLevel(int v); /// Gets profile level. [PreserveSig] int GetLevel(out int v); /// Sets video codec. /// 0 = H.264, 1 = H.265 [PreserveSig] int SetCodec(int v); /// Gets video codec. [PreserveSig] int GetCodec(out int v); } /// /// NVENC configuration interface 2 - availability check. /// [ComImport] [System.Security.SuppressUnmanagedCodeSecurity] [Guid("2A741FB6-6DE1-460B-8FCA-76DB478C9357")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] public interface INVEncConfig2 { /// Checks if NVENC is available on the system. /// True if NVENC is available /// NVENC status code [PreserveSig] int CheckNVENCAvailable([MarshalAs(UnmanagedType.Bool)] out bool result, out int status); } } ``` ### Delphi Definition (INVEncConfig) ``` uses ActiveX, ComObj; const IID_INVEncConfig: TGUID = '{9A2AC42C-3E3D-4E6A-84E5-D097292D496B}'; IID_INVEncConfig2: TGUID = '{2A741FB6-6DE1-460B-8FCA-76DB478C9357}'; CLSID_NVEncoder: TGUID = '{6EEC9161-7276-430B-A197-0D4C3BCC87E5}'; type /// /// NVENC encoder configuration interface. /// Extends IAMVideoCompression with NVENC-specific settings. /// INVEncConfig = interface(IUnknown) ['{9A2AC42C-3E3D-4E6A-84E5-D097292D496B}'] // Note: Also inherits IAMVideoCompression methods function SetDeviceType(v: Integer): HRESULT; stdcall; function GetDeviceType(out v: Integer): HRESULT; stdcall; function SetPictureStructure(v: Integer): HRESULT; stdcall; function GetPictureStructure(out v: Integer): HRESULT; stdcall; function SetNumBuffers(v: Integer): HRESULT; stdcall; function GetNumBuffers(out v: Integer): HRESULT; stdcall; function SetRateControl(v: Integer): HRESULT; stdcall; function GetRateControl(out v: Integer): HRESULT; stdcall; function SetPreset(v: TGUID): HRESULT; stdcall; function GetPreset(out v: TGUID): HRESULT; stdcall; function SetQp(v: Integer): HRESULT; stdcall; function GetQp(out v: Integer): HRESULT; stdcall; function SetBFrames(v: Integer): HRESULT; stdcall; function GetBFrames(out v: Integer): HRESULT; stdcall; function SetGOP(v: Integer): HRESULT; stdcall; function GetGOP(out v: Integer): HRESULT; stdcall; function SetBitrate(v: Integer): HRESULT; stdcall; function GetBitrate(out v: Integer): HRESULT; stdcall; function SetVbvBitrate(v: Integer): HRESULT; stdcall; function GetVbvBitrate(out v: Integer): HRESULT; stdcall; function SetVbvSize(v: Integer): HRESULT; stdcall; function GetVbvSize(out v: Integer): HRESULT; stdcall; function SetProfile(v: TGUID): HRESULT; stdcall; function GetProfile(out v: TGUID): HRESULT; stdcall; function SetLevel(v: Integer): HRESULT; stdcall; function GetLevel(out v: Integer): HRESULT; stdcall; function SetCodec(v: Integer): HRESULT; stdcall; function GetCodec(out v: Integer): HRESULT; stdcall; end; /// /// NVENC configuration interface 2 - availability check. /// INVEncConfig2 = interface(IUnknown) ['{2A741FB6-6DE1-460B-8FCA-76DB478C9357}'] function CheckNVENCAvailable(out result: BOOL; out status: Integer): HRESULT; stdcall; end; ``` ## Hardware Requirements ### GPU Generations | GPU Generation | H.264 | H.265 | Quality | Notes | | --- | --- | --- | --- | --- | | **Kepler** (GTX 600/700) | ✓ | ✗ | Basic | 1st generation NVENC | | **Maxwell** (GTX 900) | ✓ | ✓ | Good | 2nd gen, HEVC support added | | **Pascal** (GTX 10XX) | ✓ | ✓ | Better | 3rd gen, improved quality | | **Turing** (RTX 20XX) | ✓ | ✓ | Excellent | 7th gen, B-frame support | | **Ampere** (RTX 30XX) | ✓ | ✓ | Excellent | 8th gen, AV1 support | | **Ada/Hopper** (RTX 40XX) | ✓ | ✓ | Best | Latest generation | ### Performance Capabilities - **1080p @ 60fps**: All NVENC generations - **4K @ 60fps**: Maxwell and newer - **8K @ 30fps**: Turing and newer - **Simultaneous Streams**: 3-5 (varies by GPU) --- ## Methods Reference All methods inherited from `IAMVideoCompression` are available. The following are NVENC-specific extensions: ### Device Configuration #### SetDeviceType / GetDeviceType Sets or retrieves the CUDA device index for encoding. **Syntax (C++)**: ``` HRESULT SetDeviceType(int v); HRESULT GetDeviceType(int *v); ``` **Syntax (C#)**: ``` [PreserveSig] int SetDeviceType(int v); [PreserveSig] int GetDeviceType(out int v); ``` **Parameters**: - `v`: CUDA device index (0 for first GPU, 1 for second GPU, etc.) **Returns**: `S_OK` (0) on success. **Usage Notes**: - Must be called **before** connecting the encoder filter - Use 0 for systems with single GPU - For multi-GPU systems, select the GPU to use for encoding - Query available CUDA devices using CUDA API or NVIDIA tools **Example (C++)**: ``` INVEncConfig* pNVEnc = nullptr; pFilter->QueryInterface(IID_INVEncConfig, (void**)&pNVEnc); // Use first GPU pNVEnc->SetDeviceType(0); pNVEnc->Release(); ``` --- ### Picture Structure #### SetPictureStructure / GetPictureStructure Sets the picture coding type (progressive or interlaced). **Syntax (C++)**: ``` HRESULT SetPictureStructure(int v); HRESULT GetPictureStructure(int *v); ``` **Parameters**: - `v`: Picture structure type - `0` - Progressive (frame-based) - `1` - Interlaced (field-based) **Returns**: `S_OK` on success. **Usage Notes**: - Default is progressive (0) - Use interlaced (1) only for broadcast/DVD content - Progressive is recommended for modern content **Example (C++)**: ``` // Set progressive encoding pNVEnc->SetPictureStructure(0); ``` --- ### Buffer Configuration #### SetNumBuffers / GetNumBuffers Sets the number of encoding buffers. **Syntax (C++)**: ``` HRESULT SetNumBuffers(int v); HRESULT GetNumBuffers(int *v); ``` **Parameters**: - `v`: Number of buffers (typically 4-8) **Returns**: `S_OK` on success. **Usage Notes**: - More buffers = higher latency but smoother encoding - Fewer buffers = lower latency but potential frame drops - Recommended values: - Low latency: 4 buffers - Normal: 6 buffers - High quality: 8 buffers **Example (C++)**: ``` // Low latency configuration pNVEnc->SetNumBuffers(4); ``` --- ### Rate Control #### SetRateControl / GetRateControl Sets the rate control mode for bitrate management. **Syntax (C++)**: ``` HRESULT SetRateControl(int v); HRESULT GetRateControl(int *v); ``` **Parameters**: - `v`: Rate control mode - `0` - **CQP** (Constant Quantization Parameter) - Fixed quality - `1` - **VBR** (Variable Bitrate) - Variable bitrate, target quality - `2` - **CBR** (Constant Bitrate) - Fixed bitrate for streaming **Returns**: `S_OK` on success. **Rate Control Mode Details**: | Mode | Bitrate Behavior | Use Case | Quality | File Size | | --- | --- | --- | --- | --- | | **CQP** | Varies widely | Archival, highest quality | Excellent | Unpredictable | | **VBR** | Varies moderately | File storage, YouTube | Very Good | Moderate | | **CBR** | Constant | Live streaming, broadcasting | Good | Predictable | **Example (C++)**: ``` // Use CBR for live streaming pNVEnc->SetRateControl(2); pNVEnc->SetBitrate(5000000); // 5 Mbps ``` **Example (C#)**: ``` // Use VBR for file recording nvenc.SetRateControl(1); nvenc.SetBitrate(8000000); // 8 Mbps target ``` --- ### Preset Configuration #### SetPreset / GetPreset Sets the encoding preset which balances speed and quality. **Syntax (C++)**: ``` HRESULT SetPreset(GUID v); HRESULT GetPreset(GUID *v); ``` **Parameters**: - `v`: Preset GUID from NVENC SDK **Preset Options** (typical values): | Preset | Description | Speed | Quality | Use Case | |--------|-------------|-------|---------|----------| | **P1** | Fastest | ★★★★★ | ★☆☆☆☆ | Real-time low-latency | | **P2** | Faster | ★★★★☆ | ★★☆☆☆ | Live streaming | | **P3** | Fast | ★★★☆☆ | ★★★☆☆ | Standard streaming | | **P4** | Medium | ★★☆☆☆ | ★★★★☆ | Balanced (recommended) | | **P5** | Slow | ★☆☆☆☆ | ★★★★☆ | High quality streaming | | **P6** | Slower | ☆☆☆☆☆ | ★★★★★ | Archive quality | | **P7** | Slowest | ☆☆☆☆☆ | ★★★★★ | Maximum quality | **Usage Notes**: - P4 is recommended for most use cases - P1-P2 for low-latency applications - P6-P7 for maximum quality (slower encoding) - Preset affects: motion estimation, lookahead, subpixel motion **Example (C++)**: ``` // Use P4 preset (balanced) GUID presetP4 = /* GUID for P4 preset */; pNVEnc->SetPreset(presetP4); ``` --- ### Quality Parameter (QP) #### SetQp / GetQp Sets the quantization parameter for CQP mode. **Syntax (C++)**: ``` HRESULT SetQp(int v); HRESULT GetQp(int *v); ``` **Parameters**: - `v`: QP value (0-51) - Lower values = higher quality, larger files - Higher values = lower quality, smaller files - Typical range: 18-28 **Returns**: `S_OK` on success. **Usage Notes**: - Only effective when using CQP rate control mode - Ignored in CBR/VBR modes - Recommended values: - High quality: 18-22 - Medium quality: 23-26 - Low quality: 27-30 **Example (C++)**: ``` // High quality CQP encoding pNVEnc->SetRateControl(0); // CQP mode pNVEnc->SetQp(20); // High quality ``` --- ### B-Frames Configuration #### SetBFrames / GetBFrames Sets the number of B-frames between I and P frames. **Syntax (C++)**: ``` HRESULT SetBFrames(int v); HRESULT GetBFrames(int *v); ``` **Parameters**: - `v`: Number of B-frames (0-4) - `0` - No B-frames (lowest latency) - `1-2` - Moderate compression improvement - `3-4` - Best compression (higher latency) **Returns**: `S_OK` on success. **Usage Notes**: - B-frames improve compression efficiency - More B-frames = higher latency - Requires Turing (RTX 20XX) or newer for full support - Recommended values: - Low latency: 0 - Streaming: 2 - Recording: 3 **Example (C++)**: ``` // Low latency - disable B-frames pNVEnc->SetBFrames(0); // High quality recording - use B-frames pNVEnc->SetBFrames(3); ``` --- ### GOP Configuration #### SetGOP / GetGOP Sets the Group of Pictures (keyframe interval) size. **Syntax (C++)**: ``` HRESULT SetGOP(int v); HRESULT GetGOP(int *v); ``` **Parameters**: - `v`: GOP size in frames - Typical values: 30-300 frames - Frame rate × seconds = GOP size - Example: 60 fps × 2 seconds = 120 GOP size **Returns**: `S_OK` on success. **Usage Notes**: - Smaller GOP = better seeking, larger file - Larger GOP = better compression, poor seeking - For streaming: 2-4 seconds (fps × 2-4) - For recording: 5-10 seconds **Example (C++)**: ``` // 2-second GOP for 30fps streaming pNVEnc->SetGOP(60); // 5-second GOP for 60fps recording pNVEnc->SetGOP(300); ``` --- ### Bitrate Configuration #### SetBitrate / GetBitrate Sets the target bitrate for encoding. **Syntax (C++)**: ``` HRESULT SetBitrate(int v); HRESULT GetBitrate(int *v); ``` **Parameters**: - `v`: Bitrate in bits per second (bps) **Returns**: `S_OK` on success. **Recommended Bitrates**: | Resolution | Framerate | Bitrate (H.264) | Bitrate (H.265) | |------------|-----------|-----------------|-----------------| | 720p | 30 fps | 2.5-4 Mbps | 1.5-2.5 Mbps | | 720p | 60 fps | 4-6 Mbps | 2.5-4 Mbps | | 1080p | 30 fps | 4-6 Mbps | 2.5-4 Mbps | | 1080p | 60 fps | 8-12 Mbps | 5-8 Mbps | | 1440p | 30 fps | 10-15 Mbps | 6-10 Mbps | | 1440p | 60 fps | 15-25 Mbps | 10-15 Mbps | | 4K | 30 fps | 25-40 Mbps | 15-25 Mbps | | 4K | 60 fps | 45-70 Mbps | 30-45 Mbps | **Example (C++)**: ``` // 1080p @ 60fps streaming pNVEnc->SetBitrate(10000000); // 10 Mbps ``` --- ### VBV Buffer Configuration #### SetVbvBitrate / GetVbvBitrate Sets the VBV (Video Buffering Verifier) buffer bitrate. **Syntax (C++)**: ``` HRESULT SetVbvBitrate(int v); HRESULT GetVbvBitrate(int *v); ``` **Parameters**: - `v`: VBV bitrate in bps (usually same as or higher than target bitrate) **Usage Notes**: - Controls maximum bitrate spikes - Typically set to 1.0-1.5× target bitrate - Important for streaming to prevent buffer underruns --- #### SetVbvSize / GetVbvSize Sets the VBV buffer size. **Syntax (C++)**: ``` HRESULT SetVbvSize(int v); HRESULT GetVbvSize(int *v); ``` **Parameters**: - `v`: VBV buffer size in bits **Usage Notes**: - Larger buffer = smoother bitrate but higher latency - Smaller buffer = lower latency but more bitrate variance - Typical: 1-2 seconds of video at target bitrate **Example (C++)**: ``` // 10 Mbps stream with 2-second buffer pNVEnc->SetBitrate(10000000); pNVEnc->SetVbvBitrate(12000000); // 1.2× bitrate pNVEnc->SetVbvSize(20000000); // 2 seconds ``` --- ### Profile Configuration #### SetProfile / GetProfile Sets the H.264/H.265 encoding profile. **Syntax (C++)**: ``` HRESULT SetProfile(GUID v); HRESULT GetProfile(GUID *v); ``` **Parameters**: - `v`: Profile GUID **H.264 Profiles**: - **Baseline** - Basic features, mobile compatibility - **Main** - Standard features, most devices - **High** - Advanced features, HD/4K content **H.265 Profiles**: - **Main** - 8-bit, 4:2:0 - **Main 10** - 10-bit, HDR support **Usage Notes**: - Use High profile for H.264 in most cases - Use Main profile for maximum compatibility - HEVC Main 10 for HDR content --- ### Level Configuration #### SetLevel / GetLevel Sets the profile level (resolution/bitrate constraints). **Syntax (C++)**: ``` HRESULT SetLevel(int v); HRESULT GetLevel(int *v); ``` **Parameters**: - `v`: Level value (see H.264/H.265 level table) **Common H.264 Levels**: - **30** (3.0) - SD video - **31** (3.1) - 720p @ 30fps - **40** (4.0) - 1080p @ 30fps - **41** (4.1) - 1080p @ 60fps - **50** (5.0) - 4K @ 30fps - **51** (5.1) - 4K @ 60fps **Example (C++)**: ``` // 1080p @ 60fps pNVEnc->SetLevel(41); ``` --- ### Codec Selection #### SetCodec / GetCodec Sets the video codec to use. **Syntax (C++)**: ``` HRESULT SetCodec(int v); HRESULT GetCodec(int *v); ``` **Parameters**: - `v`: Codec type - `0` - H.264/AVC - `1` - H.265/HEVC **Returns**: `S_OK` on success. **Usage Notes**: - H.264 for maximum compatibility - H.265 for better compression (40-50% smaller files) - H.265 requires Maxwell (GTX 900) or newer GPU **Example (C++)**: ``` // Use H.265 pNVEnc->SetCodec(1); ``` --- ## INVEncConfig2 Methods ### CheckNVENCAvailable Checks if NVENC hardware encoding is available on the system. **Syntax (C++)**: ``` HRESULT CheckNVENCAvailable(BOOL* result, int* status); ``` **Syntax (C#)**: ``` [PreserveSig] int CheckNVENCAvailable([MarshalAs(UnmanagedType.Bool)] out bool result, out int status); ``` **Parameters**: - `result`: Receives `TRUE` if NVENC is available, `FALSE` otherwise - `status`: Receives NVENC status code (vendor-specific) **Returns**: `S_OK` (0) on success. **Usage Notes**: - Call this before attempting to use NVENC encoder - Returns `FALSE` if: - No NVIDIA GPU is present - GPU doesn't support NVENC (pre-Kepler) - NVIDIA drivers are not installed - NVENC library is not available - The status code provides additional diagnostic information **Example (C++)**: ``` #include "Intf2.h" HRESULT CheckNVENCSupport(IBaseFilter* pEncoder) { HRESULT hr; INVEncConfig2* pNVEnc2 = nullptr; hr = pEncoder->QueryInterface(IID_INVEncConfig2, (void**)&pNVEnc2); if (FAILED(hr)) { // INVEncConfig2 not supported by this filter return hr; } BOOL available = FALSE; int status = 0; hr = pNVEnc2->CheckNVENCAvailable(&available, &status); if (SUCCEEDED(hr)) { if (available) { printf("NVENC is available (status: %d)\n", status); // Proceed with NVENC configuration } else { printf("NVENC not available (status: %d)\n", status); // Fall back to software encoder } } pNVEnc2->Release(); return hr; } ``` **Example (C#)**: ``` using VisioForge.DirectShowAPI; public bool IsNVENCAvailable(IBaseFilter encoder) { var nvenc2 = encoder as INVEncConfig2; if (nvenc2 == null) { // INVEncConfig2 not supported return false; } bool available; int status; int hr = nvenc2.CheckNVENCAvailable(out available, out status); if (hr == 0) { if (available) { Console.WriteLine($"NVENC is available (status: {status})"); return true; } else { Console.WriteLine($"NVENC not available (status: {status})"); return false; } } return false; } ``` **Example (Delphi)**: ``` function CheckNVENCSupport(Encoder: IBaseFilter): Boolean; var NVEnc2: INVEncConfig2; Available: BOOL; Status: Integer; hr: HRESULT; begin Result := False; if Succeeded(Encoder.QueryInterface(IID_INVEncConfig2, NVEnc2)) then begin hr := NVEnc2.CheckNVENCAvailable(Available, Status); if Succeeded(hr) then begin if Available then begin WriteLn(Format('NVENC is available (status: %d)', [Status])); Result := True; end else begin WriteLn(Format('NVENC not available (status: %d)', [Status])); end; end; NVEnc2 := nil; end; end; ``` --- ## Complete Configuration Examples ### Example 1: Low Latency Streaming (C++) ``` #include "Intf.h" HRESULT ConfigureLowLatencyNVENC(IBaseFilter* pEncoder) { HRESULT hr; INVEncConfig* pNVEnc = nullptr; hr = pEncoder->QueryInterface(IID_INVEncConfig, (void**)&pNVEnc); if (FAILED(hr)) return hr; // Basic configuration pNVEnc->SetDeviceType(0); // First GPU pNVEnc->SetCodec(0); // H.264 pNVEnc->SetPictureStructure(0); // Progressive // Low latency settings pNVEnc->SetRateControl(2); // CBR pNVEnc->SetBitrate(5000000); // 5 Mbps pNVEnc->SetBFrames(0); // No B-frames pNVEnc->SetGOP(60); // 2-second GOP (30fps) pNVEnc->SetNumBuffers(4); // Minimal buffering // Fast preset GUID presetP2 = /* P2 GUID */; pNVEnc->SetPreset(presetP2); // Profile/Level for 1080p30 GUID highProfile = /* High Profile GUID */; pNVEnc->SetProfile(highProfile); pNVEnc->SetLevel(40); // Level 4.0 pNVEnc->Release(); return S_OK; } ``` ### Example 2: High Quality Recording (C#) ``` using System; using DirectShowLib; using VisioForge.DirectShowAPI; public class NVENCHighQualityRecording { public void ConfigureNVENC(IBaseFilter encoder) { var nvenc = encoder as INVEncConfig; if (nvenc == null) throw new NotSupportedException("NVENC not available"); // Basic configuration nvenc.SetDeviceType(0); // First GPU nvenc.SetCodec(1); // H.265 for better compression nvenc.SetPictureStructure(0); // Progressive // High quality VBR settings nvenc.SetRateControl(1); // VBR nvenc.SetBitrate(15000000); // 15 Mbps average nvenc.SetBFrames(3); // Use B-frames nvenc.SetGOP(300); // 5-second GOP (60fps) nvenc.SetNumBuffers(8); // More buffering for quality // Quality preset Guid presetP6 = /* P6 GUID */; nvenc.SetPreset(presetP6); // HEVC Main profile for 4K Guid hevcMain = /* HEVC Main GUID */; nvenc.SetProfile(hevcMain); nvenc.SetLevel(51); // Level 5.1 for 4K60 // VBV configuration nvenc.SetVbvBitrate(20000000); // 20 Mbps max nvenc.SetVbvSize(30000000); // 2-second buffer } } ``` ### Example 3: Balanced Streaming (C++) ``` HRESULT ConfigureBalancedStreaming(IBaseFilter* pEncoder) { INVEncConfig* pNVEnc = nullptr; pEncoder->QueryInterface(IID_INVEncConfig, (void**)&pNVEnc); // Device and codec pNVEnc->SetDeviceType(0); pNVEnc->SetCodec(0); // H.264 for compatibility // Balanced CBR streaming pNVEnc->SetRateControl(2); // CBR pNVEnc->SetBitrate(8000000); // 8 Mbps pNVEnc->SetBFrames(2); // Moderate B-frames pNVEnc->SetGOP(120); // 2-second GOP (60fps) pNVEnc->SetNumBuffers(6); // Standard buffering // Balanced preset P4 GUID presetP4 = /* P4 GUID */; pNVEnc->SetPreset(presetP4); // 1080p60 profile/level GUID highProfile = /* High Profile GUID */; pNVEnc->SetProfile(highProfile); pNVEnc->SetLevel(41); // VBV for streaming pNVEnc->SetVbvBitrate(10000000); // 1.25× bitrate pNVEnc->SetVbvSize(16000000); // 2-second buffer pNVEnc->Release(); return S_OK; } ``` --- ## Best Practices ### General Recommendations 1. **Use P4 preset as default** - Best balance of quality and performance 2. **CBR for streaming** - Predictable bitrate for network delivery 3. **VBR for recording** - Better quality for file storage 4. **Disable B-frames for low latency** - Reduces encoding delay 5. **Match GOP to framerate** - 2-4 seconds typical (fps × 2-4) ### Quality Optimization 1. **Higher preset = better quality** - Use P5-P7 when encoding time allows 2. **More B-frames = better compression** - Use 3 for recording 3. **Appropriate bitrate** - Don't go too low, quality suffers significantly 4. **VBV buffer size** - 1-2 seconds at target bitrate ### Performance Optimization 1. **Lower preset = faster encoding** - Use P1-P3 for real-time 2. **Disable B-frames** - Reduces latency and complexity 3. **Fewer encoding buffers** - Lower latency but potential drops 4. **Select appropriate GPU** - Use SetDeviceType() for multi-GPU systems ### Compatibility 1. **Use H.264 High profile** - Maximum compatibility 2. **Set correct level** - Match resolution and framerate 3. **CBR for streaming** - More compatible with players/servers 4. **Standard GOP size** - 2-4 seconds --- ## Troubleshooting ### Issue: NVENC Not Available **Symptoms**: QueryInterface fails for INVEncConfig **Solutions**: - Verify NVIDIA GPU is installed - Check GPU generation (Kepler or newer required) - Update NVIDIA drivers to latest version - Verify DirectShow filter is registered ### Issue: Poor Quality Output **Solutions**: ``` // Increase bitrate pNVEnc->SetBitrate(15000000); // Higher bitrate // Use better preset pNVEnc->SetPreset(presetP6); // Slower but better // Add B-frames pNVEnc->SetBFrames(3); // Better compression ``` ### Issue: High Latency **Solutions**: ``` // Disable B-frames pNVEnc->SetBFrames(0); // Use faster preset pNVEnc->SetPreset(presetP1); // Reduce buffers pNVEnc->SetNumBuffers(4); // Smaller GOP pNVEnc->SetGOP(30); // 1 second at 30fps ``` ### Issue: Bitrate Spikes **Solutions**: ``` // Use CBR instead of VBR pNVEnc->SetRateControl(2); // Configure VBV properly pNVEnc->SetVbvBitrate(bitrate * 1.2); pNVEnc->SetVbvSize(bitrate * 2); ``` --- ## Performance Benchmarks ### Typical Encoding Performance | Resolution | Preset | GPU Generation | FPS (approx) | | --- | --- | --- | --- | | 1080p | P1 | Pascal+ | 200-300 | | 1080p | P4 | Pascal+ | 150-200 | | 1080p | P7 | Pascal+ | 60-100 | | 4K | P1 | Turing+ | 90-120 | | 4K | P4 | Turing+ | 60-90 | | 4K | P7 | Turing+ | 30-50 | | ### Quality Comparison (PSNR) | | | | | Preset | Quality vs x264 | Speed vs x264 | | | -------- | ----------------- | --------------- | | | P1 | -2 dB | 100× faster | | | P4 | -0.5 dB | 50× faster | | | P7 | ≈ equal | 20× faster | | | --- | | | | ## Related Interfaces - **IAMVideoCompression** - Base DirectShow compression interface - **IBaseFilter** - DirectShow filter base interface - **IMediaControl** - Graph control (run, stop) ## See Also - [Encoding Filters Pack Overview](../../) - [Codecs Reference](../../codecs-reference/) - [Code Examples](../../examples/) - [NVIDIA NVENC Documentation](https://developer.nvidia.com/video-codec-sdk) ---END OF PAGE--- ## DirectShow Muxer and Container Format Reference Guide **URL:** https://www.visioforge.com/help/docs/directshow/filters-enc/muxers-reference/ **Description:** Container format reference for VisioForge DirectShow muxers — MP4, MKV, WebM, MPEG-TS, AVI with codec compatibility and streaming configuration. **Tags:** DirectShow, C++, Windows, Streaming, Encoding, Decoding, Metadata, HLS, MPEG-DASH, WebRTC, MP4, MKV, WebM, AVI, FLV, TS, OGG, H.264, H.265, VP8, VP9, MPEG-2, AAC, MP3, Opus, FLAC, Vorbis, WAV, AC-3, Speex # Encoding Filters Pack - Muxers Reference ## Overview This document provides comprehensive information about all container formats (muxers) supported by the DirectShow Encoding Filters Pack. Muxers combine video and audio streams into container files for storage and streaming. --- ## MP4 Container ### Overview MPEG-4 Part 14 (MP4) is the most widely used container format for video distribution. **File Extensions**: `.mp4`, `.m4v`, `.m4a` (audio only) **MIME Type**: `video/mp4`, `audio/mp4` ### Supported Codecs #### Video Codecs - H.264/AVC ✓ (Primary) - H.265/HEVC ✓ - MPEG-4 Part 2 ✓ - MPEG-2 ✗ (use MPEG-TS instead) - VP8/VP9 ✗ (use WebM instead) #### Audio Codecs - AAC ✓ (Primary) - MP3 ✓ - Opus ✗ - Vorbis ✗ - FLAC ✓ - PCM ✓ ### Features **Streaming Support**: - **Progressive Download**: ✓ (with proper moov atom placement) - **Adaptive Streaming**: ✓ (DASH, HLS with fragmented MP4) - **Live Streaming**: ✓ (fragmented MP4) **Metadata Support**: - **Basic Tags**: Title, artist, album, year - **Cover Art**: ✓ - **Chapters**: ✓ - **Subtitles**: ✓ (VTT, SRT, various text formats) **Technical Features**: - **Multiple Audio Tracks**: ✓ - **Multiple Subtitle Tracks**: ✓ - **Fast Start**: ✓ (moov atom at beginning) - **Fragmented MP4**: ✓ (for streaming) ### Best Practices **For Progressive Download (Web)**: ``` - Place moov atom at beginning (fast start) - Use H.264 Baseline/Main profile - AAC-LC audio - Keyframe interval: 2-4 seconds ``` **For Local Playback**: ``` - H.264 High profile or H.265 - AAC-LC or HE-AAC - Any keyframe interval ``` **For Streaming (DASH/HLS)**: ``` - Fragmented MP4 - H.264 Main/High profile - AAC-LC audio - Short fragments (2-6 seconds) ``` ### Compatibility | Platform/Device | Compatibility | | --- | --- | | **Windows Media Player** | ✓ | | **VLC** | ✓ | | **Web Browsers** | ✓ | | **iOS/iPhone** | ✓ | | **Android** | ✓ | | **Smart TVs** | ✓ | | **Game Consoles** | ✓ | | ### Common Issues | | | **Issue**: Video not seekable on web | | | - **Solution**: Enable fast start (moov at beginning) | | | **Issue**: Audio sync problems | | | - **Solution**: Use constant frame rate, check audio sample rate | | | --- | | ## MKV (Matroska) Container ### Overview Matroska is an open-standard, feature-rich container format. **File Extensions**: `.mkv` (video), `.mka` (audio), `.mks` (subtitles) **MIME Type**: `video/x-matroska`, `audio/x-matroska` ### Supported Codecs #### Video Codecs - H.264/AVC ✓ - H.265/HEVC ✓ - VP8 ✓ - VP9 ✓ - MPEG-4 Part 2 ✓ - MPEG-2 ✓ - AV1 ✓ #### Audio Codecs - AAC ✓ - MP3 ✓ - Opus ✓ - Vorbis ✓ - FLAC ✓ - DTS ✓ - AC-3 ✓ - PCM ✓ ### Features **Advanced Features**: - **Multiple Video Tracks**: ✓ - **Multiple Audio Tracks**: ✓ (unlimited) - **Multiple Subtitle Tracks**: ✓ (unlimited) - **Attachments**: ✓ (fonts, cover art) - **Chapters**: ✓ (with nesting) - **Tags/Metadata**: ✓ (extensive) - **Segmenting**: ✓ (linked segments) **Technical Capabilities**: - **Variable Frame Rate**: ✓ - **Lossless Audio**: ✓ - **3D/Stereoscopic**: ✓ - **HDR Metadata**: ✓ ### Best Practices **For Archival**: ``` - Use FLAC or PCM for lossless audio - Include all audio/subtitle tracks - Add chapter markers - Include metadata tags ``` **For Distribution**: ``` - H.264/H.265 video - AAC audio (most compatible) - Embedded soft subtitles - Reasonable file size ``` **For Streaming**: ``` - Not ideal for streaming - Consider MP4 or WebM instead - If used: disable complex features ``` ### Compatibility | Platform/Device | Compatibility | | --- | --- | | **Windows Media Player** | ✗ (codec pack required) | | **VLC** | ✓ | | **Web Browsers** | ✗ (no native support) | | **iOS/iPhone** | ✗ (3rd party apps only) | | **Android** | Limited (app-dependent) | | **Smart TVs** | Limited (model-dependent) | | **Media Players** | ✓ (Kodi, Plex, etc.) | ### Common Issues **Issue**: Seeking is slow - **Solution**: Enable cues (index) during muxing **Issue**: Playback stuttering with high-quality audio - **Solution**: Check decoder performance, consider AAC instead of lossless --- ## WebM Container ### Overview WebM is an open, royalty-free format designed for web use. **File Extensions**: `.webm` **MIME Type**: `video/webm`, `audio/webm` ### Supported Codecs #### Video Codecs - VP8 ✓ (WebM 1.0) - VP9 ✓ (WebM 2.0) - AV1 ✓ (experimental) - H.264 ✗ - H.265 ✗ #### Audio Codecs - Vorbis ✓ (Primary) - Opus ✓ (Recommended) - AAC ✗ - MP3 ✗ ### Features **Web Optimized**: - **HTML5 Video**: ✓ (native browser support) - **Streaming**: ✓ - **Adaptive Streaming**: ✓ (DASH) - **Low Latency**: ✓ **Metadata Support**: - **Basic Tags**: ✓ - **Chapters**: ✓ - **Subtitles**: ✓ (WebVTT) ### Best Practices **For YouTube/Web**: ``` - VP9 video codec - Opus audio codec (96-160 kbps) - Keyframe interval: 2-4 seconds - Two-pass encoding for best quality ``` **For Live Streaming**: ``` - VP8 for better encoder performance - Opus audio (low latency mode) - CBR bitrate - Short GOP ``` **For High Quality**: ``` - VP9 with high bitrate - Opus 128-256 kbps - Two-pass encoding - Quality-based rate control ``` ### Compatibility | Platform/Device | Compatibility | | --- | --- | | **Chrome** | ✓ | | **Firefox** | ✓ | | **Edge** | ✓ | | **Safari** | Limited (VP8 only) | | **Android** | ✓ | | **iOS** | Limited | | ### Common Issues | | | **Issue**: Safari won't play WebM | | | - **Solution**: Provide MP4 fallback with H.264 | | | **Issue**: Encoding too slow | | | - **Solution**: Use VP8 instead of VP9, or hardware-accelerated VP9 if available | | | --- | | ## MPEG-TS (Transport Stream) ### Overview MPEG Transport Stream is designed for broadcast and streaming, especially where error resilience is important. **File Extensions**: `.ts`, `.mts`, `.m2ts` **MIME Type**: `video/mp2t` ### Supported Codecs #### Video Codecs - H.264/AVC ✓ - H.265/HEVC ✓ - MPEG-2 ✓ - VP8/VP9 ✗ #### Audio Codecs - AAC ✓ - MP3 ✓ - AC-3 ✓ - PCM ✓ ### Features **Broadcast Features**: - **Error Resilience**: ✓ (built-in error recovery) - **Time-shifting**: ✓ - **Program Multiplexing**: ✓ (multiple programs in one stream) - **Encryption**: ✓ (conditional access) **Streaming Features**: - **HLS Streaming**: ✓ (Apple HTTP Live Streaming) - **DVB Broadcasting**: ✓ - **IPTV**: ✓ ### Best Practices **For HLS Streaming**: ``` - H.264 video - AAC audio - Segment duration: 6-10 seconds - CBR encoding - Closed GOP ``` **For Broadcasting**: ``` - MPEG-2 or H.264 - AC-3 or AAC audio - Constant bitrate - Fixed packet size (188 bytes) ``` ### Compatibility | Platform/Device | Compatibility | | --- | --- | | **HLS Players** | ✓ | | **Set-top Boxes** | ✓ | | **Smart TVs** | ✓ | | **VLC** | ✓ | | **Web Browsers** | Via HLS support | --- ## FLV (Flash Video) ### Overview Legacy format formerly used for web video (YouTube, Flash players). **File Extensions**: `.flv`, `.f4v` **MIME Type**: `video/x-flv` **Status**: ⚠️ Deprecated - Use MP4 or WebM instead ### Supported Codecs #### Video Codecs - H.264 ✓ - VP6 ✓ (legacy) - Sorenson Spark ✓ (legacy) #### Audio Codecs - AAC ✓ - MP3 ✓ - Speex ✓ ### Features - **Streaming**: ✓ (RTMP) - **Metadata**: Basic (onMetaData) - **Cue Points**: ✓ **Not Recommended**: Flash Player end-of-life (2020) makes FLV obsolete --- ## OGG Container ### Overview Open-source container primarily for Vorbis audio. **File Extensions**: `.ogg`, `.oga` (audio), `.ogv` (video) **MIME Type**: `audio/ogg`, `video/ogg` ### Supported Codecs #### Video Codecs - Theora ✓ (legacy quality) - VP8 ✗ (use WebM) #### Audio Codecs - Vorbis ✓ (Primary) - Opus ✓ - FLAC ✓ - Speex ✓ ### Features - **Streaming**: ✓ - **Chaining**: ✓ (multiple files in sequence) - **Metadata**: ✓ (Vorbis comments) ### Best Practices **For Audio**: ``` - Vorbis or Opus codec - Quality-based encoding - Vorbis comments for metadata ``` **For Video**: ``` - Not recommended - Use WebM (VP8/VP9) instead ``` ### Compatibility | Platform/Device | Compatibility | | --- | --- | | **Firefox** | ✓ | | **Chrome** | ✓ | | **VLC** | ✓ | | **Most mobile devices** | Limited | --- ## AVI (Audio Video Interleave) ### Overview Legacy Microsoft container format. **File Extensions**: `.avi` **MIME Type**: `video/x-msvideo` **Status**: ⚠️ Legacy - Use MP4 or MKV for new projects ### Supported Codecs #### Video Codecs - H.264 ✓ (limited support) - MPEG-4 Part 2 ✓ - MPEG-2 ✓ - Various legacy codecs ✓ #### Audio Codecs - MP3 ✓ - PCM ✓ - AC-3 ✓ - AAC Limited ### Limitations - **Max File Size**: 2 GB (without OpenDML) - **Limited Metadata**: Very basic - **No Streaming**: Not designed for streaming - **No Chapters**: Not supported ### When to Use - Legacy system compatibility - Capture from old hardware - Specific software requirements **Recommendation**: Use MP4 or MKV for new projects --- ## WAV Container ### Overview Uncompressed audio container. **File Extensions**: `.wav` **MIME Type**: `audio/wav`, `audio/x-wav` ### Features - **Lossless**: ✓ (PCM) - **Compressed**: ✓ (MP3, AAC in WAV wrapper) - **Metadata**: Limited (RIFF tags) ### Common Formats - **PCM 44.1 kHz 16-bit**: CD quality - **PCM 48 kHz 24-bit**: Professional audio - **PCM 96 kHz 24-bit**: High-resolution audio ### Best Practices **For Audio Production**: ``` - 48 kHz, 24-bit PCM - Mono or stereo - Avoid compression ``` **For Distribution**: ``` - Use FLAC or AAC instead - WAV files are large ``` --- ## Container Selection Guide ### For Web Delivery **Primary**: MP4 (H.264 + AAC) - **Reason**: Universal compatibility - **Fallback**: WebM (VP9 + Opus) for modern browsers ### For Professional Archival **Primary**: MKV (H.265 + FLAC) - **Reason**: Feature-rich, lossless audio support - **Alternative**: MP4 (H.265 + AAC) for better compatibility ### For Broadcast/IPTV **Primary**: MPEG-TS (H.264 + AAC) - **Reason**: Error resilience, industry standard - **Alternative**: MPEG-TS (MPEG-2 + AC-3) for legacy systems ### For Live Streaming **HLS**: MPEG-TS segments (H.264 + AAC) **DASH**: Fragmented MP4 (H.264 + AAC) **WebRTC**: Opus audio, VP8/H.264 video ### For Audio-Only **High Quality**: FLAC (.flac) or MP3 VBR (.mp3) **Streaming**: AAC in MP4 (.m4a) or Opus in WebM **Voice**: Opus in OGG or Speex --- ## Format Comparison Table | Feature | MP4 | MKV | WebM | MPEG-TS | FLV | OGG | | --- | --- | --- | --- | --- | --- | --- | | **Web Compatibility** | ★★★★★ | ★☆☆☆☆ | ★★★★☆ | ★★☆☆☆ | ☆☆☆☆☆ | ★★☆☆☆ | | **Mobile Compatibility** | ★★★★★ | ★★☆☆☆ | ★★★☆☆ | ★★★★☆ | ☆☆☆☆☆ | ★☆☆☆☆ | | **Streaming Support** | ★★★★★ | ★★☆☆☆ | ★★★★★ | ★★★★★ | ★★★☆☆ | ★★★☆☆ | | **Feature Richness** | ★★★★☆ | ★★★★★ | ★★★☆☆ | ★★★☆☆ | ★★☆☆☆ | ★★☆☆☆ | | **Codec Support** | ★★★★☆ | ★★★★★ | ★★☆☆☆ | ★★★☆☆ | ★★☆☆☆ | ★★★☆☆ | | **File Size Efficiency** | ★★★★☆ | ★★★★☆ | ★★★★★ | ★★★☆☆ | ★★★☆☆ | ★★★★☆ | | **Error Resilience** | ★★☆☆☆ | ★★☆☆☆ | ★★☆☆☆ | ★★★★★ | ★★★☆☆ | ★★☆☆☆ | --- ## Technical Specifications ### MP4 Structure ``` ftyp (file type) moov (metadata - place at beginning for fast start) ├── mvhd (movie header) ├── trak (video track) ├── trak (audio track) └── udta (user data/metadata) mdat (media data) ``` ### Fragmented MP4 (for streaming) ``` ftyp moov └── mvex (movie extends) moof (movie fragment) └── traf (track fragment) mdat (fragment data) [repeat moof/mdat for each fragment] ``` ### MKV Structure ## ``` EBML Header Segment ├── SeekHead (index) ├── Info (segment information) ├── Tracks (track definitions) ├── Chapters (optional) ├── Attachments (optional) ├── Tags (metadata) └── Cluster (media data) ``` ## See Also - [Encoding Filters Pack Overview](../) - [Codecs Reference](../codecs-reference/) - [Code Examples](../examples/) - [NVENC Interface Reference](../interfaces/nvenc/) ---END OF PAGE--- ## Register DirectShow Filters in C++, C#, and Delphi **URL:** https://www.visioforge.com/help/docs/directshow/how-to-register/ **Description:** Register DirectShow filters and SDKs in C++, C#, and Delphi with IVFRegister interface and alternative registration code examples. **Tags:** DirectShow, C++, Windows, C# **API:** IVFRegister # SDK Registration Guide DirectShow filters and SDK components often require proper registration to function correctly within your applications. This guide provides detailed implementation methods for registering DirectShow filters across multiple programming languages. ## Registration Overview Most DirectShow filters in the SDK can be registered using the IVFRegister interface. This standardized approach works consistently across development environments. However, some specialized filters (like RGB2YUV converters) are designed to work without explicit registration. ## Registration Methods by Language ### C++ Implementation The following C++ code demonstrates how to access the registration interface: ``` // {59E82754-B531-4A8E-A94D-57C75F01DA30} DEFINE_GUID(IID_IVFRegister, 0x59E82754, 0xB531, 0x4A8E, 0xA9, 0x4D, 0x57, 0xC7, 0x5F, 0x01, 0xDA, 0x30); /// /// Filter registration interface. /// DECLARE_INTERFACE_(IVFRegister, IUnknown) { /// /// Sets registered. /// /// /// License Key. /// STDMETHOD(SetLicenseKey) (THIS_ WCHAR * licenseKey )PURE; }; ``` ### C# Implementation For .NET developers, the registration interface can be imported using the following C# code: ``` /// /// Public filter registration interface. /// [ComImport] [System.Security.SuppressUnmanagedCodeSecurity] [Guid("59E82754-B531-4A8E-A94D-57C75F01DA30")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] public interface IVFRegister { /// /// Sets registered. /// /// /// License Key. /// [PreserveSig] void SetLicenseKey([In, MarshalAs(UnmanagedType.LPWStr)] string licenseKey); } ``` ### Delphi Implementation For Delphi developers, implement the registration interface as follows: ``` const IID_IVFRegister: TGUID = '{59E82754-B531-4A8E-A94D-57C75F01DA30}'; type /// /// Public filter registration interface. /// IVFRegister = interface(IUnknown) /// /// Sets registered. /// /// /// License Key. /// procedure SetLicenseKey(licenseKey: PWideChar); stdcall; end; ``` ---END OF PAGE--- ## DirectShow Filters for Video Playback, Encoding & Effects **URL:** https://www.visioforge.com/help/docs/directshow/ **Description:** DirectShow filters for FFmpeg/VLC playback, H.264/H.265/NVENC encoding, 35+ video effects, chroma key, virtual camera, and AES-256 encryption. **Tags:** DirectShow, C++, Windows # DirectShow SDKs and Filters for Video Development ## Introduction to DirectShow Technology DirectShow technology enables developers to create robust multimedia applications for capturing, processing, and playing video content. Our comprehensive suite of DirectShow filters and SDKs provides the essential building blocks for developing sophisticated video processing and playback applications with minimal effort. ## Playback and Decoding Solutions ### High-Performance Source Filters Our powerful source filters enable seamless playback of diverse video formats in your custom applications. Built upon industry-standard libraries, these filters ensure maximum compatibility and performance. #### VLC Source DirectShow Filter The VLC Source filter delivers exceptional playback capabilities for numerous media formats, leveraging the versatile VLC media framework for optimal performance and format support. - [Explore VLC Source DirectShow Filter](vlc-source-filter/) #### FFMPEG Source DirectShow Filter Our FFMPEG-based filters provide unparalleled media format compatibility, utilizing the widely-adopted FFMPEG libraries to handle virtually any video or audio format in your applications. - [Discover FFMPEG Source DirectShow Filter](ffmpeg-source-filters/) ## Advanced Encoding Solutions ### Professional Encoding Filters Our encoding filters enable developers to implement high-quality video and audio encoding directly within applications. The suite supports numerous industry-standard codecs for maximum flexibility. - [Browse the Complete Encoding Filters Pack](filters-enc/) ## Video Processing and Enhancement ### Specialized Processing Filters Transform and enhance video content with our processing filters that enable rotation, scaling, color grading, overlay capabilities, and numerous other visual effects to create professional-quality video output. - [Explore Video Processing Filters Pack](proc-filters/) ## Virtual Camera Implementation ### Virtual Camera Development SDK Create and integrate virtual camera devices into your applications with our specialized SDK. The virtual camera seamlessly interfaces with any DirectShow-compatible application, including popular video conferencing software. - [Learn about Virtual Camera SDK](virtual-camera-sdk/) ## Secure Video Solutions ### Video Content Encryption SDK Implement robust video content protection with our encryption SDK. Secure your video assets while maintaining playback compatibility with standard DirectShow players such as Windows Media Player and MPC-BE. - [Discover Video Encryption SDK](video-encryption-sdk/) ## Implementation Guides ### Technical Documentation and Tutorials Get started quickly with our detailed technical tutorials designed specifically for developers implementing DirectShow components: - [DirectShow Filter and SDK Registration Guide](how-to-register/) ---END OF PAGE--- ## DirectShow Video Effects Reference - 35+ Filters Guide **URL:** https://www.visioforge.com/help/docs/directshow/proc-filters/effects-reference/ **Description:** Complete reference for 35+ DirectShow video effects including color filters, deinterlacing, denoising, and artistic effects. **Tags:** DirectShow, C++, Windows, Streaming, Effects, Mixing, Webcam, C# **API:** CVFEffectType, CVFEffect, CVFGraphicLogoMain, CVFStretchMode, CVFTextLogoMain # Video Effects Complete Reference ## Overview The DirectShow Processing Filters Pack provides 35+ real-time video effects that can be applied individually or chained together. This reference documents all available effects, their parameters, and usage. ## Effect Categories - **Text and Graphics** - Text logos, graphic overlays - **Color Filters** - Red, green, blue, greyscale filters - **Image Adjustment** - Brightness, contrast, saturation - **Spatial Effects** - Flip, mirror, rotate - **Artistic Effects** - Marble, solarize, posterize, mosaic - **Noise and Quality** - Denoising algorithms (CAST, adaptive, mosquito) - **Deinterlacing** - Blend, triangle, CAVT methods - **Creative Effects** - Blur, shake, spray, invert --- ## Text and Graphics Effects ### ef\_text\_logo Renders text overlay on video with extensive customization options. **Effect Type**: `CVFEffectType.ef_text_logo` **Parameters** (`CVFTextLogoMain` structure): | Parameter | Type | Description | Default | |-----------|------|-------------|---------| | `x` | int | X position (pixels) | 0 | | `y` | int | Y position (pixels) | 0 | | `text` | BSTR | Text to display | "" | | `font_name` | BSTR | Font family name | "Arial" | | `font_size` | int | Font size (points) | 12 | | `font_color` | COLORREF | Text color (RGB) | 0xFFFFFF (white) | | `font_italic` | BOOL | Italic style | FALSE | | `font_bold` | BOOL | Bold style | FALSE | | `font_underline` | BOOL | Underline style | FALSE | | `font_strikeout` | BOOL | Strikethrough style | FALSE | | `transparent_bg` | BOOL | Transparent background | TRUE | | `bg_color` | COLORREF | Background color | 0x000000 (black) | | `transp` | DWORD | Transparency level (0-255) | 255 (opaque) | | `align` | CVFTextAlign | Text alignment | `al_left` | | `antialiasing` | CVFTextAntialiasingMode | Anti-aliasing mode | `am_AntiAlias` | | `gradient` | BOOL | Enable gradient | FALSE | | `gradientMode` | CVFTextGradientMode | Gradient direction | `gm_horizontal` | | `gradientColor1` | COLORREF | Gradient start color | 0xFFFFFF | | `gradientColor2` | COLORREF | Gradient end color | 0x000000 | | `borderMode` | CVFTextBorderMode | Border/outline style | `bm_none` | | `innerBorderColor` | COLORREF | Inner border color | 0x000000 | | `outerBorderColor` | COLORREF | Outer border color | 0xFFFFFF | | `innerBorderSize` | int | Inner border width | 1 | | `outerBorderSize` | int | Outer border width | 1 | | `DateMode` | BOOL | Display current date/time | FALSE | | `DateMask` | BSTR | Date format string | "" | **Text Alignment Options**: - `al_left` - Left-aligned - `al_center` - Center-aligned - `al_right` - Right-aligned **Border Modes**: - `bm_none` - No border - `bm_inner` - Inner outline - `bm_outer` - Outer outline - `bm_inner_and_outer` - Both sides - `bm_embossed` - 3D embossed effect - `bm_outline` - Standard outline - `bm_filled_outline` - Solid outline - `bm_halo` - Glow effect **Example (C++)**: ``` CVFEffect effect; effect.Type = ef_text_logo; effect.Enabled = TRUE; effect.TextLogo.x = 10; effect.TextLogo.y = 10; effect.TextLogo.text = SysAllocString(L"Live Stream"); effect.TextLogo.font_name = SysAllocString(L"Arial"); effect.TextLogo.font_size = 32; effect.TextLogo.font_color = RGB(255, 255, 255); effect.TextLogo.font_bold = TRUE; effect.TextLogo.borderMode = bm_outline; effect.TextLogo.outerBorderColor = RGB(0, 0, 0); effect.TextLogo.outerBorderSize = 2; pEffects->add_effect(effect); ``` --- ### ef\_graphic\_logo Overlays an image (logo, watermark) on video. **Effect Type**: `CVFEffectType.ef_graphic_logo` **Parameters** (`CVFGraphicLogoMain` structure): | Parameter | Type | Description | | --- | --- | --- | | `x` | UINT32 | X position (pixels) | | `y` | UINT32 | Y position (pixels) | | `Filename` | BSTR | Path to image file (BMP, PNG, JPG) | | `hBmp` | int | Handle to bitmap (alternative to filename) | | `StretchMode` | CVFStretchMode | How to scale image | | `TranspLevel` | int | Transparency level (0-255) | | `UseColorKey` | BOOL | Enable color key transparency | | `ColorKey` | COLORREF | Color to make transparent | **Stretch Modes**: - `sm_none` - Original size - `sm_stretch` - Stretch to fit - `sm_letterbox` - Fit with aspect ratio - `sm_crop` - Crop to fit **Example (C#)**: ``` var effect = new CVFEffect { Type = (int)CVFEffectType.ef_graphic_logo, Enabled = true, GraphicLogo = new CVFGraphicLogoMain { Filename = @"C:\Images\logo.png", x = 20, y = 20, StretchMode = (int)CVFStretchMode.sm_none, TranspLevel = 200, UseColorKey = false } }; effectsInterface.add_effect(effect); ``` --- ## Color Filter Effects ### ef\_blue Applies blue color filter (enhances blue, reduces other colors). **Effect Type**: `CVFEffectType.ef_blue` **Parameters**: - `pAmountI` - Filter intensity (0-100, default: 50) **Use Cases**: - Artistic blue tint - Cold atmosphere - Water/ocean scenes --- ### ef\_green Applies green color filter. **Effect Type**: `CVFEffectType.ef_green` **Parameters**: - `pAmountI` - Filter intensity (0-100) **Use Cases**: - Night vision effect - Forest/nature scenes - Matrix-style effect --- ### ef\_red Applies red color filter. **Effect Type**: `CVFEffectType.ef_red` **Parameters**: - `pAmountI` - Filter intensity (0-100) **Use Cases**: - Warm atmosphere - Sunset effect - Alert/danger scenes --- ### ef\_filter\_blue / ef\_filter\_blue\_2 Advanced blue filtering with different algorithms. **Effect Type**: `CVFEffectType.ef_filter_blue` or `ef_filter_blue_2` **Difference**: `ef_filter_blue_2` uses alternative color math for different visual results. --- ### ef\_filter\_green / ef\_filter\_green2 Advanced green filtering (two variants). **Effect Types**: `CVFEffectType.ef_filter_green`, `ef_filter_green2` --- ### ef\_filter\_red / ef\_filter\_red2 Advanced red filtering (two variants). **Effect Types**: `CVFEffectType.ef_filter_red`, `ef_filter_red2` --- ### ef\_greyscale Converts video to black and white. **Effect Type**: `CVFEffectType.ef_greyscale` **Parameters**: None (full greyscale conversion) **Use Cases**: - Classic film look - Artistic effect - Reduce color noise **Example (C++)**: ``` CVFEffect effect; effect.Type = ef_greyscale; effect.Enabled = TRUE; pEffects->add_effect(effect); ``` --- ### ef\_invert Inverts all colors (negative image). **Effect Type**: `CVFEffectType.ef_invert` **Parameters**: None **Use Cases**: - Artistic effect - X-ray appearance - Special visual effects --- ## Image Adjustment Effects ### ef\_contrast Adjusts image contrast. **Effect Type**: `CVFEffectType.ef_contrast` **Parameters**: - `pAmountI` - Contrast adjustment (-100 to +100) - Negative: Decrease contrast - Positive: Increase contrast - Default: 0 (no change) **Example (C#)**: ``` var effect = new CVFEffect { Type = (int)CVFEffectType.ef_contrast, Enabled = true, pAmountI = 25 // Increase contrast by 25% }; ``` --- ### ef\_lightness Adjusts overall brightness. **Effect Type**: `CVFEffectType.ef_lightness` **Parameters**: - `pAmountI` - Brightness adjustment (-100 to +100) - Negative: Darken - Positive: Brighten - Default: 0 --- ### ef\_darkness Darkens the image (opposite of lightness). **Effect Type**: `CVFEffectType.ef_darkness` **Parameters**: - `pAmountI` - Darkness amount (0-100) --- ### ef\_saturation Adjusts color saturation. **Effect Type**: `CVFEffectType.ef_saturation` **Parameters**: - `pAmountI` - Saturation adjustment (-100 to +100) - -100: Greyscale - 0: Original colors - +100: Hyper-saturated **Use Cases**: - Vivid colors for promotional content - Desaturate for muted look - Color grading --- ## Spatial Effects ### ef\_flip\_down Flips video vertically (upside down). **Effect Type**: `CVFEffectType.ef_flip_down` **Parameters**: None **Use Cases**: - Correct upside-down camera - Mirror effect with rotation - Special effects --- ### ef\_flip\_right Flips video horizontally (mirror). **Effect Type**: `CVFEffectType.ef_flip_right` **Parameters**: None **Use Cases**: - Webcam mirror mode - Correct mirrored camera - Symmetry effects --- ### ef\_mirror\_down Creates vertical mirror effect (top reflects to bottom). **Effect Type**: `CVFEffectType.ef_mirror_down` --- ### ef\_mirror\_right Creates horizontal mirror effect (left reflects to right). **Effect Type**: `CVFEffectType.ef_mirror_right` --- ## Artistic Effects ### ef\_blur Applies Gaussian blur to the image. **Effect Type**: `CVFEffectType.ef_blur` **Parameters**: - `pAmountI` - Blur amount (0-100) - `pSizeI` - Blur kernel size (1-20) **Use Cases**: - Background blur (depth of field simulation) - Soften image - Privacy (blur faces, license plates) **Example (C++)**: ``` CVFEffect effect; effect.Type = ef_blur; effect.Enabled = TRUE; effect.pAmountI = 50; // 50% blur strength effect.pSizeI = 10; // 10-pixel blur radius pEffects->add_effect(effect); ``` --- ### ef\_marble Creates marble/swirl texture effect. **Effect Type**: `CVFEffectType.ef_marble` **Parameters**: - `pAmountD` - Effect intensity (0.0-1.0) - `pTurbulenceI` - Turbulence amount (0-100) - `pScaleD` - Scale factor (0.1-10.0) **Use Cases**: - Artistic background - Transition effects - Psychedelic visuals --- ### ef\_posterize Reduces number of colors (poster art effect). **Effect Type**: `CVFEffectType.ef_posterize` **Parameters**: - `pAmountI` - Color levels (2-256) - Lower values: Fewer colors, more dramatic - Higher values: More colors, subtle effect **Use Cases**: - Pop art style - Comic book effect - Reduce color depth --- ### ef\_mosaic Creates pixelated/mosaic effect. **Effect Type**: `CVFEffectType.ef_mosaic` **Parameters**: - `pSizeI` - Mosaic block size (2-100 pixels) **Use Cases**: - Privacy (blur faces/identities) - Retro pixel art style - Censorship **Example (C#)**: ``` var effect = new CVFEffect { Type = (int)CVFEffectType.ef_mosaic, Enabled = true, pSizeI = 15 // 15x15 pixel blocks }; ``` --- ### ef\_solorize Creates solarization effect (partial color inversion). **Effect Type**: `CVFEffectType.ef_solorize` (legacy spelling preserved in the API — use this exact identifier) **Parameters**: - `pAmountI` - Solarization threshold (0-255) **Use Cases**: - Artistic photography effect - Retro look - Creative transitions --- ### ef\_spray Creates paint spray/splatter effect. **Effect Type**: `CVFEffectType.ef_spray` **Parameters**: - `pAmountI` - Spray intensity (0-100) --- ### ef\_shake\_down Simulates camera shake effect vertically. **Effect Type**: `CVFEffectType.ef_shake_down` **Parameters**: - `pAmountI` - Shake intensity (0-100) **Use Cases**: - Earthquake effect - Impact vibration - Handheld camera simulation --- ## Noise Processing Effects ### ef\_denoise\_cast CAST (Combined Adaptive Spatial-Temporal) denoising algorithm. **Effect Type**: `CVFEffectType.ef_denoise_cast` **Parameters** (`CVFDenoiseCAST` structure): | Parameter | Range | Default | Description | | --- | --- | --- | --- | | `TemporalDifferenceThreshold` | 0-255 | 16 | Motion detection threshold | | `NumberOfMotionPixelsThreshold` | 0-16 | 0 | Min pixels for motion | | `StrongEdgeThreshold` | 0-255 | 8 | Edge preservation | | `BlockWidth` | 1-16 | 4 | Processing block width | | `BlockHeight` | 1-16 | 4 | Processing block height | | `EdgePixelWeight` | 0-255 | 128 | Edge blending weight | | `NonEdgePixelWeight` | 0-255 | 16 | Smooth area weight | | `GaussianThresholdY` | int | 12 | Luma noise threshold | | `GaussianThresholdUV` | int | 6 | Chroma noise threshold | | `HistoryWeight` | 0-255 | 192 | Temporal filtering strength | **Use Cases**: - Low-light video cleanup - Webcam noise reduction - Compression artifact removal **Example (C++)**: ``` CVFEffect effect; effect.Type = ef_denoise_cast; effect.Enabled = TRUE; // Moderate noise reduction effect.DenoiseCAST.TemporalDifferenceThreshold = 20; effect.DenoiseCAST.StrongEdgeThreshold = 10; effect.DenoiseCAST.GaussianThresholdY = 15; effect.DenoiseCAST.GaussianThresholdUV = 8; pEffects->add_effect(effect); ``` --- ### ef\_denoise\_adaptive Adaptive noise reduction that adjusts to image content. **Effect Type**: `CVFEffectType.ef_denoise_adaptive` **Parameters**: - `pDenoiseAdaptiveThreshold` - Noise threshold (0-100) - `pDenoiseAdaptiveBlurMode` - Blur method (0-2) **Use Cases**: - General noise reduction - Video cleanup - Quality enhancement --- ### ef\_denoise\_mosquito Reduces mosquito noise (compression artifacts around edges). **Effect Type**: `CVFEffectType.ef_denoise_mosquito` **Parameters**: - `pAmountI` - Reduction strength (0-100) **Use Cases**: - Clean up heavily compressed video - Remove MPEG/H.264 artifacts - Post-processing for streaming --- ### ef\_color\_noise Adds color noise (grain) to image. **Effect Type**: `CVFEffectType.ef_color_noise` **Parameters**: - `pAmountI` - Noise amount (0-100) **Use Cases**: - Film grain effect - Retro/vintage look - Artistic texture --- ### ef\_mono\_noise Adds monochrome (black & white) noise. **Effect Type**: `CVFEffectType.ef_mono_noise` **Parameters**: - `pAmountI` - Noise amount (0-100) --- ## Deinterlacing Effects ### ef\_deint\_blend Blends interlaced fields together. **Effect Type**: `CVFEffectType.ef_deint_blend` **Parameters** (`CVFDeintBlend` structure): | Parameter | Range | Default | Description | |-----------|-------|---------|-------------| | `blendThresh1` | 0-255 | 5 | First blend threshold | | `blendThresh2` | 0-255 | 9 | Second blend threshold | | `blendConstants1` | 0.0-1.0 | 0.3 | First blend weight | | `blendConstants2` | 0.0-1.0 | 0.7 | Second blend weight | **Use Cases**: - Deinterlace analog video - Remove comb artifacts - Convert interlaced to progressive --- ### ef\_deint\_triangle Triangle interpolation deinterlacing. **Effect Type**: `CVFEffectType.ef_deint_triangle` **Parameters**: - `pDeintTriangleWeight` - Interpolation weight (0-100) **Quality**: Better edge preservation than blend --- ### ef\_deint\_cavt CAVT (Content Adaptive Vertical Temporal) deinterlacing. **Effect Type**: `CVFEffectType.ef_deint_cavt` **Parameters**: - `pDeintCAVTThreshold` - Motion threshold (0-100) **Quality**: Best quality, most CPU intensive **Use Cases**: - High-quality deinterlacing - Broadcast video conversion - Archival processing --- ## Effect Chaining Multiple effects can be applied simultaneously. Effects are processed in the order they were added. **Example: Professional Stream Enhancement**: ``` // 1. Denoise CVFEffect denoise; denoise.Type = ef_denoise_adaptive; denoise.Enabled = TRUE; denoise.pDenoiseAdaptiveThreshold = 15; pEffects->add_effect(denoise); // 2. Color correction CVFEffect saturation; saturation.Type = ef_saturation; saturation.Enabled = TRUE; saturation.pAmountI = 15; // Slight saturation boost pEffects->add_effect(saturation); // 3. Add branding CVFEffect logo; logo.Type = ef_graphic_logo; logo.Enabled = TRUE; logo.GraphicLogo.Filename = SysAllocString(L"logo.png"); logo.GraphicLogo.x = 20; logo.GraphicLogo.y = 20; pEffects->add_effect(logo); // 4. Add timestamp CVFEffect timestamp; timestamp.Type = ef_text_logo; timestamp.Enabled = TRUE; timestamp.TextLogo.DateMode = TRUE; timestamp.TextLogo.DateMask = SysAllocString(L"%Y-%m-%d %H:%M:%S"); timestamp.TextLogo.x = 20; timestamp.TextLogo.y = 1050; // Bottom left pEffects->add_effect(timestamp); ``` --- ## Performance Considerations ### CPU Usage by Effect **Low Impact** (< 5% CPU): - Color filters - Greyscale - Invert - Flip/Mirror **Medium Impact** (5-15% CPU): - Text/graphic overlays - Contrast/brightness - Posterize - Simple deinterlacing **High Impact** (15-40% CPU): - Blur (large radius) - Denoise (CAST, adaptive) - Mosaic (small blocks) - Marble/artistic effects ### Optimization Tips 1. **Limit simultaneous effects** - Each effect adds processing time 2. **Use appropriate parameters** - Larger blur radius = more CPU 3. **Disable unused effects** - Set `Enabled = FALSE` instead of removing 4. **Process at lower resolution** - Downscale, apply effects, upscale 5. **Use GPU rendering when possible** - Check for GPU-accelerated effects --- ## Common Effect Combinations ### Webcam Enhancement ``` 1. ef_denoise_adaptive (threshold: 15) 2. ef_contrast (amount: +10) 3. ef_saturation (amount: +15) 4. ef_flip_right (mirror mode) ``` ### Vintage Film Look ``` 1. ef_greyscale 2. ef_contrast (amount: +20) 3. ef_mono_noise (amount: 15) ``` ### Broadcast Quality ``` 1. ef_deint_cavt 2. ef_denoise_mosquito (amount: 20) 3. ef_saturation (amount: +5) ``` ### Privacy Mode ``` 1. ef_mosaic (size: 20) on specific region 2. ef_blur (amount: 80) as alternative ``` --- ## See Also - [Processing Filters Pack Overview](../) - [Video Effects Interface Reference](../interfaces/effects-interface/) - [Chroma Key Interface](../interfaces/chroma-key/) - [Video Mixer Interface](../interfaces/video-mixer/) - [Code Examples](../examples/) ---END OF PAGE--- ## DirectShow Video Effects, Mixer, and Chroma Key Examples **URL:** https://www.visioforge.com/help/docs/directshow/proc-filters/examples/ **Description:** Code examples for Video Effects, Video Mixer, and Chroma Key filters in C++, C#, and VB.NET with DirectShow integration. **Tags:** DirectShow, C++, Windows, Effects, Mixing, C# **API:** IBaseFilter, IVFChromaKey, IVFVideoMixer # Processing Filters Pack - Code Examples ## Overview This page provides practical code examples for using the Processing Filters Pack, which includes: - **Video Effects** - 35+ real-time effects (text, graphics, color adjustments, denoise) - **Video Mixer** - 2-16 source mixing with PIP, alpha blending, chroma key - **Chroma Key** - Green/blue screen compositing --- ## Prerequisites ### C++ Projects ``` #include #include #include "IVFEffects45.h" #include "IVFVideoMixer.h" #include "IVFChromaKey.h" #pragma comment(lib, "strmiids.lib") ``` ### C# Projects ``` using VisioForge.DirectShowAPI; using VisioForge.DirectShowLib; using System.Runtime.InteropServices; using System.Drawing; ``` **NuGet Packages**: - VisioForge.DirectShowAPI - MediaFoundationCore --- ## Video Effects Examples ### Example 1: Basic Video Effect Apply a single video effect to a source. #### C# Implementation ``` using System; using System.Runtime.InteropServices; using VisioForge.DirectShowAPI; using VisioForge.DirectShowLib; public class VideoEffectsBasicExample { private IFilterGraph2 filterGraph; private IMediaControl mediaControl; private IBaseFilter sourceFilter; private IBaseFilter effectFilter; public void PlayWithEffect(string filename, IntPtr videoWindowHandle) { filterGraph = (IFilterGraph2)new FilterGraph(); mediaControl = (IMediaControl)filterGraph; // Add source filter (e.g., File Source) filterGraph.AddSourceFilter(filename, "Source", out sourceFilter); // Add Video Effects filter effectFilter = FilterGraphTools.AddFilterFromClsid( filterGraph, Consts.CLSID_VFVideoEffects, "Video Effects"); // Configure effect using IVFEffects45 interface var effects = effectFilter as IVFEffects45; if (effects != null) { // Enable Greyscale effect via VideoEffectSimple struct var eff = new VideoEffectSimple { Type = (int)VideoEffectType.Greyscale, Enabled = true }; effects.add_effect(eff); } captureGraph.SetFiltergraph(filterGraph); // Render through effect filter captureGraph.RenderStream(null, MediaType.Video, sourceFilter, effectFilter, null); captureGraph.RenderStream(null, MediaType.Audio, sourceFilter, null, null); // Set up video window var videoWindow = (IVideoWindow)filterGraph; videoWindow.put_Owner(videoWindowHandle); videoWindow.put_WindowStyle(WindowStyle.Child | WindowStyle.ClipSiblings); // Run mediaControl.Run(); Marshal.ReleaseComObject(captureGraph); } public void Stop() { mediaControl?.Stop(); FilterGraphTools.RemoveAllFilters(filterGraph); if (sourceFilter != null) Marshal.ReleaseComObject(sourceFilter); if (effectFilter != null) Marshal.ReleaseComObject(effectFilter); if (mediaControl != null) Marshal.ReleaseComObject(mediaControl); if (filterGraph != null) Marshal.ReleaseComObject(filterGraph); } } ``` #### C++ Implementation ``` HRESULT ApplyVideoEffect(LPCWSTR filename) { IGraphBuilder* pGraph = NULL; IBaseFilter* pSource = NULL; IBaseFilter* pEffect = NULL; IVFEffects45* pEffects = NULL; // Create filter graph HRESULT hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void**)&pGraph); if (FAILED(hr)) return hr; // Add source hr = pGraph->AddSourceFilter(filename, L"Source", &pSource); if (FAILED(hr)) goto cleanup; // Create Video Effects filter hr = CoCreateInstance(CLSID_VFVideoEffects, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void**)&pEffect); if (FAILED(hr)) goto cleanup; hr = pGraph->AddFilter(pEffect, L"Video Effects"); if (FAILED(hr)) goto cleanup; // Configure effect hr = pEffect->QueryInterface(IID_IVFEffects45, (void**)&pEffects); if (SUCCEEDED(hr)) { // Enable greyscale via VideoEffectSimple struct VideoEffectSimple effect; ZeroMemory(&effect, sizeof(effect)); effect.Type = ef_greyscale; effect.Enabled = TRUE; pEffects->add_effect(&effect); pEffects->Release(); } // Connect filters and render... // (Use RenderStream or ConnectFilters) cleanup: if (pEffect) pEffect->Release(); if (pSource) pSource->Release(); if (pGraph) pGraph->Release(); return hr; } ``` --- ### Example 2: Multiple Effects Chain Apply multiple effects simultaneously. #### C# Multiple Effects ## ``` public class MultipleEffectsExample { public void ApplyMultipleEffects(IBaseFilter effectFilter) { var effects = effectFilter as IVFEffects45; if (effects != null) { // Add darkness/brightness effect (VideoEffectType.Darkness, AmountI controls level) effects.add_effect(new VideoEffectSimple { Type = (int)VideoEffectType.Darkness, Enabled = true, AmountI = 50 // 0 = darkest, 100 = brightest }); // Add contrast effect (AmountI controls intensity) effects.add_effect(new VideoEffectSimple { Type = (int)VideoEffectType.Contrast, Enabled = true, AmountI = 75 // Contrast intensity }); // Add saturation effect (AmountI controls saturation level) effects.add_effect(new VideoEffectSimple { Type = (int)VideoEffectType.Saturation, Enabled = true, AmountI = 120 // Saturation level }); } } } ``` ### Example 3: Text Overlay Add text logo overlay to video. #### C# Text Overlay ``` public void ApplyTextOverlay(IBaseFilter effectFilter) { var effects = effectFilter as IVFEffects45; if (effects != null) { var eff = new VideoEffectSimple { Type = (int)VideoEffectType.TextLogo, Enabled = true, TextLogo = new MFPTextLogo { X = 50, Y = 50, Text = "My Video Title", FontName = "Arial", FontSize = 36, FontColor = 0xFFFFFF, // White FontBold = true, TransparentBg = true, Transp = 255, // Fully opaque BorderMode = 4, // bm_outline OuterBorderColor = 0x000000, // Black outline OuterBorderSize = 2 } }; effects.add_effect(eff); } } ``` See [effects-reference.md](../effects-reference/) for the full `MFPTextLogo` structure (text alignment, gradient, date/time display, anti-aliasing, etc.). --- ### Example 4: Image Overlay Add graphic watermark or logo. #### C# Image Overlay ``` public void ApplyImageOverlay(IBaseFilter effectFilter, string imagePath) { var effects = effectFilter as IVFEffects45; if (effects != null) { var eff = new VideoEffectSimple { Type = (int)VideoEffectType.ImageLogo, Enabled = true, GraphicalLogo = new MFPGraphicalLogo { X = 10, // X position in pixels Y = 10, // Y position in pixels Filename = imagePath, TranspLevel = 200, // Semi-transparent (0-255) StretchMode = 2 // 0=None, 1=Stretch, 2=Proportional fit } }; effects.add_effect(eff); } } ``` ## See [effects-reference.md](../effects-reference/) for the full `MFPGraphicalLogo` structure. ### Example 5: Denoise Filters Apply noise reduction for cleaner video. #### C# Denoise Examples ``` public void ApplyDenoise(IBaseFilter effectFilter, VideoEffectType denoiseType) { var effects = effectFilter as IVFEffects45; if (effects != null) { var eff = new VideoEffectSimple { Type = (int)denoiseType, Enabled = true }; switch (denoiseType) { case VideoEffectType.DenoiseCAST: // CAST denoise — configure via DenoiseCAST sub-struct eff.DenoiseCAST = new MFPDenoiseCAST { TemporalDifferenceThreshold = 16, StrongEdgeThreshold = 8 }; break; case VideoEffectType.DenoiseAdaptive: // Adaptive denoise — threshold controls sensitivity eff.DenoiseAdaptiveThreshold = 20; // 0-255 eff.DenoiseAdaptiveBlurMode = 0; // 0-3 break; case VideoEffectType.DenoiseMosquito: // Mosquito denoise — AmountI controls reduction strength eff.AmountI = 30; break; } effects.add_effect(eff); } } ``` --- ### Example 6: All Available Effects Complete list of effects with basic configuration. #### C# All Effects Reference ``` public class AllEffectsExample { public void DemonstrateAllEffects(IBaseFilter effectFilter) { var effects = effectFilter as IVFEffects45; if (effects == null) return; // Color Filters effects.add_effect(new VideoEffectSimple { Type = (int)VideoEffectType.Greyscale, Enabled = true }); effects.add_effect(new VideoEffectSimple { Type = (int)VideoEffectType.Invert, Enabled = true }); effects.add_effect(new VideoEffectSimple { Type = (int)VideoEffectType.FilterRed, Enabled = true }); effects.add_effect(new VideoEffectSimple { Type = (int)VideoEffectType.FilterGreen, Enabled = true }); effects.add_effect(new VideoEffectSimple { Type = (int)VideoEffectType.FilterBlue, Enabled = true }); // Image Adjustment (AmountI controls intensity) effects.add_effect(new VideoEffectSimple { Type = (int)VideoEffectType.Darkness, Enabled = true, AmountI = 50 }); effects.add_effect(new VideoEffectSimple { Type = (int)VideoEffectType.Contrast, Enabled = true, AmountI = 75 }); effects.add_effect(new VideoEffectSimple { Type = (int)VideoEffectType.Saturation, Enabled = true, AmountI = 120 }); effects.add_effect(new VideoEffectSimple { Type = (int)VideoEffectType.Lightness, Enabled = true, AmountI = 45 }); // Spatial Transforms effects.add_effect(new VideoEffectSimple { Type = (int)VideoEffectType.FlipRight, Enabled = true }); effects.add_effect(new VideoEffectSimple { Type = (int)VideoEffectType.FlipDown, Enabled = true }); effects.add_effect(new VideoEffectSimple { Type = (int)VideoEffectType.MirrorHorizontal, Enabled = true }); effects.add_effect(new VideoEffectSimple { Type = (int)VideoEffectType.Rotate, Enabled = true, AmountI = 90 }); // Artistic Effects effects.add_effect(new VideoEffectSimple { Type = (int)VideoEffectType.Blur, Enabled = true, AmountI = 5 }); effects.add_effect(new VideoEffectSimple { Type = (int)VideoEffectType.Sharpen, Enabled = true, AmountI = 2 }); effects.add_effect(new VideoEffectSimple { Type = (int)VideoEffectType.Posterize, Enabled = true, AmountI = 8 }); effects.add_effect(new VideoEffectSimple { Type = (int)VideoEffectType.Solorize, Enabled = true, AmountI = 128 }); effects.add_effect(new VideoEffectSimple { Type = (int)VideoEffectType.Mosaic, Enabled = true, SizeI = 10 }); // Noise Reduction effects.add_effect(new VideoEffectSimple { Type = (int)VideoEffectType.DenoiseCAST, Enabled = true }); effects.add_effect(new VideoEffectSimple { Type = (int)VideoEffectType.DenoiseAdaptive, Enabled = true, DenoiseAdaptiveThreshold = 20 }); effects.add_effect(new VideoEffectSimple { Type = (int)VideoEffectType.DenoiseMosquito, Enabled = true, AmountI = 30 }); // Deinterlacing effects.add_effect(new VideoEffectSimple { Type = (int)VideoEffectType.DeinterlaceBlend, Enabled = true }); effects.add_effect(new VideoEffectSimple { Type = (int)VideoEffectType.DeinterlaceTriangle, Enabled = true }); effects.add_effect(new VideoEffectSimple { Type = (int)VideoEffectType.DeinterlaceCAVT, Enabled = true }); // Overlays (TextLogo/ImageLogo need sub-struct — see Examples 3 & 4) // To disable/remove an effect: // effects.remove_effect(effectId); // effects.clear_effects(); } } ``` > **Note:** For the full list of `VideoEffectType` members and sub-struct parameters, see [effects-reference.md](../effects-reference/). --- ## Video Mixer Examples ### Example 7: Picture-in-Picture (PIP) Mix two video sources with PIP layout. #### C# Picture-in-Picture ``` public class VideoMixerPIPExample { private IFilterGraph2 filterGraph; private IBaseFilter mixerFilter; public void CreatePIP(string mainVideoPath, string pipVideoPath, IntPtr videoWindowHandle) { filterGraph = (IFilterGraph2)new FilterGraph(); // Add main video source filterGraph.AddSourceFilter(mainVideoPath, "Main Source", out IBaseFilter mainSource); // Add PIP video source filterGraph.AddSourceFilter(pipVideoPath, "PIP Source", out IBaseFilter pipSource); // Add Video Mixer filter mixerFilter = FilterGraphTools.AddFilterFromClsid( filterGraph, Consts.CLSID_VFVideoMixer, "Video Mixer"); // Configure mixer — real IVFVideoMixer interface var mixer = mixerFilter as IVFVideoMixer; if (mixer != null) { // Set output size mixer.SetOutputParam(new VFPIPVideoOutputParam { Width = 1920, Height = 1080, FrameRateTime = 30 }); // Configure main video (input 0) - fullscreen mixer.SetInputParam(0, new VFPIPVideoInputParam { X = 0, Y = 0, Width = 1920, Height = 1080, Alpha = 255 }); // Configure PIP video (input 1) - bottom-right corner mixer.SetInputParam(1, new VFPIPVideoInputParam { X = 1440, // 1920 - 480 Y = 810, // 1080 - 270 Width = 480, Height = 270, Alpha = 255 }); // Set Z-order (layering) — per-pin, not bulk array mixer.SetInputOrder(0, 0); // Main behind mixer.SetInputOrder(1, 1); // PIP on top } // Connect filters ICaptureGraphBuilder2 captureGraph = (ICaptureGraphBuilder2)new CaptureGraphBuilder2(); captureGraph.SetFiltergraph(filterGraph); // Connect main source to mixer input 0 captureGraph.RenderStream(null, MediaType.Video, mainSource, null, mixerFilter); // Connect PIP source to mixer input 1 // Note: Requires connecting to specific input pin IPin mixerInput1 = DsFindPin.ByDirection(mixerFilter, PinDirection.Input, 1); captureGraph.RenderStream(null, MediaType.Video, pipSource, null, null); // Connect to mixerInput1 explicitly... // Render mixer output captureGraph.RenderStream(null, MediaType.Video, mixerFilter, null, null); // Setup video window var videoWindow = (IVideoWindow)filterGraph; videoWindow.put_Owner(videoWindowHandle); videoWindow.put_WindowStyle(WindowStyle.Child | WindowStyle.ClipSiblings); // Run var mediaControl = (IMediaControl)filterGraph; mediaControl.Run(); Marshal.ReleaseComObject(captureGraph); } } ``` --- ### Example 8: Multi-Source Mixing (4 inputs) Create a 2x2 grid layout with 4 video sources. #### C# 2x2 Grid Layout ## ``` public class VideoMixerGridExample { public void Create2x2Grid(string[] videoPaths, IntPtr videoWindowHandle) { if (videoPaths.Length != 4) { throw new ArgumentException("Requires exactly 4 video sources"); } var filterGraph = (IFilterGraph2)new FilterGraph(); // Add all source filters IBaseFilter[] sources = new IBaseFilter[4]; for (int i = 0; i < 4; i++) { filterGraph.AddSourceFilter(videoPaths[i], $"Source {i}", out sources[i]); } // Add Video Mixer var mixerFilter = FilterGraphTools.AddFilterFromClsid( filterGraph, Consts.CLSID_VFVideoMixer, "Video Mixer"); var mixer = mixerFilter as IVFVideoMixer; if (mixer != null) { // Set output size mixer.SetOutputParam(new VFPIPVideoOutputParam { Width = 1920, Height = 1080, FrameRateTime = 30 }); int halfWidth = 960; // 1920 / 2 int halfHeight = 540; // 1080 / 2 // Top-left (Input 0) mixer.SetInputParam(0, new VFPIPVideoInputParam { X = 0, Y = 0, Width = halfWidth, Height = halfHeight, Alpha = 255 }); // Top-right (Input 1) mixer.SetInputParam(1, new VFPIPVideoInputParam { X = halfWidth, Y = 0, Width = halfWidth, Height = halfHeight, Alpha = 255 }); // Bottom-left (Input 2) mixer.SetInputParam(2, new VFPIPVideoInputParam { X = 0, Y = halfHeight, Width = halfWidth, Height = halfHeight, Alpha = 255 }); // Bottom-right (Input 3) mixer.SetInputParam(3, new VFPIPVideoInputParam { X = halfWidth, Y = halfHeight, Width = halfWidth, Height = halfHeight, Alpha = 255 }); // Set Z-order (per-pin) for (int i = 0; i < 4; i++) { mixer.SetInputOrder(i, i); } } // Connect sources to mixer and render... // (Similar to PIP example) var mediaControl = (IMediaControl)filterGraph; mediaControl.Run(); } } ``` ### Example 9: Video Mixer with Chroma Key Mix sources with transparent background. #### C# Mixer with Chroma Key ``` public void CreateMixerWithChromaKey(string backgroundPath, string foregroundPath) { var filterGraph = (IFilterGraph2)new FilterGraph(); // Add sources filterGraph.AddSourceFilter(backgroundPath, "Background", out IBaseFilter bgSource); filterGraph.AddSourceFilter(foregroundPath, "Foreground", out IBaseFilter fgSource); // Add mixer var mixerFilter = FilterGraphTools.AddFilterFromClsid( filterGraph, Consts.CLSID_VFVideoMixer, "Video Mixer"); var mixer = mixerFilter as IVFVideoMixer; if (mixer != null) { // Configure output mixer.SetOutputParam(new VFPIPVideoOutputParam { Width = 1920, Height = 1080 }); // Background (fullscreen) mixer.SetInputParam(0, new VFPIPVideoInputParam { X = 0, Y = 0, Width = 1920, Height = 1080 }); // Foreground (centered, smaller) mixer.SetInputParam(1, new VFPIPVideoInputParam { X = 480, Y = 270, Width = 960, Height = 540 }); // Enable chroma key — mixer-wide, 4 args mixer.SetChromaSettings( enabled: true, color: ColorTranslator.ToWin32(Color.FromArgb(0, 255, 0)), // Green tolerance1: 50, tolerance2: 10); } // Connect and run... } ``` --- ## Chroma Key Examples ### Example 10: Green Screen Effect Standalone chroma key filter for green screen removal. #### C# Chroma Key Filter ``` public class ChromaKeyExample { public void ApplyGreenScreen(string videoPath, string backgroundImagePath, IntPtr videoWindowHandle) { var filterGraph = (IFilterGraph2)new FilterGraph(); // Add video source (with green screen) filterGraph.AddSourceFilter(videoPath, "Source", out IBaseFilter sourceFilter); // Add Chroma Key filter var chromaFilter = FilterGraphTools.AddFilterFromClsid( filterGraph, Consts.CLSID_VFChromaKey, "Chroma Key"); // Configure chroma key — real IVFChromaKey API var chromaKey = chromaFilter as IVFChromaKey; if (chromaKey != null) { // Set key color (green) — single int using RGB macro chromaKey.put_color(ColorTranslator.ToWin32(Color.FromArgb(0, 255, 0))); // Set contrast range (low, high bounds) chromaKey.put_contrast(50, 100); // Set background image (optional) if (!string.IsNullOrEmpty(backgroundImagePath)) { chromaKey.put_image(backgroundImagePath); } } // Connect filters: Source → Chroma Key → Renderer ICaptureGraphBuilder2 captureGraph = (ICaptureGraphBuilder2)new CaptureGraphBuilder2(); captureGraph.SetFiltergraph(filterGraph); captureGraph.RenderStream(null, MediaType.Video, sourceFilter, chromaFilter, null); captureGraph.RenderStream(null, MediaType.Audio, sourceFilter, null, null); // Setup video window var videoWindow = (IVideoWindow)filterGraph; videoWindow.put_Owner(videoWindowHandle); videoWindow.put_WindowStyle(WindowStyle.Child | WindowStyle.ClipSiblings); // Run var mediaControl = (IMediaControl)filterGraph; mediaControl.Run(); Marshal.ReleaseComObject(captureGraph); } } ``` #### C++ Chroma Key ## ``` HRESULT ApplyChromaKey(IBaseFilter* pChromaFilter) { IVFChromaKey* pChromaKey = NULL; HRESULT hr = pChromaFilter->QueryInterface(IID_IVFChromaKey, (void**)&pChromaKey); if (FAILED(hr)) return hr; // Set green color — single COLORREF argument: RGB(0, 255, 0) hr = pChromaKey->put_color(RGB(0, 255, 0)); if (FAILED(hr)) goto cleanup; // Set contrast range (low, high) hr = pChromaKey->put_contrast(40, 90); if (FAILED(hr)) goto cleanup; // Optional: Set background image hr = pChromaKey->put_image(L"C:\\backgrounds\\studio.jpg"); cleanup: pChromaKey->Release(); return hr; } ``` ### Example 11: Blue Screen with Fine Tuning Configure blue screen chroma key with optimal settings. #### C# Blue Screen ``` public void ApplyBlueScreen(IBaseFilter chromaFilter) { var chromaKey = chromaFilter as IVFChromaKey; if (chromaKey != null) { // Set blue color — single int via RGB chromaKey.put_color(ColorTranslator.ToWin32(Color.FromArgb(0, 0, 255))); // Fine-tuned contrast range for blue screen // Lower low = more strict (less tolerance) // Higher high = more loose (more tolerance) chromaKey.put_contrast(30, 80); } } ``` --- ### Example 12: Custom Color Chroma Key Use any custom color for keying. #### C# Custom Color Key ## ``` public void ApplyCustomColorKey(IBaseFilter chromaFilter, Color keyColor) { var chromaKey = chromaFilter as IVFChromaKey; if (chromaKey != null) { // Use any custom color — single int via RGB chromaKey.put_color(ColorTranslator.ToWin32(keyColor)); // Standard contrast range chromaKey.put_contrast(50, 100); } } // Example usage: // ApplyCustomColorKey(chromaFilter, Color.Magenta); // Magenta screen // ApplyCustomColorKey(chromaFilter, Color.FromArgb(255, 180, 0, 220)); // Custom purple ``` ## Complete Processing Pipeline ### Example 13: Combined Effects, Mixing, and Chroma Key Complete example combining all processing filters. #### C# Complete Pipeline ``` public class CompleteProcessingPipeline { public void CreateCompleteSetup( string mainVideoPath, string greenScreenVideoPath, string backgroundImagePath, IntPtr videoWindowHandle) { var filterGraph = (IFilterGraph2)new FilterGraph(); // 1. Main video source filterGraph.AddSourceFilter(mainVideoPath, "Main Video", out IBaseFilter mainSource); // 2. Green screen video source filterGraph.AddSourceFilter(greenScreenVideoPath, "Green Screen", out IBaseFilter gsSource); // 3. Add Chroma Key filter for green screen var chromaFilter = FilterGraphTools.AddFilterFromClsid( filterGraph, Consts.CLSID_VFChromaKey, "Chroma Key"); var chromaKey = chromaFilter as IVFChromaKey; if (chromaKey != null) { chromaKey.put_color(ColorTranslator.ToWin32(Color.FromArgb(0, 255, 0))); // Green chromaKey.put_contrast(40, 90); } // 4. Add Video Effects filter var effectsFilter = FilterGraphTools.AddFilterFromClsid( filterGraph, Consts.CLSID_VFVideoEffects, "Video Effects"); var effects = effectsFilter as IVFEffects45; if (effects != null) { // Apply effects via VideoEffectSimple structs effects.add_effect(new VideoEffectSimple { Type = (int)VideoEffectType.Darkness, Enabled = true, AmountI = 60 }); effects.add_effect(new VideoEffectSimple { Type = (int)VideoEffectType.Contrast, Enabled = true, AmountI = 80 }); // Add text overlay effects.add_effect(new VideoEffectSimple { Type = (int)VideoEffectType.TextLogo, Enabled = true, TextLogo = new MFPTextLogo { Text = "LIVE", FontSize = 48, X = 50, Y = 50, FontColor = 0xFFFFFF, FontBold = true } }); } // 5. Add Video Mixer var mixerFilter = FilterGraphTools.AddFilterFromClsid( filterGraph, Consts.CLSID_VFVideoMixer, "Video Mixer"); var mixer = mixerFilter as IVFVideoMixer; if (mixer != null) { mixer.SetOutputParam(new VFPIPVideoOutputParam { Width = 1920, Height = 1080, FrameRateTime = 30 }); // Main video (fullscreen background) mixer.SetInputParam(0, new VFPIPVideoInputParam { X = 0, Y = 0, Width = 1920, Height = 1080 }); // Chroma-keyed video (PIP) mixer.SetInputParam(1, new VFPIPVideoInputParam { X = 1200, Y = 700, Width = 640, Height = 360 }); // Set Z-order (per-pin) mixer.SetInputOrder(0, 0); mixer.SetInputOrder(1, 1); } // Connect the pipeline: // Main Source → Effects → Mixer Input 0 // GS Source → Chroma Key → Mixer Input 1 // Mixer → Renderer ICaptureGraphBuilder2 captureGraph = (ICaptureGraphBuilder2)new CaptureGraphBuilder2(); captureGraph.SetFiltergraph(filterGraph); // Connect main path captureGraph.RenderStream(null, MediaType.Video, mainSource, effectsFilter, mixerFilter); // Connect chroma key path // (Requires pin-level connections to specific mixer input) // Render mixer output captureGraph.RenderStream(null, MediaType.Video, mixerFilter, null, null); // Audio captureGraph.RenderStream(null, MediaType.Audio, mainSource, null, null); // Setup video window var videoWindow = (IVideoWindow)filterGraph; videoWindow.put_Owner(videoWindowHandle); videoWindow.put_WindowStyle(WindowStyle.Child | WindowStyle.ClipSiblings); // Run var mediaControl = (IMediaControl)filterGraph; mediaControl.Run(); Marshal.ReleaseComObject(captureGraph); } } ``` --- ## Troubleshooting ### Issue: Effect Not Visible **Solution**: Ensure effect is enabled and parameters are set on the VideoEffectSimple struct: ``` var eff = new VideoEffectSimple { Type = (int)VideoEffectType.Darkness, Enabled = true, AmountI = 75 }; effects.add_effect(eff); ``` ### Issue: Chroma Key Not Working Well **Solution**: Adjust contrast thresholds: ``` // For difficult green screens: chromaKey.put_contrast(30, 70); // Tighter range // For well-lit green screens: chromaKey.put_contrast(50, 110); // Wider range ``` ### Issue: Video Mixer Inputs Not Showing **Solution**: Verify input parameters and Z-order: ``` // Ensure inputs are on-screen via VFPIPVideoInputParam struct mixer.SetInputParam(0, new VFPIPVideoInputParam { X = 0, Y = 0, Width = 640, Height = 480 }); // Set Z-order per-pin mixer.SetInputOrder(0, 0); // Input 0 at layer 0 mixer.SetInputOrder(1, 1); // Input 1 at layer 1 ``` --- ## See Also ### Documentation - [Effects Reference](../effects-reference/) - Complete effects list - [Video Mixer Interface](../interfaces/video-mixer/) - Full API reference - [Chroma Key Interface](../interfaces/chroma-key/) - Complete interface docs ### External Resources - [DirectShow Filter Graph](https://learn.microsoft.com/en-us/windows/win32/directshow/building-the-filter-graph) ---END OF PAGE--- ## Real-Time Video Processing Filters for DirectShow Apps **URL:** https://www.visioforge.com/help/docs/directshow/proc-filters/ **Description:** Add 35+ real-time video effects, multi-source video mixer (2-16 inputs), chroma key, deinterlacing, and noise reduction to Windows apps. VisioForge COM filters. **Tags:** DirectShow, C++, Windows # DirectShow Processing Filters for Media Applications ## Introduction to DirectShow Processing Filters The DirectShow Processing Filters Pack delivers a powerful collection of specialized filters built for sophisticated audio and video manipulation in Windows applications. These filters enable developers to implement professional-grade media processing capabilities without developing complex algorithms from scratch. Designed for developers seeking to enhance their applications with advanced media functionality, this toolkit offers a streamlined approach to implementing robust audio-visual features with minimal code overhead. --- ## Installation Before using the code samples and integrating the filters into your application, you must first install the DirectShow Processing Filters Pack from the [product page](https://www.visioforge.com/processing-filters-pack). **Installation Steps**: 1. Download the Processing Filters Pack installer from the product page 2. Run the installer with administrative privileges 3. The installer will register all processing filters 4. Sample applications and source code will be available in the installation directory **Note**: All filters must be properly registered on the system before they can be used in your applications. The installer handles this automatically. --- ## Key Capabilities and Benefits ### Video Processing Capabilities #### Advanced Visual Effects - **Dynamic Effects Processing**: Apply real-time effects to video streams including blur, sharpen, sepia, grayscale, and numerous artistic filters - **Custom Effect Chaining**: Combine multiple effects sequentially for complex visual transformations - **Adjustable Parameters**: Fine-tune effect intensity and characteristics for precise control #### Professional Video Mixing - **Multi-Source Blending**: Seamlessly combine multiple video streams into a unified output - **Transition Effects**: Implement smooth transitions between video sources - **Picture-in-Picture**: Create overlay configurations with customizable positioning and scaling #### Image and Text Overlay System - **Dynamic Text Rendering**: Overlay customizable text with font control and animation - **Image Integration**: Add logos, watermarks, and informational graphics to video content - **Alpha Channel Support**: Maintain transparency information for professional compositing #### High-Quality Resize Functionality - **Multiple Algorithms**: Choose from nearest neighbor, bilinear, bicubic, and Lanczos scaling - **Aspect Ratio Control**: Maintain or adjust aspect ratios as needed - **Resolution Optimization**: Scale content for specific output requirements while preserving quality #### Video Manipulation Tools - **Rotation and Cropping**: Adjust video orientation and framing with precise control - **Deinterlacing Options**: Multiple modes available for converting interlaced content - **Noise Reduction**: Advanced algorithms for improving video clarity and quality ### Audio Processing Capabilities #### Audio Enhancement Suite - **Effect Processing**: Apply various audio effects for sound enhancement and creative manipulation - **Channel Management**: Control stereo imaging and multi-channel configurations #### Advanced Audio Controls - **Volume Optimization**: Precise volume adjustment with normalization options - **Balance Adjustment**: Fine-tune left/right channel balance for optimal sound distribution - **Pitch Modification**: Alter pitch while maintaining or changing tempo - **Delay Implementation**: Add customizable delay effects with feedback control #### Professional Sound Effects - **Echo Generation**: Create spatial echo effects with adjustable parameters - **Equalizer System**: Multi-band equalization for frequency adjustment - **Chorus Effects**: Add richness and depth to audio streams - **Flanger Processing**: Create sweeping, psychedelic audio effects ## System Requirements ### Compatible Operating Systems - Windows 11, 10, 8.1, 8, and 7 (both 32-bit and 64-bit versions) ### Development Environment Support - **Microsoft Visual Studio**: Versions 2022, 2019, 2017, 2015, 2013, 2012, and 2010 - **Embarcadero Tools**: Compatible with Delphi and C++ Builder - **Additional Environments**: Works with any development platform supporting DirectShow filters ### Technical Prerequisites - DirectX 9 or later installation - Minimum 4GB RAM (8GB+ recommended for high-resolution processing) - Multi-core processor recommended for optimal performance ## Additional Resources - [Complete Product Information](https://www.visioforge.com/processing-filters-pack) - [API Documentation](https://api.visioforge.org/proc_filters/api/index.html) - [Licensing Information](../../eula/) ## Version History and Updates ### Version 15.1 Enhancements - Integration with .Net SDKs 15.1 architecture - Significant improvements to audio and video mixing engines - Enhanced multithreading support for better performance on multi-core systems - Expanded video effects library with new processing options - Resolution of audio click artifacts in mixer component - Optimized support for ultra-high-definition 4K and 8K content processing ### Version 15.0 Improvements - Full alignment with .Net SDKs 15.0 framework - Optimized high-resolution processing for brightness, contrast, saturation, and hue filters ### Version 14.0 Updates - Complete compatibility with .Net SDKs 14.0 - Performance optimization for video resize operations - Enhanced bicubic video resize algorithm for superior quality ### Version 12.0 Refinements - Integration with .Net SDKs 12.0 infrastructure - Redesigned audio mixer with improved performance - Fixed stability issues when using crop or resize with incorrect parameters ### Version 11.0 Features - Updated to match .Net SDKs 11.0 specifications - Improved audio tempo and pitch manipulation algorithms - Optimized video balance performance for smoother processing ### Version 10.0 Developments - Alignment with .Net SDKs 10.0 architecture - Completely revamped Video Mixer component ### Version 9.0 Advancements - Integration with .Net SDKs 9.2 framework - Enhanced video effects library - Specific optimizations for 4K content processing ### Version 8.5 Initial Release - First public release, featuring filters from .Net SDKs 8.5 - Introduction of Lanczos support in video resize filter for superior quality scaling ---END OF PAGE--- ## Chroma Key DirectShow Filter - IVFChromaKey Interface **URL:** https://www.visioforge.com/help/docs/directshow/proc-filters/interfaces/chroma-key/ **Description:** IVFChromaKey interface for green screen and blue screen compositing with tolerance control and background replacement in DirectShow. **Tags:** DirectShow, C++, Windows, Effects, Mixing, C# **API:** IVFChromaKey, CVFChromaColor, IBaseFilter, IVFVideoMixer, IVFEffectsPro # IVFChromaKey Interface Reference ## Overview The `IVFChromaKey` interface provides professional chroma key (green screen/blue screen) compositing capabilities for DirectShow applications. This interface enables real-time background replacement by making specific colors transparent, allowing subjects filmed in front of colored backdrops to be composited over different backgrounds. Chroma keying is essential for virtual production, weather forecasting, video effects, and any scenario where background replacement is needed. ## Interface Definition - **Interface Name**: `IVFChromaKey` - **GUID**: `{AF6E8208-30E3-44f0-AAFE-787A6250BAB3}` - **Inherits From**: `IUnknown` - **Header File**: `vf_eff_intf.h` (C++), `IVFChromaKey.cs` (.NET) ## Capabilities - **Color Keys**: Green, blue, red, or custom RGB colors - **Contrast Adjustment**: Separate low/high contrast thresholds - **Background Replacement**: Static image or video background - **Real-Time Processing**: Hardware-accelerated when available - **Edge Quality**: Adjustable tolerance for smooth edges --- ## Methods Reference ### Contrast Threshold Configuration #### chroma\_put\_contrast Sets the contrast threshold range for chroma keying. **Syntax (C++)**: ``` HRESULT chroma_put_contrast(int low, int high); ``` **Syntax (C#)**: ``` [PreserveSig] int chroma_put_contrast(int low, int high); ``` **Parameters**: - `low`: Low contrast threshold (0-255) - Lower values = remove more similar colors - Higher values = stricter color matching - `high`: High contrast threshold (0-255) - Defines the upper bound for color matching - Creates a range of acceptable key colors **Returns**: `S_OK` (0) on success. **Usage Notes**: - These values define the color similarity range for keying - The range between `low` and `high` creates a gradient for edge smoothing - Typical ranges: - Tight keying: low=10, high=30 - Standard keying: low=30, high=70 - Loose keying: low=50, high=120 - Adjust based on lighting conditions and backdrop quality **How It Works**: ``` Pixels with chroma distance < low → Fully transparent Pixels with chroma distance > high → Fully opaque Pixels between low and high → Partially transparent (gradient) ``` **Example (C++)**: ``` IVFChromaKey* pChroma = nullptr; pFilter->QueryInterface(IID_IVFChromaKey, (void**)&pChroma); // Standard green screen configuration pChroma->chroma_put_contrast(40, 80); pChroma->Release(); ``` **Example (C#)**: ``` var chroma = filter as IVFChromaKey; if (chroma != null) { // Tight keying for clean green screen chroma.chroma_put_contrast(20, 50); } ``` --- ### Color Selection #### chroma\_put\_color Sets the chroma key color to be made transparent. **Syntax (C++)**: ``` HRESULT chroma_put_color(int color); ``` **Syntax (C#)**: ``` [PreserveSig] int chroma_put_color(int color); ``` **Parameters**: - `color`: Chroma key color value **Color Values** (CVFChromaColor enumeration): | Value | Color | RGB Equivalent | Use Case | | --- | --- | --- | --- | | `0` (Chroma\_Green) | Green | 0x00FF00 | Standard chroma key (most common) | | `1` (Chroma\_Blue) | Blue | 0x0000FF | Alternative to green | | `2` (Chroma\_Red) | Red | 0xFF0000 | Special cases | | Custom RGB | Any color | 0xRRGGBB | Specific color matching | **Returns**: `S_OK` (0) on success. **Usage Notes**: - Green is standard for chroma keying (human skin has least green) - Blue used when green objects are in scene - Can use custom RGB value for specific color matching - Color should be uniform across backdrop for best results **Example (C++)**: ``` // Use green chroma key pChroma->chroma_put_color(Chroma_Green); // Use blue chroma key pChroma->chroma_put_color(Chroma_Blue); // Use custom color (e.g., magenta) pChroma->chroma_put_color(0xFF00FF); ``` **Example (C#)**: ``` // Standard green screen chroma.chroma_put_color((int)CVFChromaColor.Chroma_Green); // Blue screen chroma.chroma_put_color((int)CVFChromaColor.Chroma_Blue); // Custom yellow-green chroma.chroma_put_color(0x88FF00); ``` --- ### Background Image #### chroma\_put\_image Sets a replacement background image for transparent areas. **Syntax (C++)**: ``` HRESULT chroma_put_image(BSTR filename); ``` **Syntax (C#)**: ``` [PreserveSig] int chroma_put_image([MarshalAs(UnmanagedType.BStr)] string filename); ``` **Parameters**: - `filename`: Path to background image file (BMP, PNG, JPG, etc.) **Returns**: `S_OK` (0) on success. **Usage Notes**: - Image is stretched to fill entire frame - Use NULL or empty string to use video background instead - Static image is more efficient than video background - Image is loaded once and cached - Supported formats: BMP, PNG, JPEG, GIF, TIFF **Example (C++)**: ``` // Set office background image pChroma->chroma_put_image(L"C:\\Backgrounds\\office.jpg"); // Remove background image (use video input instead) pChroma->chroma_put_image(NULL); ``` **Example (C#)**: ``` // Virtual studio background chroma.chroma_put_image(@"C:\Backgrounds\studio.png"); // Remove static background chroma.chroma_put_image(null); ``` --- ## Complete Configuration Examples ### Example 1: Basic Green Screen Setup (C++) ``` #include "vf_eff_intf.h" HRESULT ConfigureBasicGreenScreen(IBaseFilter* pChromaFilter) { HRESULT hr; IVFChromaKey* pChroma = nullptr; hr = pChromaFilter->QueryInterface(IID_IVFChromaKey, (void**)&pChroma); if (FAILED(hr)) return hr; // Set green as key color pChroma->chroma_put_color(Chroma_Green); // Standard contrast thresholds pChroma->chroma_put_contrast(40, 80); // Set background image pChroma->chroma_put_image(L"C:\\Backgrounds\\office_background.jpg"); pChroma->Release(); return S_OK; } ``` ### Example 2: Weather Forecast Studio (C#) ``` using System; using VisioForge.DirectShowAPI; public class WeatherStudioSetup { public void ConfigureWeatherChromaKey(IBaseFilter chromaFilter) { var chroma = chromaFilter as IVFChromaKey; if (chroma == null) throw new NotSupportedException("IVFChromaKey not available"); // Blue screen for weather maps chroma.chroma_put_color((int)CVFChromaColor.Chroma_Blue); // Tighter thresholds for clean keying chroma.chroma_put_contrast(25, 60); // Weather map background chroma.chroma_put_image(@"C:\Weather\maps\current_radar.png"); } public void UpdateWeatherMap(IVFChromaKey chroma, string mapPath) { // Dynamically update background during broadcast chroma.chroma_put_image(mapPath); } } ``` ### Example 3: Virtual Production with Custom Color (C++) ``` HRESULT ConfigureVirtualProduction(IVFChromaKey* pChroma) { // Use specific green matching your physical backdrop // Measure actual color with color picker COLORREF customGreen = RGB(60, 220, 40); // Specific green shade pChroma->chroma_put_color(customGreen); // Professional-grade thresholds // Lower values for clean, well-lit green screen pChroma->chroma_put_contrast(15, 45); // Use pre-rendered virtual environment pChroma->chroma_put_image(L"D:\\VirtualSets\\studio_environment.png"); return S_OK; } ``` ### Example 4: Adaptive Chroma Key Settings (C#) ``` public class AdaptiveChromaKey { private IVFChromaKey _chroma; public void SetupForLightingConditions(string condition) { switch (condition.ToLower()) { case "perfect": // Clean, evenly lit green screen _chroma.chroma_put_color((int)CVFChromaColor.Chroma_Green); _chroma.chroma_put_contrast(15, 40); break; case "good": // Standard lighting _chroma.chroma_put_color((int)CVFChromaColor.Chroma_Green); _chroma.chroma_put_contrast(30, 70); break; case "challenging": // Uneven lighting or wrinkled backdrop _chroma.chroma_put_color((int)CVFChromaColor.Chroma_Green); _chroma.chroma_put_contrast(50, 110); break; case "outdoor": // Natural light, harder to control _chroma.chroma_put_color((int)CVFChromaColor.Chroma_Blue); _chroma.chroma_put_contrast(60, 130); break; } } public void TestThresholds() { // Start with tight keying for (int low = 10; low <= 60; low += 10) { int high = low + 40; _chroma.chroma_put_contrast(low, high); // User reviews result and selects best setting Console.WriteLine($"Testing: Low={low}, High={high}"); System.Threading.Thread.Sleep(2000); } } } ``` --- ## Chroma Keying Best Practices ### Lighting Setup 1. **Even Illumination** 2. Use multiple light sources 3. Avoid hotspots and shadows on backdrop 4. Maintain consistent color across entire screen 5. **Subject Separation** 6. Position subject 6-10 feet from backdrop 7. Prevents green spill on subject 8. Allows independent lighting control 9. **Backdrop Quality** 10. Use proper chroma key fabric or paint 11. Keep backdrop wrinkle-free 12. Maintain consistent color saturation ### Configuration Strategy 1. **Start Conservative** ``` // Begin with tight thresholds pChroma->chroma_put_contrast(20, 50); // Gradually increase if needed pChroma->chroma_put_contrast(30, 70); ``` 2. **Test Different Lighting** 3. Adjust thresholds for your specific setup 4. Save presets for different conditions 5. Document working values 6. **Color Selection** 7. Green: Standard choice (least in skin tones) 8. Blue: When green objects in scene 9. Custom: Match actual backdrop color for best results ### Quality Optimization 1. **Camera Settings** 2. Disable auto white balance 3. Manual focus 4. Reduce sharpening (prevents edge artifacts) 5. **Threshold Tuning** 6. Low value: Controls transparency threshold 7. High value: Controls edge softness 8. Wider range = softer edges 9. **Edge Quality** ``` Tight range (low=20, high=40): - Sharp edges - May show green fringe - Best for clean backdrops Wide range (low=30, high=90): - Softer edges - Better color bleeding tolerance - More forgiving of imperfect lighting ``` --- ## Common Chroma Key Scenarios ### Scenario 1: Corporate Video Production ``` // Clean studio environment pChroma->chroma_put_color(Chroma_Green); pChroma->chroma_put_contrast(25, 55); pChroma->chroma_put_image(L"corporate_office.jpg"); ``` **Characteristics**: - Controlled lighting - Professional green screen - Static office background - High quality requirements ### Scenario 2: Gaming Streamer ``` // Home studio setup pChroma->chroma_put_color(Chroma_Green); pChroma->chroma_put_contrast(35, 75); pChroma->chroma_put_image(NULL); // Use game video as background ``` **Characteristics**: - Consumer green screen - Variable lighting - Dynamic video background - Real-time performance critical ### Scenario 3: Weather Broadcasting ``` // Blue screen with weather maps pChroma->chroma_put_color(Chroma_Blue); pChroma->chroma_put_contrast(30, 65); pChroma->chroma_put_image(L"weather_map_current.png"); ``` **Characteristics**: - Blue screen (green used in weather maps) - Dynamically changing backgrounds - Professional lighting - Presenter clothing considerations ### Scenario 4: Virtual Event Hosting ``` // Virtual conference background pChroma->chroma_put_color(Chroma_Green); pChroma->chroma_put_contrast(40, 85); pChroma->chroma_put_image(L"conference_hall.jpg"); ``` **Characteristics**: - Home/office setup - Variable quality backdrops - Forgiving settings needed - Professional appearance desired --- ## Troubleshooting ### Issue: Green Spill on Subject **Symptoms**: Green halo or tint on subject edges **Solutions**: 1. Increase subject distance from backdrop 2. Adjust lighting to reduce reflection 3. Use tighter contrast range: ``` pChroma->chroma_put_contrast(15, 35); ``` 4. Consider color correction in post ### Issue: Uneven Keying **Symptoms**: Parts of backdrop not transparent **Solutions**: 1. Check backdrop lighting uniformity 2. Increase high threshold: ``` pChroma->chroma_put_contrast(30, 100); ``` 3. Verify backdrop color consistency 4. Consider using custom color matching: ``` // Sample actual backdrop color and use it pChroma->chroma_put_color(0x40DC28); // Measured color ``` ### Issue: Subject Parts Disappearing **Symptoms**: Subject clothing or features becoming transparent **Solutions**: 1. Avoid green/blue clothing 2. Reduce contrast range: ``` pChroma->chroma_put_contrast(50, 90); ``` 3. Switch key color if needed: ``` pChroma->chroma_put_color(Chroma_Blue); // If wearing green ``` ### Issue: Rough, Jagged Edges **Symptoms**: Poor edge quality, visible pixelation **Solutions**: 1. Widen contrast range for smoother gradient: ``` pChroma->chroma_put_contrast(25, 85); ``` 2. Improve lighting quality 3. Use higher quality video source 4. Ensure subject is well-separated from backdrop ### Issue: Performance Problems **Symptoms**: Dropped frames, stuttering **Solutions**: 1. Use static image background instead of video 2. Reduce output resolution 3. Optimize threshold values (don't make too wide) 4. Consider hardware-accelerated alternatives --- ## Parameter Reference Table ### Contrast Threshold Guidelines | Lighting Quality | Backdrop | Low | High | Edge Quality | Performance | | --- | --- | --- | --- | --- | --- | | **Excellent** | Clean, even | 15-25 | 35-50 | Sharp | Best | | **Good** | Minor variations | 25-35 | 50-75 | Good | Good | | **Fair** | Some unevenness | 35-50 | 75-100 | Soft | Moderate | | **Poor** | Uneven/wrinkled | 50-70 | 100-140 | Very soft | Lower | ### Color Selection Guide | Color | RGB | Pros | Cons | Best For | | --- | --- | --- | --- | --- | | **Green** | 0x00FF00 | Least in skin, bright | Not for green objects | General use | | **Blue** | 0x0000FF | Alternative to green | Denim/blue clothing | Special cases | | **Custom** | Varies | Exact match to backdrop | Requires calibration | Professional | --- ## Integration with Video Mixer Chroma key filter is often used with Video Mixer for advanced compositing: ``` // Chroma key filter removes green IVFChromaKey* pChroma = /* ... */; pChroma->chroma_put_color(Chroma_Green); pChroma->chroma_put_contrast(30, 70); // Video mixer combines subject with background IVFVideoMixer* pMixer = /* ... */; // Input 0: Background video // Input 1: Chroma-keyed subject (transparent background) ``` See [Video Mixer Interface](../video-mixer/) for details. --- ## Related Interfaces - **IVFVideoMixer** - Combine chroma-keyed video with backgrounds - **IVFEffects45** - Additional video effects - **IVFEffectsPro** - Advanced effect processing ## See Also - [Processing Filters Pack Overview](../../) - [Video Mixer Interface](../video-mixer/) - [Effects Reference](../../effects-reference/) - [Code Examples](../../examples/) ---END OF PAGE--- ## DirectShow Video Effects and Processing Filter API Reference **URL:** https://www.visioforge.com/help/docs/directshow/proc-filters/interfaces/effects-interface/ **Description:** DirectShow Processing Filters API reference for video effects, audio enhancement, resize, chroma key, and video mixing interfaces. **Tags:** DirectShow, C++, Windows, Effects, Mixing, Screen Capture, C# **API:** VideoEffectType, IVFEffectsPro, IVFResize, IBaseFilter, IVFAudioEnhancer # Processing Filters - Effects Interfaces Reference ## Overview This document provides comprehensive API reference for all interfaces in the DirectShow Processing Filters Pack. These interfaces enable video effects, audio enhancement, chroma keying, video mixing, screen capture, and advanced processing capabilities. --- ## Interface Quick Reference | Interface | GUID | Purpose | | --- | --- | --- | | **IVFEffects45** | {5E767DA8-97AF-4607-B95F-8CC6010B84CA} | Simple video effects | | **IVFEffectsPro** | {9A794ABE-98AD-45AF-BBB0-042172C74C79} | Advanced effects with sample grabber | | **IVFResize** | {12BC6F20-2812-4660-8684-10F3FD3B4487} | Video resize and crop | | **IVFVideoMixer** | {3318300E-F6F1-4d81-8BC3-9DB06B09F77A} | Multi-source video mixing | | **IVFChromaKey** | {AF6E8208-30E3-44f0-AAFE-787A6250BAB3} | Chroma keying (green screen) | | **IVFAudioEnhancer** | {C2C0512A-AE91-4B4D-B4E0-913A0227DCD7} | Audio channel gains | | **IVFAudioEnhancer3** | {915E95CE-70F6-4FA5-B608-9B0BCDBE06B3} | IEEE float audio output | | **IVFAudioChannelMapper** | {EDB8F865-0A81-4E98-866F-B6F5F17C8FC2} | Audio channel mapping | | **IVFScreenCapture3** | {259E0009-9963-4a71-91AE-34B96D754899} | Screen capture configuration | | **IVFMotDetConfig** | {B10E9A0C-3D99-46D4-A397-6E0BC5BC3D76} | Motion detection | | **IVFPushConfig** | {F1876E64-C7AC-4B5B-8F64-67B5BB8CEAE4} | Push source configuration | | --- | | | ## Video Effects Interfaces ### IVFEffects45 Simple interface for adding and managing video effects. **GUID**: `{5E767DA8-97AF-4607-B95F-8CC6010B84CA}` **C# Definition**: ``` [ComImport] [Guid("5E767DA8-97AF-4607-B95F-8CC6010B84CA")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] public interface IVFEffects45 { /// /// Adds video effect. /// [PreserveSig] void add_effect([In] VFVideoEffectSimple effect); /// /// Sets video effects settings. /// [PreserveSig] void set_effect_settings([In] VFVideoEffectSimple effect); /// /// Removes effect. /// [PreserveSig] void remove_effect([In] int id); /// /// Clears effects. /// [PreserveSig] void clear_effects(); } ``` **Methods**: | Method | Description | | --- | --- | | `add_effect` | Adds a new video effect to the processing chain | | `set_effect_settings` | Updates parameters of an existing effect | | `remove_effect` | Removes effect by its ID | | `clear_effects` | Removes all effects | **Example (C#)**: ``` var effects = filter as IVFEffects45; if (effects != null) { // Add blur effect var blur = new VFVideoEffectSimple { EffectType = VideoEffectType.Blur, Enabled = true, Id = 1 }; effects.add_effect(blur); // Add grayscale effect var gray = new VFVideoEffectSimple { EffectType = VideoEffectType.Greyscale, Enabled = true, Id = 2 }; effects.add_effect(gray); } ``` **VFVideoEffectSimple Structure**: ``` public struct VFVideoEffectSimple { public VideoEffectType EffectType; // Effect type public bool Enabled; // Enable/disable public int Id; // Unique identifier public VFTextLogo TextLogo; // Text logo parameters public VFGraphicalLogo GraphicalLogo; // Image logo parameters (also called ImageLogo) } ``` --- ### IVFEffectsPro Advanced effects interface with sample grabber callback support. **GUID**: `{9A794ABE-98AD-45AF-BBB0-042172C74C79}` **C# Definition**: ``` [ComImport] [Guid("9A794ABE-98AD-45AF-BBB0-042172C74C79")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] public interface IVFEffectsPro { /// /// Sets filter parts state. /// [PreserveSig] void set_enabled( [In, MarshalAs(UnmanagedType.Bool)] bool effects, [In, MarshalAs(UnmanagedType.Bool)] bool motdet, [In, MarshalAs(UnmanagedType.Bool)] bool chroma, [In, MarshalAs(UnmanagedType.Bool)] bool sg); /// /// Sets callback for RGB24 buffer. /// [PreserveSig] int set_sg_callback_24([MarshalAs(UnmanagedType.FunctionPtr)] BufferCBProc callback); /// /// Sets callback for RGB32 buffer. /// [PreserveSig] int set_sg_callback_32([MarshalAs(UnmanagedType.FunctionPtr)] BufferCBProc callback); /// /// Sets sample grabber handle. /// [PreserveSig] int put_sg_app_handle(object handle); /// /// Sets sample grabber unique handle id. /// [PreserveSig] int put_sg_app_handle_id([MarshalAs(UnmanagedType.U4)] uint handle_id); } ``` **Buffer Callback Delegate**: ``` public delegate int BufferCBProc( [In] IntPtr handle, [In] uint handle_id, [In] IntPtr pBuffer, int bufferLen, int width, int height, long startTime, long stopTime, [MarshalAs(UnmanagedType.Bool)] ref bool updateFrame); ``` **Methods**: | Method | Description | |--------|-------------| | `set_enabled` | Enable/disable filter components (effects, motion detection, chroma key, sample grabber) | | `set_sg_callback_24` | Set callback for RGB24 format frames | | `set_sg_callback_32` | Set callback for RGB32 format frames | | `put_sg_app_handle` | Set application handle for callbacks | | `put_sg_app_handle_id` | Set unique identifier for callbacks | **Example (C#)**: ``` var effectsPro = filter as IVFEffectsPro; if (effectsPro != null) { // Enable effects and sample grabber effectsPro.set_enabled( effects: true, motdet: false, chroma: false, sg: true); // Set up frame callback effectsPro.put_sg_app_handle(this.Handle); effectsPro.put_sg_app_handle_id(12345); effectsPro.set_sg_callback_32(OnFrameCallback); } private int OnFrameCallback( IntPtr handle, uint handle_id, IntPtr pBuffer, int bufferLen, int width, int height, long startTime, long stopTime, ref bool updateFrame) { // Process frame data // pBuffer points to RGB32 data return 0; } ``` --- ## Video Resize Interface ### IVFResize Controls video resizing, cropping, rotation, and resize quality. **GUID**: `{12BC6F20-2812-4660-8684-10F3FD3B4487}` **C# Definition**: ``` [ComImport] [Guid("12BC6F20-2812-4660-8684-10F3FD3B4487")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] public interface IVFResize { /// /// Sets resolution. /// [PreserveSig] int put_Resolution([In] uint x, [In] uint y); /// /// Sets resize mode. /// [PreserveSig] int put_ResizeMode([In] VFResizeMode mode, [In] bool letterbox); /// /// Sets crop coordinates. /// [PreserveSig] int put_Crop([In] uint left, [In] uint top, [In] uint right, [In] uint bottom); /// /// Sets filter mode. /// [PreserveSig] int put_FilterMode([In] VFResizeFilterMode mode); /// /// Sets rotate mode. /// [PreserveSig] int put_RotateMode([In] VFRotateMode mode); } ``` **VFResizeMode Enumeration**: ``` public enum VFResizeMode { rmStretch = 0, // Stretch to fit (may distort) rmLetterbox = 1, // Maintain aspect ratio with letterbox rmCrop = 2 // Crop to fit } ``` **VFResizeFilterMode Enumeration**: ``` public enum VFResizeFilterMode { NearestNeighbor = 0, // Fastest, lowest quality Bilinear = 1, // Good quality, fast Bicubic = 2, // High quality (default) Lanczos = 3 // Highest quality, slower } ``` **VFRotateMode Enumeration**: ``` public enum VFRotateMode { RM_0 = 0, // No rotation RM_90 = 1, // 90 degrees clockwise RM_180 = 2, // 180 degrees RM_270 = 3 // 270 degrees clockwise (90 CCW) } ``` **Example (C#)**: ``` var resize = filter as IVFResize; if (resize != null) { // Resize to 1280x720 with letterbox resize.put_Resolution(1280, 720); resize.put_ResizeMode(VFResizeMode.rmLetterbox, true); // Use high quality bicubic resize resize.put_FilterMode(VFResizeFilterMode.Bicubic); // Rotate 90 degrees resize.put_RotateMode(VFRotateMode.RM_90); // Crop 10 pixels from each side resize.put_Crop(10, 10, 10, 10); } ``` --- ## Audio Enhancement Interfaces ### IVFAudioEnhancer Controls audio channel gains, auto gain, and normalization. **GUID**: `{C2C0512A-AE91-4B4D-B4E0-913A0227DCD7}` **C# Definition**: ``` [ComImport] [Guid("C2C0512A-AE91-4B4D-B4E0-913A0227DCD7")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] public interface IVFAudioEnhancer { [PreserveSig] int get_auto_gain([Out, MarshalAs(UnmanagedType.Bool)] out bool auto_gain); [PreserveSig] int set_auto_gain([MarshalAs(UnmanagedType.Bool)] bool auto_gain); [PreserveSig] int get_normalize([Out, MarshalAs(UnmanagedType.Bool)] out bool normalize); [PreserveSig] int set_normalize([MarshalAs(UnmanagedType.Bool)] bool normalize); [PreserveSig] int get_input_gains(out float l, out float c, out float r, out float sl, out float sr, out float lfe); [PreserveSig] int set_input_gains(float l, float c, float r, float sl, float sr, float lfe); [PreserveSig] int get_output_gains(out float l, out float c, out float r, out float sl, out float sr, out float lfe); [PreserveSig] int set_output_gains(float l, float c, float r, float sl, float sr, float lfe); [PreserveSig] int get_time_shift(out int time_shift); [PreserveSig] int set_time_shift(int time_shift); } ``` **Channel Parameters**: - `l` - Left channel - `c` - Center channel - `r` - Right channel - `sl` - Surround left - `sr` - Surround right - `lfe` - Low frequency effects (subwoofer) **Example (C#)**: ``` var audio = filter as IVFAudioEnhancer; if (audio != null) { // Enable auto gain and normalization audio.set_auto_gain(true); audio.set_normalize(true); // Boost left and right channels by 20% audio.set_output_gains( l: 1.2f, c: 1.0f, r: 1.2f, sl: 1.0f, sr: 1.0f, lfe: 1.0f); } ``` --- ### IVFAudioEnhancer3 Enables IEEE floating-point audio output format. **GUID**: `{915E95CE-70F6-4FA5-B608-9B0BCDBE06B3}` **C# Definition**: ``` [ComImport] [Guid("915E95CE-70F6-4FA5-B608-9B0BCDBE06B3")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] public interface IVFAudioEnhancer3 { [PreserveSig] int get_ieee_output_enabled([Out, MarshalAs(UnmanagedType.Bool)] out bool enabled); [PreserveSig] int set_ieee_output_enabled([MarshalAs(UnmanagedType.Bool)] bool enabled); } ``` **Example (C#)**: ``` var audio3 = filter as IVFAudioEnhancer3; if (audio3 != null) { // Enable IEEE float output for professional audio processing audio3.set_ieee_output_enabled(true); } ``` --- ## Screen Capture Interface ### IVFScreenCapture3 Controls screen capture mode, region, frame rate, and mouse cursor visibility. **GUID**: `{259E0009-9963-4a71-91AE-34B96D754899}` **C# Definition**: ``` [ComImport] [Guid("259E0009-9963-4a71-91AE-34B96D754899")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] public interface IVFScreenCapture3 { [PreserveSig] int init(); [PreserveSig] int set_fps([In] double fps); [PreserveSig] int set_rect([In] VFRect rect); [PreserveSig] int set_mouse([In] bool draw); [PreserveSig] int set_display_index([In] int index); [PreserveSig] int set_mode([In] VFScreenCaptureMode mode); [PreserveSig] int refresh_pic(); [PreserveSig] int set_stream([In] IStream stream, [In] long length); [PreserveSig] int set_window_handle([In] IntPtr handle); [PreserveSig] int get_window_size([In] IntPtr handle, [Out] out int width, [Out] out int height); } ``` **VFScreenCaptureMode Enumeration**: ``` public enum VFScreenCaptureMode { scmScreen = 0, // Capture entire screen or region scmWindow = 1, // Capture specific window scmMemory = 2 // Use memory stream as source } ``` **VFRect Structure**: ``` public struct VFRect { public int Left; public int Top; public int Right; public int Bottom; } ``` **Example (C#)**: ``` var capture = filter as IVFScreenCapture3; if (capture != null) { // Initialize capture capture.init(); // Capture at 30 FPS capture.set_fps(30.0); // Capture specific region var rect = new VFRect { Left = 100, Top = 100, Right = 1920, Bottom = 1080 }; capture.set_rect(rect); // Show mouse cursor capture.set_mouse(true); // Capture primary display capture.set_display_index(0); // Set screen capture mode capture.set_mode(VFScreenCaptureMode.scmScreen); } ``` **Example: Window Capture**: ``` // Capture specific window IntPtr windowHandle = FindWindow(null, "Calculator"); if (windowHandle != IntPtr.Zero) { capture.set_mode(VFScreenCaptureMode.scmWindow); capture.set_window_handle(windowHandle); // Get window size capture.get_window_size(windowHandle, out int width, out int height); Console.WriteLine($"Window size: {width}x{height}"); } ``` --- ## Common Structures and Enumerations ### VFVideoEffectType Complete enumeration of all available video effects. ``` public enum VideoEffectType { Undefined = -1, // Undefined effect // Text and Graphics TextLogo = 0, // Text overlay ImageLogo = 1, // Image/logo overlay // Color Filters Blue, // Blue color filter FilterBlue, // Blue channel filter FilterGreen, // Green channel filter FilterRed, // Red channel filter Green, // Green color filter Red, // Red color filter Greyscale, // Convert to grayscale // Image Adjustments Blur, // Blur effect Contrast, // Contrast adjustment Darkness, // Darken effect Lightness, // Brighten effect Saturation, // Saturation adjustment Sharpen, // Sharpen effect Smooth, // Smooth/soften effect // Spatial Transformations FlipDown, // Flip vertically (deprecated: use FlipVertical) FlipRight, // Flip horizontally (deprecated: use FlipHorizontal) MirrorHorizontal, // Mirror horizontally MirrorVertical, // Mirror vertically Rotate, // Rotate effect Zoom, // Zoom effect Pan, // Pan/position effect // Artistic Effects ColorNoise, // Color noise MonoNoise, // Monochrome noise Mosaic, // Mosaic/pixelate effect Posterize, // Posterize effect ShakeDown, // Shake effect Solorize, // Solarize effect Spray, // Spray effect Invert, // Invert colors // Denoising DenoiseCAST, // CAST denoising algorithm DenoiseAdaptive, // Adaptive denoising DenoiseMosquito, // Mosquito noise reduction DenoiseSNR, // SNR-based denoising MaxineDenoise, // NVIDIA Maxine AI denoising // Deinterlacing DeinterlaceBlend, // Deinterlace (blend method) DeinterlaceTriangle, // Deinterlace (triangle method) DeinterlaceCAVT, // Deinterlace (CAVT method) // Transitions FadeIn, // Fade-in transition FadeOut, // Fade-out transition // Advanced Effects ScrollingTextLogo, // Scrolling text overlay MaxineArtifactReduction, // NVIDIA Maxine artifact reduction LUT, // Look-Up Table color grading } ``` **Effect Categories**: | Category | Effects | | --- | --- | | **Text & Graphics** | TextLogo, ImageLogo, ScrollingTextLogo | | **Color Filters** | Blue, FilterBlue, FilterGreen, FilterRed, Green, Red, Greyscale | | **Image Adjustments** | Blur, Contrast, Darkness, Lightness, Saturation, Sharpen, Smooth | | **Spatial** | FlipDown, FlipRight, MirrorHorizontal, MirrorVertical, Rotate, Zoom, Pan | | **Artistic** | ColorNoise, MonoNoise, Mosaic, Posterize, ShakeDown, Solorize, Spray, Invert | | **Denoising** | DenoiseCAST, DenoiseAdaptive, DenoiseMosquito, DenoiseSNR, MaxineDenoise | | **Deinterlacing** | DeinterlaceBlend, DeinterlaceTriangle, DeinterlaceCAVT | | **Transitions** | FadeIn, FadeOut | | **Advanced** | LUT, MaxineArtifactReduction | **NVIDIA Maxine Effects** (require NVIDIA RTX GPU): - `MaxineDenoise` - AI-powered video denoising - `MaxineArtifactReduction` - Reduce compression artifacts --- ### VFTextLogo Comprehensive text logo configuration structure. ``` [StructLayout(LayoutKind.Sequential)] public struct VFTextLogo { public int X; // X position public int Y; // Y position public bool TransparentBg; // Transparent background public int FontSize; // Font size (points) public bool FontItalic; // Italic style public bool FontBold; // Bold style public bool FontUnderline; // Underline style public bool FontStrikeout; // Strikeout style public int FontColor; // Font color (RGB) public int BGColor; // Background color public bool RightToLeft; // RTL text direction public bool Vertical; // Vertical text public int Align; // Text alignment public int DrawQuality; // Draw quality public int Antialiasing; // Antialiasing mode public int RectWidth; // Bounding rect width public int RectHeight; // Bounding rect height public int RotationMode; // Text rotation public int FlipMode; // Text flip mode public int Transp; // Transparency (0-255) public bool Gradient; // Enable gradient public int GradientMode; // Gradient direction public int GradientColor1; // Gradient start color public int GradientColor2; // Gradient end color public int InnerBorderColor; // Inner border color public int OuterBorderColor; // Outer border color public int InnerBorderSize; // Inner border width public int OuterBorderSize; // Outer border width public int DrawMode; // Draw mode public int BorderMode; // Border style public int EffectMode; // Effect mode public int ShapeType; // Text shape } ``` --- ### VFGraphicalLogo Image logo configuration structure. ``` [StructLayout(LayoutKind.Sequential)] public struct VFGraphicalLogo { public int X; // X position public int Y; // Y position public int Width; // Image width public int Height; // Image height public int Transp; // Transparency (0-255) public int RotationMode; // Rotation angle public int FlipMode; // Flip mode public VFVideoEffectStretchMode StretchMode; // Stretch mode } ``` --- ## Complete Configuration Examples ### Example 1: Professional Text Overlay (C#) ``` using VisioForge.DirectShowAPI; public void AddProfessionalTextOverlay(IBaseFilter effectsFilter) { var effects = effectsFilter as IVFEffects45; if (effects == null) return; var textEffect = new VFVideoEffectSimple { EffectType = VideoEffectType.TextLogo, Enabled = true, Id = 1, TextLogo = new VFTextLogo { X = 50, Y = 50, FontSize = 36, FontBold = true, FontColor = 0xFFFFFF, // White TransparentBg = true, Antialiasing = 2, // High quality Transp = 230, // Slightly transparent Gradient = true, GradientMode = 0, // Horizontal GradientColor1 = 0xFFFFFF, // White GradientColor2 = 0x0080FF, // Orange BorderMode = 6, // Filled outline OuterBorderColor = 0x000000, // Black OuterBorderSize = 2 } }; effects.add_effect(textEffect); } ``` ### Example 2: Multi-Effect Chain (C#) ``` public void ApplyMultipleEffects(IBaseFilter effectsFilter) { var effects = effectsFilter as IVFEffects45; if (effects == null) return; // 1. Deinterlace effects.add_effect(new VFVideoEffectSimple { EffectType = VideoEffectType.DeinterlaceBlend, Enabled = true, Id = 1 }); // 2. Denoise effects.add_effect(new VFVideoEffectSimple { EffectType = VideoEffectType.DenoiseAdaptive, Enabled = true, Id = 2 }); // 3. Adjust contrast effects.add_effect(new VFVideoEffectSimple { EffectType = VideoEffectType.Contrast, Enabled = true, Id = 3 }); // 4. Add watermark effects.add_effect(new VFVideoEffectSimple { EffectType = VideoEffectType.ImageLogo, Enabled = true, Id = 4, GraphicalLogo = new VFGraphicalLogo { X = 1800, Y = 50, Width = 100, Height = 100, Transp = 200, StretchMode = VFVideoEffectStretchMode.Stretch } }); } ``` ### Example 3: High-Quality Resize with Rotation (C#) ``` public void ConfigureResizeAndRotate(IBaseFilter resizeFilter) { var resize = resizeFilter as IVFResize; if (resize == null) return; // Resize to 4K resize.put_Resolution(3840, 2160); // Maintain aspect ratio with letterbox resize.put_ResizeMode(VFResizeMode.rmLetterbox, true); // Use highest quality Lanczos algorithm resize.put_FilterMode(VFResizeFilterMode.Lanczos); // Rotate 90 degrees clockwise resize.put_RotateMode(VFRotateMode.RM_90); // No cropping resize.put_Crop(0, 0, 0, 0); } ``` ### Example 4: Sample Grabber with Effects (C#) ## ``` public class EffectsWithFrameCapture { private IVFEffectsPro _effectsPro; public void Setup(IBaseFilter effectsFilter) { _effectsPro = effectsFilter as IVFEffectsPro; if (_effectsPro == null) return; // Enable effects and sample grabber _effectsPro.set_enabled( effects: true, motdet: false, chroma: false, sg: true); // Set up callback _effectsPro.put_sg_app_handle(IntPtr.Zero); _effectsPro.put_sg_app_handle_id(1); _effectsPro.set_sg_callback_32(OnFrameReceived); } private int OnFrameReceived( IntPtr handle, uint handle_id, IntPtr pBuffer, int bufferLen, int width, int height, long startTime, long stopTime, ref bool updateFrame) { // Process frame Console.WriteLine($"Frame: {width}x{height}, {bufferLen} bytes"); // Can modify frame data in pBuffer // Set updateFrame = true to update the frame return 0; } } ``` ## See Also - [Video Mixer Interface](../video-mixer/) - Multi-source video mixing - [Chroma Key Interface](../chroma-key/) - Green screen compositing - [Effects Reference](../../effects-reference/) - Complete effects catalog - [Processing Filters Pack Overview](../../) - [Code Examples](../../examples/) ---END OF PAGE--- ## DirectShow Video Mixer Filter - PIP and Chroma Key API **URL:** https://www.visioforge.com/help/docs/directshow/proc-filters/interfaces/video-mixer/ **Description:** IVFVideoMixer interface for mixing 2-16 video sources with PIP, chroma keying, transparency, and customizable layout configurations. **Tags:** DirectShow, C++, Windows, Effects, Mixing, Webcam, C# **API:** IVFVideoMixer, IBaseFilter, IVFChromaKey # IVFVideoMixer Interface Reference ## Overview The `IVFVideoMixer` interface provides comprehensive control over multi-source video mixing in DirectShow applications. This interface enables Picture-in-Picture (PIP), video compositing, chroma keying, and flexible layout management for combining multiple video streams into a single output. The Video Mixer filter can handle 2-16 input video sources, each with independent position, size, transparency, and z-order configuration. ## Interface Definition - **Interface Name**: `IVFVideoMixer` - **GUID**: `{3318300E-F6F1-4d81-8BC3-9DB06B09F77A}` - **Inherits From**: `IUnknown` - **Header File**: `yk_video_mixer_filter_define.h` (C++), `IVFVideoMixer.cs` (.NET) ## Capabilities - **Input Pins**: 2-16 simultaneous video sources - **Chroma Keying**: Green/blue screen support per input - **Resize Quality**: Multiple interpolation algorithms - **Z-Order**: Independent layering control - **Transparency**: Per-input alpha blending - **Position/Size**: Pixel-accurate placement --- ## Methods Reference ### Input Parameter Management #### SetInputParam Configures parameters for a specific input pin. **Syntax (C++)**: ``` int SetInputParam(int pin_index, VFPIPVideoInputParam param); ``` **Syntax (C#)**: ``` [PreserveSig] int SetInputParam([In] int pin_index, [In] VFPIPVideoInputParam param); ``` **Parameters**: - `pin_index`: Zero-based input pin index (0 = first input, 1 = second, etc.) - `param`: Structure containing input configuration (see below) **Returns**: `0` on success, error code otherwise. **VFPIPVideoInputParam Structure**: | Field | Type | Description | |-------|------|-------------| | `Enabled` | bool | Enable/disable this input | | `Left` | int | X position (pixels) | | `Top` | int | Y position (pixels) | | `Width` | int | Width (pixels) | | `Height` | int | Height (pixels) | | `Alpha` | int | Transparency (0-255, 255=opaque) | | `Visible` | bool | Visibility flag | | `ZOrder` | int | Layer order (higher = foreground) | | `StretchMode` | VFPIPResizeQuality | Resize quality | **Usage Notes**: - Pin 0 is typically the background/main source - Pins 1+ are overlay sources - Position (0,0) is top-left corner - Size can differ from source resolution (automatic scaling) - Alpha blending requires some GPU overhead **Example (C++)**: ``` IVFVideoMixer* pMixer = nullptr; pFilter->QueryInterface(IID_IVFVideoMixer, (void**)&pMixer); // Configure second input (overlay) VFPIPVideoInputParam param; param.Enabled = true; param.Visible = true; param.Left = 50; param.Top = 50; param.Width = 640; param.Height = 360; param.Alpha = 255; // Fully opaque param.ZOrder = 10; // On top of background pMixer->SetInputParam(1, param); pMixer->Release(); ``` **Example (C#)**: ``` var mixer = filter as IVFVideoMixer; // Configure PIP in bottom-right corner var param = new VFPIPVideoInputParam { Enabled = true, Visible = true, Left = 1600, // Assuming 1920x1080 output Top = 820, Width = 320, // Small PIP Height = 180, Alpha = 255, ZOrder = 100 // Top layer }; mixer.SetInputParam(1, param); ``` --- #### GetInputParam Retrieves current parameters for a specific input pin. **Syntax (C++)**: ``` int GetInputParam(int pin_index, VFPIPVideoInputParam *param); ``` **Syntax (C#)**: ``` [PreserveSig] int GetInputParam([In] int pin_index, [Out] out VFPIPVideoInputParam param); ``` **Parameters**: - `pin_index`: Zero-based input pin index - `param`: [out] Receives current input configuration **Returns**: `0` on success. **Example (C++)**: ``` VFPIPVideoInputParam param; pMixer->GetInputParam(1, ¶m); printf("Input 1 position: %d,%d\n", param.Left, param.Top); printf("Input 1 size: %dx%d\n", param.Width, param.Height); ``` --- #### GetInputParam2 Retrieves parameters by pin interface reference instead of index. **Syntax (C++)**: ``` int GetInputParam2(IPin *pin, VFPIPVideoInputParam *param); ``` **Syntax (C#)**: ``` [PreserveSig] int GetInputParam2([In] object pin, [Out] out VFPIPVideoInputParam param); ``` **Parameters**: - `pin`: DirectShow IPin interface pointer - `param`: [out] Receives input configuration **Returns**: `0` on success. **Usage Notes**: - Alternative to GetInputParam when you have pin reference - Useful when enumerating pins dynamically --- ### Output Configuration #### SetOutputParam Configures the mixer's output video format. **Syntax (C++)**: ``` int SetOutputParam(VFPIPVideoOutputParam param); ``` **Syntax (C#)**: ``` [PreserveSig] int SetOutputParam([In] VFPIPVideoOutputParam param); ``` **Parameters**: - `param`: Output configuration structure **VFPIPVideoOutputParam Structure**: | Field | Type | Description | | --- | --- | --- | | `Width` | int | Output width (pixels) | | `Height` | int | Output height (pixels) | | `FrameRate` | double | Output frame rate (fps) | | `BackgroundColor` | COLORREF | Background color (RGB) | **Usage Notes**: - Must be called before connecting downstream filters - All inputs are scaled/positioned relative to output size - Frame rate can differ from inputs (mixer handles timing) **Example (C++)**: ``` VFPIPVideoOutputParam output; output.Width = 1920; output.Height = 1080; output.FrameRate = 30.0; output.BackgroundColor = RGB(0, 0, 0); // Black background pMixer->SetOutputParam(output); ``` **Example (C#)**: ``` var output = new VFPIPVideoOutputParam { Width = 1280, Height = 720, FrameRate = 60.0, BackgroundColor = 0x003300 // Dark green }; mixer.SetOutputParam(output); ``` --- #### GetOutputParam Retrieves current output configuration. **Syntax (C++)**: ``` int GetOutputParam(VFPIPVideoOutputParam *param); ``` **Syntax (C#)**: ``` [PreserveSig] int GetOutputParam([Out] out VFPIPVideoOutputParam param); ``` **Parameters**: - `param`: [out] Receives output configuration **Returns**: `0` on success. --- ### Chroma Key Configuration #### SetChromaSettings Configures chroma key (green/blue screen) settings for compositing. **Syntax (C++)**: ``` int SetChromaSettings(bool enabled, int color, int tolerance1, int tolerance2); ``` **Syntax (C#)**: ``` [PreserveSig] int SetChromaSettings([In, MarshalAs(UnmanagedType.Bool)] bool enabled, int color, int tolerance1, int tolerance2); ``` **Parameters**: - `enabled`: Enable/disable chroma keying - `color`: Key color (0=green, 1=blue, 2=red, or custom RGB) - `tolerance1`: Color matching tolerance (0-255) - `tolerance2`: Edge tolerance (0-255) **Returns**: `0` on success. **Usage Notes**: - Applies to all inputs that have chroma color - Lower tolerance = stricter color matching - Higher tolerance = more colors removed (may affect subject) - tolerance2 helps with edge smoothing **Chroma Color Values**: - `0` - Green (most common) - `1` - Blue - `2` - Red - Custom RGB value **Example (C++)**: ``` // Enable green screen with moderate tolerance pMixer->SetChromaSettings(true, 0, 50, 30); ``` **Example (C#)**: ``` // Blue screen with tight tolerance mixer.SetChromaSettings(true, 1, 30, 20); // Disable chroma keying mixer.SetChromaSettings(false, 0, 0, 0); ``` --- ### Layer Order Management #### SetInputOrder Sets the z-order (layer order) for a specific input. **Syntax (C++)**: ``` int SetInputOrder(int pin_index, int order); ``` **Syntax (C#)**: ``` [PreserveSig] int SetInputOrder(int pin_index, int order); ``` **Parameters**: - `pin_index`: Zero-based input pin index - `order`: Z-order value (higher = foreground) **Returns**: `0` on success. **Usage Notes**: - Higher order values render on top - Typical range: 0-100 - Can be changed dynamically during playback - Alternative to setting ZOrder in VFPIPVideoInputParam **Example (C++)**: ``` // Background pMixer->SetInputOrder(0, 0); // Middle layer pMixer->SetInputOrder(1, 50); // Top overlay pMixer->SetInputOrder(2, 100); ``` --- ### Quality Configuration #### SetResizeQuality Sets the resize quality/algorithm for all inputs. **Syntax (C++)**: ``` int SetResizeQuality(VFPIPResizeQuality quality); ``` **Syntax (C#)**: ``` [PreserveSig] int SetResizeQuality(VFPIPResizeQuality quality); ``` **Parameters**: - `quality`: Resize quality mode **VFPIPResizeQuality Enumeration**: | Value | Algorithm | Quality | Speed | Use Case | | --- | --- | --- | --- | --- | | **NearestNeighbor** | Nearest pixel | Low | ★★★★★ | Pixel art, fast preview | | **Bilinear** | Linear interpolation | Medium | ★★★★☆ | Standard quality | | **Bicubic** | Cubic interpolation | High | ★★★☆☆ | High quality (default) | | **Lanczos** | Lanczos-3 | Highest | ★★☆☆☆ | Professional quality | **Usage Notes**: - Bicubic is recommended for most use cases - Lanczos for maximum quality when performance allows - Bilinear for real-time performance - NearestNeighbor only for special cases **Example (C++)**: ``` // High quality mixing pMixer->SetResizeQuality(VFPIPResizeQuality::Lanczos); // Performance mode pMixer->SetResizeQuality(VFPIPResizeQuality::Bilinear); ``` --- ## Complete Configuration Examples ### Example 1: Picture-in-Picture (C++) ``` #include "yk_video_mixer_filter_define.h" HRESULT ConfigurePIPLayout(IBaseFilter* pMixerFilter) { HRESULT hr; IVFVideoMixer* pMixer = nullptr; hr = pMixerFilter->QueryInterface(IID_IVFVideoMixer, (void**)&pMixer); if (FAILED(hr)) return hr; // Set 1080p output VFPIPVideoOutputParam output; output.Width = 1920; output.Height = 1080; output.FrameRate = 30.0; output.BackgroundColor = RGB(0, 0, 0); pMixer->SetOutputParam(output); // Configure main video (input 0 - background) VFPIPVideoInputParam main; main.Enabled = true; main.Visible = true; main.Left = 0; main.Top = 0; main.Width = 1920; main.Height = 1080; main.Alpha = 255; main.ZOrder = 0; // Background pMixer->SetInputParam(0, main); // Configure PIP (input 1 - bottom-right corner) VFPIPVideoInputParam pip; pip.Enabled = true; pip.Visible = true; pip.Left = 1560; // 1920 - 360 (width) + margin pip.Top = 860; // 1080 - 220 (height) + margin pip.Width = 360; pip.Height = 202; // 16:9 aspect pip.Alpha = 255; pip.ZOrder = 100; // Foreground pMixer->SetInputParam(1, pip); // High quality resize pMixer->SetResizeQuality(VFPIPResizeQuality::Bicubic); pMixer->Release(); return S_OK; } ``` ### Example 2: Split Screen (C#) ``` using VisioForge.DirectShowAPI; public class SplitScreenMixer { public void ConfigureSplitScreen(IBaseFilter mixerFilter) { var mixer = mixerFilter as IVFVideoMixer; if (mixer == null) throw new NotSupportedException("IVFVideoMixer not available"); // 1920x1080 output var output = new VFPIPVideoOutputParam { Width = 1920, Height = 1080, FrameRate = 30.0, BackgroundColor = 0x000000 }; mixer.SetOutputParam(output); // Left half - Input 0 var leftInput = new VFPIPVideoInputParam { Enabled = true, Visible = true, Left = 0, Top = 0, Width = 960, // Half width Height = 1080, Alpha = 255, ZOrder = 0 }; mixer.SetInputParam(0, leftInput); // Right half - Input 1 var rightInput = new VFPIPVideoInputParam { Enabled = true, Visible = true, Left = 960, // Offset by half Top = 0, Width = 960, Height = 1080, Alpha = 255, ZOrder = 0 }; mixer.SetInputParam(1, rightInput); mixer.SetResizeQuality(VFPIPResizeQuality.Bicubic); } } ``` ### Example 3: Chroma Key Overlay (C++) ``` HRESULT ConfigureChromaKeyOverlay(IVFVideoMixer* pMixer) { // 1080p output VFPIPVideoOutputParam output; output.Width = 1920; output.Height = 1080; output.FrameRate = 30.0; output.BackgroundColor = RGB(0, 0, 0); pMixer->SetOutputParam(output); // Background scene (input 0) VFPIPVideoInputParam background; background.Enabled = true; background.Visible = true; background.Left = 0; background.Top = 0; background.Width = 1920; background.Height = 1080; background.Alpha = 255; background.ZOrder = 0; pMixer->SetInputParam(0, background); // Person in front of green screen (input 1) VFPIPVideoInputParam subject; subject.Enabled = true; subject.Visible = true; subject.Left = 400; subject.Top = 100; subject.Width = 1120; subject.Height = 880; subject.Alpha = 255; subject.ZOrder = 10; pMixer->SetInputParam(1, subject); // Enable green screen chroma keying pMixer->SetChromaSettings( true, // Enable 0, // Green 60, // Color tolerance 40 // Edge tolerance ); // High quality for best chroma key edges pMixer->SetResizeQuality(VFPIPResizeQuality::Lanczos); return S_OK; } ``` ### Example 4: Multi-Camera Grid (C#) ## ``` public void Configure2x2Grid(IVFVideoMixer mixer) { // 1920x1080 output var output = new VFPIPVideoOutputParam { Width = 1920, Height = 1080, FrameRate = 30.0, BackgroundColor = 0x101010 // Dark gray }; mixer.SetOutputParam(output); int cellWidth = 960; int cellHeight = 540; int gap = 10; // Top-left camera (input 0) mixer.SetInputParam(0, new VFPIPVideoInputParam { Enabled = true, Visible = true, Left = gap, Top = gap, Width = cellWidth - gap * 2, Height = cellHeight - gap * 2, Alpha = 255, ZOrder = 0 }); // Top-right camera (input 1) mixer.SetInputParam(1, new VFPIPVideoInputParam { Enabled = true, Visible = true, Left = cellWidth + gap, Top = gap, Width = cellWidth - gap * 2, Height = cellHeight - gap * 2, Alpha = 255, ZOrder = 0 }); // Bottom-left camera (input 2) mixer.SetInputParam(2, new VFPIPVideoInputParam { Enabled = true, Visible = true, Left = gap, Top = cellHeight + gap, Width = cellWidth - gap * 2, Height = cellHeight - gap * 2, Alpha = 255, ZOrder = 0 }); // Bottom-right camera (input 3) mixer.SetInputParam(3, new VFPIPVideoInputParam { Enabled = true, Visible = true, Left = cellWidth + gap, Top = cellHeight + gap, Width = cellWidth - gap * 2, Height = cellHeight - gap * 2, Alpha = 255, ZOrder = 0 }); mixer.SetResizeQuality(VFPIPResizeQuality.Bicubic); } ``` ## Common Mixing Scenarios ### Scenario 1: News Broadcast Style ``` +------------------------------------------+ | | | Main Camera (full screen) | | | | +-----------+ | | | Guest | | | | Camera | | | +-----------+ | +------------------------------------------+ ``` **Configuration**: - Input 0: Main camera (1920x1080) - Input 1: Guest PIP (320x180, bottom-right) - Z-Order: Guest on top - Resize Quality: Bicubic ### Scenario 2: Gaming Stream ``` +------------------------------------------+ | | | Game Capture (main) | | | | +----------+ | | | Webcam | | | +----------+ | +------------------------------------------+ ``` **Configuration**: - Input 0: Game capture (1920x1080) - Input 1: Webcam (280x210, top-left) - Optional: Chroma key if webcam has green screen - Z-Order: Webcam on top ### Scenario 3: Virtual Production ``` +------------------------------------------+ | | | Background Scene (pre-rendered) | | | | [Person with green screen | | composited on top] | | | +------------------------------------------+ ``` **Configuration**: - Input 0: Virtual background - Input 1: Camera with green screen - Chroma key: Enabled, green, tolerance 60/40 - Resize Quality: Lanczos for best edge quality --- ## Performance Considerations ### CPU/GPU Usage **Low Impact Configurations**: - 2-4 inputs - Bilinear resize - No chroma keying - No transparency (Alpha = 255) **Medium Impact**: - 5-8 inputs - Bicubic resize - Basic chroma keying - Some transparency **High Impact**: - 9+ inputs - Lanczos resize - Complex chroma keying - Multiple transparent layers ### Optimization Tips 1. **Use appropriate resize quality**: 2. Preview: Bilinear 3. Production: Bicubic 4. Maximum quality: Lanczos (if performance allows) 5. **Minimize chroma keying overhead**: 6. Only enable when needed 7. Use tight tolerance values 8. Consider hardware-accelerated alternative 9. **Limit number of inputs**: 10. Each input adds processing overhead 11. Disable unused inputs (Enabled = false) 12. **Match source resolutions**: 13. Less scaling = better performance 14. Pre-scale sources if possible --- ## Best Practices ### Layout Design 1. **Plan z-order carefully** - Background lowest, overlays highest 2. **Leave margins** - Don't position elements at exact edges 3. **Maintain aspect ratios** - Avoid distortion 4. **Test at target resolution** - Verify positioning accuracy ### Chroma Keying 1. **Proper lighting** - Even lighting on green screen 2. **Adjust tolerance** - Start low, increase gradually 3. **Quality setting** - Use Lanczos for best edges 4. **Test conditions** - Different lighting scenarios ### Dynamic Changes 1. **Update parameters smoothly** - Avoid abrupt position changes 2. **Cache configurations** - Store presets for quick switching 3. **Validate parameters** - Check bounds before applying 4. **Handle errors** - Check return values --- ## Troubleshooting ### Issue: Video Not Appearing **Check**: - `Enabled = true` - `Visible = true` - `Alpha > 0` - Position within output bounds - Source filter is running ### Issue: Poor Quality Scaling **Solution**: ``` pMixer->SetResizeQuality(VFPIPResizeQuality::Lanczos); ``` ### Issue: Chroma Key Not Working **Check**: - Chroma settings enabled - Correct color selected (0=green, 1=blue) - Increase tolerance values - Verify source has uniform green screen **Example**: ``` // Try higher tolerance pMixer->SetChromaSettings(true, 0, 80, 60); ``` ### Issue: Performance Problems **Solutions**: - Reduce number of active inputs - Use faster resize quality - Disable chroma keying if not needed - Pre-scale input sources --- ## Related Interfaces - **IBaseFilter** - DirectShow filter interface - **IPin** - DirectShow pin interface (for GetInputParam2) - **IVFEffects45** - Video effects (can combine with mixer) - **IVFChromaKey** - Dedicated chroma key interface ## See Also - [Processing Filters Pack Overview](../../) - [Effects Reference](../../effects-reference/) - [Chroma Key Interface](../chroma-key/) - [Code Examples](../../examples/) ---END OF PAGE--- ## DirectShow Video Encryption Examples - C#, C++, Delphi **URL:** https://www.visioforge.com/help/docs/directshow/video-encryption-sdk/examples/ **Description:** Encrypt and decrypt MP4 video files using VisioForge DirectShow filters. AES-256 examples with password protection and binary key modes. **Tags:** Video Encryption SDK, DirectShow, C++, Windows, Encoding, MP4, H.264, AAC, C# **API:** IBaseFilter, IVFCryptoConfig, IFileSinkFilter, SourceFilter, VideoEncoder # Video Encryption SDK - Code Examples ## Overview This page provides comprehensive, working code examples for encrypting and decrypting video files using the Video Encryption SDK. Examples cover: - **Basic Encryption** - Encrypt video files with password protection - **File Decryption** - Decrypt and play encrypted video files - **Advanced Scenarios** - Binary keys, file-based keys, custom encoding settings - **Error Handling** - Robust error checking and recovery All examples include complete implementations in C++, C#, and Delphi. Interface naming across language wrappers The native C++ header (`encryptor_intf.h`) declares this interface as `ICryptoConfig` with `IID_ICryptoConfig`. The C# and Delphi wrappers expose the same interface as `IVFCryptoConfig` (and the password provider as `IVFPasswordProvider`). Both names share GUID `{BAA5BD1E-3B30-425e-AB3B-CC20764AC253}` and refer to the same COM interface — the C++ snippets below use `ICryptoConfig` while the C#/Delphi snippets use `IVFCryptoConfig`. --- ## Prerequisites ### C++ Projects ``` #include #include #include "encryptor_intf.h" #pragma comment(lib, "strmiids.lib") #pragma comment(lib, "quartz.lib") ``` ### C# Projects ``` using System; using System.Runtime.InteropServices; using VisioForge.DirectShowAPI; using VisioForge.DirectShowLib; ``` **Required NuGet Packages**: - VisioForge.DirectShowAPI - VisioForge.DirectShowLib ### Delphi Projects ## ``` uses DirectShow9, EncryptorIntf; ``` ## Example 1: Basic Video Encryption Encrypt a video file with string password. ### C# Implementation ``` using System; using System.Runtime.InteropServices; using VisioForge.DirectShowAPI; using VisioForge.DirectShowLib; public class BasicVideoEncryption { private IFilterGraph2 filterGraph; private IMediaControl mediaControl; private IMediaEventEx mediaEvent; public void EncryptVideo(string inputFile, string outputFile, string password) { try { // Create filter graph filterGraph = (IFilterGraph2)new FilterGraph(); mediaControl = (IMediaControl)filterGraph; mediaEvent = (IMediaEventEx)filterGraph; // Add source filter int hr = filterGraph.AddSourceFilter(inputFile, "Source", out IBaseFilter sourceFilter); DsError.ThrowExceptionForHR(hr); // Add video encoder (H.264) var videoEncoder = FilterGraphTools.AddFilterFromClsid( filterGraph, Consts.CLSID_VFH264Encoder, "H.264 Encoder" ); // Add audio encoder (AAC) var audioEncoder = FilterGraphTools.AddFilterFromClsid( filterGraph, Consts.CLSID_VFAACEncoder, "AAC Encoder" ); // Add encrypt muxer filter var encryptMuxer = (IBaseFilter)Activator.CreateInstance( Type.GetTypeFromCLSID(new Guid("F1D3727A-88DE-49ab-A635-280BEFEFF902")) ); hr = filterGraph.AddFilter(encryptMuxer, "Encrypt Muxer"); DsError.ThrowExceptionForHR(hr); // Configure encryption password var cryptoConfig = encryptMuxer as IVFCryptoConfig; if (cryptoConfig != null) { // Apply password using helper method cryptoConfig.ApplyString(password); // Verify password is set hr = cryptoConfig.HavePassword(); if (hr != 0) { throw new Exception("Failed to set encryption password"); } Console.WriteLine("Encryption password configured successfully"); } else { throw new Exception("IVFCryptoConfig interface not available"); } // Set output file var fileSink = encryptMuxer as IFileSinkFilter; if (fileSink != null) { hr = fileSink.SetFileName(outputFile, null); DsError.ThrowExceptionForHR(hr); } // Build filter graph connections ICaptureGraphBuilder2 captureGraph = (ICaptureGraphBuilder2)new CaptureGraphBuilder2(); hr = captureGraph.SetFiltergraph(filterGraph); DsError.ThrowExceptionForHR(hr); // Connect video path: Source → H.264 Encoder → Encrypt Muxer hr = captureGraph.RenderStream( null, MediaType.Video, sourceFilter, videoEncoder, encryptMuxer ); DsError.ThrowExceptionForHR(hr); // Connect audio path: Source → AAC Encoder → Encrypt Muxer hr = captureGraph.RenderStream( null, MediaType.Audio, sourceFilter, audioEncoder, encryptMuxer ); DsError.ThrowExceptionForHR(hr); Console.WriteLine("Filter graph built successfully"); Console.WriteLine("Starting encryption..."); // Start encoding hr = mediaControl.Run(); DsError.ThrowExceptionForHR(hr); // Wait for completion EventCode eventCode; do { hr = mediaEvent.WaitForCompletion(1000, out eventCode); } while (eventCode == 0); Console.WriteLine("Encryption completed successfully!"); // Cleanup Marshal.ReleaseComObject(captureGraph); } catch (Exception ex) { Console.WriteLine($"ERROR: {ex.Message}"); throw; } finally { Stop(); } } public void Stop() { if (mediaControl != null) { mediaControl.Stop(); } if (filterGraph != null) { FilterGraphTools.RemoveAllFilters(filterGraph); } if (mediaEvent != null) Marshal.ReleaseComObject(mediaEvent); if (mediaControl != null) Marshal.ReleaseComObject(mediaControl); if (filterGraph != null) Marshal.ReleaseComObject(filterGraph); } } // Usage: // var encryptor = new BasicVideoEncryption(); // encryptor.EncryptVideo(@"C:\input.mp4", @"C:\output.encrypted.mp4", "MySecurePassword123"); ``` ### C++ Implementation ``` #include #include #include "encryptor_intf.h" class BasicVideoEncryption { private: IGraphBuilder* pGraph; IMediaControl* pControl; IMediaEvent* pEvent; public: BasicVideoEncryption() : pGraph(NULL), pControl(NULL), pEvent(NULL) {} HRESULT EncryptVideo(LPCWSTR inputFile, LPCWSTR outputFile, LPCWSTR password) { HRESULT hr; // Create filter graph hr = CoCreateInstance( CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void**)&pGraph ); if (FAILED(hr)) return hr; // Get control and event interfaces pGraph->QueryInterface(IID_IMediaControl, (void**)&pControl); pGraph->QueryInterface(IID_IMediaEvent, (void**)&pEvent); // Add source filter IBaseFilter* pSource = NULL; hr = pGraph->AddSourceFilter(inputFile, L"Source", &pSource); if (FAILED(hr)) goto cleanup; // Add video encoder (H.264) IBaseFilter* pVideoEncoder = NULL; hr = CoCreateInstance( CLSID_VFH264Encoder, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void**)&pVideoEncoder ); if (FAILED(hr)) goto cleanup; hr = pGraph->AddFilter(pVideoEncoder, L"H.264 Encoder"); // Add audio encoder (AAC) IBaseFilter* pAudioEncoder = NULL; hr = CoCreateInstance( CLSID_VFAACEncoder, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void**)&pAudioEncoder ); if (FAILED(hr)) goto cleanup; hr = pGraph->AddFilter(pAudioEncoder, L"AAC Encoder"); // Add encrypt muxer IBaseFilter* pMuxer = NULL; hr = CoCreateInstance( CLSID_EncryptMuxer, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void**)&pMuxer ); if (FAILED(hr)) goto cleanup; hr = pGraph->AddFilter(pMuxer, L"Encrypt Muxer"); // Configure encryption ICryptoConfig* pCrypto = NULL; hr = pMuxer->QueryInterface(IID_ICryptoConfig, (void**)&pCrypto); if (SUCCEEDED(hr)) { // Set password hr = pCrypto->put_Password( (LPBYTE)password, wcslen(password) * sizeof(wchar_t) ); if (SUCCEEDED(hr)) { // Verify password is set HRESULT hrPassword = pCrypto->HavePassword(); if (hrPassword == S_OK) { wprintf(L"Encryption password configured successfully\n"); } else { wprintf(L"WARNING: Password not set\n"); } } pCrypto->Release(); } // Set output file IFileSinkFilter* pFileSink = NULL; hr = pMuxer->QueryInterface(IID_IFileSinkFilter, (void**)&pFileSink); if (SUCCEEDED(hr)) { hr = pFileSink->SetFileName(outputFile, NULL); pFileSink->Release(); } // Build graph using Intelligent Connect ICaptureGraphBuilder2* pBuilder = NULL; hr = CoCreateInstance( CLSID_CaptureGraphBuilder2, NULL, CLSCTX_INPROC_SERVER, IID_ICaptureGraphBuilder2, (void**)&pBuilder ); if (SUCCEEDED(hr)) { pBuilder->SetFiltergraph(pGraph); // Connect video path pBuilder->RenderStream( NULL, &MEDIATYPE_Video, pSource, pVideoEncoder, pMuxer ); // Connect audio path pBuilder->RenderStream( NULL, &MEDIATYPE_Audio, pSource, pAudioEncoder, pMuxer ); pBuilder->Release(); } wprintf(L"Starting encryption...\n"); // Run the graph hr = pControl->Run(); if (FAILED(hr)) goto cleanup; // Wait for completion long evCode; pEvent->WaitForCompletion(INFINITE, &evCode); wprintf(L"Encryption completed successfully!\n"); cleanup: if (pMuxer) pMuxer->Release(); if (pVideoEncoder) pVideoEncoder->Release(); if (pAudioEncoder) pAudioEncoder->Release(); if (pSource) pSource->Release(); Stop(); return hr; } void Stop() { if (pControl) { pControl->Stop(); } if (pEvent) pEvent->Release(); if (pControl) pControl->Release(); if (pGraph) pGraph->Release(); pEvent = NULL; pControl = NULL; pGraph = NULL; } }; // Usage: // BasicVideoEncryption encryptor; // encryptor.EncryptVideo(L"C:\\input.mp4", L"C:\\output.encrypted.mp4", L"MySecurePassword123"); ``` ### Delphi Implementation ``` uses DirectShow9, ActiveX, EncryptorIntf; type TBasicVideoEncryption = class private FFilterGraph: IGraphBuilder; FMediaControl: IMediaControl; FMediaEvent: IMediaEvent; public function EncryptVideo(const InputFile, OutputFile, Password: WideString): HRESULT; procedure Stop; end; function TBasicVideoEncryption.EncryptVideo(const InputFile, OutputFile, Password: WideString): HRESULT; var SourceFilter: IBaseFilter; VideoEncoder: IBaseFilter; AudioEncoder: IBaseFilter; EncryptMuxer: IBaseFilter; CryptoConfig: IVFCryptoConfig; FileSink: IFileSinkFilter; CaptureGraph: ICaptureGraphBuilder2; EventCode: Integer; begin Result := E_FAIL; try // Create filter graph Result := CoCreateInstance(CLSID_FilterGraph, nil, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, FFilterGraph); if Failed(Result) then Exit; // Get control and event interfaces FFilterGraph.QueryInterface(IID_IMediaControl, FMediaControl); FFilterGraph.QueryInterface(IID_IMediaEvent, FMediaEvent); // Add source filter Result := FFilterGraph.AddSourceFilter(PWideChar(InputFile), 'Source', SourceFilter); if Failed(Result) then Exit; // Add video encoder (H.264) Result := CoCreateInstance(CLSID_VFH264Encoder, nil, CLSCTX_INPROC_SERVER, IID_IBaseFilter, VideoEncoder); if Succeeded(Result) then FFilterGraph.AddFilter(VideoEncoder, 'H.264 Encoder'); // Add audio encoder (AAC) Result := CoCreateInstance(CLSID_VFAACEncoder, nil, CLSCTX_INPROC_SERVER, IID_IBaseFilter, AudioEncoder); if Succeeded(Result) then FFilterGraph.AddFilter(AudioEncoder, 'AAC Encoder'); // Add encrypt muxer Result := CoCreateInstance(CLSID_EncryptMuxer, nil, CLSCTX_INPROC_SERVER, IID_IBaseFilter, EncryptMuxer); if Failed(Result) then Exit; FFilterGraph.AddFilter(EncryptMuxer, 'Encrypt Muxer'); // Configure encryption if Supports(EncryptMuxer, IVFCryptoConfig, CryptoConfig) then begin // Set password // pBuffer is opaque binary data (PByte); cast through PWideChar to reuse // the wide-string buffer, length in bytes = char count * 2. Result := CryptoConfig.put_Password(PByte(PWideChar(Password)), Length(Password) * 2); if Succeeded(Result) then begin // Verify password is set if CryptoConfig.HavePassword = S_OK then WriteLn('Encryption password configured successfully') else WriteLn('WARNING: Password not set'); end; end; // Set output file if Supports(EncryptMuxer, IFileSinkFilter, FileSink) then FileSink.SetFileName(PWideChar(OutputFile), nil); // Build graph connections Result := CoCreateInstance(CLSID_CaptureGraphBuilder2, nil, CLSCTX_INPROC_SERVER, IID_ICaptureGraphBuilder2, CaptureGraph); if Succeeded(Result) then begin CaptureGraph.SetFiltergraph(FFilterGraph); // Connect video path CaptureGraph.RenderStream(nil, @MEDIATYPE_Video, SourceFilter, VideoEncoder, EncryptMuxer); // Connect audio path CaptureGraph.RenderStream(nil, @MEDIATYPE_Audio, SourceFilter, AudioEncoder, EncryptMuxer); end; WriteLn('Starting encryption...'); // Run the graph Result := FMediaControl.Run; if Failed(Result) then Exit; // Wait for completion repeat FMediaEvent.WaitForCompletion(1000, EventCode); until EventCode <> 0; WriteLn('Encryption completed successfully!'); finally Stop; end; end; procedure TBasicVideoEncryption.Stop; begin if Assigned(FMediaControl) then FMediaControl.Stop; FMediaEvent := nil; FMediaControl := nil; FFilterGraph := nil; end; // Usage: // var // Encryptor: TBasicVideoEncryption; // begin // Encryptor := TBasicVideoEncryption.Create; // try // Encryptor.EncryptVideo('C:\input.mp4', 'C:\output.encrypted.mp4', 'MySecurePassword123'); // finally // Encryptor.Free; // end; // end; ``` --- ## Example 2: Video Decryption and Playback Decrypt an encrypted video file and play it. ### C# Implementation ## ``` public class VideoDecryption { private IFilterGraph2 filterGraph; private IMediaControl mediaControl; private IMediaEventEx mediaEvent; private IVideoWindow videoWindow; public void DecryptAndPlay(string encryptedFile, string password, IntPtr windowHandle) { try { // Create filter graph filterGraph = (IFilterGraph2)new FilterGraph(); mediaControl = (IMediaControl)filterGraph; mediaEvent = (IMediaEventEx)filterGraph; videoWindow = (IVideoWindow)filterGraph; // Add decrypt demuxer filter var decryptDemuxer = (IBaseFilter)Activator.CreateInstance( Type.GetTypeFromCLSID(new Guid("D2C761F0-9988-4f79-9B0E-FB2B79C65851")) ); int hr = filterGraph.AddFilter(decryptDemuxer, "Decrypt Demuxer"); DsError.ThrowExceptionForHR(hr); // Configure decryption (MUST use same password as encryption) var cryptoConfig = decryptDemuxer as IVFCryptoConfig; if (cryptoConfig != null) { // Apply password cryptoConfig.ApplyString(password); // Verify password is set hr = cryptoConfig.HavePassword(); if (hr != 0) { throw new Exception("Failed to set decryption password"); } Console.WriteLine("Decryption password configured successfully"); } else { throw new Exception("IVFCryptoConfig interface not available"); } // Load encrypted file var fileSource = decryptDemuxer as IFileSourceFilter; if (fileSource != null) { hr = fileSource.Load(encryptedFile, null); DsError.ThrowExceptionForHR(hr); } // Build graph - render video and audio outputs ICaptureGraphBuilder2 captureGraph = (ICaptureGraphBuilder2)new CaptureGraphBuilder2(); hr = captureGraph.SetFiltergraph(filterGraph); DsError.ThrowExceptionForHR(hr); // Render video output hr = captureGraph.RenderStream( null, MediaType.Video, decryptDemuxer, null, null ); DsError.ThrowExceptionForHR(hr); // Render audio output hr = captureGraph.RenderStream( null, MediaType.Audio, decryptDemuxer, null, null ); // Audio is optional, don't fail if not present // Configure video window hr = videoWindow.put_Owner(windowHandle); hr = videoWindow.put_WindowStyle(WindowStyle.Child | WindowStyle.ClipChildren | WindowStyle.ClipSiblings); hr = videoWindow.put_MessageDrain(windowHandle); Console.WriteLine("Starting playback..."); // Start playback hr = mediaControl.Run(); DsError.ThrowExceptionForHR(hr); Console.WriteLine("Decryption and playback started successfully!"); Marshal.ReleaseComObject(captureGraph); } catch (Exception ex) { Console.WriteLine($"ERROR: {ex.Message}"); throw; } } public void Stop() { if (mediaControl != null) { mediaControl.Stop(); } if (videoWindow != null) { videoWindow.put_Visible(OABool.False); videoWindow.put_Owner(IntPtr.Zero); } if (filterGraph != null) { FilterGraphTools.RemoveAllFilters(filterGraph); } if (videoWindow != null) Marshal.ReleaseComObject(videoWindow); if (mediaEvent != null) Marshal.ReleaseComObject(mediaEvent); if (mediaControl != null) Marshal.ReleaseComObject(mediaControl); if (filterGraph != null) Marshal.ReleaseComObject(filterGraph); } public void SetVideoWindowSize(int width, int height) { if (videoWindow != null) { videoWindow.SetWindowPosition(0, 0, width, height); } } } // Usage: // var decryptor = new VideoDecryption(); // decryptor.DecryptAndPlay(@"C:\output.encrypted.mp4", "MySecurePassword123", this.Handle); ``` ## Example 3: Using File as Encryption Key Use a file's content as the encryption key instead of a password. ### C# Implementation ``` public class FileKeyEncryption { public void EncryptWithFileKey(string inputFile, string outputFile, string keyFile) { var filterGraph = (IFilterGraph2)new FilterGraph(); var mediaControl = (IMediaControl)filterGraph; try { // Setup filter graph (source, encoders, muxer) // ... (same as Example 1) // Add encrypt muxer var encryptMuxer = (IBaseFilter)Activator.CreateInstance( Type.GetTypeFromCLSID(new Guid("F1D3727A-88DE-49ab-A635-280BEFEFF902")) ); filterGraph.AddFilter(encryptMuxer, "Encrypt Muxer"); // Configure encryption using file as key var cryptoConfig = encryptMuxer as IVFCryptoConfig; if (cryptoConfig != null) { // Use file content as encryption key (SHA-256 hash of file) cryptoConfig.ApplyFile(keyFile); Console.WriteLine($"Using key file: {keyFile}"); Console.WriteLine("File content hashed with SHA-256 for encryption"); // Verify int hr = cryptoConfig.HavePassword(); if (hr == 0) { Console.WriteLine("Encryption key configured successfully"); } } // Continue with filter graph setup and encoding... } finally { // Cleanup } } public void DecryptWithFileKey(string encryptedFile, string keyFile) { var filterGraph = (IFilterGraph2)new FilterGraph(); try { // Add decrypt demuxer var decryptDemuxer = (IBaseFilter)Activator.CreateInstance( Type.GetTypeFromCLSID(new Guid("D2C761F0-9988-4f79-9B0E-FB2B79C65851")) ); filterGraph.AddFilter(decryptDemuxer, "Decrypt Demuxer"); // Configure decryption using same key file var cryptoConfig = decryptDemuxer as IVFCryptoConfig; if (cryptoConfig != null) { // MUST use same key file as encryption cryptoConfig.ApplyFile(keyFile); Console.WriteLine($"Using key file for decryption: {keyFile}"); } // Continue with playback setup... } finally { // Cleanup } } } // Usage: // var encryptor = new FileKeyEncryption(); // encryptor.EncryptWithFileKey(@"C:\input.mp4", @"C:\output.encrypted.mp4", @"C:\keys\encryption.key"); // encryptor.DecryptWithFileKey(@"C:\output.encrypted.mp4", @"C:\keys\encryption.key"); ``` --- ## Example 4: Using Binary Key Data Generate and use binary key data for encryption. ### C# Implementation ## ``` using System.Security.Cryptography; using System.IO; public class BinaryKeyEncryption { public byte[] GenerateRandomKey(int keySize = 32) { // Generate cryptographically secure random key byte[] key = new byte[keySize]; using (var rng = new RNGCryptoServiceProvider()) { rng.GetBytes(key); } return key; } public void SaveKeyToFile(byte[] key, string keyFile) { File.WriteAllBytes(keyFile, key); Console.WriteLine($"Key saved to: {keyFile}"); } public byte[] LoadKeyFromFile(string keyFile) { return File.ReadAllBytes(keyFile); } public void EncryptWithBinaryKey(string inputFile, string outputFile, byte[] keyData) { var filterGraph = (IFilterGraph2)new FilterGraph(); try { // Setup filter graph and add encrypt muxer var encryptMuxer = (IBaseFilter)Activator.CreateInstance( Type.GetTypeFromCLSID(new Guid("F1D3727A-88DE-49ab-A635-280BEFEFF902")) ); filterGraph.AddFilter(encryptMuxer, "Encrypt Muxer"); // Configure encryption with binary key var cryptoConfig = encryptMuxer as IVFCryptoConfig; if (cryptoConfig != null) { // Apply binary key (will be hashed with SHA-256) cryptoConfig.ApplyBinary(keyData); Console.WriteLine($"Binary key applied (length: {keyData.Length} bytes)"); // Verify int hr = cryptoConfig.HavePassword(); if (hr == 0) { Console.WriteLine("Encryption key configured successfully"); } } // Continue with encoding... } finally { // Cleanup } } public void CompleteWorkflow() { // Generate random encryption key byte[] encryptionKey = GenerateRandomKey(32); Console.WriteLine($"Generated {encryptionKey.Length * 8}-bit encryption key"); // Save key securely string keyFile = @"C:\keys\video_encryption_key.bin"; SaveKeyToFile(encryptionKey, keyFile); // Encrypt video with binary key EncryptWithBinaryKey( @"C:\input.mp4", @"C:\output.encrypted.mp4", encryptionKey ); Console.WriteLine("Video encrypted successfully!"); Console.WriteLine($"Key file: {keyFile}"); Console.WriteLine("Keep this key file secure - it's required for decryption!"); // Later, for decryption: // byte[] key = LoadKeyFromFile(keyFile); // DecryptWithBinaryKey(@"C:\output.encrypted.mp4", key); } } // Usage: // var encryptor = new BinaryKeyEncryption(); // encryptor.CompleteWorkflow(); ``` ## Example 5: Encryption with Custom Encoder Settings Encrypt video with specific H.264 encoding parameters. ### C# Implementation ``` public class CustomEncodingEncryption { public void EncryptWithCustomSettings( string inputFile, string outputFile, string password, int videoBitrate = 5000000, int audioBitrate = 192000) { var filterGraph = (IFilterGraph2)new FilterGraph(); var mediaControl = (IMediaControl)filterGraph; try { // Add source filterGraph.AddSourceFilter(inputFile, "Source", out IBaseFilter sourceFilter); // Add and configure H.264 encoder var videoEncoder = FilterGraphTools.AddFilterFromClsid( filterGraph, Consts.CLSID_VFH264Encoder, "H.264 Encoder" ); // Configure H.264 encoder (if interface available) var h264Config = videoEncoder as IH264Encoder; if (h264Config != null) { h264Config.put_Bitrate(videoBitrate); h264Config.put_Profile(77); // Main profile h264Config.put_Level(41); // Level 4.1 (1080p) h264Config.put_RateControl(1); // CBR h264Config.put_GOP(60); // 2 seconds at 30fps Console.WriteLine($"H.264 configured: {videoBitrate / 1000000.0} Mbps, Main profile, Level 4.1"); } // Add and configure AAC encoder var audioEncoder = FilterGraphTools.AddFilterFromClsid( filterGraph, Consts.CLSID_VFAACEncoder, "AAC Encoder" ); // Configure AAC encoder (if interface available) var aacConfig = audioEncoder as IVFAACEncoder; if (aacConfig != null) { aacConfig.SetBitrate((uint)audioBitrate); aacConfig.SetProfile(2); // AAC-LC aacConfig.SetOutputFormat(0); // Raw AAC for MP4 Console.WriteLine($"AAC configured: {audioBitrate / 1000} kbps, AAC-LC profile"); } // Add encrypt muxer var encryptMuxer = (IBaseFilter)Activator.CreateInstance( Type.GetTypeFromCLSID(new Guid("F1D3727A-88DE-49ab-A635-280BEFEFF902")) ); filterGraph.AddFilter(encryptMuxer, "Encrypt Muxer"); // Configure encryption var cryptoConfig = encryptMuxer as IVFCryptoConfig; if (cryptoConfig != null) { cryptoConfig.ApplyString(password); Console.WriteLine("Encryption configured"); } // Set output file var fileSink = encryptMuxer as IFileSinkFilter; fileSink?.SetFileName(outputFile, null); // Build connections ICaptureGraphBuilder2 captureGraph = (ICaptureGraphBuilder2)new CaptureGraphBuilder2(); captureGraph.SetFiltergraph(filterGraph); captureGraph.RenderStream(null, MediaType.Video, sourceFilter, videoEncoder, encryptMuxer); captureGraph.RenderStream(null, MediaType.Audio, sourceFilter, audioEncoder, encryptMuxer); Console.WriteLine("Starting encoding with custom settings..."); // Run encoding int hr = mediaControl.Run(); DsError.ThrowExceptionForHR(hr); // Wait for completion var mediaEvent = (IMediaEventEx)filterGraph; EventCode eventCode; do { hr = mediaEvent.WaitForCompletion(1000, out eventCode); } while (eventCode == 0); Console.WriteLine("Encoding and encryption completed!"); Marshal.ReleaseComObject(captureGraph); } finally { // Cleanup mediaControl?.Stop(); FilterGraphTools.RemoveAllFilters(filterGraph); } } } // Usage: // var encryptor = new CustomEncodingEncryption(); // encryptor.EncryptWithCustomSettings( // @"C:\input.mp4", // @"C:\output.encrypted.mp4", // "MySecurePassword123", // videoBitrate: 8000000, // 8 Mbps // audioBitrate: 256000 // 256 kbps // ); ``` --- ## Example 6: Error Handling and Validation Comprehensive error handling for encryption/decryption. ### C# Implementation ## ``` public class RobustEncryption { private IFilterGraph2 filterGraph; private IMediaControl mediaControl; public enum EncryptionResult { Success, FileNotFound, InvalidPassword, InterfaceNotAvailable, FilterGraphError, EncodingError, Unknown } public EncryptionResult EncryptVideoSafely( string inputFile, string outputFile, string password) { try { // Validate inputs if (string.IsNullOrEmpty(inputFile)) { Console.WriteLine("ERROR: Input file path is empty"); return EncryptionResult.FileNotFound; } if (!File.Exists(inputFile)) { Console.WriteLine($"ERROR: Input file not found: {inputFile}"); return EncryptionResult.FileNotFound; } if (string.IsNullOrEmpty(password)) { Console.WriteLine("ERROR: Password is empty"); return EncryptionResult.InvalidPassword; } if (password.Length < 8) { Console.WriteLine("WARNING: Password is less than 8 characters (not recommended)"); } Console.WriteLine("Input validation passed"); // Create filter graph filterGraph = (IFilterGraph2)new FilterGraph(); if (filterGraph == null) { Console.WriteLine("ERROR: Failed to create filter graph"); return EncryptionResult.FilterGraphError; } mediaControl = (IMediaControl)filterGraph; // Add source filter int hr = filterGraph.AddSourceFilter(inputFile, "Source", out IBaseFilter sourceFilter); if (hr != 0 || sourceFilter == null) { Console.WriteLine($"ERROR: Failed to add source filter (HRESULT: 0x{hr:X8})"); return EncryptionResult.FilterGraphError; } // Add encoders var videoEncoder = FilterGraphTools.AddFilterFromClsid( filterGraph, Consts.CLSID_VFH264Encoder, "H.264 Encoder" ); if (videoEncoder == null) { Console.WriteLine("ERROR: Failed to create video encoder"); return EncryptionResult.FilterGraphError; } var audioEncoder = FilterGraphTools.AddFilterFromClsid( filterGraph, Consts.CLSID_VFAACEncoder, "AAC Encoder" ); // Add encrypt muxer var encryptMuxer = (IBaseFilter)Activator.CreateInstance( Type.GetTypeFromCLSID(new Guid("F1D3727A-88DE-49ab-A635-280BEFEFF902")) ); if (encryptMuxer == null) { Console.WriteLine("ERROR: Failed to create encrypt muxer"); return EncryptionResult.FilterGraphError; } hr = filterGraph.AddFilter(encryptMuxer, "Encrypt Muxer"); if (hr != 0) { Console.WriteLine($"ERROR: Failed to add encrypt muxer (HRESULT: 0x{hr:X8})"); return EncryptionResult.FilterGraphError; } // Configure encryption var cryptoConfig = encryptMuxer as IVFCryptoConfig; if (cryptoConfig == null) { Console.WriteLine("ERROR: IVFCryptoConfig interface not available"); return EncryptionResult.InterfaceNotAvailable; } try { cryptoConfig.ApplyString(password); } catch (Exception ex) { Console.WriteLine($"ERROR: Failed to apply password: {ex.Message}"); return EncryptionResult.InvalidPassword; } // Verify password is set hr = cryptoConfig.HavePassword(); if (hr != 0) { Console.WriteLine("ERROR: Password verification failed"); return EncryptionResult.InvalidPassword; } Console.WriteLine("Encryption password configured successfully"); // Set output file var fileSink = encryptMuxer as IFileSinkFilter; if (fileSink != null) { hr = fileSink.SetFileName(outputFile, null); if (hr != 0) { Console.WriteLine($"ERROR: Failed to set output file (HRESULT: 0x{hr:X8})"); return EncryptionResult.FilterGraphError; } } // Build filter graph ICaptureGraphBuilder2 captureGraph = (ICaptureGraphBuilder2)new CaptureGraphBuilder2(); hr = captureGraph.SetFiltergraph(filterGraph); hr = captureGraph.RenderStream( null, MediaType.Video, sourceFilter, videoEncoder, encryptMuxer ); if (hr != 0) { Console.WriteLine($"WARNING: Video connection failed (HRESULT: 0x{hr:X8})"); } hr = captureGraph.RenderStream( null, MediaType.Audio, sourceFilter, audioEncoder, encryptMuxer ); if (hr != 0) { Console.WriteLine($"WARNING: Audio connection failed (HRESULT: 0x{hr:X8}) - continuing without audio"); } Console.WriteLine("Filter graph built successfully"); Console.WriteLine("Starting encryption..."); // Start encoding hr = mediaControl.Run(); if (hr != 0) { Console.WriteLine($"ERROR: Failed to start encoding (HRESULT: 0x{hr:X8})"); return EncryptionResult.EncodingError; } // Monitor progress var mediaEvent = (IMediaEventEx)filterGraph; EventCode eventCode; long param1, param2; do { hr = mediaEvent.GetEvent(out eventCode, out param1, out param2, 1000); if (hr == 0) { mediaEvent.FreeEventParams(eventCode, param1, param2); if (eventCode == EventCode.Complete) { break; } else if (eventCode == EventCode.ErrorAbort) { Console.WriteLine($"ERROR: Encoding aborted (event code: {eventCode})"); return EncryptionResult.EncodingError; } } } while (true); Console.WriteLine("Encryption completed successfully!"); // Verify output file exists if (File.Exists(outputFile)) { FileInfo fi = new FileInfo(outputFile); Console.WriteLine($"Output file created: {outputFile}"); Console.WriteLine($"File size: {fi.Length / (1024.0 * 1024.0):F2} MB"); } else { Console.WriteLine("WARNING: Output file not found after encoding"); } Marshal.ReleaseComObject(captureGraph); return EncryptionResult.Success; } catch (Exception ex) { Console.WriteLine($"EXCEPTION: {ex.Message}"); Console.WriteLine($"Stack trace: {ex.StackTrace}"); return EncryptionResult.Unknown; } finally { Cleanup(); } } private void Cleanup() { try { if (mediaControl != null) { mediaControl.Stop(); Marshal.ReleaseComObject(mediaControl); } if (filterGraph != null) { FilterGraphTools.RemoveAllFilters(filterGraph); Marshal.ReleaseComObject(filterGraph); } } catch (Exception ex) { Console.WriteLine($"Cleanup error: {ex.Message}"); } } } // Usage: // var encryptor = new RobustEncryption(); // var result = encryptor.EncryptVideoSafely( // @"C:\input.mp4", // @"C:\output.encrypted.mp4", // "MySecurePassword123" // ); // // if (result == RobustEncryption.EncryptionResult.Success) // { // Console.WriteLine("SUCCESS!"); // } // else // { // Console.WriteLine($"FAILED: {result}"); // } ``` ## Best Practices ### Password Security 1. **Use Strong Passwords** 2. Minimum 16 characters 3. Mix of uppercase, lowercase, numbers, symbols 4. Avoid dictionary words 5. Use password managers to generate/store 6. **Key Storage** 7. Never hardcode passwords in source code 8. Use secure key storage (Windows DPAPI, KeyVault, etc.) 9. Implement proper access controls 10. **Key Distribution** 11. Use secure channels for key distribution 12. Consider public-key encryption for key exchange 13. Implement key rotation policies ### Implementation Security **GOOD: Secure password handling** ``` public void SetEncryptionPassword(IVFCryptoConfig config) { // Get password from secure storage string password = SecureStorage.GetPassword(); try { config.ApplyString(password); } finally { // Clear password from memory password = null; GC.Collect(); } } ``` **BAD: Hardcoded password** ``` public void SetEncryptionPassword(IVFCryptoConfig config) { config.ApplyString("MyPassword123"); // DON'T DO THIS! } ``` ### File Security - Use appropriate file permissions for encrypted files - Implement secure deletion for temporary files - Consider encrypting key files with additional encryption - Log access to encrypted content for audit trails ### Implementation Guidelines 1. **Always Validate Inputs** 2. Check file existence before processing 3. Validate password is not empty 4. Verify filter interfaces are available 5. **Error Handling** 6. Check HRESULT values from COM calls 7. Use try-catch blocks for exceptions 8. Provide meaningful error messages 9. **Resource Management** 10. Always release COM objects 11. Use `finally` blocks for cleanup 12. Stop filter graph before releasing 13. **Testing** 14. Test with various input formats 15. Verify encrypted files can be decrypted 16. Test error conditions (wrong password, etc.) --- ## Troubleshooting ### Common Error Codes | HRESULT | Description | Solution | | --- | --- | --- | | `E_INVALIDARG` | Invalid buffer or size | Check buffer pointer and size parameters | | `E_POINTER` | Null pointer | Ensure pointers are valid before calling | | `E_FAIL` | General failure | Check filter state and configuration | | `S_FALSE` | No password set | Call `put_Password` before `HavePassword` | | ### Error Handling Example | | | | ``` public bool ConfigureEncryption(IBaseFilter muxer, string password) { var cryptoConfig = muxer as IVFCryptoConfig; if (cryptoConfig == null) { Console.WriteLine("ERROR: Filter does not support IVFCryptoConfig"); return false; } try { // Set password cryptoConfig.ApplyString(password); // Verify int hr = cryptoConfig.HavePassword(); if (hr != 0) { Console.WriteLine("ERROR: Password not set correctly"); return false; } Console.WriteLine("Encryption configured successfully"); return true; } catch (Exception ex) { Console.WriteLine($"ERROR: Failed to configure encryption: {ex.Message}"); return false; } } ``` | | | | --- | | | ### Common Issues #### "Filter not registered" Error **Problem**: CLSID not found **Solution**: ``` # Register filters (run as Administrator) regsvr32 "C:\Path\To\EncryptMuxer.ax" regsvr32 "C:\Path\To\DecryptDemuxer.ax" ``` #### "Interface not available" Error **Problem**: Cannot query IVFCryptoConfig **Solution**: - Verify filter version is correct - Check filter is properly registered - Ensure COM interfaces are compatible #### Decryption Fails with Garbled Video **Problem**: Wrong password used for decryption **Solution**: - Verify same password is used for encryption and decryption - Check password encoding (Unicode vs. ANSI) - Ensure no typos in password #### Output File is Empty or Corrupt **Problem**: Encoding failed silently **Solution**: - Check all encoder filters are properly connected - Verify encoder configurations are valid - Monitor IMediaEventEx for error events - Check disk space is available --- ## See Also - [Video Encryption SDK Overview](../) - Product features - [Interface Reference](../interface-reference/) - Complete API documentation - [DirectShow Encoding Filters Pack](../../filters-enc/) - Compatible encoders - [GitHub Samples](https://github.com/visioforge/directshow-samples/tree/main/Video%20Encryption%20SDK) - Complete source code ---END OF PAGE--- ## AES-256 Video Encryption Using DirectShow COM Filters **URL:** https://www.visioforge.com/help/docs/directshow/video-encryption-sdk/ **Description:** Encrypt H.264/AAC MP4 video with AES-256 using DirectShow filters. VisioForge SDK with password and binary key modes for C++, C#, and Delphi. **Tags:** Video Encryption SDK, DirectShow, C++, Windows **API:** IVFCryptoConfig, IVFPasswordProvider # Video Encryption SDK ## Introduction to Video Encryption The [Video Encryption SDK](https://www.visioforge.com/video-encryption-sdk) provides robust tools for encoding video files into MP4 H264/AAC format with advanced encryption capabilities. Developers can secure their media content using custom passwords or binary data encryption methods. The SDK integrates seamlessly with any DirectShow application through a complete set of filters. These filters come with extensive interfaces allowing developers to fine-tune settings according to specific security requirements and implementation needs. --- ## Installation Before using the code samples and integrating the SDK into your application, you must first install the Video Encryption SDK from the [product page](https://www.visioforge.com/video-encryption-sdk). **Installation Steps**: 1. Download the SDK installer from the product page 2. Run the installer with administrative privileges 3. The installer will register all necessary DirectShow filters 4. Sample applications and source code will be available in the installation directory **Note**: The SDK filters must be properly registered on the system before they can be used in your applications. The installer handles this automatically. --- ## Integration Flexibility You can implement the SDK in various DirectShow applications as filters for both encryption and decryption processes. The system works effectively with: - Live video sources - File-based video sources - Software video encoders - GPU-accelerated video encoders from the [DirectShow Encoding Filters pack](https://www.visioforge.com/encoding-filters-pack) (available separately) - Third-party DirectShow filters for additional video encoding options ## Key Features and Capabilities ### Core Functionality - **Secure Encryption/Decryption**: Process video files or capture streams with robust security algorithms - **Format Support**: Full H264 encoder support for video content - **Audio Handling**: Complete AAC encoder support for audio streams - **Flexible Security Options**: Implement encryption using either binary data or string passwords ### Performance Optimization - AES-256 encryption engine for maximum security - CPU hardware acceleration support - GPU acceleration compatibility - Optimized for high-speed encryption processes ## Development Resources ### Code Samples and Documentation The SDK includes comprehensive code samples for multiple programming languages: - C# implementation examples - C++ reference code - Delphi sample projects These samples provide practical implementation guidance for developers building secure video applications. ### Demo Application Explore the included Video Encryptor application for a hands-on demonstration of the SDK's capabilities in a working environment. --- ## API Reference ### Core Interfaces The SDK provides comprehensive COM interfaces for encryption and decryption: #### IVFCryptoConfig Primary interface for configuring encryption settings on the muxer filter (encryption) and demuxer filter (decryption). **GUID**: `{BAA5BD1E-3B30-425e-AB3B-CC20764AC253}` **Methods**: - `put_Provider` - Set password provider for advanced scenarios (binary keys, dynamic passwords) - `get_Provider` - Get password provider interface - `put_Password` - Set encryption password or key directly (binary data) - `HavePassword` - Check if password is set #### IVFPasswordProvider Callback interface for advanced password provision scenarios such as binary data keys, dynamic password generation, or custom key derivation. **GUID**: `{6F8162B5-778D-42b5-9242-1BBABB24FFC4}` **Methods**: - `QueryPassword` - Query password for specific file **Use Cases**: - Binary key data provision - Dynamic password generation - File-specific encryption keys - Custom key derivation functions #### Helper Classes The SDK includes helper extension methods for .NET developers: - `ApplyString` - Apply string password (hashed with SHA-256) - `ApplyFile` - Use file as encryption key (SHA-256 hash of file content) - `ApplyBinary` - Apply binary key data (hashed with SHA-256) ### Filter CLSIDs | Filter | CLSID | Purpose | | --- | --- | --- | | **Encrypt Muxer** | `{F1D3727A-88DE-49ab-A635-280BEFEFF902}` | Muxer with encryption | | **Decrypt Demuxer** | `{D2C761F0-9988-4f79-9B0E-FB2B79C65851}` | Demuxer with decryption | For detailed interface documentation and code examples, see the [Interface Reference](interface-reference/). --- ## Code Examples ### Quick Start - Encryption #### C# Example ``` using VisioForge.DirectShowAPI; // Get crypto config interface from encrypt muxer var cryptoConfig = muxerFilter as IVFCryptoConfig; if (cryptoConfig != null) { // Apply string password cryptoConfig.ApplyString("MySecurePassword123"); // Or use file as key // cryptoConfig.ApplyFile(@"C:\keys\mykey.bin"); // Or use binary data // byte[] keyData = new byte[] { 0x01, 0x02, 0x03, ... }; // cryptoConfig.ApplyBinary(keyData); } ``` #### C++ Example ``` #include "encryptor_intf.h" ICryptoConfig* pCrypto = nullptr; hr = pMuxer->QueryInterface(IID_ICryptoConfig, (void**)&pCrypto); if (SUCCEEDED(hr)) { // Set password const wchar_t* password = L"MySecurePassword123"; hr = pCrypto->put_Password( (LPBYTE)password, wcslen(password) * sizeof(wchar_t) ); pCrypto->Release(); } ``` ### Decryption #### C# Example ``` // Get crypto config interface from decrypt demuxer var cryptoConfig = demuxerFilter as IVFCryptoConfig; if (cryptoConfig != null) { // Must use same password/key as encryption cryptoConfig.ApplyString("MySecurePassword123"); } ``` For complete examples including filter graph setup, see the [Examples Page](examples/). --- ## Sample Applications The SDK includes working sample applications demonstrating encryption and decryption workflows: ### Included Samples - **Encryption Demo** - Demonstrates video file encryption with H.264/AAC encoding - **Player Demo** - Shows decryption and playback of encrypted video files ### GitHub Repository Complete source code for all samples is available: - [Video Encryption SDK Samples](https://github.com/visioforge/directshow-samples/tree/main/Video%20Encryption%20SDK) - C#, C++, and Delphi examples These samples include: - Complete filter graph construction - Encryption configuration - Decryption and playback - Error handling - Best practices implementation --- ## Licensing Information - [End User License Agreement](../../eula/) ## Version History ### Version 11.4 - Full compatibility with VisioForge .Net SDKs 11.4 - Enhanced Nvidia NVENC support for H264 and H265 video encoders - Improved Intel QuickSync support for H264 video encoder - Added NV12 colorspace support for enhanced performance ### Version 11.0 - Complete compatibility with VisioForge .Net SDKs 11.0 - Enhanced GPU encoders support - Upgraded AAC encoder functionality ### Version 10.0 - Full compatibility with VisioForge .Net SDKs 10.0 - Enhanced compatibility with H264 and H265 video formats - Integrated AMD AMF acceleration support - Added Intel QuickSync technology support ### Version 9.0 - Significantly improved encryption processing speed - Added CPU hardware acceleration capabilities - Implemented new engine based on AES-256 encryption - Added file usage as a key (with binary array support) - Integrated NVENC support for GPU acceleration - Enhanced AAC HE encoder support ### Version 8.0 - Updated video and audio encoders - Improved filter encryption performance ### Version 7.0 - Initial release as a standalone product - Previously integrated within Video Capture SDK, Video Edit SDK, and Media Player SDK - Compatible with any DirectShow application without requiring additional VisioForge SDKs --- ## Resources - [Product Page](https://www.visioforge.com/video-encryption-sdk) - Purchase, licensing, and product information - [Sample Applications](https://github.com/visioforge/directshow-samples/tree/main/Video%20Encryption%20SDK) - Complete source code examples --- ## See Also - [Interface Reference](interface-reference/) - Complete API documentation - [Examples](examples/) - Comprehensive code examples for encryption and decryption - [DirectShow Encoding Filters Pack](../filters-enc/) - Compatible video encoders (H.264, H.265, AAC) ---END OF PAGE--- ## IVFCryptoConfig COM Interface - Video Encryption API **URL:** https://www.visioforge.com/help/docs/directshow/video-encryption-sdk/interface-reference/ **Description:** IVFCryptoConfig and IVFPasswordProvider COM interfaces for AES-256 video encryption in DirectShow. Methods, GUIDs, and usage for C++, C#, Delphi. **Tags:** Video Encryption SDK, DirectShow, C++, Windows, C# **API:** IVFCryptoConfig, IVFPasswordProvider, IBaseFilter, MuxerFilter # Video Encryption SDK - Interface Reference ## Overview The Video Encryption SDK provides COM interfaces for encrypting and decrypting MP4 video files with AES-256 encryption. This reference covers all interfaces, methods, and helper classes for C++, C#, and Delphi developers. --- ## IVFCryptoConfig Interface Primary interface for configuring encryption passwords and keys on both the encryption muxer and decryption demuxer filters. ### Interface GUID ``` {BAA5BD1E-3B30-425e-AB3B-CC20764AC253} ``` ### Inheritance ## Inherits from `IUnknown` ### Interface Definitions #### C++ Definition ``` #include "encryptor_intf.h" // {BAA5BD1E-3B30-425e-AB3B-CC20764AC253} DEFINE_GUID(IID_ICryptoConfig, 0xbaa5bd1e, 0x3b30, 0x425e, 0xab, 0x3b, 0xcc, 0x20, 0x76, 0x4a, 0xc2, 0x53); DECLARE_INTERFACE_(ICryptoConfig, IUnknown) { STDMETHOD(put_Provider)(THIS_ IPasswordProvider* pProvider) PURE; STDMETHOD(get_Provider)(THIS_ IPasswordProvider** ppProvider) PURE; STDMETHOD(put_Password)(THIS_ LPBYTE pBuffer, LONG lSize) PURE; STDMETHOD(HavePassword)(THIS_) PURE; }; ``` #### C# Definition ``` using System; using System.Runtime.InteropServices; [ComImport] [Guid("BAA5BD1E-3B30-425e-AB3B-CC20764AC253")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] public interface IVFCryptoConfig { // NOTE: put_Provider / get_Provider are stubs in the managed wrapper — // the parameter is literally named `passwordProviderNotUsed` because the // .NET marshaling for IVFPasswordProvider is not wired up. From C# call // put_Password directly with the binary key bytes. [PreserveSig] int put_Provider([In] IVFPasswordProvider passwordProviderNotUsed); [PreserveSig] int get_Provider([Out] IVFPasswordProvider passwordProviderNotUsed); [PreserveSig] int put_Password(IntPtr buffer, [In] int size); [PreserveSig] int HavePassword(); } ``` C# password provider not supported The managed `put_Provider` / `get_Provider` wrappers are **non-functional stubs** (note the `passwordProviderNotUsed` parameter name). To set passwords from C#, call `put_Password` with the raw key bytes via `IntPtr` (or use the `ApplyString` helper). Custom `IVFPasswordProvider` callbacks must be implemented from C++ or Delphi. #### Delphi Definition ``` type IVFCryptoConfig = interface(IUnknown) ['{BAA5BD1E-3B30-425e-AB3B-CC20764AC253}'] function put_Provider(pProvider: IUnknown): HRESULT; stdcall; function get_Provider(out pProvider: IUnknown): HRESULT; stdcall; function put_Password(pBuffer: PByte; lSize: Integer): HRESULT; stdcall; function HavePassword(): HRESULT; stdcall; end; ``` Naming across language wrappers The native C++ header (`encryptor_intf.h`) uses `ICryptoConfig` / `IPasswordProvider`. The C# and Delphi wrappers expose the same interface as `IVFCryptoConfig` / `IVFPasswordProvider`. Both names refer to the **same** GUID `{BAA5BD1E-3B30-425e-AB3B-CC20764AC253}`. --- ### Methods #### put\_Provider Sets a password provider callback interface for advanced encryption scenarios. **C++ Syntax**: ``` HRESULT put_Provider(IPasswordProvider* pProvider); ``` **C# Syntax**: ``` int put_Provider(IVFPasswordProvider passwordProvider); ``` **Parameters**: - `pProvider` / `passwordProvider` - Password provider interface that implements `IVFPasswordProvider` **Return Value**: - `S_OK` (0) on success - Error HRESULT on failure **Remarks**: Use this method for advanced scenarios where you need: - Dynamic password generation based on file name - Binary key data provision through a callback - Custom key derivation functions - File-specific encryption keys - Per-file password policies For simple string passwords, using `put_Password` directly is more straightforward. The password provider is useful when you need runtime password determination or when implementing a custom key management system. **Example Use Cases**: 1. **Binary Key Provider**: Provide 256-bit encryption keys from a key management system 2. **Dynamic Passwords**: Generate different passwords based on file names or metadata 3. **Key Derivation**: Implement custom key derivation functions (PBKDF2, Argon2, etc.) 4. **Secure Storage Integration**: Retrieve keys from hardware security modules (HSM) or key vaults --- #### get\_Provider Gets the currently set password provider interface. **C++ Syntax**: ``` HRESULT get_Provider(IPasswordProvider** ppProvider); ``` **C# Syntax**: ``` int get_Provider(IVFPasswordProvider passwordProvider); ``` **Parameters**: - `ppProvider` / `passwordProvider` - Pointer to receive password provider interface **Return Value**: - `S_OK` (0) on success - `E_POINTER` if ppProvider is NULL - Error HRESULT on failure **Remarks**: Retrieves the password provider interface that was previously set with `put_Provider`. Returns NULL if no provider has been set. --- #### put\_Password Sets the encryption password or binary key data. **C++ Syntax**: ``` HRESULT put_Password(LPBYTE pBuffer, LONG lSize); ``` **C# Syntax**: ``` int put_Password(IntPtr buffer, int size); ``` **Delphi Syntax**: ``` function put_Password(pBuffer: PByte; lSize: Integer): HRESULT; stdcall; ``` **Parameters**: - `pBuffer` / `buffer` - Pointer to password or binary key data - `lSize` / `size` - Size of buffer in bytes **Return Value**: - `S_OK` (0) on success - `E_INVALIDARG` if buffer is null or size is invalid - Error HRESULT on failure **Remarks**: - The SDK uses AES-256 encryption, which requires a 256-bit (32-byte) key - If you provide a password string, it should be hashed to 256 bits (use SHA-256) - The same password/key must be used for both encryption and decryption - For string passwords, use the helper methods (C# only) or hash manually - Binary data is hashed with SHA-256 internally to generate the encryption key **Example (C++)**: ``` ICryptoConfig* pCrypto = nullptr; hr = pMuxer->QueryInterface(IID_ICryptoConfig, (void**)&pCrypto); if (SUCCEEDED(hr)) { // Using string password (must convert to proper format) const wchar_t* password = L"MySecurePassword123"; hr = pCrypto->put_Password( (LPBYTE)password, wcslen(password) * sizeof(wchar_t) ); pCrypto->Release(); } ``` **Example (C#)**: ``` var cryptoConfig = muxerFilter as IVFCryptoConfig; if (cryptoConfig != null) { // Using helper method (recommended) cryptoConfig.ApplyString("MySecurePassword123"); // Or manually with IntPtr string password = "MySecurePassword123"; IntPtr ptr = Marshal.StringToCoTaskMemUni(password); try { cryptoConfig.put_Password(ptr, password.Length * 2); } finally { Marshal.FreeCoTaskMem(ptr); } } ``` **Example (Delphi)**: ``` var CryptoConfig: IVFCryptoConfig; Password: WideString; begin if Supports(MuxerFilter, IVFCryptoConfig, CryptoConfig) then begin Password := 'MySecurePassword123'; // pBuffer is opaque binary data (LPBYTE); cast the wide-string pointer to PByte // and pass byte length (UTF-16 chars * 2). CryptoConfig.put_Password(PByte(PWideChar(Password)), Length(Password) * 2); end; end; ``` --- #### HavePassword Checks whether a password has been set on the filter. **C++ Syntax**: ``` HRESULT HavePassword(); ``` **C# Syntax**: ``` int HavePassword(); ``` **Delphi Syntax**: ``` function HavePassword(): HRESULT; stdcall; ``` **Parameters**: None **Return Value**: - `S_OK` (0) if password is set - `S_FALSE` (1) if no password is set - Error HRESULT on failure **Remarks**: Use this method to verify that a password has been configured before starting the filter graph. **Example (C++)**: ``` ICryptoConfig* pCrypto = nullptr; hr = pMuxer->QueryInterface(IID_ICryptoConfig, (void**)&pCrypto); if (SUCCEEDED(hr)) { HRESULT hrPassword = pCrypto->HavePassword(); if (hrPassword == S_OK) { // Password is set, can start encoding } else { // No password set MessageBox(NULL, L"Please set encryption password", L"Error", MB_OK); } pCrypto->Release(); } ``` **Example (C#)**: ``` var cryptoConfig = muxerFilter as IVFCryptoConfig; if (cryptoConfig != null) { int hr = cryptoConfig.HavePassword(); if (hr == 0) // S_OK { // Password is set Console.WriteLine("Password configured successfully"); } else { // No password Console.WriteLine("Warning: No password set"); } } ``` --- ## IVFPasswordProvider Interface Callback interface for advanced password provision scenarios including binary key data, dynamic password generation, and custom key derivation functions. ### Interface GUID ``` {6F8162B5-778D-42b5-9242-1BBABB24FFC4} ``` ### Inheritance ## Inherits from `IUnknown` ### Interface Definitions #### C++ Definition ``` // {6F8162B5-778D-42b5-9242-1BBABB24FFC4} DEFINE_GUID(IID_IPasswordProvider, 0x6f8162b5, 0x778d, 0x42b5, 0x92, 0x42, 0x1b, 0xba, 0xbb, 0x24, 0xff, 0xc4); DECLARE_INTERFACE_(IPasswordProvider, IUnknown) { STDMETHOD(QueryPassword)( THIS_ LPCWSTR pszFileName, LPBYTE pBuffer, LONG* plSize ) PURE; }; ``` #### C# Definition ``` [ComImport] [Guid("6F8162B5-778D-42b5-9242-1BBABB24FFC4")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] public interface IVFPasswordProvider { [PreserveSig] int QueryPassword( [MarshalAs(UnmanagedType.LPWStr)] string pszFileName, [In, Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] byte[] pBuffer, [In, Out] ref int plSize ); } ``` --- ### Methods #### QueryPassword Called by the filter to query the password or binary key data for a specific file. **C++ Syntax**: ``` HRESULT QueryPassword( LPCWSTR pszFileName, LPBYTE pBuffer, LONG* plSize ); ``` **C# Syntax**: ``` int QueryPassword( string pszFileName, byte[] pBuffer, ref int plSize ); ``` **Parameters**: - `pszFileName` - File name for which password is requested (can be used to determine file-specific keys) - `pBuffer` - Buffer to receive password data or binary key - `plSize` - Pointer to buffer size (input: max buffer size, output: actual data size returned) **Return Value**: - `S_OK` (0) if password provided successfully - `E_OUTOFMEMORY` if buffer is too small (set plSize to required size) - Error HRESULT on failure **Remarks**: Implement this interface to: - Provide binary key data (256-bit keys for AES-256) - Generate file-specific encryption keys based on file name - Retrieve keys from external key management systems - Implement custom password derivation logic For simple scenarios with a single password for all files, using `IVFCryptoConfig::put_Password` directly is more straightforward. **Implementation Example (C#)**: ``` public class CustomPasswordProvider : IVFPasswordProvider { public int QueryPassword(string pszFileName, byte[] pBuffer, ref int plSize) { // Generate file-specific key byte[] key = GenerateKeyForFile(pszFileName); if (pBuffer == null || plSize < key.Length) { plSize = key.Length; return unchecked((int)0x8007000E); // E_OUTOFMEMORY } Array.Copy(key, pBuffer, key.Length); plSize = key.Length; return 0; // S_OK } private byte[] GenerateKeyForFile(string fileName) { // Custom key generation logic using (var sha256 = SHA256.Create()) { string seed = "MySalt" + fileName; return sha256.ComputeHash(Encoding.UTF8.GetBytes(seed)); } } } ``` --- ## C# Helper Methods The SDK provides convenient extension methods for C# developers in the `VFCryptoConfigHelper` class. ### ApplyString Applies a string password with automatic SHA-256 hashing. **Syntax**: ``` public static int ApplyString(this IVFCryptoConfig cryptoConfig, string key) ``` **Parameters**: - `cryptoConfig` - The IVFCryptoConfig interface instance - `key` - String password to apply **Return Value**: - `0` on success - Throws `Exception` if key is null or empty **Remarks**: - Automatically converts string to Unicode and applies SHA-256 hashing - Most common method for setting passwords - Ensures consistent password format across encryption/decryption **Example**: ``` var cryptoConfig = muxerFilter as IVFCryptoConfig; if (cryptoConfig != null) { cryptoConfig.ApplyString("MySecurePassword123"); } ``` --- ### ApplyFile Uses a file's content as the encryption key (SHA-256 hash of file). **Syntax**: ``` public static int ApplyFile(this IVFCryptoConfig cryptoConfig, string key) ``` **Parameters**: - `cryptoConfig` - The IVFCryptoConfig interface instance - `key` - Path to file to use as encryption key **Return Value**: - `0` on success - Throws `FileNotFoundException` if file doesn't exist - Throws `Exception` if key is null or empty **Remarks**: - Reads entire file content and computes SHA-256 hash - Useful for using key files or certificates as encryption keys - File content is never stored, only the hash - Same file must be used for both encryption and decryption **Example**: ``` var cryptoConfig = muxerFilter as IVFCryptoConfig; if (cryptoConfig != null) { cryptoConfig.ApplyFile(@"C:\keys\encryption.key"); } ``` **Security Note**: - Store key files securely - Use appropriate file permissions - Consider using dedicated key storage systems for production --- ### ApplyBinary Applies binary key data with automatic SHA-256 hashing. **Syntax**: ``` public static int ApplyBinary(this IVFCryptoConfig cryptoConfig, byte[] key) ``` **Parameters**: - `cryptoConfig` - The IVFCryptoConfig interface instance - `key` - Binary key data (any length) **Return Value**: - `0` on success - Throws `Exception` if key is null or empty **Remarks**: - Accepts binary key data of any length - Automatically computes SHA-256 hash to generate 256-bit key - Useful for programmatically generated keys or key derivation **Example**: ``` var cryptoConfig = muxerFilter as IVFCryptoConfig; if (cryptoConfig != null) { // Generate random key byte[] keyData = new byte[32]; using (var rng = new RNGCryptoServiceProvider()) { rng.GetBytes(keyData); } // Apply binary key cryptoConfig.ApplyBinary(keyData); // Store keyData securely for later decryption SaveKeyToSecureStorage(keyData); } ``` --- ## Filter CLSIDs ### Encrypt Muxer Filter Muxes video and audio streams into encrypted format. **CLSID**: ``` // {F1D3727A-88DE-49ab-A635-280BEFEFF902} DEFINE_GUID(CLSID_EncryptMuxer, 0xf1d3727a, 0x88de, 0x49ab, 0xa6, 0x35, 0x28, 0xb, 0xef, 0xef, 0xf9, 0x2); ``` **Usage (C++)**: ``` IBaseFilter* pMuxer = nullptr; hr = CoCreateInstance( CLSID_EncryptMuxer, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void**)&pMuxer ); ``` **Usage (C#)**: ``` var muxerFilter = (IBaseFilter)Activator.CreateInstance( Type.GetTypeFromCLSID(new Guid("F1D3727A-88DE-49ab-A635-280BEFEFF902")) ); ``` --- ### Decrypt Demuxer Filter Demuxes and decrypts encrypted files. **CLSID**: ``` // {D2C761F0-9988-4f79-9B0E-FB2B79C65851} DEFINE_GUID(CLSID_EncryptDemuxer, 0xd2c761f0, 0x9988, 0x4f79, 0x9b, 0xe, 0xfb, 0x2b, 0x79, 0xc6, 0x58, 0x51); ``` **Usage (C++)**: ``` IBaseFilter* pDemuxer = nullptr; hr = CoCreateInstance( CLSID_EncryptDemuxer, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void**)&pDemuxer ); ``` **Usage (C#)**: ``` var demuxerFilter = (IBaseFilter)Activator.CreateInstance( Type.GetTypeFromCLSID(new Guid("D2C761F0-9988-4f79-9B0E-FB2B79C65851")) ); ``` --- ## See Also - [Video Encryption SDK Overview](../) - Product features and capabilities - [Examples](../examples/) - Complete code examples - [DirectShow Encoding Filters Pack](../../filters-enc/) - Compatible encoders ---END OF PAGE--- ## Virtual Camera DirectShow Examples - C++, C#, VB.NET **URL:** https://www.visioforge.com/help/docs/directshow/virtual-camera-sdk/examples/ **Description:** Stream video to virtual camera devices and capture from them in DirectShow. Code examples for frame rendering, real-time effects, and multi-instance setup. **Tags:** Virtual Camera SDK, DirectShow, C++, Windows, WinForms, Streaming, Virtual Camera, Webcam, C# **API:** IBaseFilter, IVFLiveVideoSource, IVFVirtualCameraSink, IVFVirtualCameraSource # Virtual Camera SDK - Code Examples ## Overview This page provides practical code examples for using the Virtual Camera SDK. The SDK enables you to: - **Write TO virtual camera**: Stream video from files, real cameras, or individual frames to virtual camera devices - **Read FROM virtual camera**: Capture video from virtual camera devices (appears as regular webcam to applications) - Apply real-time video effects and processing - Support multiple virtual camera instances The virtual camera appears as a standard webcam to applications like Zoom, Teams, OBS, and other video conferencing software. --- ## Architecture Overview The Virtual Camera SDK provides three main filter types: 1. **CLSID\_VFVirtualCameraSource**: Reads FROM virtual camera device (acts as a video capture source) 2. **CLSID\_VFVirtualCameraSink**: Writes TO virtual camera device (acts as a renderer) 3. **CLSID\_VFVideoPushSource**: Push source for frame-by-frame rendering (image sequences, custom rendering) **Typical workflows**: - File/Camera → VirtualCameraSink → Virtual Camera Device → Other Applications - Virtual Camera Device → VirtualCameraSource → Your Application - PushSource (frames) → VirtualCameraSink → Virtual Camera Device → Other Applications --- ## Prerequisites ### C# Projects ``` using System; using System.Runtime.InteropServices; using VisioForge.DirectShowAPI; using VisioForge.DirectShowLib; ``` **Required NuGet Packages**: - `VisioForge.DirectShowAPI` - DirectShow wrapper library **Key CLSIDs**: ``` // Filter CLSIDs (available in Consts class) public static readonly Guid CLSID_VFVirtualCameraSource = new Guid("AA4DA14E-644B-487a-A7CB-517A390B4BB8"); // Read from virtual camera public static readonly Guid CLSID_VFVirtualCameraSink = new Guid("AA6AB4DF-9670-4913-88BB-2CB381C19340"); // Write to virtual camera public static readonly Guid CLSID_VFVirtualAudioCardSource = new Guid("B5A463DF-4016-4C34-AA4F-48EC1B51C73F"); // Audio source public static readonly Guid CLSID_VFVirtualAudioCardSink = new Guid("1A2673B0-553E-4027-AECC-839405468950"); // Audio sink // Push source for frame-by-frame rendering public static readonly Guid CLSID_VFVideoPushSource = new Guid("38D15306-BBC6-4D6C-A89C-9621604D9FC1"); ``` ### C++ Projects ``` #include #include #include "ivirtualcamera.h" #pragma comment(lib, "strmiids.lib") // Filter CLSIDs DEFINE_GUID(CLSID_VFVirtualCameraSource, 0xAA4DA14E, 0x644B, 0x487a, 0xA7, 0xCB, 0x51, 0x7A, 0x39, 0x0B, 0x4B, 0xB8); DEFINE_GUID(CLSID_VFVirtualCameraSink, 0xAA6AB4DF, 0x9670, 0x4913, 0x88, 0xBB, 0x2C, 0xB3, 0x81, 0xC1, 0x93, 0x40); DEFINE_GUID(CLSID_VFVirtualAudioCardSource, 0xB5A463DF, 0x4016, 0x4C34, 0xAA, 0x4F, 0x48, 0xEC, 0x1B, 0x51, 0xC7, 0x3F); DEFINE_GUID(CLSID_VFVirtualAudioCardSink, 0x1A2673B0, 0x553E, 0x4027, 0xAE, 0xCC, 0x83, 0x94, 0x05, 0x46, 0x89, 0x50); DEFINE_GUID(CLSID_VFVideoPushSource, 0x38D15306, 0xBBC6, 0x4D6C, 0xA8, 0x9C, 0x96, 0x21, 0x60, 0x4D, 0x9F, 0xC1); ``` --- ## Example 1: Stream Video File to Virtual Camera This example demonstrates streaming a video file to a virtual camera device. ### C# Implementation ``` using System; using System.Runtime.InteropServices; using VisioForge.DirectShowAPI; using VisioForge.DirectShowLib; public class VirtualCameraFileStreaming { private IFilterGraph2 filterGraphSource; private ICaptureGraphBuilder2 captureGraphSource; private IMediaControl mediaControlSource; private IMediaEventEx mediaEventExSource; private IBaseFilter sourceVideoFilter; private IBaseFilter sinkVideoFilter; private IBaseFilter sinkAudioFilter; public void StreamFileToVirtualCamera(string videoFile) { try { // Create filter graph filterGraphSource = (IFilterGraph2)new FilterGraph(); captureGraphSource = (ICaptureGraphBuilder2)new CaptureGraphBuilder2(); mediaControlSource = (IMediaControl)filterGraphSource; mediaEventExSource = (IMediaEventEx)filterGraphSource; // Attach the filter graph to the capture graph int hr = captureGraphSource.SetFiltergraph(filterGraphSource); DsError.ThrowExceptionForHR(hr); // Add Virtual Camera Sink for video sinkVideoFilter = FilterGraphTools.AddFilterFromClsid( filterGraphSource, Consts.CLSID_VFVirtualCameraSink, "VisioForge Virtual Camera Sink - Video"); // Optional: Set license key for purchased version var sinkIntf = sinkVideoFilter as IVFVirtualCameraSink; sinkIntf?.set_license("YOUR-LICENSE-KEY"); // Use "TRIAL" for trial version // Add Virtual Camera Sink for audio sinkAudioFilter = FilterGraphTools.AddFilterFromClsid( filterGraphSource, Consts.CLSID_VFVirtualAudioCardSink, "VisioForge Virtual Camera Sink - Audio"); // Add source filter for the video file // DirectShow automatically selects appropriate source filter filterGraphSource.AddSourceFilter(videoFile, "Source file", out sourceVideoFilter); // Render video stream: Source → Virtual Camera Sink hr = captureGraphSource.RenderStream(null, null, sourceVideoFilter, null, sinkVideoFilter); DsError.ThrowExceptionForHR(hr); // Render audio stream: Source → Virtual Camera Sink hr = captureGraphSource.RenderStream(null, null, sourceVideoFilter, null, sinkAudioFilter); // Note: Audio errors are not critical, better to check if audio is available // Start playback hr = mediaControlSource.Run(); DsError.ThrowExceptionForHR(hr); Console.WriteLine("Streaming to virtual camera. Press any key to stop..."); } catch (Exception ex) { Console.WriteLine($"Error: {ex.Message}"); Cleanup(); throw; } } public void Cleanup() { // Stop playback if (mediaControlSource != null) { mediaControlSource.Stop(); } // Stop receiving events mediaEventExSource?.SetNotifyWindow(IntPtr.Zero, 0, IntPtr.Zero); // Remove all filters FilterGraphTools.RemoveAllFilters(filterGraphSource); // Release DirectShow interfaces if (mediaControlSource != null) { Marshal.ReleaseComObject(mediaControlSource); mediaControlSource = null; } if (mediaEventExSource != null) { Marshal.ReleaseComObject(mediaEventExSource); mediaEventExSource = null; } if (sourceVideoFilter != null) { Marshal.ReleaseComObject(sourceVideoFilter); sourceVideoFilter = null; } if (sinkVideoFilter != null) { Marshal.ReleaseComObject(sinkVideoFilter); sinkVideoFilter = null; } if (sinkAudioFilter != null) { Marshal.ReleaseComObject(sinkAudioFilter); sinkAudioFilter = null; } if (captureGraphSource != null) { Marshal.ReleaseComObject(captureGraphSource); captureGraphSource = null; } if (filterGraphSource != null) { Marshal.ReleaseComObject(filterGraphSource); filterGraphSource = null; } } } ``` ### C++ Implementation ## ``` #include #include "ivirtualcamera.h" HRESULT StreamFileToVirtualCamera(LPCWSTR videoFile) { HRESULT hr = S_OK; IGraphBuilder* pGraph = NULL; ICaptureGraphBuilder2* pBuild = NULL; IMediaControl* pControl = NULL; IBaseFilter* pSourceFilter = NULL; IBaseFilter* pSinkVideoFilter = NULL; IBaseFilter* pSinkAudioFilter = NULL; // Initialize COM CoInitialize(NULL); // Create the filter graph manager hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void**)&pGraph); if (FAILED(hr)) return hr; // Create the Capture Graph Builder hr = CoCreateInstance(CLSID_CaptureGraphBuilder2, NULL, CLSCTX_INPROC_SERVER, IID_ICaptureGraphBuilder2, (void**)&pBuild); if (FAILED(hr)) goto cleanup; // Set the filter graph hr = pBuild->SetFiltergraph(pGraph); if (FAILED(hr)) goto cleanup; // Create Virtual Camera Sink filter for video hr = CoCreateInstance(CLSID_VFVirtualCameraSink, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void**)&pSinkVideoFilter); if (FAILED(hr)) goto cleanup; hr = pGraph->AddFilter(pSinkVideoFilter, L"VisioForge Virtual Camera Sink - Video"); if (FAILED(hr)) goto cleanup; // Create Virtual Camera Sink filter for audio hr = CoCreateInstance(CLSID_VFVirtualAudioCardSink, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void**)&pSinkAudioFilter); if (FAILED(hr)) goto cleanup; hr = pGraph->AddFilter(pSinkAudioFilter, L"VisioForge Virtual Camera Sink - Audio"); if (FAILED(hr)) goto cleanup; // Add source filter for the file hr = pGraph->AddSourceFilter(videoFile, L"Source File", &pSourceFilter); if (FAILED(hr)) goto cleanup; // Render video stream hr = pBuild->RenderStream(NULL, NULL, pSourceFilter, NULL, pSinkVideoFilter); if (FAILED(hr)) goto cleanup; // Render audio stream (errors not critical) pBuild->RenderStream(NULL, NULL, pSourceFilter, NULL, pSinkAudioFilter); // Get media control interface hr = pGraph->QueryInterface(IID_IMediaControl, (void**)&pControl); if (SUCCEEDED(hr)) { // Start playback hr = pControl->Run(); } cleanup: // Release interfaces if (pControl) pControl->Release(); if (pSinkAudioFilter) pSinkAudioFilter->Release(); if (pSinkVideoFilter) pSinkVideoFilter->Release(); if (pSourceFilter) pSourceFilter->Release(); if (pBuild) pBuild->Release(); if (pGraph) pGraph->Release(); return hr; } ``` ## Example 2: Stream Physical Camera to Virtual Camera This example demonstrates capturing from a physical webcam and streaming it to a virtual camera device. ### C# Implementation ``` using System; using System.Runtime.InteropServices; using VisioForge.DirectShowAPI; using VisioForge.DirectShowLib; public class VirtualCameraFromPhysicalCamera { private IFilterGraph2 filterGraph; private ICaptureGraphBuilder2 captureGraph; private IMediaControl mediaControl; private IBaseFilter cameraFilter; private IBaseFilter virtualCameraSink; public void StreamCameraToVirtualCamera(string physicalCameraName) { try { // Create filter graph filterGraph = (IFilterGraph2)new FilterGraph(); captureGraph = (ICaptureGraphBuilder2)new CaptureGraphBuilder2(); mediaControl = (IMediaControl)filterGraph; // Attach filter graph to capture graph int hr = captureGraph.SetFiltergraph(filterGraph); DsError.ThrowExceptionForHR(hr); // Add physical camera filter cameraFilter = FilterGraphTools.AddFilterByName( filterGraph, FilterCategory.VideoInputDevice, physicalCameraName); if (cameraFilter == null) { throw new Exception($"Camera '{physicalCameraName}' not found"); } // Add Virtual Camera Sink virtualCameraSink = FilterGraphTools.AddFilterFromClsid( filterGraph, Consts.CLSID_VFVirtualCameraSink, "Virtual Camera Sink"); // Optional: Set license var sinkIntf = virtualCameraSink as IVFVirtualCameraSink; sinkIntf?.set_license("TRIAL"); // Render stream: Physical Camera → Virtual Camera Sink hr = captureGraph.RenderStream( null, MediaType.Video, cameraFilter, null, virtualCameraSink); DsError.ThrowExceptionForHR(hr); // Start capture hr = mediaControl.Run(); DsError.ThrowExceptionForHR(hr); Console.WriteLine("Streaming physical camera to virtual camera..."); } catch (Exception ex) { Console.WriteLine($"Error: {ex.Message}"); Cleanup(); throw; } } public void Cleanup() { if (mediaControl != null) { mediaControl.Stop(); } FilterGraphTools.RemoveAllFilters(filterGraph); if (cameraFilter != null) { Marshal.ReleaseComObject(cameraFilter); cameraFilter = null; } if (virtualCameraSink != null) { Marshal.ReleaseComObject(virtualCameraSink); virtualCameraSink = null; } if (mediaControl != null) { Marshal.ReleaseComObject(mediaControl); mediaControl = null; } if (captureGraph != null) { Marshal.ReleaseComObject(captureGraph); captureGraph = null; } if (filterGraph != null) { Marshal.ReleaseComObject(filterGraph); filterGraph = null; } } } ``` --- ## Example 3: Stream Image Sequence to Virtual Camera (Frame-by-Frame) This example demonstrates rendering individual frames (image sequence or slideshow) to a virtual camera device. ### C# Implementation ## ``` using System; using System.Drawing; using System.Drawing.Imaging; using System.IO; using System.Runtime.InteropServices; using VisioForge.DirectShowAPI; using VisioForge.DirectShowLib; public class VirtualCameraFrameByFrame { private IFilterGraph2 filterGraphSource; private ICaptureGraphBuilder2 captureGraphSource; private IMediaControl mediaControlSource; private IBaseFilter sourceVideoFilter; private IBaseFilter sinkVideoFilter; private IVFLiveVideoSource pushSource; private System.Windows.Forms.Timer framePushTimer; private int currentFrameIndex = 0; private Bitmap[] frames; public void StreamImageSequenceToVirtualCamera(string[] imageFiles, float frameRate = 10) { try { // Load images into memory frames = new Bitmap[imageFiles.Length]; for (int i = 0; i < imageFiles.Length; i++) { frames[i] = new Bitmap(imageFiles[i]); } if (frames.Length == 0) { throw new Exception("No images to display"); } int width = frames[0].Width; int height = frames[0].Height; // Create filter graph filterGraphSource = (IFilterGraph2)new FilterGraph(); captureGraphSource = (ICaptureGraphBuilder2)new CaptureGraphBuilder2(); mediaControlSource = (IMediaControl)filterGraphSource; int hr = captureGraphSource.SetFiltergraph(filterGraphSource); DsError.ThrowExceptionForHR(hr); // Add Virtual Camera Sink sinkVideoFilter = FilterGraphTools.AddFilterFromClsid( filterGraphSource, Consts.CLSID_VFVirtualCameraSink, "VisioForge Virtual Camera Sink - Video"); var sinkIntf = sinkVideoFilter as IVFVirtualCameraSink; sinkIntf?.set_license("TRIAL"); // Add push source filter Guid CLSID_VFVideoPushSource = new Guid("38D15306-BBC6-4D6C-A89C-9621604D9FC1"); sourceVideoFilter = FilterGraphTools.AddFilterFromClsid( filterGraphSource, CLSID_VFVideoPushSource, "VisioForge Video Push Source"); if (sourceVideoFilter == null) { throw new Exception("Unable to create VisioForge Push Source filter."); } // Get IVFLiveVideoSource interface pushSource = sourceVideoFilter as IVFLiveVideoSource; if (pushSource == null) { throw new Exception("Unable to get IVFLiveVideoSource interface."); } // Configure bitmap format var bmiHeader = new BitmapInfoHeader { BitCount = 24, Compression = 0, Width = width, Height = height, Planes = 1, Size = Marshal.SizeOf(typeof(BitmapInfoHeader)), ImageSize = GetStrideRGB24(width) * height }; pushSource.SetBitmapInfo(bmiHeader); pushSource.SetFrameRate(frameRate); // Connect filters: Push Source → Virtual Camera Sink hr = captureGraphSource.RenderStream(null, null, sourceVideoFilter, null, sinkVideoFilter); DsError.ThrowExceptionForHR(hr); // Start the graph hr = mediaControlSource.Run(); DsError.ThrowExceptionForHR(hr); // Setup timer to push frames framePushTimer = new System.Windows.Forms.Timer(); framePushTimer.Interval = (int)(1000 / frameRate); framePushTimer.Tick += PushFrame; framePushTimer.Start(); Console.WriteLine("Streaming image sequence to virtual camera..."); } catch (Exception ex) { Console.WriteLine($"Error: {ex.Message}"); Cleanup(); throw; } } private void PushFrame(object sender, EventArgs e) { if (frames == null || frames.Length == 0 || pushSource == null) return; // Get current frame Bitmap frame = frames[currentFrameIndex]; // Lock bitmap data BitmapData bmpData = frame.LockBits( new Rectangle(0, 0, frame.Width, frame.Height), ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb); try { // AddFrame takes an AVFrameData (LPStruct), NOT a raw IntPtr. // Build it from the locked bitmap before pushing. int frameSize = bmpData.Stride * frame.Height; long durationTicks = (long)(10_000_000.0 / frameRate); // 100ns units var avFrame = new AVFrameData { Data = bmpData.Scan0, Size = frameSize, StartTime = currentFrameIndex * durationTicks, StopTime = (currentFrameIndex + 1) * durationTicks }; pushSource.AddFrame(avFrame); } finally { frame.UnlockBits(bmpData); } // Move to next frame (loop) currentFrameIndex = (currentFrameIndex + 1) % frames.Length; } private int GetStrideRGB24(int width) { return ((width * 24 + 31) / 32) * 4; } public void Cleanup() { // Stop timer if (framePushTimer != null) { framePushTimer.Stop(); framePushTimer.Dispose(); framePushTimer = null; } // Stop playback if (mediaControlSource != null) { mediaControlSource.Stop(); } // Release frames if (frames != null) { foreach (var frame in frames) { frame?.Dispose(); } frames = null; } // Release DirectShow interfaces pushSource = null; FilterGraphTools.RemoveAllFilters(filterGraphSource); if (sourceVideoFilter != null) { Marshal.ReleaseComObject(sourceVideoFilter); sourceVideoFilter = null; } if (sinkVideoFilter != null) { Marshal.ReleaseComObject(sinkVideoFilter); sinkVideoFilter = null; } if (mediaControlSource != null) { Marshal.ReleaseComObject(mediaControlSource); mediaControlSource = null; } if (captureGraphSource != null) { Marshal.ReleaseComObject(captureGraphSource); captureGraphSource = null; } if (filterGraphSource != null) { Marshal.ReleaseComObject(filterGraphSource); filterGraphSource = null; } } } ``` ## Example 4: Read From Virtual Camera This example demonstrates capturing video from a virtual camera device (useful for testing or monitoring what's being sent to the virtual camera). ### C# Implementation ``` using System; using System.Runtime.InteropServices; using VisioForge.DirectShowAPI; using VisioForge.DirectShowLib; using MediaFoundation; using MediaFoundation.EVR; public class VirtualCameraCapture { private IFilterGraph2 filterGraph; private ICaptureGraphBuilder2 captureGraph; private IMediaControl mediaControl; private IBaseFilter virtualCameraSource; private IBaseFilter videoRenderer; public void CaptureFromVirtualCamera(IntPtr videoWindowHandle) { try { // Create filter graph filterGraph = (IFilterGraph2)new FilterGraph(); captureGraph = (ICaptureGraphBuilder2)new CaptureGraphBuilder2(); mediaControl = (IMediaControl)filterGraph; int hr = captureGraph.SetFiltergraph(filterGraph); DsError.ThrowExceptionForHR(hr); // Add Virtual Camera Source filter virtualCameraSource = FilterGraphTools.AddFilterFromClsid( filterGraph, Consts.CLSID_VFVirtualCameraSource, "VisioForge Virtual Camera"); if (virtualCameraSource == null) { throw new Exception("Unable to create Virtual Camera Source filter"); } // NOTE: IVFVirtualCameraSource exposes only SetCustomVideoSize() and // FixResolution(). Licensing lives on the SINK side (IVFVirtualCameraSink::set_license) // because that is the filter that publishes content to the virtual camera; the source // filter shown here only consumes it. // Create Enhanced Video Renderer (EVR) Guid CLSID_EVR = new Guid("FA10746C-9B63-4B6C-BC49-FC300EA5F256"); videoRenderer = FilterGraphTools.AddFilterFromClsid(filterGraph, CLSID_EVR, "EVR"); // Configure EVR var evrConfig = videoRenderer as IEVRFilterConfig; evrConfig?.SetNumberOfStreams(1); // Set video window var getService = videoRenderer as MediaFoundation.IMFGetService; if (getService != null) { getService.GetService( MediaFoundation.MFServices.MR_VIDEO_RENDER_SERVICE, typeof(MediaFoundation.IMFVideoDisplayControl).GUID, out var videoDisplayControlObj); var videoDisplayControl = videoDisplayControlObj as MediaFoundation.IMFVideoDisplayControl; videoDisplayControl?.SetVideoWindow(videoWindowHandle); } // Render stream: Virtual Camera Source → EVR hr = captureGraph.RenderStream( null, MediaType.Video, virtualCameraSource, null, videoRenderer); DsError.ThrowExceptionForHR(hr); // Start playback hr = mediaControl.Run(); DsError.ThrowExceptionForHR(hr); Console.WriteLine("Capturing from virtual camera..."); } catch (Exception ex) { Console.WriteLine($"Error: {ex.Message}"); Cleanup(); throw; } } public void Cleanup() { if (mediaControl != null) { mediaControl.Stop(); } FilterGraphTools.RemoveAllFilters(filterGraph); if (virtualCameraSource != null) { Marshal.ReleaseComObject(virtualCameraSource); virtualCameraSource = null; } if (videoRenderer != null) { Marshal.ReleaseComObject(videoRenderer); videoRenderer = null; } if (mediaControl != null) { Marshal.ReleaseComObject(mediaControl); mediaControl = null; } if (captureGraph != null) { Marshal.ReleaseComObject(captureGraph); captureGraph = null; } if (filterGraph != null) { Marshal.ReleaseComObject(filterGraph); filterGraph = null; } } } ``` --- ## Additional Resources For more detailed information, see: - [Virtual Camera SDK Product Page](https://www.visioforge.com/virtual-camera-sdk) - [End User License Agreement](../../../eula/) - [Sample Code Repository](https://github.com/visioforge/directshow-samples/tree/main/Virtual%20Camera%20SDK) ## Support - **Technical Support**: https://support.visioforge.com/ - **Discord Community**: https://discord.com/invite/yvXUG56WCH ---END OF PAGE--- ## Windows Virtual Camera SDK — DirectShow for Zoom, Teams, OBS **URL:** https://www.visioforge.com/help/docs/directshow/virtual-camera-sdk/ **Description:** Create virtual webcams recognized by Zoom, Teams, OBS, and browsers. VisioForge DirectShow SDK streams any video source with audio to virtual camera devices. **Tags:** Virtual Camera SDK, DirectShow, C++, Windows, Streaming, Virtual Camera **API:** IVFVirtualCameraSink, SinkFilter, IBaseFilter # DirectShow Virtual Camera SDK ## Overview Our robust DirectShow-based Virtual Camera SDK enables developers to implement powerful virtual camera functionality in their applications. The SDK provides sink filters that can be utilized as output in Video Capture SDK or Video Edit SDK environments, while the source filters can be employed as video sources for various capture applications. With this versatile toolkit, you can stream video content from virtually any source directly to a virtual camera device. These virtual devices are fully compatible with popular communication platforms such as `Skype`, `Zoom`, `Microsoft Teams`, web browsers, and numerous other applications that support DirectShow virtual cameras. The SDK also includes comprehensive audio streaming capabilities for complete multimedia solutions. To help you get started quickly, the SDK package includes a fully-functional sample application that demonstrates how to stream video content from files to virtual camera devices. Download the SDK from our [product page](https://www.visioforge.com/virtual-camera-sdk) to start integrating virtual camera functionality into your applications today. --- ## Installation Before using the code samples and integrating the SDK into your application, you must first install the Virtual Camera SDK from the [product page](https://www.visioforge.com/virtual-camera-sdk). **Installation Steps**: 1. Download the SDK installer from the product page 2. Run the installer with administrative privileges 3. The installer will register the virtual camera driver and all necessary DirectShow filters 4. Sample applications and source code will be available in the installation directory **Note**: The virtual camera driver and filters must be properly registered on the system before they can be used in your applications. The installer handles this automatically. --- ## Key Features and Capabilities - **Multiple Source Support**: Stream video to virtual camera from files, network streams, or capture devices - **Architecture Compatibility**: Full x86/x64 architecture support - **High-Resolution Support**: Stream video content up to 4K resolution - **Customization Options**: Define and implement custom camera names - **SDK Integration**: Seamless integration with other development tools - **Audio Support**: Complete audio streaming capabilities - **Professional Applications**: Perfect for teleconferencing, streaming, and professional video applications ## Technical Implementation ### Sample DirectShow Graph Architecture The diagram below illustrates the standard DirectShow graph implementation when using the Virtual Camera SDK: ### License Registration via Registry You can register the filter with your valid license key using the Windows registry system. Configure licensing using the following registry key: ``` HKEY_LOCAL_MACHINE\SOFTWARE\VisioForge\Virtual Camera SDK\License ``` Set your purchased license key as a string value in this registry location. ### Deployment Guidelines For proper deployment, copy and COM-register the SDK DirectShow filters - these are the files in the `Redist` folder with .ax extension. Registration can be performed using `regsvr32.exe` or through COM registration in your application installer. Please note that administrative privileges are required for successful registration. ### No-Signal Application Configuration You can configure an application to run automatically when the virtual camera is not connected to any video source. Configure the no-signal application using this registry key: ``` HKEY_LOCAL_MACHINE\SOFTWARE\VisioForge\Virtual Camera SDK\StartupEXE ``` Set the executable file name as a string value. ### No-Signal Image Configuration Instead of displaying a black screen when no video source is available, you can configure a custom image to be shown. Configure the no-signal image using this registry key: ``` HKEY_LOCAL_MACHINE\SOFTWARE\VisioForge\Virtual Camera SDK\BackgroundImage ``` Set the image file path as a string value. ## Interface Reference ### IVFVirtualCameraSink Interface The `IVFVirtualCameraSink` interface is used to configure the virtual camera sink filter, primarily for license registration. **Interface GUID**: `{A96631D2-4AC9-4F09-9F34-FF8229087DEB}` **Inherits From**: `IUnknown` #### C# Definition ``` using System; using System.Runtime.InteropServices; /// /// Virtual camera sink interface for license configuration. /// [ComImport] [System.Security.SuppressUnmanagedCodeSecurity] [Guid("A96631D2-4AC9-4F09-9F34-FF8229087DEB")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] public interface IVFVirtualCameraSink { /// /// Sets the license key for the virtual camera sink filter. /// /// License key string ("TRIAL" for trial version) /// HRESULT (0 for success) [PreserveSig] int set_license([MarshalAs(UnmanagedType.LPStr)] string license); } ``` Native C++/Delphi take ANSI; the SDK's bundled C# demo uses LPWStr The native `IVFVirtualCameraSink::set_license` parameter is `LPCSTR` (ANSI) in C++ and `PAnsiChar` in Delphi. The C# demo wrapper bundled with the SDK declares `[MarshalAs(UnmanagedType.LPWStr)]` — a known marshaling discrepancy in the demo. Pure-ASCII license keys (e.g., `"TRIAL"`, hex-encoded license strings) round-trip cleanly either way; if you need to match the native ABI exactly, use `LPStr` as shown above. **Usage Example (C#)**: ``` // Add Virtual Camera Sink filter var sinkFilter = FilterGraphTools.AddFilterFromClsid( filterGraph, Consts.CLSID_VFVirtualCameraSink, "VisioForge Virtual Camera Sink"); // Set license var sinkIntf = sinkFilter as IVFVirtualCameraSink; if (sinkIntf != null) { sinkIntf.set_license("YOUR-LICENSE-KEY"); // or "TRIAL" for trial version } ``` #### C++ Definition ``` #include // {A96631D2-4AC9-4F09-9F34-FF8229087DEB} DEFINE_GUID(IID_IVFVirtualCameraSink, 0xa96631d2, 0x4ac9, 0x4f09, 0x9f, 0x34, 0xff, 0x82, 0x29, 0x8, 0x7d, 0xeb); /// /// Virtual camera sink interface for license configuration. /// DECLARE_INTERFACE_(IVFVirtualCameraSink, IUnknown) { /// /// Sets the license key for the virtual camera sink filter. /// /// License key ANSI string ("TRIAL" for trial version) /// HRESULT (S_OK for success) STDMETHOD(set_license) (THIS_ LPCSTR license ) PURE; }; ``` **Usage Example (C++)**: ``` IBaseFilter* pSinkFilter = nullptr; IVFVirtualCameraSink* pSinkIntf = nullptr; // Create Virtual Camera Sink filter hr = CoCreateInstance(CLSID_VFVirtualCameraSink, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void**)&pSinkFilter); if (SUCCEEDED(hr)) { // Query interface hr = pSinkFilter->QueryInterface(IID_IVFVirtualCameraSink, (void**)&pSinkIntf); if (SUCCEEDED(hr)) { // Set license — LPCSTR (ANSI), not wide string hr = pSinkIntf->set_license("YOUR-LICENSE-KEY"); // or "TRIAL" pSinkIntf->Release(); } } ``` #### Delphi Definition ``` uses ActiveX, ComObj; const IID_IVFVirtualCameraSink: TGUID = '{A96631D2-4AC9-4F09-9F34-FF8229087DEB}'; type /// /// Virtual camera sink interface for license configuration. /// IVFVirtualCameraSink = interface(IUnknown) ['{A96631D2-4AC9-4F09-9F34-FF8229087DEB}'] /// /// Sets the license key for the virtual camera sink filter. /// /// License key ANSI string ('TRIAL' for trial version) /// HRESULT (S_OK for success) function set_license(license: PAnsiChar): HRESULT; stdcall; end; ``` **Usage Example (Delphi)**: ``` var SinkFilter: IBaseFilter; SinkIntf: IVFVirtualCameraSink; begin // Create Virtual Camera Sink filter if Succeeded(CoCreateInstance(CLSID_VFVirtualCameraSink, nil, CLSCTX_INPROC_SERVER, IID_IBaseFilter, SinkFilter)) then begin // Query interface if Succeeded(SinkFilter.QueryInterface(IID_IVFVirtualCameraSink, SinkIntf)) then begin // Set license — PAnsiChar (ANSI string) SinkIntf.set_license(PAnsiChar(AnsiString('YOUR-LICENSE-KEY'))); // or AnsiString('TRIAL') SinkIntf := nil; end; end; end; ``` --- ## Third-Party Libraries and Integration The Virtual Camera SDK contains third-party components that are used in the demo applications. These components are not required for the core SDK functionality. The Delphi and .NET demonstration applications utilize third-party libraries to simplify DirectShow development. The C++ demo applications are built without external dependencies. ### .NET Integration .NET applications leverage [DirectShowLib.Net (LGPL)](https://sourceforge.net/projects/directshownet/) to implement DirectShow functionality in managed code environments. Developers can create console applications, WinForms, or WPF applications using .NET. The included demo applications utilize WinForms for the user interface. ### Delphi Integration Delphi applications use [DSPack (MPL)](https://code.google.com/archive/p/dspack/) to implement DirectShow functionality. While modern Delphi versions include built-in DirectShow support, DSPack is utilized in the demo applications to maintain compatibility with older Delphi versions. ### C++ Integration The C++ demo applications do not require third-party libraries and are built using the standard DirectShow SDK (part of Windows SDK). Developers can utilize MFC, ATL, or other C++ frameworks to build their applications. The included demo applications are built with MFC. ## System Requirements The SDK is compatible with the following Microsoft Windows operating systems: - Windows 7, 8, 8.1, 10, and 11 - Windows Server 2008, 2012, 2016, 2019, and 2022 ## Version History and Updates ### Version 14.0 - Performance optimizations and enhancements - Improved Windows 11 compatibility - Enhanced support for modern web browsers - Minor updates and bug fixes ### Version 12.0 - Windows 10 support improvements - Performance enhancements - 8K resolution support added - Improved Mozilla Firefox and Microsoft Edge compatibility - Various minor updates ### Version 11.0 - Critical bug fixes implemented - Updated Google Chrome compatibility - Resolved audio clicks issues in various web browsers and applications ### Version 10.0 - High frame rate support added - Significant performance improvements - Minor updates and bug fixes ### Version 9.0 - 4K video resolution support added - Updated support for contemporary web browsers - Various minor updates and improvements ### Version 8.0 - Added background image functionality for no-signal scenarios - Implemented application auto-run for no-signal conditions - Enhanced Skype compatibility ### Version 7.1 - Audio streaming support via virtual audio output and virtual microphone input - PCM audio format support with customizable sample rates and channel configuration - Bug fixes and performance improvements - Additional video resolutions added ### Version 7.0 - Initial release as a standalone product - Previously included in Video Edit SDK and Video Capture SDK - Compatible with any DirectShow application ## Additional Resources - [End User License Agreement](../../eula/) ---END OF PAGE--- ## VLC Source DirectShow Filter Integration Code Examples **URL:** https://www.visioforge.com/help/docs/directshow/vlc-source-filter/examples/ **Description:** Code examples for VLC Source Filter with multi-track audio, subtitles, 360° video, and custom VLC parameters in DirectShow. **Tags:** DirectShow, C++, Windows, WinForms, Playback, Streaming, Decoding, RTSP, HLS, MP4, MKV, AVI, MOV, C#, VB.NET **API:** IBaseFilter, IVFRegister # Code Examples ## Overview This page provides practical code examples for using the VLC Source Filter in DirectShow applications. The VLC Source Filter supports multi-audio tracks, subtitles, 360° video, and custom VLC command-line options. --- ## Prerequisites ### C++ Projects ``` #include #include #include "ivlcsrc.h" // Single header from SDK — declares IVlcSrc, IVlcSrc2, IVlcSrc3 + CLSID/IID GUIDs #pragma comment(lib, "strmiids.lib") ``` ### C# Projects ``` using VisioForge.DirectShowAPI; using VisioForge.DirectShowLib; using System.Runtime.InteropServices; using System.Text; ``` **NuGet Packages**: - VisioForge.DirectShowAPI - MediaFoundationCore --- ## Example 1: Basic File Playback Play a local media file with VLC Source Filter. ### C++ Implementation ``` #include #include "ivlcsrc.h" // CLSID for VLC Source Filter DEFINE_GUID(CLSID_VFVLCSource, 0x3fc97748, 0x7cb6, 0x4195, 0x89, 0xde, 0x07, 0x17, 0x58, 0x2a, 0x48, 0x63); HRESULT PlayVLCFile(LPCWSTR filename, HWND hVideoWindow) { IGraphBuilder* pGraph = NULL; IMediaControl* pControl = NULL; IBaseFilter* pSourceFilter = NULL; IVlcSrc* pVlcSrc = NULL; HRESULT hr = S_OK; // Create Filter Graph hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void**)&pGraph); if (FAILED(hr)) return hr; // Create VLC Source Filter hr = CoCreateInstance(CLSID_VFVLCSource, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void**)&pSourceFilter); if (FAILED(hr)) goto cleanup; // Add filter to graph hr = pGraph->AddFilter(pSourceFilter, L"VLC Source"); if (FAILED(hr)) goto cleanup; // Get VLC interface hr = pSourceFilter->QueryInterface(IID_IVlcSrc, (void**)&pVlcSrc); if (FAILED(hr)) goto cleanup; // Load file hr = pVlcSrc->SetFile((WCHAR*)filename); if (FAILED(hr)) goto cleanup; // Build and render graph ICaptureGraphBuilder2* pBuild = NULL; hr = CoCreateInstance(CLSID_CaptureGraphBuilder2, NULL, CLSCTX_INPROC_SERVER, IID_ICaptureGraphBuilder2, (void**)&pBuild); if (SUCCEEDED(hr)) { hr = pBuild->SetFiltergraph(pGraph); // Render video and audio hr = pBuild->RenderStream(NULL, &MEDIATYPE_Video, pSourceFilter, NULL, NULL); hr = pBuild->RenderStream(NULL, &MEDIATYPE_Audio, pSourceFilter, NULL, NULL); pBuild->Release(); } // Run graph hr = pGraph->QueryInterface(IID_IMediaControl, (void**)&pControl); if (SUCCEEDED(hr)) { hr = pControl->Run(); } cleanup: if (pVlcSrc) pVlcSrc->Release(); if (pControl) pControl->Release(); if (pSourceFilter) pSourceFilter->Release(); if (pGraph) pGraph->Release(); return hr; } ``` ### C# Implementation ``` using System; using System.Runtime.InteropServices; using VisioForge.DirectShowAPI; using VisioForge.DirectShowLib; public class VLCSourceBasicExample { private IFilterGraph2 filterGraph; private IMediaControl mediaControl; private IVideoWindow videoWindow; private IBaseFilter sourceFilter; public void PlayFile(string filename, IntPtr videoWindowHandle) { try { // Create filter graph filterGraph = (IFilterGraph2)new FilterGraph(); mediaControl = (IMediaControl)filterGraph; videoWindow = (IVideoWindow)filterGraph; // Create and add VLC Source filter sourceFilter = FilterGraphTools.AddFilterFromClsid( filterGraph, Consts.CLSID_VFVLCSource, "VLC Source"); // Load file using IVlcSrc interface var vlcSrc = sourceFilter as IVlcSrc; if (vlcSrc != null) { int hr = vlcSrc.SetFile(filename); DsError.ThrowExceptionForHR(hr); } // Render streams ICaptureGraphBuilder2 captureGraph = (ICaptureGraphBuilder2)new CaptureGraphBuilder2(); int result = captureGraph.SetFiltergraph(filterGraph); DsError.ThrowExceptionForHR(result); captureGraph.RenderStream(null, MediaType.Video, sourceFilter, null, null); captureGraph.RenderStream(null, MediaType.Audio, sourceFilter, null, null); // Set video window videoWindow.put_Owner(videoWindowHandle); videoWindow.put_WindowStyle(WindowStyle.Child | WindowStyle.ClipSiblings); videoWindow.put_Visible(OABool.True); // Run graph mediaControl.Run(); Marshal.ReleaseComObject(captureGraph); } catch (Exception ex) { Console.WriteLine($"Error: {ex.Message}"); } } public void Stop() { if (mediaControl != null) { mediaControl.Stop(); } if (videoWindow != null) { videoWindow.put_Visible(OABool.False); videoWindow.put_Owner(IntPtr.Zero); } FilterGraphTools.RemoveAllFilters(filterGraph); if (sourceFilter != null) Marshal.ReleaseComObject(sourceFilter); if (videoWindow != null) Marshal.ReleaseComObject(videoWindow); if (mediaControl != null) Marshal.ReleaseComObject(mediaControl); if (filterGraph != null) Marshal.ReleaseComObject(filterGraph); } } ``` ### VB.NET Implementation ``` Imports System.Runtime.InteropServices Imports VisioForge.DirectShowAPI Imports VisioForge.DirectShowLib Public Class VLCSourceBasicExample Private filterGraph As IFilterGraph2 Private mediaControl As IMediaControl Private videoWindow As IVideoWindow Private sourceFilter As IBaseFilter Public Sub PlayFile(filename As String, videoWindowHandle As IntPtr) Try ' Create filter graph filterGraph = DirectCast(New FilterGraph(), IFilterGraph2) mediaControl = DirectCast(filterGraph, IMediaControl) videoWindow = DirectCast(filterGraph, IVideoWindow) ' Create and add VLC Source filter sourceFilter = FilterGraphTools.AddFilterFromClsid( filterGraph, Consts.CLSID_VFVLCSource, "VLC Source") ' Load file Dim vlcSrc = DirectCast(sourceFilter, IVlcSrc) If vlcSrc IsNot Nothing Then Dim hr As Integer = vlcSrc.SetFile(filename) DsError.ThrowExceptionForHR(hr) End If ' Render streams Dim captureGraph As ICaptureGraphBuilder2 = DirectCast(New CaptureGraphBuilder2(), ICaptureGraphBuilder2) captureGraph.SetFiltergraph(filterGraph) captureGraph.RenderStream(Nothing, MediaType.Video, sourceFilter, Nothing, Nothing) captureGraph.RenderStream(Nothing, MediaType.Audio, sourceFilter, Nothing, Nothing) ' Set video window videoWindow.put_Owner(videoWindowHandle) videoWindow.put_WindowStyle(WindowStyle.Child Or WindowStyle.ClipSiblings) videoWindow.put_Visible(OABool.True) ' Run graph mediaControl.Run() Marshal.ReleaseComObject(captureGraph) Catch ex As Exception Console.WriteLine($"Error: {ex.Message}") End Try End Sub Public Sub [Stop]() If mediaControl IsNot Nothing Then mediaControl.Stop() End If If videoWindow IsNot Nothing Then videoWindow.put_Visible(OABool.False) videoWindow.put_Owner(IntPtr.Zero) End If FilterGraphTools.RemoveAllFilters(filterGraph) If sourceFilter IsNot Nothing Then Marshal.ReleaseComObject(sourceFilter) If videoWindow IsNot Nothing Then Marshal.ReleaseComObject(videoWindow) If mediaControl IsNot Nothing Then Marshal.ReleaseComObject(mediaControl) If filterGraph IsNot Nothing Then Marshal.ReleaseComObject(filterGraph) End Sub End Class ``` --- ## Example 2: Audio Track Selection List and select audio tracks from multi-audio files. ### C# Audio Track Management ``` public class VLCAudioTrackExample { private IFilterGraph2 filterGraph; private IMediaControl mediaControl; private IBaseFilter sourceFilter; public void PlayWithAudioTrackSelection(string filename, IntPtr videoWindowHandle) { filterGraph = (IFilterGraph2)new FilterGraph(); mediaControl = (IMediaControl)filterGraph; // Create VLC Source filter sourceFilter = FilterGraphTools.AddFilterFromClsid( filterGraph, Consts.CLSID_VFVLCSource, "VLC Source"); // Load file var vlcSrc = sourceFilter as IVlcSrc; if (vlcSrc != null) { vlcSrc.SetFile(filename); // Get audio track count int audioCount = 0; vlcSrc.GetAudioTracksCount(out audioCount); Console.WriteLine($"Total audio tracks: {audioCount}"); // List all audio tracks for (int i = 0; i < audioCount; i++) { int trackId; StringBuilder trackName = new StringBuilder(256); vlcSrc.GetAudioTrackInfo(i, out trackId, trackName); Console.WriteLine($"Track {i}: ID={trackId}, Name={trackName}"); } // Get currently active track int currentTrackId; vlcSrc.GetAudioTrack(out currentTrackId); Console.WriteLine($"Currently active track ID: {currentTrackId}"); // Select a specific track (e.g., track index 1) if (audioCount > 1) { int desiredTrackId; StringBuilder name = new StringBuilder(256); vlcSrc.GetAudioTrackInfo(1, out desiredTrackId, name); vlcSrc.SetAudioTrack(desiredTrackId); Console.WriteLine($"Switched to track: {name}"); } } // Build and run graph ICaptureGraphBuilder2 captureGraph = (ICaptureGraphBuilder2)new CaptureGraphBuilder2(); captureGraph.SetFiltergraph(filterGraph); captureGraph.RenderStream(null, MediaType.Video, sourceFilter, null, null); captureGraph.RenderStream(null, MediaType.Audio, sourceFilter, null, null); var videoWindow = (IVideoWindow)filterGraph; videoWindow.put_Owner(videoWindowHandle); videoWindow.put_WindowStyle(WindowStyle.Child | WindowStyle.ClipSiblings); mediaControl.Run(); Marshal.ReleaseComObject(captureGraph); } // Method to switch audio track during playback public void SwitchAudioTrack(int trackIndex) { var vlcSrc = sourceFilter as IVlcSrc; if (vlcSrc != null) { int trackId; StringBuilder trackName = new StringBuilder(256); vlcSrc.GetAudioTrackInfo(trackIndex, out trackId, trackName); vlcSrc.SetAudioTrack(trackId); Console.WriteLine($"Switched to audio track: {trackName}"); } } } ``` ### C++ Audio Track Management ## ``` void ListAndSelectAudioTracks(IVlcSrc* pVlcSrc) { int audioCount = 0; pVlcSrc->GetAudioTracksCount(&audioCount); wprintf(L"Total audio tracks: %d\n", audioCount); // List all tracks for (int i = 0; i < audioCount; i++) { int trackId = 0; WCHAR trackName[256] = {0}; pVlcSrc->GetAudioTrackInfo(i, &trackId, trackName); wprintf(L"Track %d: ID=%d, Name=%s\n", i, trackId, trackName); } // Get current track int currentId = 0; pVlcSrc->GetAudioTrack(¤tId); wprintf(L"Current track ID: %d\n", currentId); // Select track by index (e.g., track 1) if (audioCount > 1) { int trackId = 0; WCHAR name[256] = {0}; pVlcSrc->GetAudioTrackInfo(1, &trackId, name); pVlcSrc->SetAudioTrack(trackId); wprintf(L"Switched to track: %s\n", name); } } ``` ## Example 3: Subtitle Management Select and manage subtitle tracks. ### C# Subtitle Management ``` public class VLCSubtitleExample { private IBaseFilter sourceFilter; public void ManageSubtitles(string filename) { // Assume filter is already created and added to graph var vlcSrc = sourceFilter as IVlcSrc; if (vlcSrc != null) { vlcSrc.SetFile(filename); // Get subtitle count int subtitleCount = 0; vlcSrc.GetSubtitlesCount(out subtitleCount); Console.WriteLine($"Total subtitle tracks: {subtitleCount}"); // List all subtitles for (int i = 0; i < subtitleCount; i++) { int subtitleId; StringBuilder subtitleName = new StringBuilder(256); vlcSrc.GetSubtitleInfo(i, out subtitleId, subtitleName); Console.WriteLine($"Subtitle {i}: ID={subtitleId}, Name={subtitleName}"); } // Enable subtitle (e.g., subtitle index 0) if (subtitleCount > 0) { int subtitleId; StringBuilder name = new StringBuilder(256); vlcSrc.GetSubtitleInfo(0, out subtitleId, name); vlcSrc.SetSubtitle(subtitleId); Console.WriteLine($"Enabled subtitle: {name}"); } // Disable subtitles (use ID -1) // vlcSrc.SetSubtitle(-1); } } // Method to switch subtitles during playback public void SwitchSubtitle(int subtitleIndex) { var vlcSrc = sourceFilter as IVlcSrc; if (vlcSrc != null) { if (subtitleIndex < 0) { // Disable subtitles vlcSrc.SetSubtitle(-1); Console.WriteLine("Subtitles disabled"); } else { int subtitleId; StringBuilder name = new StringBuilder(256); vlcSrc.GetSubtitleInfo(subtitleIndex, out subtitleId, name); vlcSrc.SetSubtitle(subtitleId); Console.WriteLine($"Switched to subtitle: {name}"); } } } } ``` ### C++ Subtitle Management ``` void ManageSubtitles(IVlcSrc* pVlcSrc) { int subtitleCount = 0; pVlcSrc->GetSubtitlesCount(&subtitleCount); wprintf(L"Total subtitles: %d\n", subtitleCount); // List all subtitles for (int i = 0; i < subtitleCount; i++) { int subtitleId = 0; WCHAR subtitleName[256] = {0}; pVlcSrc->GetSubtitleInfo(i, &subtitleId, subtitleName); wprintf(L"Subtitle %d: ID=%d, Name=%s\n", i, subtitleId, subtitleName); } // Enable first subtitle if (subtitleCount > 0) { int id = 0; WCHAR name[256] = {0}; pVlcSrc->GetSubtitleInfo(0, &id, name); pVlcSrc->SetSubtitle(id); wprintf(L"Enabled subtitle: %s\n", name); } // Disable subtitles // pVlcSrc->SetSubtitle(-1); } ``` --- ## Example 4: Custom VLC Command-Line Options Pass custom VLC parameters using IVlcSrc2 interface. ### C# Custom VLC Parameters ``` using System; using System.Collections.Generic; using System.Runtime.InteropServices; using VisioForge.Core.Helpers; using VisioForge.DirectShowAPI; using VisioForge.DirectShowLib; public class VLCCustomOptionsExample { public void PlayWithCustomVLCOptions(string filename, IntPtr videoWindowHandle) { var filterGraph = (IFilterGraph2)new FilterGraph(); var sourceFilter = FilterGraphTools.AddFilterFromClsid( filterGraph, Consts.CLSID_VFVLCSource, "VLC Source"); // Set custom VLC command-line options using IVlcSrc2 var vlcSrc2 = sourceFilter as IVlcSrc2; if (vlcSrc2 != null) { // Create list of VLC command-line parameters var parameters = new List(); parameters.Add("--avcodec-hw=any"); // Enable hardware decoding parameters.Add("--network-caching=1000"); // 1 second network cache parameters.Add("--live-caching=300"); // 300ms for live streams parameters.Add("--file-caching=300"); // 300ms for files parameters.Add("--sout-mux-caching=2000"); // Output muxing cache parameters.Add("--vout=direct3d11"); // Use Direct3D11 renderer parameters.Add("--verbose=2"); // Logging level // Convert strings to native UTF-8 IntPtr array var array = new IntPtr[parameters.Count]; for (int i = 0; i < parameters.Count; i++) { array[i] = StringHelper.NativeUtf8FromString(parameters[i]); } try { // Call SetCustomCommandLine with IntPtr array int hr = vlcSrc2.SetCustomCommandLine(array, parameters.Count); DsError.ThrowExceptionForHR(hr); } finally { // Free allocated unmanaged memory for (int i = 0; i < array.Length; i++) { Marshal.FreeHGlobal(array[i]); } } } // Load file using IVlcSrc var vlcSrc = sourceFilter as IVlcSrc; if (vlcSrc != null) { vlcSrc.SetFile(filename); } // Build and run graph ICaptureGraphBuilder2 captureGraph = (ICaptureGraphBuilder2)new CaptureGraphBuilder2(); captureGraph.SetFiltergraph(filterGraph); captureGraph.RenderStream(null, MediaType.Video, sourceFilter, null, null); captureGraph.RenderStream(null, MediaType.Audio, sourceFilter, null, null); var videoWindow = (IVideoWindow)filterGraph; videoWindow.put_Owner(videoWindowHandle); videoWindow.put_WindowStyle(WindowStyle.Child | WindowStyle.ClipSiblings); var mediaControl = (IMediaControl)filterGraph; mediaControl.Run(); Marshal.ReleaseComObject(captureGraph); } } ``` ### Common VLC Options Here are common VLC parameter combinations. Remember to use the proper marshaling pattern shown above. ``` // Network streaming options var networkOptions = new List { "--network-caching=3000", // 3 seconds for network streams "--rtsp-tcp", // Force TCP for RTSP "--http-reconnect" // Auto-reconnect HTTP streams }; // Hardware decoding options var hwDecodeOptions = new List { "--avcodec-hw=any" // Auto-detect hardware // Alternative options: // "--avcodec-hw=dxva2" // Use DXVA2 // "--avcodec-hw=d3d11va" // Use D3D11VA // "--avcodec-hw=nvdec" // Use NVIDIA NVDEC }; // Low latency options var lowLatencyOptions = new List { "--network-caching=0", "--live-caching=0", "--file-caching=0", "--sout-mux-caching=0", "--clock-jitter=0", "--drop-late-frames", "--skip-frames" }; // 360° video options var video360Options = new List { "--video-filter=transform", "--transform-type=hflip", "--vout-filter=rotate" }; // Subtitle options var subtitleOptions = new List { "--sub-autodetect-file", // Auto-detect subtitle files "--sub-language=eng", // Preferred subtitle language "--freetype-fontsize=20" // Subtitle font size }; // Audio options var audioOptions = new List { "--audio-desync=0", // Audio synchronization "--audiotrack-language=eng", // Preferred audio language "--audio-filter=normvol" // Volume normalization }; // Complete example with multiple options var completeOptions = new List { "--avcodec-hw=any", "--network-caching=1000", "--rtsp-tcp", "--sub-autodetect-file", "--verbose=1" }; // Helper method to apply VLC parameters private void ApplyVLCParameters(IVlcSrc2 vlcSrc2, List parameters) { if (vlcSrc2 == null || parameters == null || parameters.Count == 0) return; var array = new IntPtr[parameters.Count]; for (int i = 0; i < parameters.Count; i++) { array[i] = StringHelper.NativeUtf8FromString(parameters[i]); } try { int hr = vlcSrc2.SetCustomCommandLine(array, parameters.Count); DsError.ThrowExceptionForHR(hr); } finally { for (int i = 0; i < array.Length; i++) { Marshal.FreeHGlobal(array[i]); } } } ``` --- ## Example 5: Frame Rate Override Override source frame rate using IVlcSrc3 interface. ### C# Frame Rate Override ``` public class VLCFrameRateExample { public void PlayWithCustomFrameRate(string filename, double fps, IntPtr videoWindowHandle) { var filterGraph = (IFilterGraph2)new FilterGraph(); var sourceFilter = FilterGraphTools.AddFilterFromClsid( filterGraph, Consts.CLSID_VFVLCSource, "VLC Source"); // Set custom frame rate using IVlcSrc3 var vlcSrc3 = sourceFilter as IVlcSrc3; if (vlcSrc3 != null) { // Override frame rate (e.g., 30.0, 25.0, 60.0) int hr = vlcSrc3.SetDefaultFrameRate(fps); DsError.ThrowExceptionForHR(hr); Console.WriteLine($"Frame rate set to: {fps} fps"); } // Load file var vlcSrc = sourceFilter as IVlcSrc; if (vlcSrc != null) { vlcSrc.SetFile(filename); } // Build and run graph ICaptureGraphBuilder2 captureGraph = (ICaptureGraphBuilder2)new CaptureGraphBuilder2(); captureGraph.SetFiltergraph(filterGraph); captureGraph.RenderStream(null, MediaType.Video, sourceFilter, null, null); captureGraph.RenderStream(null, MediaType.Audio, sourceFilter, null, null); var videoWindow = (IVideoWindow)filterGraph; videoWindow.put_Owner(videoWindowHandle); videoWindow.put_WindowStyle(WindowStyle.Child | WindowStyle.ClipSiblings); var mediaControl = (IMediaControl)filterGraph; mediaControl.Run(); Marshal.ReleaseComObject(captureGraph); } } ``` ### C++ Frame Rate Override ``` #include "ivlcsrc.h" void SetCustomFrameRate(IBaseFilter* pFilter, double fps) { IVlcSrc3* pVlcSrc3 = nullptr; HRESULT hr = pFilter->QueryInterface(IID_IVlcSrc3, (void**)&pVlcSrc3); if (SUCCEEDED(hr)) { hr = pVlcSrc3->SetDefaultFrameRate(fps); if (SUCCEEDED(hr)) { wprintf(L"Frame rate set to: %.2f fps\n", fps); } pVlcSrc3->Release(); } } ``` --- ## Example 6: Network Streaming (RTSP/HLS) Stream from network sources. ### C# Network Streaming ## ``` public class VLCNetworkStreamingExample { public void PlayRTSPStream(string rtspUrl, IntPtr videoWindowHandle) { var filterGraph = (IFilterGraph2)new FilterGraph(); var sourceFilter = FilterGraphTools.AddFilterFromClsid( filterGraph, Consts.CLSID_VFVLCSource, "VLC Source"); // Configure for RTSP streaming var vlcSrc2 = sourceFilter as IVlcSrc2; if (vlcSrc2 != null) { var parameters = new List { "--rtsp-tcp", // Use TCP transport "--network-caching=300", // Low latency (300ms) "--rtsp-frame-buffer-size=500000", // Frame buffer size "--drop-late-frames", // Drop late frames "--skip-frames" // Skip frames if needed }; var array = new IntPtr[parameters.Count]; for (int i = 0; i < parameters.Count; i++) { array[i] = StringHelper.NativeUtf8FromString(parameters[i]); } try { vlcSrc2.SetCustomCommandLine(array, parameters.Count); } finally { for (int i = 0; i < array.Length; i++) { Marshal.FreeHGlobal(array[i]); } } } // Load RTSP stream var vlcSrc = sourceFilter as IVlcSrc; if (vlcSrc != null) { // Example: "rtsp://camera.example.com:554/stream" vlcSrc.SetFile(rtspUrl); } // Build and run graph ICaptureGraphBuilder2 captureGraph = (ICaptureGraphBuilder2)new CaptureGraphBuilder2(); captureGraph.SetFiltergraph(filterGraph); captureGraph.RenderStream(null, MediaType.Video, sourceFilter, null, null); captureGraph.RenderStream(null, MediaType.Audio, sourceFilter, null, null); var videoWindow = (IVideoWindow)filterGraph; videoWindow.put_Owner(videoWindowHandle); videoWindow.put_WindowStyle(WindowStyle.Child | WindowStyle.ClipSiblings); var mediaControl = (IMediaControl)filterGraph; mediaControl.Run(); Marshal.ReleaseComObject(captureGraph); } public void PlayHLSStream(string hlsUrl, IntPtr videoWindowHandle) { var filterGraph = (IFilterGraph2)new FilterGraph(); var sourceFilter = FilterGraphTools.AddFilterFromClsid( filterGraph, Consts.CLSID_VFVLCSource, "VLC Source"); // Configure for HLS streaming var vlcSrc2 = sourceFilter as IVlcSrc2; if (vlcSrc2 != null) { var parameters = new List { "--http-reconnect", // Auto-reconnect "--network-caching=3000", // 3 second buffer for HLS "--hls-segment-threads=3", // Parallel segment download "--avcodec-hw=any" // Hardware decoding }; var array = new IntPtr[parameters.Count]; for (int i = 0; i < parameters.Count; i++) { array[i] = StringHelper.NativeUtf8FromString(parameters[i]); } try { vlcSrc2.SetCustomCommandLine(array, parameters.Count); } finally { for (int i = 0; i < array.Length; i++) { Marshal.FreeHGlobal(array[i]); } } } // Load HLS stream var vlcSrc = sourceFilter as IVlcSrc; if (vlcSrc != null) { // Example: "https://example.com/stream/playlist.m3u8" vlcSrc.SetFile(hlsUrl); } // Build and run graph ICaptureGraphBuilder2 captureGraph = (ICaptureGraphBuilder2)new CaptureGraphBuilder2(); captureGraph.SetFiltergraph(filterGraph); captureGraph.RenderStream(null, MediaType.Video, sourceFilter, null, null); captureGraph.RenderStream(null, MediaType.Audio, sourceFilter, null, null); var videoWindow = (IVideoWindow)filterGraph; videoWindow.put_Owner(videoWindowHandle); videoWindow.put_WindowStyle(WindowStyle.Child | WindowStyle.ClipSiblings); var mediaControl = (IMediaControl)filterGraph; mediaControl.Run(); Marshal.ReleaseComObject(captureGraph); } } ``` ## Example 7: License Activation Activate purchased license. ### C# License Activation ``` public void PlayWithLicense(string filename, string licenseKey, IntPtr videoWindowHandle) { var filterGraph = (IFilterGraph2)new FilterGraph(); var sourceFilter = FilterGraphTools.AddFilterFromClsid( filterGraph, Consts.CLSID_VFVLCSource, "VLC Source"); // Activate license var registration = sourceFilter as IVFRegister; if (registration != null) { int hr = registration.SetLicenseKey(licenseKey); if (hr != 0) { throw new Exception("License activation failed"); } } // Load and play file var vlcSrc = sourceFilter as IVlcSrc; if (vlcSrc != null) { vlcSrc.SetFile(filename); } ICaptureGraphBuilder2 captureGraph = (ICaptureGraphBuilder2)new CaptureGraphBuilder2(); captureGraph.SetFiltergraph(filterGraph); captureGraph.RenderStream(null, MediaType.Video, sourceFilter, null, null); captureGraph.RenderStream(null, MediaType.Audio, sourceFilter, null, null); var videoWindow = (IVideoWindow)filterGraph; videoWindow.put_Owner(videoWindowHandle); videoWindow.put_WindowStyle(WindowStyle.Child | WindowStyle.ClipSiblings); var mediaControl = (IMediaControl)filterGraph; mediaControl.Run(); Marshal.ReleaseComObject(captureGraph); } ``` --- ## Example 8: Complete Multi-Track Player Full-featured media player with all VLC Source features. ### C# Complete Example ``` using System; using System.Collections.Generic; using System.Runtime.InteropServices; using System.Text; using System.Windows.Forms; using VisioForge.DirectShowAPI; using VisioForge.DirectShowLib; public class VLCMediaPlayer : IDisposable { private IFilterGraph2 filterGraph; private ICaptureGraphBuilder2 captureGraph; private IMediaControl mediaControl; private IMediaSeeking mediaSeeking; private IVideoWindow videoWindow; private IMediaEventEx mediaEventEx; private IBaseFilter sourceFilter; private const int WM_GRAPHNOTIFY = 0x8000 + 1; public event EventHandler PlaybackComplete; public List AudioTracks { get; private set; } = new List(); public List Subtitles { get; private set; } = new List(); public class AudioTrackInfo { public int Index { get; set; } public int Id { get; set; } public string Name { get; set; } } public class SubtitleInfo { public int Index { get; set; } public int Id { get; set; } public string Name { get; set; } } public void Initialize(IntPtr windowHandle, IntPtr notifyHandle) { filterGraph = (IFilterGraph2)new FilterGraph(); captureGraph = (ICaptureGraphBuilder2)new CaptureGraphBuilder2(); mediaControl = (IMediaControl)filterGraph; mediaSeeking = (IMediaSeeking)filterGraph; videoWindow = (IVideoWindow)filterGraph; mediaEventEx = (IMediaEventEx)filterGraph; int hr = mediaEventEx.SetNotifyWindow(notifyHandle, WM_GRAPHNOTIFY, IntPtr.Zero); DsError.ThrowExceptionForHR(hr); hr = captureGraph.SetFiltergraph(filterGraph); DsError.ThrowExceptionForHR(hr); } public void LoadFile(string filename, string licenseKey = null, string vlcOptions = null, double? frameRate = null) { sourceFilter = FilterGraphTools.AddFilterFromClsid( filterGraph, Consts.CLSID_VFVLCSource, "VLC Source"); // Register license if (!string.IsNullOrEmpty(licenseKey)) { var registration = sourceFilter as IVFRegister; registration?.SetLicenseKey(licenseKey); } // Set custom VLC options if (!string.IsNullOrEmpty(vlcOptions)) { var vlcSrc2 = sourceFilter as IVlcSrc2; if (vlcSrc2 != null) { // Parse space-separated options into list var parameters = new List(vlcOptions.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries)); var array = new IntPtr[parameters.Count]; for (int i = 0; i < parameters.Count; i++) { array[i] = StringHelper.NativeUtf8FromString(parameters[i]); } try { vlcSrc2.SetCustomCommandLine(array, parameters.Count); } finally { for (int i = 0; i < array.Length; i++) { Marshal.FreeHGlobal(array[i]); } } } } // Set frame rate override if (frameRate.HasValue) { var vlcSrc3 = sourceFilter as IVlcSrc3; vlcSrc3?.SetDefaultFrameRate(frameRate.Value); } // Load file var vlcSrc = sourceFilter as IVlcSrc; if (vlcSrc != null) { int hr = vlcSrc.SetFile(filename); DsError.ThrowExceptionForHR(hr); // Enumerate audio tracks LoadAudioTracks(vlcSrc); // Enumerate subtitles LoadSubtitles(vlcSrc); } // Build graph int result = captureGraph.RenderStream(null, MediaType.Video, sourceFilter, null, null); result = captureGraph.RenderStream(null, MediaType.Audio, sourceFilter, null, null); } private void LoadAudioTracks(IVlcSrc vlcSrc) { AudioTracks.Clear(); int count = 0; vlcSrc.GetAudioTracksCount(out count); for (int i = 0; i < count; i++) { int id; StringBuilder name = new StringBuilder(256); vlcSrc.GetAudioTrackInfo(i, out id, name); AudioTracks.Add(new AudioTrackInfo { Index = i, Id = id, Name = name.ToString() }); } } private void LoadSubtitles(IVlcSrc vlcSrc) { Subtitles.Clear(); int count = 0; vlcSrc.GetSubtitlesCount(out count); for (int i = 0; i < count; i++) { int id; StringBuilder name = new StringBuilder(256); vlcSrc.GetSubtitleInfo(i, out id, name); Subtitles.Add(new SubtitleInfo { Index = i, Id = id, Name = name.ToString() }); } } public void SetVideoWindow(IntPtr handle, int width, int height) { if (videoWindow != null) { videoWindow.put_Owner(handle); videoWindow.put_WindowStyle(WindowStyle.Child | WindowStyle.ClipSiblings); videoWindow.SetWindowPosition(0, 0, width, height); videoWindow.put_Visible(OABool.True); } } public void Play() => mediaControl?.Run(); public void Pause() => mediaControl?.Pause(); public void Stop() => mediaControl?.Stop(); public void SelectAudioTrack(int trackIndex) { var vlcSrc = sourceFilter as IVlcSrc; if (vlcSrc != null && trackIndex >= 0 && trackIndex < AudioTracks.Count) { vlcSrc.SetAudioTrack(AudioTracks[trackIndex].Id); } } public void SelectSubtitle(int subtitleIndex) { var vlcSrc = sourceFilter as IVlcSrc; if (vlcSrc != null) { if (subtitleIndex < 0) { vlcSrc.SetSubtitle(-1); // Disable } else if (subtitleIndex < Subtitles.Count) { vlcSrc.SetSubtitle(Subtitles[subtitleIndex].Id); } } } public void Seek(long timeInSeconds) { if (mediaSeeking != null) { long seekPos = timeInSeconds * 10000000; mediaSeeking.SetPositions(ref seekPos, AMSeekingSeekingFlags.AbsolutePositioning, IntPtr.Zero, AMSeekingSeekingFlags.NoPositioning); } } public long GetPosition() { if (mediaSeeking != null) { mediaSeeking.GetCurrentPosition(out long position); return position / 10000000; } return 0; } public long GetDuration() { if (mediaSeeking != null) { mediaSeeking.GetDuration(out long duration); return duration / 10000000; } return 0; } public void HandleGraphEvent() { if (mediaEventEx != null) { while (mediaEventEx.GetEvent(out EventCode eventCode, out IntPtr param1, out IntPtr param2, 0) == 0) { mediaEventEx.FreeEventParams(eventCode, param1, param2); if (eventCode == EventCode.Complete) { PlaybackComplete?.Invoke(this, EventArgs.Empty); } } } } public void Dispose() { if (mediaControl != null) { mediaControl.Stop(); } if (mediaEventEx != null) { mediaEventEx.SetNotifyWindow(IntPtr.Zero, 0, IntPtr.Zero); } if (videoWindow != null) { videoWindow.put_Visible(OABool.False); videoWindow.put_Owner(IntPtr.Zero); } FilterGraphTools.RemoveAllFilters(filterGraph); if (sourceFilter != null) Marshal.ReleaseComObject(sourceFilter); if (videoWindow != null) Marshal.ReleaseComObject(videoWindow); if (mediaSeeking != null) Marshal.ReleaseComObject(mediaSeeking); if (mediaEventEx != null) Marshal.ReleaseComObject(mediaEventEx); if (captureGraph != null) Marshal.ReleaseComObject(captureGraph); if (mediaControl != null) Marshal.ReleaseComObject(mediaControl); if (filterGraph != null) Marshal.ReleaseComObject(filterGraph); } } ``` ### Usage Example ## ``` public partial class MainForm : Form { private VLCMediaPlayer player; public MainForm() { InitializeComponent(); player = new VLCMediaPlayer(); } private void btnLoad_Click(object sender, EventArgs e) { OpenFileDialog dlg = new OpenFileDialog(); dlg.Filter = "Video Files|*.mp4;*.mkv;*.avi;*.mov|All Files|*.*"; if (dlg.ShowDialog() == DialogResult.OK) { player.Initialize(panelVideo.Handle, this.Handle); // Custom VLC options for hardware decoding string vlcOptions = "--avcodec-hw=any --network-caching=1000"; player.LoadFile(dlg.FileName, vlcOptions: vlcOptions); player.SetVideoWindow(panelVideo.Handle, panelVideo.Width, panelVideo.Height); // Populate audio track combo box comboAudioTracks.Items.Clear(); foreach (var track in player.AudioTracks) { comboAudioTracks.Items.Add(track.Name); } if (comboAudioTracks.Items.Count > 0) { comboAudioTracks.SelectedIndex = 0; } // Populate subtitle combo box comboSubtitles.Items.Clear(); comboSubtitles.Items.Add("None"); foreach (var subtitle in player.Subtitles) { comboSubtitles.Items.Add(subtitle.Name); } comboSubtitles.SelectedIndex = 0; player.Play(); } } private void comboAudioTracks_SelectedIndexChanged(object sender, EventArgs e) { player.SelectAudioTrack(comboAudioTracks.SelectedIndex); } private void comboSubtitles_SelectedIndexChanged(object sender, EventArgs e) { player.SelectSubtitle(comboSubtitles.SelectedIndex - 1); // -1 because of "None" item } protected override void WndProc(ref Message m) { if (m.Msg == 0x8000 + 1) { player?.HandleGraphEvent(); } base.WndProc(ref m); } private void MainForm_FormClosing(object sender, FormClosingEventArgs e) { player?.Dispose(); } } ``` ## Troubleshooting ### Issue: "Class not registered" Error **Solution**: Ensure VLC Source filter is registered: ``` regsvr32 VisioForge_VLC_Source.ax ``` ### Issue: Audio/Subtitle Track Count Returns 0 **Cause**: Tracks not yet available (filter graph not built yet) **Solution**: Audio and subtitle information is only available after the file is loaded and the graph is built. Call track enumeration methods after `SetFile()` and building the graph. ``` // Load file first pVlcSrc->SetFile(L"movie.mkv"); // Build filter graph pGraph->RenderFile(L"movie.mkv", nullptr); // NOW query tracks int count = 0; pVlcSrc->GetAudioTracksCount(&count); ``` ### Issue: Custom VLC Options Not Working **Solution**: Ensure VLC options are set before loading the file, and use the correct marshaling: ``` // Correct order and usage: var vlcSrc2 = sourceFilter as IVlcSrc2; if (vlcSrc2 != null) { var parameters = new List { "--network-caching=1000", "--rtsp-tcp" }; var array = new IntPtr[parameters.Count]; for (int i = 0; i < parameters.Count; i++) { array[i] = StringHelper.NativeUtf8FromString(parameters[i]); } try { vlcSrc2.SetCustomCommandLine(array, parameters.Count); // 1. Set options first } finally { for (int i = 0; i < array.Length; i++) { Marshal.FreeHGlobal(array[i]); } } } var vlcSrc = sourceFilter as IVlcSrc; vlcSrc?.SetFile(filename); // 2. Then load file // Build and run graph... ``` ### Issue: RTSP Stream Has High Latency **Solution**: Configure VLC for minimal network buffering and use TCP transport: ``` // C++ example IVlcSrc2* pVlcSrc2 = nullptr; hr = pFilter->QueryInterface(IID_IVlcSrc2, (void**)&pVlcSrc2); if (SUCCEEDED(hr)) { const char* params[] = { "--network-caching=50", "--live-caching=50", "--rtsp-tcp", "--no-audio-time-stretch" }; // Convert to wide strings and then to IntPtr equivalents // (In C++, you can pass ANSI/UTF-8 strings directly in some cases, // but for consistency with the interface, use proper conversion) pVlcSrc2->Release(); } ``` ``` // C# example var vlcSrc2 = sourceFilter as IVlcSrc2; if (vlcSrc2 != null) { var lowLatencyOptions = new List { "--network-caching=50", "--live-caching=50", "--rtsp-tcp", "--no-audio-time-stretch" }; var array = new IntPtr[lowLatencyOptions.Count]; for (int i = 0; i < lowLatencyOptions.Count; i++) { array[i] = StringHelper.NativeUtf8FromString(lowLatencyOptions[i]); } try { vlcSrc2.SetCustomCommandLine(array, lowLatencyOptions.Count); } finally { for (int i = 0; i < array.Length; i++) { Marshal.FreeHGlobal(array[i]); } } } ``` ### Issue: Hardware Acceleration Not Working **Solution**: Explicitly specify the hardware decoder to use: ``` // C++ example - Try explicit hardware decoder IVlcSrc2* pVlcSrc2 = nullptr; hr = pFilter->QueryInterface(IID_IVlcSrc2, (void**)&pVlcSrc2); if (SUCCEEDED(hr)) { const char* params[] = { "--avcodec-hw=d3d11va" // For Windows 8+ // or "--avcodec-hw=dxva2" for Windows 7 }; // Proper conversion and calling required pVlcSrc2->Release(); } ``` ``` // C# example var vlcSrc2 = sourceFilter as IVlcSrc2; if (vlcSrc2 != null) { var hwOptions = new List { "--avcodec-hw=dxva2" // or d3d11va, nvdec, any }; var array = new IntPtr[hwOptions.Count]; for (int i = 0; i < hwOptions.Count; i++) { array[i] = StringHelper.NativeUtf8FromString(hwOptions[i]); } try { vlcSrc2.SetCustomCommandLine(array, hwOptions.Count); } finally { for (int i = 0; i < array.Length; i++) { Marshal.FreeHGlobal(array[i]); } } } ``` --- ## See Also ### Documentation - [Interface Reference](../interface-reference/) - Complete API reference - [Deployment Guide](../../deployment/) - Filter deployment ### External Resources - [VLC Command-Line Documentation](https://www.videolan.org/doc/) - [DirectShow Programming Guide](https://learn.microsoft.com/en-us/windows/win32/DirectShow/directshow) ---END OF PAGE--- ## VLC Source DirectShow Filter - 200+ Formats & Streams **URL:** https://www.visioforge.com/help/docs/directshow/vlc-source-filter/ **Description:** DirectShow source filter powered by libVLC for playing 200+ formats, 4K/8K video, and RTSP/HLS/UDP network streams with hardware decoding. C++, C#, Delphi. **Tags:** DirectShow, C++, Windows, Streaming, Editing **API:** IFileSourceFilter, IBaseFilter, IVFRegister # VLC Source DirectShow Filter ## Overview The VLC Source DirectShow filter empowers developers to seamlessly integrate advanced media playback capabilities into any DirectShow-based application. This powerful component enables smooth playback of various video files and network streams across multiple formats and protocols. Our SDK package delivers a complete solution with all necessary VLC player DLLs bundled alongside a flexible DirectShow filter. The package provides both standard file-selection interfaces and extensive options for custom filter configurations to match your specific development requirements. For complete product details and licensing options, visit the [product page](https://www.visioforge.com/vlc-source-directshow-filter). --- ## Installation Before using the code samples and integrating the filter into your application, you must first install the VLC Source DirectShow Filter from the [product page](https://www.visioforge.com/vlc-source-directshow-filter). **Installation Steps**: 1. Download the SDK installer from the product page 2. Run the installer with administrative privileges 3. The installer will register the VLC Source filter and deploy all necessary VLC DLLs 4. Sample applications and source code will be available in the installation directory **Note**: The filter must be properly registered on the system before it can be used in your applications. The installer handles this automatically. --- ## Technical Specifications ### Supported DirectShow Interfaces The filter implements these standard DirectShow interfaces for maximum compatibility: - **IAMStreamSelect** - Comprehensive video and audio stream selection capabilities - **IAMStreamConfig** - Advanced video and audio configuration settings - **IFileSourceFilter** - Flexible specification of filename or URL sources - **IMediaSeeking** - Robust timeline seeking and positioning support ### Key Features - Hardware-accelerated decoding for optimal performance - Support for 4K and 8K video playback - Extensive format compatibility including modern codecs - Network stream handling (RTSP, HLS, DASH, etc.) - Subtitle rendering and management - Multi-language audio track support - 360° video playback capabilities - HDR content support ## Implementation Examples ### C++ Integration Example ``` #include #include #include #include "ivlcsrc.h" // VLC Source Filter CLSID DEFINE_GUID(CLSID_VlcSource, 0x3fc97748, 0x7cb6, 0x4195, 0x89, 0xde, 0x07, 0x17, 0x58, 0x2a, 0x48, 0x63); HRESULT InitializeVLCSource(HWND hVideoWindow) { HRESULT hr = S_OK; IFilterGraph2* pGraph = NULL; ICaptureGraphBuilder2* pBuild = NULL; IMediaControl* pControl = NULL; IBaseFilter* pVLCSource = NULL; IBaseFilter* pVideoRenderer = NULL; IFileSourceFilter* pFileSource = NULL; // Initialize COM CoInitialize(NULL); // Create the filter graph manager hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IFilterGraph2, (void**)&pGraph); if (FAILED(hr)) return hr; // Create the Capture Graph Builder hr = CoCreateInstance(CLSID_CaptureGraphBuilder2, NULL, CLSCTX_INPROC_SERVER, IID_ICaptureGraphBuilder2, (void**)&pBuild); if (FAILED(hr)) goto cleanup; // Set the filter graph to the capture graph builder hr = pBuild->SetFiltergraph(pGraph); if (FAILED(hr)) goto cleanup; // Create the VLC Source filter hr = CoCreateInstance(CLSID_VlcSource, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void**)&pVLCSource); if (FAILED(hr)) goto cleanup; // Add the filter to the graph hr = pGraph->AddFilter(pVLCSource, L"VLC Source"); if (FAILED(hr)) goto cleanup; // Load the media file using IFileSourceFilter interface hr = pVLCSource->QueryInterface(IID_IFileSourceFilter, (void**)&pFileSource); if (SUCCEEDED(hr) && pFileSource) { hr = pFileSource->Load(L"C:\\media\\sample.mp4", NULL); pFileSource->Release(); if (FAILED(hr)) goto cleanup; } // Create Enhanced Video Renderer (EVR) CLSID CLSID_EVR = { 0xFA10746C, 0x9B63, 0x4B6C, { 0xBC, 0x49, 0xFC, 0x30, 0x0E, 0xA5, 0xF2, 0x56 } }; hr = CoCreateInstance(CLSID_EVR, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void**)&pVideoRenderer); if (FAILED(hr)) goto cleanup; hr = pGraph->AddFilter(pVideoRenderer, L"EVR"); if (FAILED(hr)) goto cleanup; // Configure EVR IEVRFilterConfig* pConfig = NULL; hr = pVideoRenderer->QueryInterface(IID_IEVRFilterConfig, (void**)&pConfig); if (SUCCEEDED(hr) && pConfig) { pConfig->SetNumberOfStreams(1); pConfig->Release(); } // Set video window IMFGetService* pGetService = NULL; hr = pVideoRenderer->QueryInterface(IID_IMFGetService, (void**)&pGetService); if (SUCCEEDED(hr) && pGetService) { IMFVideoDisplayControl* pDisplayControl = NULL; hr = pGetService->GetService(MR_VIDEO_RENDER_SERVICE, IID_IMFVideoDisplayControl, (void**)&pDisplayControl); if (SUCCEEDED(hr) && pDisplayControl) { pDisplayControl->SetVideoWindow(hVideoWindow); pDisplayControl->Release(); } pGetService->Release(); } // Render the streams hr = pBuild->RenderStream(NULL, &MEDIATYPE_Video, pVLCSource, NULL, pVideoRenderer); if (FAILED(hr)) goto cleanup; hr = pBuild->RenderStream(NULL, &MEDIATYPE_Audio, pVLCSource, NULL, NULL); // Audio errors are not critical // Get the media control interface for playback control hr = pGraph->QueryInterface(IID_IMediaControl, (void**)&pControl); if (SUCCEEDED(hr)) { // Start playback hr = pControl->Run(); } cleanup: // Release interfaces if (pControl) pControl->Release(); if (pVideoRenderer) pVideoRenderer->Release(); if (pVLCSource) pVLCSource->Release(); if (pBuild) pBuild->Release(); if (pGraph) pGraph->Release(); return hr; } ``` ### C# Integration (.NET) ``` using System; using System.Runtime.InteropServices; using MediaFoundation; using MediaFoundation.EVR; using VisioForge.DirectShowAPI; using VisioForge.DirectShowLib; // Initialize the VLC Source filter in C# using DirectShowLib public class VLCSourcePlayer { private IFilterGraph2 filterGraph; private ICaptureGraphBuilder2 captureGraph; private IMediaControl mediaControl; private IMediaSeeking mediaSeeking; private IMediaEventEx mediaEventEx; private IBaseFilter sourceFilter; private IBaseFilter videoRenderer; public void Initialize(string filename, IntPtr videoWindowHandle) { try { // Create the filter graph manager filterGraph = (IFilterGraph2)new FilterGraph(); captureGraph = (ICaptureGraphBuilder2)new CaptureGraphBuilder2(); mediaControl = (IMediaControl)filterGraph; mediaSeeking = (IMediaSeeking)filterGraph; mediaEventEx = (IMediaEventEx)filterGraph; // Attach the filter graph to the capture graph int hr = captureGraph.SetFiltergraph(filterGraph); DsError.ThrowExceptionForHR(hr); // Create the VLC Source filter using the correct CLSID sourceFilter = FilterGraphTools.AddFilterFromClsid( filterGraph, Consts.CLSID_VFVLCSource, "VLC Source"); // Optional: Register purchased version // var reg = sourceFilter as IVFRegister; // reg?.SetLicenseKey("your-license-key-here"); // Load the media file or URL using IFileSourceFilter interface var sourceFilterIntf = sourceFilter as IFileSourceFilter; hr = sourceFilterIntf.Load(filename, null); DsError.ThrowExceptionForHR(hr); // Create video renderer (EVR - Enhanced Video Renderer) Guid CLSID_EVR = new Guid("FA10746C-9B63-4B6C-BC49-FC300EA5F256"); videoRenderer = FilterGraphTools.AddFilterFromClsid(filterGraph, CLSID_EVR, "EVR"); // Configure EVR var evrConfig = videoRenderer as IEVRFilterConfig; evrConfig?.SetNumberOfStreams(1); // Set video window for rendering var getService = videoRenderer as MediaFoundation.IMFGetService; if (getService != null) { getService.GetService( MediaFoundation.MFServices.MR_VIDEO_RENDER_SERVICE, typeof(MediaFoundation.IMFVideoDisplayControl).GUID, out var videoDisplayControlObj); var videoDisplayControl = videoDisplayControlObj as MediaFoundation.IMFVideoDisplayControl; videoDisplayControl?.SetVideoWindow(videoWindowHandle); } // Render the streams hr = captureGraph.RenderStream(null, MediaType.Video, sourceFilter, null, videoRenderer); DsError.ThrowExceptionForHR(hr); hr = captureGraph.RenderStream(null, MediaType.Audio, sourceFilter, null, null); // Note: Audio rendering errors are not critical for video-only playback // Start playback hr = mediaControl.Run(); DsError.ThrowExceptionForHR(hr); } catch (Exception ex) { Console.WriteLine($"Error initializing VLC Source: {ex.Message}"); Cleanup(); throw; } } public void Cleanup() { // Stop playback if (mediaControl != null) { mediaControl.StopWhenReady(); mediaControl.Stop(); } // Stop receiving events mediaEventEx?.SetNotifyWindow(IntPtr.Zero, 0, IntPtr.Zero); // Remove all filters FilterGraphTools.RemoveAllFilters(filterGraph); // Release DirectShow interfaces if (mediaControl != null) { Marshal.ReleaseComObject(mediaControl); mediaControl = null; } if (mediaSeeking != null) { Marshal.ReleaseComObject(mediaSeeking); mediaSeeking = null; } if (mediaEventEx != null) { Marshal.ReleaseComObject(mediaEventEx); mediaEventEx = null; } if (sourceFilter != null) { Marshal.ReleaseComObject(sourceFilter); sourceFilter = null; } if (videoRenderer != null) { Marshal.ReleaseComObject(videoRenderer); videoRenderer = null; } if (captureGraph != null) { Marshal.ReleaseComObject(captureGraph); captureGraph = null; } if (filterGraph != null) { Marshal.ReleaseComObject(filterGraph); filterGraph = null; } } } ``` **Key CLSIDs and GUIDs:** ``` // VLC Source Filter CLSID public static readonly Guid CLSID_VFVLCSource = new Guid("3FC97748-7CB6-4195-89DE-0717582A4863"); // IVlcSrc Interface IID [Guid("77493EB7-6D00-41C5-9535-7C593824E892")] public interface IVlcSrc { /* ... */ } // IVlcSrc2 Interface IID (for custom command-line parameters) [Guid("CCE122C0-172C-4626-B4B6-42B039E541CB")] public interface IVlcSrc2 : IVlcSrc { /* ... */ } // IVlcSrc3 Interface IID (for frame rate override) [Guid("3DFBED0C-E4A8-401C-93EF-CBBFB65223DD")] public interface IVlcSrc3 : IVlcSrc2 { /* ... */ } // IVFRegister Interface IID (for licensing) [Guid("59E82754-B531-4A8E-A94D-57C75F01DA30")] public interface IVFRegister { /* ... */ } ``` **Required NuGet Packages:** - `VisioForge.DirectShowAPI` - DirectShow wrapper library - `MediaFoundation.Net` - Media Foundation wrapper for EVR renderer **Audio Track Selection Example:** ``` // Enumerate and select audio tracks var vlcSrc = sourceFilter as IVlcSrc; if (vlcSrc != null) { int audioCount = 0; vlcSrc.GetAudioTracksCount(out audioCount); for (int i = 0; i < audioCount; i++) { int trackId; var trackName = new StringBuilder(256); vlcSrc.GetAudioTrackInfo(i, out trackId, trackName); Console.WriteLine($"Track {i}: {trackName} (ID: {trackId})"); } // Select specific audio track if (audioCount > 1) { int desiredTrackId; var name = new StringBuilder(256); vlcSrc.GetAudioTrackInfo(1, out desiredTrackId, name); vlcSrc.SetAudioTrack(desiredTrackId); } } ``` **Custom VLC Options Example:** `IVlcSrc2::SetCustomCommandLine` takes an array of UTF-8 native strings (`char* params[]` in `ivlcsrc.h`), not a managed `string[]`. The C# wrapper marshals the parameters as `IntPtr[]` of unmanaged UTF-8 buffers — allocate with `StringHelper.NativeUtf8FromString()` and free with `Marshal.FreeHGlobal()` after the call. Passing a raw `string[]` would marshal as ANSI and corrupt non-ASCII flags. ``` // Configure VLC for low-latency RTSP streaming var vlcSrc2 = sourceFilter as IVlcSrc2; if (vlcSrc2 != null) { var parameters = new[] { "--network-caching=300", // Low network buffer "--rtsp-tcp", // Force TCP for RTSP "--avcodec-hw=any", // Enable hardware decoding "--live-caching=300" // Low live stream buffer }; // Convert managed strings to native UTF-8 IntPtr array var array = new IntPtr[parameters.Length]; for (int i = 0; i < parameters.Length; i++) { array[i] = StringHelper.NativeUtf8FromString(parameters[i]); } try { int hr = vlcSrc2.SetCustomCommandLine(array, parameters.Length); DsError.ThrowExceptionForHR(hr); } finally { // Free unmanaged UTF-8 buffers for (int i = 0; i < array.Length; i++) { Marshal.FreeHGlobal(array[i]); } } // Then load the stream var vlcSrc = vlcSrc2 as IVlcSrc; vlcSrc?.SetFile("rtsp://192.168.1.100/stream"); } ``` See [examples.md](examples/) for the canonical helper pattern reused across multiple scenarios (Example 4 binary key with custom flags, low-latency variants, etc.). ## Version History ### Version 2026.3.4 - Updated to VLC v3.0.23 core - Upgraded build toolset to MSVC v143 (Visual Studio 2022) - Fixed crash on graph teardown during `libvlc_media_player_stop()` - Replaced Boost dependencies with C++ standard library equivalents ### Version 15.0 - Enhanced playback quality across numerous formats - Improved subtitle rendering engine - Updated codec implementations including dav1d, ffmpeg, and libvpx - Added Super Resolution scaling with nVidia and Intel GPU acceleration ### Version 14.0 - Updated to VLC v3.0.18 core - Fixed DxVA/D3D11 compatibility issues with HEVC content - Resolved OpenGL resizing problems for smoother playback ### Version 12.0 - Upgraded to VLC v3.0.16 engine - Added support for new Fourcc formats (E-AC3 and AV1) - Fixed stability issues with VP9 streams ### Version 11.1 - Incorporated VLC v3.0.11 - Optimized HLS playlist update mechanism - Enhanced WebVTT subtitle handling and display ### Version 11.0 - Built on VLC v3.0.10 foundation - Fixed critical regression issues with HLS streams ### Version 10.4 - Major update to VLC 3.0 architecture - Enabled hardware decoding by default for 4K and 8K content - Added 10-bit color depth and HDR support - Implemented 360-degree video and 3D audio capabilities - Introduced Blu-Ray Java menu support ### Version 10.0 - Initial release as a standalone DirectShow filter - For earlier version history, please refer to Video Capture SDK .Net changelog ## Additional Resources - [End User License Agreement](../../eula/) - [Code Samples](https://github.com/visioforge/) ---END OF PAGE--- ## VLC Source DirectShow Filter Full Interface Reference **URL:** https://www.visioforge.com/help/docs/directshow/vlc-source-filter/interface-reference/ **Description:** IVlcSrc family interfaces for multi-track audio, subtitle support, and custom VLC command-line options in DirectShow applications. **Tags:** DirectShow, C++, Windows, IP Camera, RTSP, HLS, MP4, MKV, C# **API:** IBaseFilter # VLC Source Filter Interface Reference ## Overview The VLC Source DirectShow filter exposes three progressive interfaces (`IVlcSrc`, `IVlcSrc2`, `IVlcSrc3`) that provide comprehensive control over media playback, audio/subtitle track selection, and VLC configuration. These interfaces enable developers to leverage VLC's powerful media framework within DirectShow applications. ## Interface Hierarchy ``` IUnknown └── IVlcSrc └── IVlcSrc2 └── IVlcSrc3 ``` Each interface extends the previous one, adding new capabilities while maintaining backward compatibility. --- ## IVlcSrc Interface The base interface providing essential file loading and track selection capabilities. ### Interface Definition - **Interface Name**: `IVlcSrc` - **GUID**: `{77493EB7-6D00-41C5-9535-7C593824E892}` - **Inherits From**: `IUnknown` - **Header File**: `ivlcsrc.h` (C++), `IVlcSrc.cs` (.NET) ### Methods #### SetFile Sets the media file or URL to play. **Syntax (C++)**: ``` HRESULT SetFile(WCHAR *file); ``` **Syntax (C#)**: ``` [PreserveSig] int SetFile([MarshalAs(UnmanagedType.LPWStr)] string file); ``` **Parameters**: - `file`: Wide-character string containing the file path or URL. **Returns**: `S_OK` (0) on success, error code otherwise. **Supported Sources**: - Local files: `C:\Videos\movie.mp4` - HTTP streams: `https://example.com/stream.m3u8` - RTSP streams: `rtsp://example.com/live` - HLS playlists: `https://example.com/playlist.m3u8` - DASH streams: `https://example.com/manifest.mpd` - DVB-T/C/S broadcasts - Network shares: `\\server\share\video.mkv` **Example (C++)**: ``` IVlcSrc* pVlcSrc = nullptr; pFilter->QueryInterface(IID_IVlcSrc, (void**)&pVlcSrc); pVlcSrc->SetFile(L"C:\\Videos\\movie.mkv"); pVlcSrc->Release(); ``` **Example (C#)**: ``` var vlcSrc = filter as IVlcSrc; if (vlcSrc != null) { vlcSrc.SetFile(@"C:\Videos\movie.mkv"); } ``` --- ### Audio Track Management #### GetAudioTracksCount Retrieves the total number of available audio tracks. **Syntax (C++)**: ``` HRESULT GetAudioTracksCount(int *count); ``` **Syntax (C#)**: ``` [PreserveSig] int GetAudioTracksCount(out int count); ``` **Parameters**: - `count`: [out] Receives the number of audio tracks. **Returns**: `S_OK` (0) on success. **Usage Notes**: - Call after the file is loaded and the filter graph is built - Returns 0 if no audio tracks are available or file not loaded **Example (C++)**: ``` int audioCount = 0; pVlcSrc->GetAudioTracksCount(&audioCount); printf("Audio tracks: %d\n", audioCount); ``` --- #### GetAudioTrackInfo Retrieves information about a specific audio track. **Syntax (C++)**: ``` HRESULT GetAudioTrackInfo(int number, int *id, WCHAR *name); ``` **Syntax (C#)**: ``` [PreserveSig] int GetAudioTrackInfo(int number, out int id, [MarshalAs(UnmanagedType.LPWStr)] StringBuilder name); ``` **Parameters**: - `number`: Zero-based track index (0 to count-1). - `id`: [out] Receives the track ID. - `name`: [out] Buffer to receive the track name (must be pre-allocated, minimum 256 characters). **Returns**: `S_OK` (0) on success. **Usage Notes**: - Pre-allocate name buffer with at least 256 wide characters - Track names typically include language and codec information - Track ID is used with SetAudioTrack() **Example (C++)**: ``` int audioCount = 0; pVlcSrc->GetAudioTracksCount(&audioCount); for (int i = 0; i < audioCount; i++) { int id = 0; WCHAR name[256] = {0}; pVlcSrc->GetAudioTrackInfo(i, &id, name); wprintf(L"Track %d - ID: %d, Name: %s\n", i, id, name); } ``` **Example (C#)**: ``` int count = 0; vlcSrc.GetAudioTracksCount(out count); for (int i = 0; i < count; i++) { int id; var name = new StringBuilder(256); vlcSrc.GetAudioTrackInfo(i, out id, name); Console.WriteLine($"Track {i} - ID: {id}, Name: {name}"); } ``` --- #### GetAudioTrack Retrieves the ID of the currently active audio track. **Syntax (C++)**: ``` HRESULT GetAudioTrack(int *id); ``` **Syntax (C#)**: ``` [PreserveSig] int GetAudioTrack(out int id); ``` **Parameters**: - `id`: [out] Receives the current audio track ID. **Returns**: `S_OK` (0) on success. **Example (C++)**: ``` int currentTrack = 0; pVlcSrc->GetAudioTrack(¤tTrack); printf("Current audio track ID: %d\n", currentTrack); ``` --- #### SetAudioTrack Sets the active audio track by ID. **Syntax (C++)**: ``` HRESULT SetAudioTrack(int id); ``` **Syntax (C#)**: ``` [PreserveSig] int SetAudioTrack(int id); ``` **Parameters**: - `id`: The track ID to activate (obtained from GetAudioTrackInfo). **Returns**: `S_OK` (0) on success, error code if track ID is invalid. **Usage Notes**: - Can be called during playback to switch tracks dynamically - Use -1 to disable all audio tracks - Track switching may cause brief audio interruption **Example (C++)**: ``` // Switch to second audio track int trackId = 0; pVlcSrc->GetAudioTrackInfo(1, &trackId, nullptr); pVlcSrc->SetAudioTrack(trackId); ``` **Example (C#)**: ``` // Switch to first audio track int trackId; var name = new StringBuilder(256); vlcSrc.GetAudioTrackInfo(0, out trackId, name); vlcSrc.SetAudioTrack(trackId); ``` --- ### Subtitle Track Management #### GetSubtitlesCount Retrieves the total number of available subtitle tracks. **Syntax (C++)**: ``` HRESULT GetSubtitlesCount(int *count); ``` **Syntax (C#)**: ``` [PreserveSig] int GetSubtitlesCount(out int count); ``` **Parameters**: - `count`: [out] Receives the number of subtitle tracks. **Returns**: `S_OK` (0) on success. **Example (C++)**: ``` int subtitleCount = 0; pVlcSrc->GetSubtitlesCount(&subtitleCount); printf("Subtitle tracks: %d\n", subtitleCount); ``` --- #### GetSubtitleInfo Retrieves information about a specific subtitle track. **Syntax (C++)**: ``` HRESULT GetSubtitleInfo(int number, int *id, WCHAR *name); ``` **Syntax (C#)**: ``` [PreserveSig] int GetSubtitleInfo(int number, out int id, [MarshalAs(UnmanagedType.LPWStr)] StringBuilder name); ``` **Parameters**: - `number`: Zero-based track index (0 to count-1). - `id`: [out] Receives the subtitle track ID. - `name`: [out] Buffer to receive the subtitle track name (minimum 256 characters). **Returns**: `S_OK` (0) on success. **Example (C++)**: ``` int subCount = 0; pVlcSrc->GetSubtitlesCount(&subCount); for (int i = 0; i < subCount; i++) { int id = 0; WCHAR name[256] = {0}; pVlcSrc->GetSubtitleInfo(i, &id, name); wprintf(L"Subtitle %d - ID: %d, Name: %s\n", i, id, name); } ``` --- #### GetSubtitle Retrieves the ID of the currently active subtitle track. **Syntax (C++)**: ``` HRESULT GetSubtitle(int *id); ``` **Syntax (C#)**: ``` [PreserveSig] int GetSubtitle(out int id); ``` **Parameters**: - `id`: [out] Receives the current subtitle track ID. **Returns**: `S_OK` (0) on success. --- #### SetSubtitle Sets the active subtitle track by ID. **Syntax (C++)**: ``` HRESULT SetSubtitle(int id); ``` **Syntax (C#)**: ``` [PreserveSig] int SetSubtitle(int id); ``` **Parameters**: - `id`: The subtitle track ID to activate. **Returns**: `S_OK` (0) on success. **Usage Notes**: - Use -1 to disable subtitles - Subtitle rendering is performed by VLC's internal renderer - Can be switched during playback **Example (C++)**: ``` // Enable first subtitle track int subtitleId = 0; pVlcSrc->GetSubtitleInfo(0, &subtitleId, nullptr); pVlcSrc->SetSubtitle(subtitleId); // Disable subtitles pVlcSrc->SetSubtitle(-1); ``` --- ## IVlcSrc2 Interface Extends `IVlcSrc` with custom VLC command-line parameter support. ### Interface Definition - **Interface Name**: `IVlcSrc2` - **GUID**: `{CCE122C0-172C-4626-B4B6-42B039E541CB}` - **Inherits From**: `IVlcSrc` - **Header File**: `ivlcsrc.h` (C++), `IVlcSrc.cs` (.NET) ### Methods #### SetCustomCommandLine Sets custom VLC command-line parameters. **Syntax (C++)**: ``` HRESULT SetCustomCommandLine(char* params[], int length); ``` **Syntax (C#)**: ``` [PreserveSig] int SetCustomCommandLine([In][Out][MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPStr)] IntPtr[] params_, int size); ``` **Parameters**: - `params_`: Array of IntPtr pointers to UTF-8 encoded strings containing VLC command-line parameters. - `size`: Number of parameters in the array. **Returns**: `S_OK` (0) on success. **Usage Notes**: - Must be called **before** loading the media file with SetFile() - Parameters must be converted to native UTF-8 IntPtr using StringHelper.NativeUtf8FromString() - Memory allocated for IntPtr parameters must be freed after the call using Marshal.FreeHGlobal() - Parameters are passed directly to libVLC initialization - Invalid parameters are ignored with warnings in VLC log - Use standard VLC command-line syntax (see VLC documentation) **Common VLC Parameters**: | Parameter | Description | Example Value | | --- | --- | --- | | `--network-caching` | Network caching in ms | `1000` | | `--file-caching` | File caching in ms | `300` | | `--live-caching` | Live stream caching in ms | `300` | | `--avcodec-hw` | Hardware acceleration | `any`, `dxva2`, `d3d11va` | | `--verbose` | Logging verbosity | `2` | | `--rtsp-tcp` | Force RTSP over TCP | (flag, no value) | | `--no-audio` | Disable audio | (flag, no value) | | `--sout-mux-caching` | Output muxer caching | `1000` | **Example (C++)**: ``` IVlcSrc2* pVlcSrc2 = nullptr; pFilter->QueryInterface(IID_IVlcSrc2, (void**)&pVlcSrc2); // Configure for low-latency RTSP char* params[] = { "--network-caching=300", "--rtsp-tcp", "--avcodec-hw=d3d11va", "--verbose=2" }; pVlcSrc2->SetCustomCommandLine(params, 4); pVlcSrc2->SetFile(L"rtsp://192.168.1.100/stream"); pVlcSrc2->Release(); ``` **Example (C#)**: ``` using System; using System.Collections.Generic; using System.Runtime.InteropServices; using VisioForge.Core.Helpers; var vlcSrc2 = filter as IVlcSrc2; if (vlcSrc2 != null) { // Enable hardware acceleration and adjust caching var parameters = new List { "--avcodec-hw=any", "--network-caching=1000", "--file-caching=300" }; // Convert strings to native UTF-8 IntPtr array var array = new IntPtr[parameters.Count]; for (int i = 0; i < parameters.Count; i++) { array[i] = StringHelper.NativeUtf8FromString(parameters[i]); } try { vlcSrc2.SetCustomCommandLine(array, parameters.Count); vlcSrc2.SetFile(@"C:\Videos\movie.mkv"); } finally { // Free allocated unmanaged memory for (int i = 0; i < array.Length; i++) { Marshal.FreeHGlobal(array[i]); } } } ``` **Example (Delphi)**: libVLC parses the command line as **UTF-8**, not the system ANSI codepage. `PAnsiChar` literals are ASCII-safe but corrupt non-ASCII characters; encode each parameter to UTF-8 explicitly via `UTF8Encode` (or store an `AnsiString` with `CP_UTF8`). For a pure-ASCII parameter set, `PAnsiChar` literals happen to round-trip cleanly, but the snippet below uses the safe pattern. ``` var VlcSrc2: IVlcSrc2; P0, P1, P2: AnsiString; Params: array[0..2] of PAnsiChar; begin if Succeeded(Filter.QueryInterface(IID_IVlcSrc2, VlcSrc2)) then begin P0 := UTF8Encode('--network-caching=500'); P1 := UTF8Encode('--rtsp-tcp'); P2 := UTF8Encode('--avcodec-hw=dxva2'); Params[0] := PAnsiChar(P0); Params[1] := PAnsiChar(P1); Params[2] := PAnsiChar(P2); VlcSrc2.SetCustomCommandLine(@Params, 3); VlcSrc2.SetFile('rtsp://example.com/stream'); end; end; ``` --- ## IVlcSrc3 Interface Extends `IVlcSrc2` with frame rate override capability. ### Interface Definition - **Interface Name**: `IVlcSrc3` - **GUID**: `{3DFBED0C-E4A8-401C-93EF-CBBFB65223DD}` - **Inherits From**: `IVlcSrc2` - **Header File**: `ivlcsrc.h` (C++), `IVlcSrc.cs` (.NET) ### Methods #### SetDefaultFrameRate Sets a default frame rate for media without frame rate information. **Syntax (C++)**: ``` HRESULT SetDefaultFrameRate(double frameRate); ``` **Syntax (C#)**: ``` [PreserveSig] int SetDefaultFrameRate(double frameRate); ``` **Parameters**: - `frameRate`: Frame rate in frames per second (e.g., 29.97, 30.0, 25.0, 60.0). **Returns**: `S_OK` (0) on success. **Usage Notes**: - Must be called **before** loading the media file - Used when source media doesn't specify frame rate - Particularly useful for network streams without timing information - Common values: 23.976, 24.0, 25.0, 29.97, 30.0, 50.0, 59.94, 60.0 **Example (C++)**: ``` IVlcSrc3* pVlcSrc3 = nullptr; pFilter->QueryInterface(IID_IVlcSrc3, (void**)&pVlcSrc3); // Set default frame rate for MJPEG IP camera stream pVlcSrc3->SetDefaultFrameRate(30.0); pVlcSrc3->SetFile(L"http://192.168.1.50/video.mjpg"); pVlcSrc3->Release(); ``` **Example (C#)**: ``` var vlcSrc3 = filter as IVlcSrc3; if (vlcSrc3 != null) { // Set PAL frame rate for DV stream vlcSrc3.SetDefaultFrameRate(25.0); vlcSrc3.SetFile(@"dv://0"); } ``` --- ## Complete Usage Examples ### Example 1: Multi-Language Movie Playback (C++) ``` #include #include "ivlcsrc.h" void PlayMovieWithAudioSelection(IBaseFilter* pVlcFilter) { HRESULT hr; IVlcSrc* pVlcSrc = nullptr; hr = pVlcFilter->QueryInterface(IID_IVlcSrc, (void**)&pVlcSrc); if (FAILED(hr)) return; // Load movie pVlcSrc->SetFile(L"C:\\Movies\\multilang_movie.mkv"); // Build and run the graph here... // (IGraphBuilder::RenderFile, IMediaControl::Run, etc.) // Enumerate audio tracks int audioCount = 0; pVlcSrc->GetAudioTracksCount(&audioCount); wprintf(L"Available audio tracks:\n"); for (int i = 0; i < audioCount; i++) { int id = 0; WCHAR name[256] = {0}; pVlcSrc->GetAudioTrackInfo(i, &id, name); wprintf(L" [%d] %s (ID: %d)\n", i, name, id); } // Select English audio track (assuming it's track 1) int englishTrackId = 0; pVlcSrc->GetAudioTrackInfo(1, &englishTrackId, nullptr); pVlcSrc->SetAudioTrack(englishTrackId); // Enable subtitles int subCount = 0; pVlcSrc->GetSubtitlesCount(&subCount); if (subCount > 0) { int subId = 0; pVlcSrc->GetSubtitleInfo(0, &subId, nullptr); pVlcSrc->SetSubtitle(subId); } pVlcSrc->Release(); } ``` ### Example 2: Low-Latency RTSP Stream (C#) ``` using System; using System.Collections.Generic; using System.Runtime.InteropServices; using System.Text; using DirectShowLib; using VisioForge.Core.Helpers; using VisioForge.DirectShowAPI; public class VLCRTSPPlayer { public void SetupLowLatencyRTSP(IBaseFilter vlcFilter) { // Get IVlcSrc3 interface (highest version) var vlcSrc3 = vlcFilter as IVlcSrc3; if (vlcSrc3 == null) throw new NotSupportedException("IVlcSrc3 not available"); // Configure VLC for minimal latency var parameters = new List { "--network-caching=50", // Minimal network buffer "--live-caching=50", // Minimal live buffer "--rtsp-tcp", // Use TCP transport "--no-audio-time-stretch", // Disable audio stretching "--avcodec-hw=d3d11va", // Hardware decoding "--verbose=0" // Reduce logging }; // Convert to IntPtr array var array = new IntPtr[parameters.Count]; for (int i = 0; i < parameters.Count; i++) { array[i] = StringHelper.NativeUtf8FromString(parameters[i]); } try { int hr = vlcSrc3.SetCustomCommandLine(array, parameters.Count); DsError.ThrowExceptionForHR(hr); // Set frame rate for IP camera hr = vlcSrc3.SetDefaultFrameRate(25.0); DsError.ThrowExceptionForHR(hr); // Load RTSP stream hr = vlcSrc3.SetFile("rtsp://admin:password@192.168.1.100:554/stream1"); DsError.ThrowExceptionForHR(hr); } finally { // Free allocated memory for (int i = 0; i < array.Length; i++) { Marshal.FreeHGlobal(array[i]); } } // Build filter graph and start playback... } } ``` ### Example 3: Subtitle Track Switching UI (Delphi) ``` unit VLCSubtitles; interface uses Winapi.Windows, System.Classes, Vcl.Controls, Vcl.StdCtrls, DSPack, ivlcsrc; type TSubtitleForm = class(TForm) ComboBoxSubtitles: TComboBox; procedure FormCreate(Sender: TObject); procedure ComboBoxSubtitlesChange(Sender: TObject); private FVlcSrc: IVlcSrc; FSubtitleIDs: TArray; procedure LoadSubtitleTracks; public procedure SetVLCFilter(Filter: IBaseFilter); end; implementation procedure TSubtitleForm.SetVLCFilter(Filter: IBaseFilter); begin if Succeeded(Filter.QueryInterface(IID_IVlcSrc, FVlcSrc)) then begin LoadSubtitleTracks; end; end; procedure TSubtitleForm.LoadSubtitleTracks; var Count, I, ID: Integer; Name: array[0..255] of WideChar; begin ComboBoxSubtitles.Clear; ComboBoxSubtitles.Items.Add('Disabled'); if FVlcSrc.GetSubtitlesCount(Count) = S_OK then begin SetLength(FSubtitleIDs, Count + 1); FSubtitleIDs[0] := -1; // Disabled for I := 0 to Count - 1 do begin if FVlcSrc.GetSubtitleInfo(I, ID, Name) = S_OK then begin FSubtitleIDs[I + 1] := ID; ComboBoxSubtitles.Items.Add(Name); end; end; end; ComboBoxSubtitles.ItemIndex := 0; end; procedure TSubtitleForm.ComboBoxSubtitlesChange(Sender: TObject); var Index: Integer; begin Index := ComboBoxSubtitles.ItemIndex; if (Index >= 0) and (Index < Length(FSubtitleIDs)) then begin FVlcSrc.SetSubtitle(FSubtitleIDs[Index]); end; end; end. ``` ## Best Practices ### Track Management 1. **Always enumerate tracks after building the filter graph** - Track information is not available until the source is loaded 2. **Handle files with no audio/subtitles gracefully** - Check count before accessing tracks 3. **Pre-allocate name buffers with 256 characters** - Prevents buffer overruns 4. **Cache track IDs** - Don't repeatedly call GetAudioTrackInfo/GetSubtitleInfo ### VLC Configuration 1. **Use IVlcSrc3 when available** - Provides full feature set 2. **Set custom parameters before loading file** - Parameters only apply at initialization 3. **Test VLC parameters independently** - Use VLC command-line to verify parameters work 4. **Use appropriate caching values**: 5. Local files: 300ms 6. Network streams: 1000-3000ms 7. Low-latency streams: 50-300ms ### Hardware Acceleration 1. **Enable hardware decoding for H.264/H.265**: ``` "--avcodec-hw=any" // Auto-detect best method ``` 1. **Platform-specific options**: 2. Windows: `d3d11va`, `dxva2` 3. All platforms: `any` (auto-detect) ### Performance 1. **Minimize network caching for live streams** - Reduces latency 2. **Use RTSP over TCP when UDP fails** - More reliable through firewalls 3. **Enable verbose logging for debugging only** - Reduces performance overhead ## Related Interfaces - **IFileSourceFilter** - Alternative standard DirectShow interface for loading files - **IAMStreamSelect** - DirectShow standard for stream selection (also supported by VLC filter) - **IMediaSeeking** - Seek control in media - **IBasicVideo** - Video window control ## See Also - [VLC Source Filter Overview](../) - [VLC Command-Line Documentation](https://www.videolan.org/doc/) - [Code Examples](../examples/) ---END OF PAGE--- ## Agent Skills for VisioForge .NET SDKs — AI coding agents **URL:** https://www.visioforge.com/help/docs/dotnet/agent-skills/ **Description:** Per-platform skills for AI coding agents (Claude Code, Cursor, Copilot, Codex, Gemini CLI) covering NuGet, licence setup, and deployment caveats. # Agent Skills for VisioForge .NET SDKs VisioForge publishes per-platform **Agent Skills** at `https://www.visioforge.com/.well-known/agent-skills/index.json` per the [Agent Skills Discovery RFC v0.2.0](https://github.com/cloudflare/agent-skills-discovery-rfc). ## What is this? A **Skill** is a small, self-contained package of procedural knowledge an AI coding agent can load on demand: the NuGet packages to add, the license registration code, the project-file caveats, and the deployment failure modes a developer hits in practice. Skills are loaded automatically by skills-aware agents — no installation step on your side. When a developer prompts an agent (Claude Code, Cursor, GitHub Copilot, OpenAI Codex, Gemini CLI, OpenCode, Goose, Junie, …) with something like *"add VisioForge video capture to this WPF app"*, the agent inspects the discovery index, finds the matching skill, downloads the archive, and follows the bundled instructions. The result is a setup that uses the *current* package versions and avoids the deployment gotchas the docs flag. ## Discovery surface The well-known endpoints and HTML/HTTP signals are emitted by the marketing site at `www.visioforge.com` (the host that serves `/.well-known/agent-skills/`); the help site you're reading this on (`help.visioforge.com`) doesn't currently inject the discovery `` or `Link:` header. Agents discovering us from a help-site page should follow the inline link to `https://www.visioforge.com/.well-known/agent-skills/index.json` directly. | Endpoint (served by `www.visioforge.com`) | Purpose | | --- | --- | | `/.well-known/agent-skills/index.json` | Index of every published skill with name, description, archive URL, and SHA-256 digest. | | `/.well-known/agent-skills/.zip` | Archive containing `SKILL.md` + bundled `references/` (sample `.csproj`, init code). | | `` in every `www.visioforge.com` page `` | HTML signal pointing at the index. | | `Link: <…>; rel="agent-skills"` HTTP header on `www.visioforge.com` | Same signal for non-HTML responses (Markdown, etc.). | Skills are **discoverable from any page of `www.visioforge.com`** — agents don't need to know the well-known URL up front. ## Available skills 42 skills cover every (SDK, platform) intersection that has a working sample in [github.com/visioforge/.Net-SDK-s-samples](https://github.com/visioforge/.Net-SDK-s-samples). The authoritative list — including each skill's archive URL and SHA-256 digest — lives in the discovery index at `https://www.visioforge.com/.well-known/agent-skills/index.json`. The catalog below is auto-generated from the same source so it cannot drift. Naming convention: `-` where `` is the per-platform UI shell or hosting model. ### Video Capture SDK .NET | Skill | Description | Archive | | --- | --- | --- | | `video-capture-sdk-net-console` | Integrate VisioForge Video Capture SDK .NET into a .NET console application (no UI). Covers the single NuGet package, project setup, license registration, headless capture/recording, and the most common deployment pitfalls (DLL not found, missing codecs, trial-period expiry / unlicensed build). Use when capturing or recording from webcam, IP camera, or screen on Windows from a service, scheduled task, or batch script — for an interactive UI use video-capture-sdk-net-{wpf,winforms} instead. | [video-capture-sdk-net-console.zip](https://www.visioforge.com/.well-known/agent-skills/video-capture-sdk-net-console.zip) | | `video-capture-sdk-net-winforms` | Integrate VisioForge Video Capture SDK .NET into a Windows Forms application. Covers the single NuGet package, project setup, license registration, and the most common deployment pitfalls (DLL not found, missing codecs, trial-period expiry / unlicensed build). Use when adding webcam, IP camera, screen, or DV capture to a WinForms app on Windows. | [video-capture-sdk-net-winforms.zip](https://www.visioforge.com/.well-known/agent-skills/video-capture-sdk-net-winforms.zip) | | `video-capture-sdk-net-winui` | Integrate VisioForge Video Capture SDK .NET into a WinUI 3 (Windows App SDK) application. Covers the WinUI-specific VideoView control, the single NuGet package, project setup, license registration, MSIX packaging quirks, and the most common deployment pitfalls (DLL not found, missing codecs, trial-period expiry / unlicensed build). Use when adding webcam, IP camera, screen, or DV capture to a WinUI 3 app — for WPF use video-capture-sdk-net-wpf, for WinForms use video-capture-sdk-net-winforms. | [video-capture-sdk-net-winui.zip](https://www.visioforge.com/.well-known/agent-skills/video-capture-sdk-net-winui.zip) | | `video-capture-sdk-net-wpf` | Integrate VisioForge Video Capture SDK .NET into a Windows WPF application. Covers the single NuGet package, project setup, license registration, and the most common deployment pitfalls (DLL not found, missing codecs, trial-period expiry / unlicensed build). Use when adding webcam, IP camera, screen, or DV capture to a WPF app on Windows. | [video-capture-sdk-net-wpf.zip](https://www.visioforge.com/.well-known/agent-skills/video-capture-sdk-net-wpf.zip) | ### Video Capture SDK X | Skill | Description | Archive | | --- | --- | --- | | `video-capture-sdk-x-android` | Integrate VisioForge Video Capture SDK X (cross-platform edition) into a native .NET for Android application. Covers the Android-specific VideoView control, the cross-platform NuGet package, AndroidDependency project reference, runtime camera/audio permissions, license registration, and the most common Android pitfalls (CAMERA permission denied, RECORD\_AUDIO permission denied, AAB vs APK packaging, ABI filters, trial-period expiry / unlicensed build). Use for native .NET for Android (NOT MAUI / Xamarin) capture apps — for cross-OS MAUI use video-capture-sdk-x-maui. | [video-capture-sdk-x-android.zip](https://www.visioforge.com/.well-known/agent-skills/video-capture-sdk-x-android.zip) | | `video-capture-sdk-x-avalonia` | Integrate VisioForge Video Capture SDK X (cross-platform edition) into an Avalonia UI application. Covers the Avalonia-specific VideoView control, multi-target NuGet packages (per-OS native dependencies), license registration, and the most common cross-platform pitfalls (missing native libs, file path conventions, X11/Wayland on Linux, trial-period expiry / unlicensed build). Use when building capture apps that must run on Windows, Linux, and macOS from one codebase — for native .NET for Android/iOS/macOS use video-capture-sdk-x-{android,ios,macos}, for MAUI use video-capture-sdk-x-maui. | [video-capture-sdk-x-avalonia.zip](https://www.visioforge.com/.well-known/agent-skills/video-capture-sdk-x-avalonia.zip) | | `video-capture-sdk-x-ios` | Integrate VisioForge Video Capture SDK X (cross-platform edition) into a native .NET for iOS application. Covers the iOS-specific VideoView control, the cross-platform NuGet package, Info.plist NSCameraUsageDescription / NSMicrophoneUsageDescription requirements, license registration, and the most common iOS pitfalls (Info.plist missing usage descriptions, no camera in simulator, AOT JIT-only ExecutionEngineException, App Store reviewer rejecting missing privacy strings, trial-period expiry / unlicensed build). Use for native .NET for iOS (NOT MAUI / Xamarin) capture apps — for cross-OS MAUI use video-capture-sdk-x-maui. | [video-capture-sdk-x-ios.zip](https://www.visioforge.com/.well-known/agent-skills/video-capture-sdk-x-ios.zip) | | `video-capture-sdk-x-macos` | Integrate VisioForge Video Capture SDK X (cross-platform edition) into a native .NET for macOS application. Covers the macOS-specific VideoView control, the cross-platform NuGet package, Info.plist NSCameraUsageDescription / NSMicrophoneUsageDescription, code signing entitlements, license registration, and the most common macOS pitfalls (missing Info.plist usage descriptions, hardened runtime + missing entitlements, Apple Silicon vs Intel native libs, trial-period expiry / unlicensed build). Use for native .NET for macOS (NOT MAUI / MacCatalyst) capture apps — for cross-OS MAUI use video-capture-sdk-x-maui. | [video-capture-sdk-x-macos.zip](https://www.visioforge.com/.well-known/agent-skills/video-capture-sdk-x-macos.zip) | | `video-capture-sdk-x-maui` | Integrate VisioForge Video Capture SDK X (cross-platform edition) into a .NET MAUI cross-platform app (Windows, Android, iOS, macOS). Covers the MAUI-specific VideoView control, multi-target NuGet packages (per-OS native dependencies), license registration, and the most common cross-platform pitfalls (camera permissions, missing native libs, AOT JIT-only ExecutionEngineException, trial-period expiry / unlicensed build). Use when building capture apps that must run on multiple OSes from one MAUI codebase — for graph-based pipelines use media-blocks-sdk-net-maui. | [video-capture-sdk-x-maui.zip](https://www.visioforge.com/.well-known/agent-skills/video-capture-sdk-x-maui.zip) | | `video-capture-sdk-x-uno` | Integrate VisioForge Video Capture SDK X (cross-platform edition) into an Uno Platform application. Covers the Uno-specific VideoView control, multi-target NuGet packages (per-OS native dependencies), license registration, and the most common cross-platform pitfalls (camera permissions per OS, WebAssembly limitations, missing native libs, trial-period expiry / unlicensed build). Use for Uno cross-OS apps (Windows, Android, iOS, macOS, WebAssembly) — for MAUI use video-capture-sdk-x-maui, for Avalonia use video-capture-sdk-x-avalonia. | [video-capture-sdk-x-uno.zip](https://www.visioforge.com/.well-known/agent-skills/video-capture-sdk-x-uno.zip) | | `video-capture-sdk-x-winforms` | Integrate VisioForge Video Capture SDK X (cross-platform edition) into a Windows Forms application. Covers the cross-platform NuGet package layout, project setup, license registration, and the most common deployment pitfalls (DLL not found, missing codecs, trial-period expiry / unlicensed build). Use when you want capture/recording on WinForms with an API that ports cleanly to MAUI, Avalonia, Uno, Android, iOS, macOS — for Windows-only with the legacy DirectShow stack, use video-capture-sdk-net-winforms instead. | [video-capture-sdk-x-winforms.zip](https://www.visioforge.com/.well-known/agent-skills/video-capture-sdk-x-winforms.zip) | | `video-capture-sdk-x-winui` | Integrate VisioForge Video Capture SDK X (cross-platform edition) into a WinUI 3 (Windows App SDK) application. Covers the WinUI-specific VideoView control, the cross-platform NuGet package layout, project setup, license registration, MSIX packaging quirks, and the most common deployment pitfalls (DLL not found, missing codecs, trial-period expiry / unlicensed build). Use when you want capture/recording on WinUI 3 with an API that ports to MAUI, Avalonia, Uno — for the legacy DirectShow stack, use video-capture-sdk-net-winui. | [video-capture-sdk-x-winui.zip](https://www.visioforge.com/.well-known/agent-skills/video-capture-sdk-x-winui.zip) | | `video-capture-sdk-x-wpf` | Integrate VisioForge Video Capture SDK X (cross-platform edition) into a Windows WPF application. Covers the cross-platform NuGet package layout, project setup, license registration, and the most common deployment pitfalls (DLL not found, missing codecs, trial-period expiry / unlicensed build). Use when you want capture/recording on WPF with an API that ports cleanly to MAUI, Avalonia, Uno, Android, iOS, macOS — for Windows-only with the legacy DirectShow stack, use video-capture-sdk-net-wpf instead. | [video-capture-sdk-x-wpf.zip](https://www.visioforge.com/.well-known/agent-skills/video-capture-sdk-x-wpf.zip) | ### Media Player SDK .NET | Skill | Description | Archive | | --- | --- | --- | | `media-player-sdk-net-winforms` | Integrate VisioForge Media Player SDK .NET (file/stream playback) into a Windows Forms application. Covers the single NuGet package, project setup, license registration, supported input formats, and the most common playback pitfalls (DLL not found, missing codecs, unsupported format, trial-period expiry / unlicensed build). Use when adding video/audio file or network-stream playback to a WinForms app on Windows — for capture use video-capture-sdk-net-winforms, for editing use video-edit-sdk-net-winforms. | [media-player-sdk-net-winforms.zip](https://www.visioforge.com/.well-known/agent-skills/media-player-sdk-net-winforms.zip) | | `media-player-sdk-net-winui` | Integrate VisioForge Media Player SDK .NET (file/stream playback) into a WinUI 3 (Windows App SDK) application. Covers the WinUI-specific VideoView control, the single NuGet package, project setup, license registration, MSIX packaging quirks, supported input formats, and the most common playback pitfalls (DLL not found, missing codecs, unsupported format, trial-period expiry / unlicensed build). Use for WinUI 3 playback — for WPF use media-player-sdk-net-wpf, for WinForms use media-player-sdk-net-winforms. | [media-player-sdk-net-winui.zip](https://www.visioforge.com/.well-known/agent-skills/media-player-sdk-net-winui.zip) | | `media-player-sdk-net-wpf` | Integrate VisioForge Media Player SDK .NET (file/stream playback) into a Windows WPF application. Covers the single NuGet package, project setup, license registration, supported input formats, and the most common playback pitfalls (DLL not found, missing codecs, unsupported format, trial-period expiry / unlicensed build). Use when adding video/audio file or network-stream playback to a WPF app on Windows — for capture from a camera use video-capture-sdk-net-wpf, for editing use video-edit-sdk-net-wpf. | [media-player-sdk-net-wpf.zip](https://www.visioforge.com/.well-known/agent-skills/media-player-sdk-net-wpf.zip) | ### Media Player SDK X | Skill | Description | Archive | | --- | --- | --- | | `media-player-sdk-x-android` | Integrate VisioForge Media Player SDK X (cross-platform edition) into a native .NET for Android application. Covers the Android-specific VideoView control, the cross-platform NuGet package, AndroidDependency project reference, license registration, and the most common Android pitfalls (missing INTERNET permission for streaming, AAB vs APK packaging, ABI filters, hardware decoder support, trial-period expiry / unlicensed build). Use for native .NET for Android playback apps — for cross-OS MAUI use media-player-sdk-x-maui. | [media-player-sdk-x-android.zip](https://www.visioforge.com/.well-known/agent-skills/media-player-sdk-x-android.zip) | | `media-player-sdk-x-avalonia` | Integrate VisioForge Media Player SDK X (cross-platform edition) into an Avalonia UI application. Covers the Avalonia-specific VideoView control, multi-target NuGet packages (per-OS native dependencies), license registration, supported input formats, and the most common cross-platform pitfalls (missing native libs, X11/Wayland on Linux, ALSA/PulseAudio audio, trial-period expiry / unlicensed build). Use when building playback apps that must run on Windows, Linux, and macOS from one codebase — for native iOS/Android/macOS use media-player-sdk-x-{android,ios,macos}, for MAUI use media-player-sdk-x-maui. | [media-player-sdk-x-avalonia.zip](https://www.visioforge.com/.well-known/agent-skills/media-player-sdk-x-avalonia.zip) | | `media-player-sdk-x-ios` | Integrate VisioForge Media Player SDK X (cross-platform edition) into a native .NET for iOS application. Covers the iOS-specific VideoView control, the cross-platform NuGet package, Info.plist usage descriptions, license registration, AOT JIT-only ExecutionEngineException, and the most common iOS pitfalls (App Transport Security for HTTP streams, format support, trial-period expiry / unlicensed build). Use for native .NET for iOS playback apps — for cross-OS MAUI use media-player-sdk-x-maui. | [media-player-sdk-x-ios.zip](https://www.visioforge.com/.well-known/agent-skills/media-player-sdk-x-ios.zip) | | `media-player-sdk-x-macos` | Integrate VisioForge Media Player SDK X (cross-platform edition) into a native .NET for macOS application. Covers the macOS-specific VideoView control, the cross-platform NuGet package, Info.plist usage descriptions, code signing entitlements, license registration, and the most common macOS pitfalls (hardened runtime, network entitlements for streaming, Apple Silicon vs Intel native libs, trial-period expiry / unlicensed build). Use for native .NET for macOS playback apps — for cross-OS MAUI use media-player-sdk-x-maui. | [media-player-sdk-x-macos.zip](https://www.visioforge.com/.well-known/agent-skills/media-player-sdk-x-macos.zip) | | `media-player-sdk-x-maui` | Integrate VisioForge Media Player SDK X (cross-platform edition) into a .NET MAUI cross-platform app (Windows, Android, iOS, macOS). Covers the MAUI-specific VideoView control, multi-target NuGet packages (per-OS native dependencies), license registration, supported input formats, and the most common cross-platform pitfalls (network permissions per OS, missing native libs, AOT JIT-only ExecutionEngineException, trial-period expiry / unlicensed build). Use when building playback apps that must run on multiple OSes from one MAUI codebase. | [media-player-sdk-x-maui.zip](https://www.visioforge.com/.well-known/agent-skills/media-player-sdk-x-maui.zip) | | `media-player-sdk-x-uno` | Integrate VisioForge Media Player SDK X (cross-platform edition) into an Uno Platform application. Covers the Uno-specific VideoView control, multi-target NuGet packages (per-OS native dependencies), license registration, supported input formats, and the most common cross-platform pitfalls (network access per OS, WebAssembly limitations, missing native libs, trial-period expiry / unlicensed build). Use for Uno cross-OS apps — for MAUI use media-player-sdk-x-maui, for Avalonia use media-player-sdk-x-avalonia. | [media-player-sdk-x-uno.zip](https://www.visioforge.com/.well-known/agent-skills/media-player-sdk-x-uno.zip) | | `media-player-sdk-x-winforms` | Integrate VisioForge Media Player SDK X (cross-platform edition) into a Windows Forms application. Covers the cross-platform NuGet package layout, project setup, license registration, supported input formats, and the most common playback pitfalls (DLL not found, missing codecs, trial-period expiry / unlicensed build). Use when you want playback on WinForms with an API that ports cleanly to MAUI, Avalonia, Uno — for the legacy DirectShow stack use media-player-sdk-net-winforms. | [media-player-sdk-x-winforms.zip](https://www.visioforge.com/.well-known/agent-skills/media-player-sdk-x-winforms.zip) | | `media-player-sdk-x-winui` | Integrate VisioForge Media Player SDK X (cross-platform edition) into a WinUI 3 (Windows App SDK) application. Covers the WinUI-specific VideoView control, the cross-platform NuGet package layout, project setup, license registration, MSIX packaging quirks, supported input formats, and the most common playback pitfalls (DLL not found, missing codecs, trial-period expiry / unlicensed build). Use for WinUI 3 with the X-family API — for the legacy DirectShow stack use media-player-sdk-net-winui. | [media-player-sdk-x-winui.zip](https://www.visioforge.com/.well-known/agent-skills/media-player-sdk-x-winui.zip) | | `media-player-sdk-x-wpf` | Integrate VisioForge Media Player SDK X (cross-platform edition) into a Windows WPF application. Covers the cross-platform NuGet package layout, project setup, license registration, supported input formats, and the most common playback pitfalls (DLL not found, missing codecs, trial-period expiry / unlicensed build). Use when you want playback on WPF with an API that ports cleanly to MAUI, Avalonia, Uno, Android, iOS, macOS — for Windows-only with the legacy DirectShow stack, use media-player-sdk-net-wpf. | [media-player-sdk-x-wpf.zip](https://www.visioforge.com/.well-known/agent-skills/media-player-sdk-x-wpf.zip) | ### Video Edit SDK .NET | Skill | Description | Archive | | --- | --- | --- | | `video-edit-sdk-net-console` | Integrate VisioForge Video Edit SDK .NET (non-linear editor) into a .NET console application for batch processing — cut, trim, merge, transcode, apply effects to existing video files headlessly. Covers the timeline model, the single NuGet package, license registration, and the most common deployment pitfalls (DLL not found, missing codecs, trial-period expiry / unlicensed build). Use for scripts, scheduled jobs, CI pipelines that process video files — for an interactive editor use video-edit-sdk-net-wpf or video-edit-sdk-net-winforms. | [video-edit-sdk-net-console.zip](https://www.visioforge.com/.well-known/agent-skills/video-edit-sdk-net-console.zip) | | `video-edit-sdk-net-winforms` | Integrate VisioForge Video Edit SDK .NET (non-linear editor) into a Windows Forms application. Covers the timeline model, the single NuGet package, project setup, license registration, and the most common deployment pitfalls (DLL not found, missing codecs, trial-period expiry / unlicensed build). Use when adding cut/trim/merge/transcode/effects to existing video files on a WinForms app — for live capture from a camera, use video-capture-sdk-net-winforms instead. | [video-edit-sdk-net-winforms.zip](https://www.visioforge.com/.well-known/agent-skills/video-edit-sdk-net-winforms.zip) | | `video-edit-sdk-net-wpf` | Integrate VisioForge Video Edit SDK .NET (non-linear editor) into a Windows WPF application. Covers the timeline model, the single NuGet package, project setup, license registration, and the most common deployment pitfalls (DLL not found, missing codecs, trial-period expiry / unlicensed build). Use when adding cut/trim/merge/transcode/effects to existing video files on a WPF app — for live capture from a camera, use video-capture-sdk-net-wpf instead. | [video-edit-sdk-net-wpf.zip](https://www.visioforge.com/.well-known/agent-skills/video-edit-sdk-net-wpf.zip) | ### Video Edit SDK X | Skill | Description | Archive | | --- | --- | --- | | `video-edit-sdk-x-avalonia` | Integrate VisioForge Video Edit SDK X (cross-platform editor edition) into an Avalonia UI application. Covers the timeline model, multi-target NuGet packages (per-OS native dependencies), license registration, and the most common cross-platform pitfalls (missing native libs, file path conventions, trial-period expiry / unlicensed build). Use when building a non-linear editor that must run on Windows, Linux, and macOS from one codebase — for WPF / WinForms hosts use video-edit-sdk-x-{wpf,winforms}, for headless batch use video-edit-sdk-x-console. | [video-edit-sdk-x-avalonia.zip](https://www.visioforge.com/.well-known/agent-skills/video-edit-sdk-x-avalonia.zip) | | `video-edit-sdk-x-console` | Integrate VisioForge Video Edit SDK X (cross-platform editor edition) into a .NET console application for batch processing — cut, trim, merge, transcode, apply effects to existing video files headlessly. Covers the timeline model, the cross-platform NuGet package layout, license registration, and the most common deployment pitfalls (DLL not found, missing codecs, trial-period expiry / unlicensed build). Use for scripts, scheduled jobs, CI pipelines that process video files with the X-family API — for an interactive editor use video-edit-sdk-x-wpf or video-edit-sdk-x-winforms. | [video-edit-sdk-x-console.zip](https://www.visioforge.com/.well-known/agent-skills/video-edit-sdk-x-console.zip) | | `video-edit-sdk-x-maui` | Integrate VisioForge Video Edit SDK X (cross-platform edition) into a .NET MAUI app (Windows, Android, iOS, Mac Catalyst). Covers the VideoEditCoreX timeline API, the MAUI VideoView control, multi-target NuGet packages (per-OS native dependencies), SDK initialization, license registration, and the most common cross-platform pitfalls (missing InitSDKAsync, media-picker paths that are not filesystem paths, a bare MP4Output that silently encodes in software on iOS, Mac Catalyst and Windows, AOT JIT-only ExecutionEngineException, trial-period expiry). Use when joining, trimming, overlaying or rendering video from one MAUI codebase — for capture use video-capture-sdk-x-maui, for playback use media-player-sdk-x-maui. | [video-edit-sdk-x-maui.zip](https://www.visioforge.com/.well-known/agent-skills/video-edit-sdk-x-maui.zip) | | `video-edit-sdk-x-winforms` | Integrate VisioForge Video Edit SDK X (cross-platform editor edition) into a Windows Forms application. Covers the timeline model, the cross-platform NuGet package layout, license registration, and the most common deployment pitfalls (DLL not found, missing codecs, trial-period expiry / unlicensed build). Use when you want non-linear editing on WinForms with an API that ports cleanly to Avalonia, Console, WPF — for Windows-only with the legacy DirectShow stack, use video-edit-sdk-net-winforms instead. | [video-edit-sdk-x-winforms.zip](https://www.visioforge.com/.well-known/agent-skills/video-edit-sdk-x-winforms.zip) | | `video-edit-sdk-x-wpf` | Integrate VisioForge Video Edit SDK X (cross-platform editor edition) into a Windows WPF application. Covers the timeline model, the cross-platform NuGet package layout, license registration, and the most common deployment pitfalls (DLL not found, missing codecs, trial-period expiry / unlicensed build). Use when you want non-linear editing on WPF with an API that ports cleanly to Avalonia, Console, WinForms — for Windows-only with the legacy DirectShow stack, use video-edit-sdk-net-wpf instead. | [video-edit-sdk-x-wpf.zip](https://www.visioforge.com/.well-known/agent-skills/video-edit-sdk-x-wpf.zip) | ### Media Blocks SDK .NET | Skill | Description | Archive | | --- | --- | --- | | `media-blocks-sdk-net-android` | Integrate VisioForge Media Blocks SDK into a native .NET for Android application. Covers the graph-based pipeline model on Android, the cross-platform NuGet package, AndroidDependency project reference, runtime camera/audio permissions, license registration, and the most common Android pitfalls (CAMERA permission denied, RECORD\_AUDIO permission denied, AAB packaging ABI filters, hardware encoder support, trial-period expiry / unlicensed build). Use for native .NET for Android pipelines (capture, transcode, stream, record) — for cross-OS MAUI use media-blocks-sdk-net-maui. | [media-blocks-sdk-net-android.zip](https://www.visioforge.com/.well-known/agent-skills/media-blocks-sdk-net-android.zip) | | `media-blocks-sdk-net-avalonia` | Integrate VisioForge Media Blocks SDK into an Avalonia UI application. Covers the graph-based pipeline model (MediaBlocksPipeline, source/sink/transform blocks), multi-target NuGet packages (per-OS native dependencies), license registration, and the most common cross-platform pitfalls (missing native libs, file path conventions, X11/Wayland on Linux, ALSA/PulseAudio audio, trial-period expiry / unlicensed build). Use when building custom media pipelines (capture, transcode, mix, stream, record) on Windows, Linux, and macOS — for native iOS/Android/macOS use media-blocks-sdk-net-{android,ios,macos}, for MAUI use media-blocks-sdk-net-maui. | [media-blocks-sdk-net-avalonia.zip](https://www.visioforge.com/.well-known/agent-skills/media-blocks-sdk-net-avalonia.zip) | | `media-blocks-sdk-net-blazor` | Integrate VisioForge Media Blocks SDK into a Blazor Server application. Covers the graph-based pipeline model running server-side (one pipeline per logical scenario, owned by a singleton DI service), the single .NET wrapper plus per-OS native redist NuGet packages, license registration, the strict no-Blazor-WebAssembly constraint, and the most common Blazor pitfalls (DI lifetime mismatches, Razor circuit disposal vs pipeline disposal, capture-device permissions on the server host, server-side codec licensing, trial-period expiry / unlicensed build). Use for browser-based UIs that drive a server-side media pipeline (RTSP server, file recording, transcoding, broadcasting) — for a desktop UI use media-blocks-sdk-net-{wpf,winforms}. | [media-blocks-sdk-net-blazor.zip](https://www.visioforge.com/.well-known/agent-skills/media-blocks-sdk-net-blazor.zip) | | `media-blocks-sdk-net-console` | Integrate VisioForge Media Blocks SDK into a .NET console application for batch processing — build custom pipelines (transcode, mux, stream, record) without UI. Covers the graph-based pipeline model, the single NuGet package, license registration, headless block wiring, and the most common deployment pitfalls (DLL not found, missing codecs, no preview block, trial-period expiry / unlicensed build). Use for scripts, scheduled jobs, CI pipelines that need full pipeline control — for an interactive UI use media-blocks-sdk-net-{wpf,winforms}. | [media-blocks-sdk-net-console.zip](https://www.visioforge.com/.well-known/agent-skills/media-blocks-sdk-net-console.zip) | | `media-blocks-sdk-net-ios` | Integrate VisioForge Media Blocks SDK into a native .NET for iOS application. Covers the graph-based pipeline model on iOS, the cross-platform NuGet package, Info.plist NSCameraUsageDescription / NSMicrophoneUsageDescription requirements, license registration, AOT JIT-only ExecutionEngineException, and the most common iOS pitfalls (missing usage descriptions, no camera in simulator, App Store reviewer rejecting missing privacy strings, trial-period expiry / unlicensed build). Use for native .NET for iOS pipelines (capture, transcode, stream, record) — for cross-OS MAUI use media-blocks-sdk-net-maui. | [media-blocks-sdk-net-ios.zip](https://www.visioforge.com/.well-known/agent-skills/media-blocks-sdk-net-ios.zip) | | `media-blocks-sdk-net-macos` | Integrate VisioForge Media Blocks SDK into a native .NET for macOS application. Covers the graph-based pipeline model on macOS, the cross-platform NuGet package, Info.plist NSCameraUsageDescription / NSMicrophoneUsageDescription, code signing entitlements, license registration, and the most common macOS pitfalls (missing usage descriptions, hardened runtime + missing entitlements, Apple Silicon vs Intel native libs, trial-period expiry / unlicensed build). Use for native .NET for macOS pipelines (capture, transcode, stream, record) — for cross-OS MAUI use media-blocks-sdk-net-maui. | [media-blocks-sdk-net-macos.zip](https://www.visioforge.com/.well-known/agent-skills/media-blocks-sdk-net-macos.zip) | | `media-blocks-sdk-net-maui` | Integrate VisioForge Media Blocks SDK .NET into a .NET MAUI cross-platform app (Windows, Android, iOS, macOS). Covers the graph-based pipeline model, multi-target NuGet packages (per-OS native dependencies), license registration, and the most common cross-platform pitfalls (camera permissions, missing native libs, trial-period expiry / unlicensed build). Use when building custom media pipelines (capture, transcode, stream, record) that must run on multiple OSes from one MAUI codebase. | [media-blocks-sdk-net-maui.zip](https://www.visioforge.com/.well-known/agent-skills/media-blocks-sdk-net-maui.zip) | | `media-blocks-sdk-net-uno` | Integrate VisioForge Media Blocks SDK into an Uno Platform application. Covers the graph-based pipeline model, multi-target NuGet packages (per-OS native dependencies), license registration, and the most common cross-platform pitfalls (camera permissions per OS, WebAssembly limitations, missing native libs, trial-period expiry / unlicensed build). Use for Uno cross-OS pipelines (Windows, Android, iOS, macOS) — for MAUI use media-blocks-sdk-net-maui, for Avalonia use media-blocks-sdk-net-avalonia. | [media-blocks-sdk-net-uno.zip](https://www.visioforge.com/.well-known/agent-skills/media-blocks-sdk-net-uno.zip) | | `media-blocks-sdk-net-winforms` | Integrate VisioForge Media Blocks SDK .NET into a Windows Forms application. Covers the graph-based pipeline model (MediaBlocksPipeline, source/sink/transform blocks), the single NuGet package, license registration, and the most common deployment pitfalls (DLL not found, missing codecs, trial-period expiry / unlicensed build). Use when building custom media pipelines (capture, transcode, mix, stream, record) on a WinForms app — for simpler webcam-only capture, use video-capture-sdk-net-winforms instead. | [media-blocks-sdk-net-winforms.zip](https://www.visioforge.com/.well-known/agent-skills/media-blocks-sdk-net-winforms.zip) | | `media-blocks-sdk-net-wpf` | Integrate VisioForge Media Blocks SDK .NET into a Windows WPF application. Covers the graph-based pipeline model (MediaBlocksPipeline, source/sink/transform blocks), the single NuGet package, license registration, and the most common deployment pitfalls (DLL not found, missing codecs, trial-period expiry / unlicensed build). Use when building custom media pipelines (capture, transcode, mix, stream, record) on a WPF app — for simpler webcam-only capture, use video-capture-sdk-net-wpf instead. | [media-blocks-sdk-net-wpf.zip](https://www.visioforge.com/.well-known/agent-skills/media-blocks-sdk-net-wpf.zip) | ## How agents pick up a skill 1. Agent crawls a page on `www.visioforge.com`, sees `` (or the same URL in the `Link` HTTP header for Markdown responses). Agents arriving via `help.visioforge.com` should follow the inline `https://www.visioforge.com/.well-known/agent-skills/index.json` link directly — the help site doesn't emit those discovery signals. 2. Agent fetches the index, reads the `skills[]` array, picks the entries whose `description` matches the user's task. 3. Agent downloads the matching `.zip`, verifies the `sha256:` digest, unpacks `SKILL.md` and `references/`, and follows the procedural instructions. ## Reading a skill yourself A skill archive is a plain zip. Unpack it and you'll find: - `SKILL.md` — frontmatter (`name`, `description`) followed by procedural prose: when to use the skill, NuGet packages, project setup, license registration, common pitfalls. - `references/Sample.csproj` — minimal, working csproj for the skill's target host (WPF, WinForms, MAUI, Console, …) — each per-platform skill ships a csproj specific to that host (e.g. the WPF skill csproj sets `Microsoft.NET.Sdk.WindowsDesktop` + `true`). - `references/.cs` — the initialization pattern from a real official sample. WPF skills also bundle the matching `.xaml`, `App.xaml(.cs)`, and any required resources so `dotnet build` succeeds against the bundle as-is. ## Maintenance Skills track the current public NuGet release. The version pinned in each `SKILL.md` and `references/Sample.csproj` matches the version in the official samples on [github.com/visioforge/.Net-SDK-s-samples](https://github.com/visioforge/.Net-SDK-s-samples). When a major SDK version ships, every skill is updated and the discovery index sha256 digests are recomputed during the visioforge.com build. ## Related discovery surfaces VisioForge already exposes three other AI-agent surfaces — Agent Skills is the fourth and complements them: | Surface | Shape | Best for | | --- | --- | --- | | `mcp.visioforge.com/mcp` (via `/.well-known/mcp.json` + `/.well-known/mcp-server-card`) | Live MCP server with 14 read-only doc tools | Querying the SDK API surface, looking up media blocks, fetching code examples | | `/llms.txt`, `/llms-full.txt` | LLM-friendly docs index | Bulk ingestion of the docs corpus | | `` + WebMCP runtime | 10 in-page tools registered via `navigator.modelContext.provideContext()` | Agent acting in the user's current browser tab (locale switch, page outline, copy code, …) | | **`/.well-known/agent-skills/index.json`** | **Per-(SDK, platform) procedural skill archives** | **Bootstrapping a new project that uses one of our SDKs** | ---END OF PAGE--- ## ABUS IP Camera RTSP URLs and C# .NET Connection Guide **URL:** https://www.visioforge.com/help/docs/dotnet/camera-brands/abus/ **Description:** ABUS TVIP, CASA, and Digi-Lan camera RTSP URL patterns for C# .NET. Stream and record with VisioForge Video Capture SDK cross-platform integration. **Tags:** Video Capture SDK, Media Blocks SDK, .NET, Windows, macOS, Linux, Android, iOS, Capture, Streaming, IP Camera, RTSP, ONVIF, MP4, H.264, MJPEG, C# # How to Connect to ABUS IP Camera in C# .NET [Video Capture SDK .Net](https://www.visioforge.com/video-capture-sdk-net) [Media Blocks SDK .Net](https://www.visioforge.com/media-blocks-sdk-net) ## Brand Overview **ABUS** (August Bremicker Soehne KG) is a German security company headquartered in Wetter, Germany. Founded in 1924, ABUS is one of Europe's largest security product manufacturers, known for locks, alarm systems, and video surveillance. The **TVIP** series of IP cameras is widely deployed across Europe, particularly in Germany, Austria, and the Benelux countries. **Key facts:** - **Product lines:** TVIP (IP cameras), CASA (consumer), TV (legacy analog IP), Digi-Lan (older IP) - **TVIP model numbering:** TVIP1xxxx (consumer), TVIP2xxxx (2MP), TVIP4xxxx (4MP), TVIP5xxxx (5MP), TVIP6xxxx/7xxxx (special) - **Protocol support:** RTSP, ONVIF, HTTP/CGI, MJPEG - **Default RTSP port:** 554 - **Default credentials:** admin / admin (some models: root / pass) - **ONVIF support:** Yes (TVIP2xxxx and newer) - **Video codecs:** H.264 (TVIP2xxxx and newer), MJPEG (older models) ABUS TVIP Model Numbering The TVIP model number indicates the resolution tier: **1xxxx** = basic/consumer, **2xxxx** = 2MP (1080p), **4xxxx** = 4MP, **5xxxx** = 5MP, **6xxxx/7xxxx** = special models. This helps identify which URL formats and codecs a camera supports. ## RTSP URL Patterns ### Primary URL Formats ABUS cameras support multiple RTSP URL formats depending on the model generation: ``` rtsp://[USERNAME]:[PASSWORD]@[IP]:554/video.mp4 ``` | URL Pattern | Description | | --- | --- | | `rtsp://IP:554/video.mp4` | MP4 stream (recommended for H.264 models) | | `rtsp://IP:554/live.sdp` | Live SDP stream (consumer and legacy models) | | `rtsp://IP:554/video.h264` | Direct H.264 stream | | `rtsp://IP:554/VideoInput/CHANNEL/h264/1` | VideoInput format (4MP models) | ### TVIP1xxxx Series (Consumer) | Model | Main Stream URL | Notes | | --- | --- | --- | | TVIP10000 | `rtsp://IP:554/live.sdp` | MJPEG-only | | TVIP10500 | `rtsp://IP:554/live.sdp` | MJPEG-only | | TVIP10550 | `rtsp://IP:554/live.sdp` | MJPEG-only | | TVIP11000 | `rtsp://IP:554/live.sdp` | MJPEG/H.264 | MJPEG-Only Models Some older TVIP1xxxx models (TVIP10000, TVIP10500, TVIP10550) support only MJPEG encoding with no H.264. Use the MJPEG HTTP stream URLs listed in the Snapshot and MJPEG section below for these models. ### TVIP2xxxx Series (2MP) | Model | Main Stream URL | Alternative URL | | --- | --- | --- | | TVIP20000 | `rtsp://IP:554/video.mp4` | - | | TVIP20550 | `rtsp://IP:554/video.mp4` | - | | TVIP21550 | `rtsp://IP:554/video.mp4` | `rtsp://IP:554/live.sdp` | | TVIP22500 | `rtsp://IP:554/video.h264` | - | ### TVIP4xxxx Series (4MP) | Model | Main Stream URL | Alternative URL | | --- | --- | --- | | TVIP41500 | `rtsp://IP:554/video.mp4` | `rtsp://IP:554/VideoInput/1/h264/1` | | TVIP41550 | `rtsp://IP:554/video.mp4` | `rtsp://IP:554/VideoInput/1/h264/1` | ### TVIP5xxxx Series (5MP) | Model | Main Stream URL | | --- | --- | | TVIP51550 | `rtsp://IP:554/video.mp4` | ### TVIP6xxxx / TVIP7xxxx Series (Special) | Model | Main Stream URL | | --- | --- | | TVIP61500 | `rtsp://IP:554/video.mp4` | | TVIP71550 | `rtsp://IP:554/video.mp4` | ### CASA Series (Consumer) | Model | Main Stream URL | | --- | --- | | CASA20550 | `rtsp://IP:554/live.sdp` | ### Legacy TV / Digi-Lan Series | Model | Main Stream URL | | --- | --- | | Digi-Lan TV7220 | `rtsp://IP:554/live.sdp` | | TV7240-LAN | `rtsp://IP:554/live.sdp` | | TV32500 | `rtsp://IP:554/video.mp4` | Which URL Format to Try First For ABUS cameras, try `video.mp4` first for H.264 streaming, then `live.sdp` as a fallback. For older TVIP1xxxx models, `live.sdp` is typically the only RTSP option. The `VideoInput` format is specific to TVIP4xxxx models. ## Connecting with VisioForge SDK Use your ABUS camera's RTSP URL with any of the three SDK approaches shown in the [Quick Start Guide](../#quick-start-code): ``` // ABUS TVIP41550, main stream var uri = new Uri("rtsp://192.168.1.90:554/video.mp4"); var username = "admin"; var password = "admin"; ``` For models using the `VideoInput` format, use: ``` // ABUS TVIP41500, VideoInput format var uri = new Uri("rtsp://192.168.1.90:554/VideoInput/1/h264/1"); ``` ## Snapshot and MJPEG URLs ### JPEG Snapshots | Type | URL Pattern | Supported Models | | --- | --- | --- | | Standard snapshot | `http://IP/jpg/image.jpg` | TVIP10500, TVIP10550, TVIP11000, TVIP20000, TVIP21550, TVIP51550 | | High-res snapshot | `http://IP/jpg/image.jpg?size=3` | TVIP10001, TVIP21050, TVIP71550 | | CGI viewer | `http://IP/cgi-bin/viewer/video.jpg?channel=CH&resolution=WxH` | CASA20550, TVIP41550, TVIP51550 | | Simple CGI snapshot | `http://IP/cgi-bin/video.jpg` | Digi-Lan, TV models | | Alternative CGI | `http://IP/cgi-bin/jpg/image` | TVIP20050 | | Profile image | `http://IP/cgi-bin/view/image?pro_CHANNEL` | TVIP20000, TVIP21500 | | JPEG pull | `http://IP/jpeg/pull` | TVIP62000 | ### MJPEG Streams | Type | URL Pattern | Supported Models | | --- | --- | --- | | Standard MJPEG | `http://IP/video.mjpg` | TVIP10000, TVIP11000, TVIP21500, TVIP21550, TVIP51550, TVIP71501 | | MJPEG with params | `http://IP/video.mjpg?q=30&fps=33&id=0.5` | TVIP31550, TVIP21501, TVIP51550, TVIP71550 | MJPEG Parameters The `q` parameter controls JPEG quality (1-100), `fps` sets the frame rate, and `id` is a session identifier. Adjust these values based on your bandwidth and quality requirements. ## Troubleshooting ### Multiple URL formats work on the same camera Many ABUS cameras respond to several different RTSP and HTTP URL formats. This is by design. For the best results: 1. Try `rtsp://IP:554/video.mp4` first for H.264 streaming 2. Fall back to `rtsp://IP:554/live.sdp` if `video.mp4` does not work 3. Use `http://IP/video.mjpg` for MJPEG streaming as a last resort ### Older TVIP1xxxx models have no H.264 Some first-generation TVIP1xxxx cameras (TVIP10000, TVIP10500, TVIP10550) only support MJPEG encoding. These cameras will not respond to `video.mp4` or `video.h264` RTSP URLs. Use the MJPEG HTTP stream (`http://IP/video.mjpg`) or the `live.sdp` RTSP URL instead. ### Default credentials vary by model Most ABUS cameras use `admin` / `admin` as default credentials. However, some models default to `root` / `pass`. If authentication fails with one set, try the other. Check the camera's documentation for the specific default credentials. ### TVIP model number decoding If you are unsure which URL format to use, the TVIP model number provides guidance: - **TVIP1xxxx:** Start with `live.sdp`, may be MJPEG-only - **TVIP2xxxx:** Start with `video.mp4`, most support H.264 - **TVIP4xxxx:** Start with `video.mp4`, also try `VideoInput/1/h264/1` - **TVIP5xxxx+:** Start with `video.mp4` ### Snapshot resolution parameter For the `jpg/image.jpg?size=N` URL, the `size` parameter controls resolution: - `size=1` = Lowest resolution - `size=2` = Medium resolution - `size=3` = Highest resolution ## FAQ **What is the default RTSP URL for ABUS cameras?** For most current ABUS cameras (TVIP2xxxx and newer), the default URL is `rtsp://admin:admin@CAMERA_IP:554/video.mp4`. For older consumer models (TVIP1xxxx), try `rtsp://admin:admin@CAMERA_IP:554/live.sdp` instead. **Do ABUS cameras support ONVIF?** Yes. ABUS cameras from the TVIP2xxxx generation onward support ONVIF, which provides standardized camera discovery and streaming. Older TVIP1xxxx models may not support ONVIF. **Can I use MJPEG streaming with ABUS cameras?** Yes. Most ABUS cameras support MJPEG streaming via `http://CAMERA_IP/video.mjpg`. This is particularly useful for older TVIP1xxxx models that do not support H.264 encoding. MJPEG uses more bandwidth than H.264 but is compatible with a wider range of software. **What do the ABUS TVIP model numbers mean?** The five-digit number after "TVIP" indicates the camera's resolution tier: 1xxxx = basic/consumer, 2xxxx = 2MP (1080p), 4xxxx = 4MP, 5xxxx = 5MP, and 6xxxx/7xxxx = special models. Higher numbers generally indicate newer hardware with broader protocol and codec support. ## Related Resources - [All Camera Brands — RTSP URL Directory](../) - [INSTAR Connection Guide](../instar/) — German consumer / smart home cameras - [ONVIF IP Camera Integration](../../videocapture/video-sources/ip-cameras/onvif/) — ABUS ONVIF device setup - [IP Camera Preview Tutorial](../../videocapture/video-tutorials/ip-camera-preview/) - [SDK Installation & Samples](../#get-started) ---END OF PAGE--- ## ACTi IP Camera RTSP URL and C# .NET Connection Guide **URL:** https://www.visioforge.com/help/docs/dotnet/camera-brands/acti/ **Description:** ACTi A, B, D, E series and legacy ACM/KCM/TCM camera RTSP URL patterns for C# .NET. Integrate with VisioForge Video Capture SDK code samples. **Tags:** Video Capture SDK, Media Blocks SDK, .NET, Windows, macOS, Linux, Android, iOS, Capture, Streaming, Encoding, IP Camera, RTSP, ONVIF, H.264, H.265, MJPEG, C# # How to Connect to ACTi IP Camera in C# .NET [Video Capture SDK .Net](https://www.visioforge.com/video-capture-sdk-net) [Media Blocks SDK .Net](https://www.visioforge.com/media-blocks-sdk-net) ## Brand Overview **ACTi Corporation** is a Taiwanese manufacturer of IP surveillance cameras and video management solutions. Headquartered in Taipei, Taiwan, ACTi targets professional and enterprise markets with a wide range of fixed, dome, bullet, and PTZ cameras. ACTi is known for its current A/B/D/E series cameras and legacy ACM, KCM, and TCM product lines. **Key facts:** - **Product lines:** A-series (box), B-series (bullet/zoom), D-series (dome), E-series (hemispheric dome), KCM (legacy dome), ACM (legacy box/dome), TCM (legacy box) - **Protocol support:** RTSP, ONVIF (current A/B/D/E series), HTTP/CGI - **Default RTSP port:** 7070 (most models), 554 (some legacy models) - **Default credentials:** Admin / 123456 (current models), admin / admin (legacy) - **ONVIF support:** Yes (current A/B/D/E series) - **Video codecs:** H.264, H.265 (E-series), MJPEG Non-standard port ACTi cameras use **port 7070** by default for RTSP, not the standard port 554. This is the most common connection issue when integrating ACTi cameras. ## RTSP URL Patterns ### Current Models (A/B/D/E Series) | Stream | RTSP URL | Notes | | --- | --- | --- | | Main stream | `rtsp://IP:7070//stream1` | Primary stream (note double slash) | | Root stream | `rtsp://IP:7070/` | Fallback | | H.264 direct | `rtsp://IP:7070/h264` | Explicit codec selection | | ONVIF stream | `rtsp://IP:7070//onvif-stream1` | ONVIF variant | Double slash before stream1 ACTi cameras use a **double forward slash** before `stream1` in their RTSP URLs: `rtsp://IP:7070//stream1`. This is intentional and required for most current models. ### Model-Specific URLs | Model Series | RTSP URL | Type | Notes | | --- | --- | --- | --- | | D11, D21, D31, D32 | `rtsp://IP:7070//stream1` | Dome | Current | | D42, D51, D52, D55, D72 | `rtsp://IP:7070//stream1` | Dome | Current | | E12, E32, E33, E43, E46 | `rtsp://IP:7070//stream1` | Hemispheric | Current, H.265 capable | | E51, E52, E63, E65, E73 | `rtsp://IP:7070//stream1` | Hemispheric | Current, H.265 capable | | E82, E84, E96 | `rtsp://IP:7070//stream1` | Hemispheric | Current, H.265 capable | | B53, B87, B95 | `rtsp://IP:7070//stream1` | Bullet/Zoom | Current | | A-series (box) | `rtsp://IP:7070//stream1` | Box | Current | ### Legacy Models Legacy ACTi cameras may use port 554 or 7070 depending on the model and firmware version: | Model Series | RTSP URL | Type | Notes | | --- | --- | --- | --- | | ACM-1011 | `rtsp://IP:554/` or `rtsp://IP:7070/` | Box | Legacy | | ACM-3401 | `rtsp://IP:554/` or `rtsp://IP:7070/` | Dome | Legacy | | ACM-5601 | `rtsp://IP:554/` or `rtsp://IP:7070/` | Box | Legacy | | ACM-7411 | `rtsp://IP:554/` or `rtsp://IP:7070/` | Dome | Legacy | | KCM-3311 | `rtsp://IP:7070/` | Dome | Legacy | | KCM-5611 | `rtsp://IP:7070/` | Dome | Legacy | | KCM-7211 | `rtsp://IP:7070/` | Dome | Legacy | | TCM-1231 | `rtsp://IP:7070/` | Box | Legacy | | TCM-3511 | `rtsp://IP:7070/` | Box | Legacy | | TCM-5111 | `rtsp://IP:7070/` | Box | Legacy | | TCM-5311 | `rtsp://IP:7070/` | Box | Legacy | ## Connecting with VisioForge SDK Use your ACTi camera's RTSP URL with any of the three SDK approaches shown in the [Quick Start Guide](../#quick-start-code): ``` // ACTi D/E series camera, main stream -- note port 7070, not 554! var uri = new Uri("rtsp://192.168.1.50:7070//stream1"); var username = "Admin"; var password = "123456"; ``` For legacy ACM models that use port 554, change the port accordingly. For a simpler root stream, use `rtsp://IP:7070/` as the URL. ## Snapshot and MJPEG URLs | Type | URL Pattern | Notes | | --- | --- | --- | | CGI Snapshot | `http://IP/cgi-bin/encoder?USER=USERNAME&PWD=PASSWORD&SNAPSHOT` | Authenticated snapshot | | HTTP Streaming | `http://IP/cgi-bin/cmd/system?GET_STREAM&USER=USERNAME&PWD=PASSWORD` | Continuous stream | | JPEG Image | `http://IP/jpg/image.jpg` | Direct JPEG | | JPEG (alt) | `http://IP/now.jpg` | Alternative snapshot path | ## Troubleshooting ### Port 7070, not 554 The most common ACTi connection issue is using the standard port 554. ACTi cameras default to **port 7070** for RTSP. If your connection times out or is refused, verify you are using the correct port. - Correct: `rtsp://IP:7070//stream1` - Likely incorrect: `rtsp://IP:554//stream1` (unless using a legacy ACM model) ### Double slash before stream1 ACTi current-generation cameras use a **double forward slash** before `stream1`: - Correct: `rtsp://IP:7070//stream1` - May not work: `rtsp://IP:7070/stream1` ### Default credentials differ by generation - **Current models (A/B/D/E series):** Username `Admin` (capital A), password `123456` - **Legacy models (ACM/KCM/TCM):** Username `admin` (lowercase), password `admin` Always change default credentials before deploying cameras on a production network. ### Legacy ACM models and port 554 Some older ACM-series cameras (ACM-1011, ACM-3401, ACM-5601, ACM-7411) may use port 554 instead of 7070. If port 7070 fails on a legacy model, try port 554 with the root URL `rtsp://IP:554/`. ### ONVIF availability ONVIF is only supported on current-generation cameras (A, B, D, and E series). Legacy ACM, KCM, and TCM cameras do not support ONVIF. For legacy models, use direct RTSP or HTTP URLs. ## FAQ **What is the default RTSP URL for ACTi cameras?** For current ACTi cameras (A/B/D/E series), use `rtsp://Admin:123456@CAMERA_IP:7070//stream1`. Note the non-standard port 7070 and double slash before `stream1`. For legacy models, try `rtsp://admin:admin@CAMERA_IP:7070/` or `rtsp://admin:admin@CAMERA_IP:554/`. **Why does ACTi use port 7070 instead of 554?** ACTi chose port 7070 as their default RTSP port. This can be changed in the camera's web interface, but the factory default is 7070 for most models. Some legacy ACM-series cameras default to port 554. **Does ACTi support H.265?** Current E-series cameras (hemispheric dome models) support H.265 encoding. Other current series (A, B, D) primarily use H.264. Legacy models (ACM, KCM, TCM) support H.264 and MJPEG only. **What is the difference between ACTi product series?** ACTi organizes cameras by letter: **A** = box cameras, **B** = bullet and zoom cameras, **D** = dome cameras, **E** = hemispheric dome cameras. Legacy product lines include ACM (box/dome), KCM (dome), and TCM (box). ## Related Resources - [All Camera Brands — RTSP URL Directory](../) - [Vivotek Connection Guide](../vivotek/) — Taiwanese enterprise cameras - [GeoVision Connection Guide](../geovision/) — Taiwanese professional cameras - [ONVIF IP Camera Integration](../../videocapture/video-sources/ip-cameras/onvif/) — ACTi ONVIF device setup - [IP Camera Preview Tutorial](../../videocapture/video-tutorials/ip-camera-preview/) - [SDK Installation & Samples](../#get-started) ---END OF PAGE--- ## Amcrest IP Camera RTSP URL Format and C# .NET Setup **URL:** https://www.visioforge.com/help/docs/dotnet/camera-brands/amcrest/ **Description:** Amcrest IP2M, IP4M, IP5M, IP8M, and NVR RTSP URL patterns for C# .NET. Stream and record using VisioForge SDK with ONVIF auto-discovery support. **Tags:** Video Capture SDK, Media Blocks SDK, .NET, Windows, macOS, Linux, Android, iOS, Capture, Streaming, IP Camera, RTSP, ONVIF, MJPEG, C# # How to Connect to Amcrest IP Camera in C# .NET [Video Capture SDK .Net](https://www.visioforge.com/video-capture-sdk-net) [Media Blocks SDK .Net](https://www.visioforge.com/media-blocks-sdk-net) ## Brand Overview **Amcrest** (Amcrest Technologies LLC) is an American consumer security camera brand based in Houston, Texas. Amcrest cameras are manufactured by **Dahua Technology** and use Dahua firmware and protocols. This means Amcrest cameras share identical RTSP URL patterns, web interfaces, and API endpoints with Dahua cameras. Amcrest has become one of the best-selling IP camera brands on Amazon in North America. **Key facts:** - **Product lines:** IP2M (1080p), IP4M (4MP), IP5M (5MP), IP8M (4K/8MP), ASH (smart home), NV (NVRs) - **Protocol support:** RTSP, ONVIF, HTTP/CGI, Amcrest Cloud, RTMP - **Default RTSP port:** 554 - **Default credentials:** admin / admin (must be changed on first login with newer firmware) - **ONVIF support:** Yes (all current models) - **Video codecs:** H.264 (all models), H.265 (IP4M and newer) - **OEM base:** Dahua (identical RTSP URL format) Amcrest = Dahua Amcrest cameras use Dahua firmware and the exact same RTSP URL format as Dahua cameras. If you're familiar with Dahua integration, Amcrest works identically. See our [Dahua connection guide](../dahua/) for additional details. ## RTSP URL Patterns ### Standard URL Format Amcrest uses the Dahua `cam/realmonitor` URL pattern: ``` rtsp://[USERNAME]:[PASSWORD]@[IP]:554/cam/realmonitor?channel=1&subtype=0 ``` | Parameter | Value | Description | | --- | --- | --- | | `channel` | 1, 2, 3... | Camera channel (1 for standalone cameras) | | `subtype` | 0 | Main stream (highest resolution) | | `subtype` | 1 | Sub stream (lower resolution, less bandwidth) | | `subtype` | 2 | Third stream (if supported, mobile-optimized) | ### Camera Models | Model | Resolution | Main Stream URL | Audio | | --- | --- | --- | --- | | IP2M-841 (1080p bullet) | 1920x1080 | `rtsp://IP:554/cam/realmonitor?channel=1&subtype=0` | Yes | | IP2M-844 (1080p dome) | 1920x1080 | `rtsp://IP:554/cam/realmonitor?channel=1&subtype=0` | Yes | | IP4M-1051 (4MP bullet) | 2688x1520 | `rtsp://IP:554/cam/realmonitor?channel=1&subtype=0` | Yes | | IP5M-T1179E (5MP turret) | 2592x1944 | `rtsp://IP:554/cam/realmonitor?channel=1&subtype=0` | Yes | | IP8M-2493E (4K bullet) | 3840x2160 | `rtsp://IP:554/cam/realmonitor?channel=1&subtype=0` | Yes | | IP8M-T2599E (4K turret) | 3840x2160 | `rtsp://IP:554/cam/realmonitor?channel=1&subtype=0` | Yes | | ASH-41 (pan/tilt) | 2560x1440 | `rtsp://IP:554/cam/realmonitor?channel=1&subtype=0` | Yes | | ASH-42 (indoor) | 1920x1080 | `rtsp://IP:554/cam/realmonitor?channel=1&subtype=0` | Yes | ### NVR Channel URLs For Amcrest NVRs (NV4108E, NV4216E, NV5216E, etc.): | Channel | Main Stream | Sub Stream | | --- | --- | --- | | Camera 1 | `rtsp://IP:554/cam/realmonitor?channel=1&subtype=0` | `rtsp://IP:554/cam/realmonitor?channel=1&subtype=1` | | Camera 2 | `rtsp://IP:554/cam/realmonitor?channel=2&subtype=0` | `rtsp://IP:554/cam/realmonitor?channel=2&subtype=1` | | Camera N | `rtsp://IP:554/cam/realmonitor?channel=N&subtype=0` | `rtsp://IP:554/cam/realmonitor?channel=N&subtype=1` | ### Alternative URL Formats Some older Amcrest models or firmware versions support these alternative URLs: | URL Pattern | Notes | | --- | --- | | `rtsp://IP:554/cam/realmonitor?channel=1&subtype=0` | Standard (recommended) | | `rtsp://IP:554/cam/realmonitor?channel=1&subtype=0&unicast=true` | Force unicast | | `rtsp://IP:554/cam/realmonitor?channel=1&subtype=0&proto=Onvif` | ONVIF-compatible | ## Connecting with VisioForge SDK Use your Amcrest camera's RTSP URL with any of the three SDK approaches shown in the [Quick Start Guide](../#quick-start-code): ``` // Amcrest IP4M-1051, main stream var uri = new Uri("rtsp://192.168.1.90:554/cam/realmonitor?channel=1&subtype=0"); var username = "admin"; var password = "YourPassword"; ``` For sub-stream access, use `subtype=1` instead of `subtype=0`. ## Snapshot and MJPEG URLs | Type | URL Pattern | Notes | | --- | --- | --- | | JPEG Snapshot | `http://IP/cgi-bin/snapshot.cgi?channel=1` | Requires basic auth | | JPEG Snapshot (legacy) | `http://IP/cgi-bin/snapshot.cgi?loginuse=USER&loginpas=PASS` | URL-based auth | | MJPEG Stream | `http://IP/cgi-bin/mjpg/video.cgi?channel=1&subtype=1` | Continuous MJPEG | | Current image | `http://IP/onvif-http/snapshot?channel=1` | ONVIF HTTP snapshot | ## Troubleshooting ### "401 Unauthorized" error Amcrest cameras with newer firmware require the password to be changed from the default on first login. If you haven't set up the camera via the web interface or Amcrest app yet: 1. Access the camera at `http://CAMERA_IP` in a browser 2. Complete the initial setup wizard 3. Set a strong password 4. Use those credentials in your RTSP URL ### Port 554 vs custom port Some Amcrest firmware versions allow changing the RTSP port. Check the port setting at: - Web interface: **Setup > Network > Port > RTSP Port** - Default is 554 ### Stream type confusion - `subtype=0` = Main stream (full resolution, higher bandwidth) - `subtype=1` = Sub stream (reduced resolution, lower bandwidth) - `subtype=2` = Third stream (if available, typically for mobile) ### Amcrest SmartHome (ASH) cameras The ASH series cameras (like ASH-41, ASH-42) use the same RTSP URL format but some models require enabling RTSP in the Amcrest Smart Home app first. ## FAQ **Are Amcrest and Dahua cameras the same?** Amcrest cameras are manufactured by Dahua and use Dahua firmware. The RTSP URL format (`cam/realmonitor?channel=1&subtype=0`) is identical. Any code written for Dahua cameras works with Amcrest and vice versa. The main differences are branding, warranty, and North American support. **What is the default RTSP URL for Amcrest cameras?** The URL is `rtsp://admin:password@CAMERA_IP:554/cam/realmonitor?channel=1&subtype=0` for the main stream. Replace `channel=1` with the appropriate channel for NVR setups and `subtype=0` with `subtype=1` for the sub stream. **Do Amcrest cameras support ONVIF?** Yes. All current Amcrest cameras support ONVIF Profile S and Profile T. ONVIF is enabled by default on most models. **Can I use Amcrest cameras without the Amcrest cloud?** Yes. RTSP, ONVIF, and the web interface all work locally without any cloud dependency. The Amcrest cloud service is optional and only needed for remote viewing through Amcrest's apps. ## Related Resources - [All Camera Brands — RTSP URL Directory](../) - [Dahua Connection Guide](../dahua/) — Same URL format (OEM base) - [Lorex Connection Guide](../lorex/) — Also uses Dahua URL format - [IP Camera Preview Tutorial](../../videocapture/video-tutorials/ip-camera-preview/) - [SDK Installation & Samples](../#get-started) ---END OF PAGE--- ## Annke Camera RTSP URL Patterns with C# .NET Examples **URL:** https://www.visioforge.com/help/docs/dotnet/camera-brands/annke/ **Description:** Annke C500, C800, CZ400, NC400 and NVR RTSP URL patterns for C# .NET. Integrate with VisioForge Video Capture SDK for streaming and recording. **Tags:** Video Capture SDK, Media Blocks SDK, .NET, Windows, macOS, Linux, Android, iOS, Capture, Streaming, Decoding, IP Camera, RTSP, ONVIF, H.265, MJPEG, C# # How to Connect to Annke IP Camera in C# .NET [Video Capture SDK .Net](https://www.visioforge.com/video-capture-sdk-net) [Media Blocks SDK .Net](https://www.visioforge.com/media-blocks-sdk-net) ## Brand Overview **Annke** (Annke Innovation Co., Ltd.) is a consumer and prosumer security camera brand based in Hong Kong, primarily selling through Amazon and direct-to-consumer channels. Annke cameras are manufactured using **Hikvision** OEM hardware, and most models use Hikvision-compatible firmware and RTSP URL patterns. Annke offers competitive pricing on PoE cameras, NVRs, and complete surveillance kits. **Key facts:** - **Product lines:** C-series (IP cameras), CZ-series (PTZ), NC-series (NVRs), I-series (turret/dome) - **Protocol support:** RTSP, ONVIF Profile S, HTTP/CGI - **Default RTSP port:** 554 - **Default credentials:** admin / (set during initial setup; some models: admin / admin) - **ONVIF support:** Yes (all current models) - **Video codecs:** H.264, H.265 (4MP and above) - **OEM base:** Hikvision (most models use Hikvision-compatible firmware) Annke Uses Hikvision Firmware Most Annke cameras use Hikvision OEM firmware. The RTSP URL format (`/Streaming/Channels/`) is identical to Hikvision. See our [Hikvision connection guide](../hikvision/) for additional details and troubleshooting. ## RTSP URL Patterns ### Standard URL Format Annke cameras use the Hikvision `Streaming/Channels` URL pattern: ``` rtsp://[USERNAME]:[PASSWORD]@[IP]:554/Streaming/Channels/[CHANNEL_ID] ``` | Channel ID | Stream | Description | | --- | --- | --- | | 101 | Main stream | Full resolution | | 102 | Sub stream | Lower resolution | | 103 | Third stream | Mobile-optimized (if supported) | ### Camera Models | Model | Resolution | Main Stream URL | Audio | | --- | --- | --- | --- | | C500 (5MP bullet) | 2592x1944 | `rtsp://IP:554/Streaming/Channels/101` | Yes | | C800 (4K bullet) | 3840x2160 | `rtsp://IP:554/Streaming/Channels/101` | Yes | | C1200 (12MP bullet) | 4000x3000 | `rtsp://IP:554/Streaming/Channels/101` | Yes | | CZ400 (4MP PTZ) | 2560x1440 | `rtsp://IP:554/Streaming/Channels/101` | Yes | | I91BN (4K turret) | 3840x2160 | `rtsp://IP:554/Streaming/Channels/101` | Yes | | I91BM (4K dome) | 3840x2160 | `rtsp://IP:554/Streaming/Channels/101` | Yes | | NC400 (4ch NVR) | N/A | See NVR section | N/A | | N48PAW (8ch PoE NVR) | N/A | See NVR section | N/A | ### NVR Channel URLs For Annke NVRs (NC400, N48PAW, N46PCK, etc.): | Channel | Main Stream | Sub Stream | | --- | --- | --- | | Camera 1 | `rtsp://IP:554/Streaming/Channels/101` | `rtsp://IP:554/Streaming/Channels/102` | | Camera 2 | `rtsp://IP:554/Streaming/Channels/201` | `rtsp://IP:554/Streaming/Channels/202` | | Camera N | `rtsp://IP:554/Streaming/Channels/N01` | `rtsp://IP:554/Streaming/Channels/N02` | ### Alternative URL Formats Some Annke models (especially non-Hikvision OEM variants) use different URL patterns: | URL Pattern | Notes | | --- | --- | | `rtsp://IP:554/Streaming/Channels/101` | Hikvision-style (most models) | | `rtsp://IP:554/h264/ch1/main/av_stream` | Older Hikvision firmware | | `rtsp://IP:554/cam/realmonitor?channel=1&subtype=0` | Dahua-style (some older models) | ## Connecting with VisioForge SDK Use your Annke camera's RTSP URL with any of the three SDK approaches shown in the [Quick Start Guide](../#quick-start-code): ``` // Annke C800 (4K bullet), main stream var uri = new Uri("rtsp://192.168.1.90:554/Streaming/Channels/101"); var username = "admin"; var password = "YourPassword"; ``` For sub-stream access, use `/Streaming/Channels/102` instead. ## Snapshot and MJPEG URLs | Type | URL Pattern | Notes | | --- | --- | --- | | JPEG Snapshot | `http://IP/ISAPI/Streaming/channels/101/picture` | Requires digest auth | | MJPEG Stream | `http://IP/ISAPI/Streaming/channels/102/httpPreview` | Sub stream as MJPEG | | Legacy Snapshot | `http://IP/Streaming/channels/1/picture` | Older firmware | ## Troubleshooting ### Camera requires activation Annke cameras with newer firmware require initial activation (password setup) before RTSP access works. Use the camera's web interface at `http://CAMERA_IP` or Annke's SADP-compatible discovery tool. ### Hikvision URL format not working Some Annke models use different OEM firmware. If `/Streaming/Channels/101` does not work, try: 1. `/h264/ch1/main/av_stream` (older Hikvision firmware) 2. `/cam/realmonitor?channel=1&subtype=0` (Dahua-style) 3. Use ONVIF discovery to automatically retrieve the correct stream URL ### H.265 stream issues Annke 4K cameras (C800, I91BN) default to H.265 encoding. If playback fails, switch the camera to H.264 in the web interface or install the HEVC decoder redistributable. ## FAQ **What is the default RTSP URL for Annke cameras?** Most Annke cameras use `rtsp://admin:password@CAMERA_IP:554/Streaming/Channels/101` for the main stream. Use channel `102` for the sub stream. This is the same format as Hikvision cameras. **Are Annke cameras Hikvision OEMs?** Most Annke cameras use Hikvision OEM hardware and firmware. The RTSP URL format, web interface, and API are typically identical to Hikvision. Some Annke models may use different OEM bases. **Do Annke cameras support ONVIF?** Yes. All current Annke cameras support ONVIF Profile S, providing standardized discovery and stream access. **Can I mix Annke cameras with Hikvision NVRs?** Yes. Since Annke cameras use Hikvision-compatible protocols, they work natively with Hikvision NVRs and vice versa. You can also mix Annke cameras into any ONVIF-compatible NVR or VMS. ## Related Resources - [All Camera Brands — RTSP URL Directory](../) - [Hikvision Connection Guide](../hikvision/) — Same URL format (OEM base) - [LTS Connection Guide](../lts/) — Another Hikvision OEM - [Dahua Connection Guide](../dahua/) — Alternative OEM ecosystem - [IP Camera Preview Tutorial](../../videocapture/video-tutorials/ip-camera-preview/) - [SDK Installation & Samples](../#get-started) ---END OF PAGE--- ## Connect Aqara Camera in C# .NET — Token-Based RTSP Guide **URL:** https://www.visioforge.com/help/docs/dotnet/camera-brands/aqara/ **Description:** Connect Aqara cameras in C# / .NET via RTSP. Token-based URLs for G2H, G3, E1, and G4 Doorbell. Aqara Home app setup and code samples included. **Tags:** Video Capture SDK, Media Blocks SDK, .NET, Windows, macOS, Linux, Android, iOS, Capture, Streaming, IP Camera, RTSP, ONVIF, H.264, C# **API:** RTSPSourceSettings # How to Connect to Aqara Camera in C# .NET [Video Capture SDK .Net](https://www.visioforge.com/video-capture-sdk-net) [Media Blocks SDK .Net](https://www.visioforge.com/media-blocks-sdk-net) ## Brand Overview **Aqara** is a Chinese smart home brand (by Lumi United Technology) that produces Zigbee/Thread-based smart home devices and cameras. Aqara cameras are unique in the market because they double as smart home hubs (Zigbee gateway) while also functioning as security cameras. Aqara primarily integrates with Apple HomeKit and supports RTSP for local streaming. **Key facts:** - **Product lines:** Camera Hub G2H/G3 (hub + camera), E1 (camera-only), G4 (doorbell) - **Protocol support:** RTSP, Apple HomeKit Secure Video, Zigbee 3.0 (hub function) - **Default RTSP port:** 554 - **Default credentials:** None — RTSP URL includes token - **ONVIF support:** No - **Video codecs:** H.264 - **Unique feature:** Cameras serve as Zigbee smart home hubs RTSP Must Be Enabled in Aqara Home App Aqara cameras have RTSP support but it must be enabled through the **Aqara Home** app. The app generates a unique RTSP URL with an authentication token. RTSP access works independently of HomeKit Secure Video. ## Enabling RTSP on Aqara Cameras 1. Open the **Aqara Home** app on your phone 2. Select your camera device 3. Go to **Camera Settings** (gear icon) 4. Find **RTSP** or **Network streaming** 5. Enable RTSP 6. The app will display the full RTSP URL with authentication token 7. Copy this URL for use in your application ## RTSP URL Patterns ### Standard URL Format Aqara cameras use a token-based RTSP URL: ``` rtsp://[IP]:554/live/ch00_1?token=[AUTH_TOKEN] ``` The authentication token is generated by the Aqara Home app and is unique per camera. ### Camera Models | Model | Type | RTSP Support | Resolution | Hub Function | | --- | --- | --- | --- | --- | | Camera Hub G2H Pro | Hub + camera | Yes | 1920x1080 | Zigbee 3.0 | | Camera Hub G3 | Hub + camera | Yes | 2304x1296 (2K) | Zigbee 3.0 | | Camera E1 | Camera only | Yes | 1920x1080 | No | | G4 Video Doorbell | Doorbell | Limited | 1600x1200 | No | ### URL Variations | URL Pattern | Description | | --- | --- | | `rtsp://IP:554/live/ch00_1?token=TOKEN` | Main stream (recommended) | | `rtsp://IP:554/live/ch00_0?token=TOKEN` | Sub stream (lower resolution) | ## Connecting with VisioForge SDK Use your Aqara camera's RTSP URL with any of the three SDK approaches shown in the [Quick Start Guide](../#quick-start-code): ``` // Aqara Camera Hub G3, main stream (token from Aqara Home app) var uri = new Uri("rtsp://192.168.1.90:554/live/ch00_1?token=YOUR_TOKEN_HERE"); var username = ""; // auth is in the token var password = ""; ``` Token-Based Authentication Aqara cameras do not use username/password authentication for RTSP. Instead, the authentication token is embedded in the URL. Leave the username and password fields empty in `RTSPSourceSettings.CreateAsync()` and include the token in the URI. ## Troubleshooting ### RTSP URL not working 1. Verify RTSP is enabled in the Aqara Home app 2. Check that the token in the URL matches what the app displays 3. Ensure the camera and your application are on the same network 4. Try regenerating the RTSP URL in the app (Settings > RTSP > regenerate) ### Token expires or changes The RTSP token may change after: - Camera firmware updates - Aqara Home app re-pairing - Disabling and re-enabling RTSP If your stream stops working, check the Aqara Home app for an updated URL. ### No ONVIF support Aqara cameras do not support ONVIF. You cannot use ONVIF discovery to find Aqara cameras. The RTSP URL must be obtained from the Aqara Home app. ### Limited to H.264 Aqara cameras encode in H.264 only. There is no H.265 option. This ensures broad compatibility but uses more bandwidth than H.265 at equivalent quality. ## FAQ **What is the default RTSP URL for Aqara cameras?** Aqara cameras use `rtsp://CAMERA_IP:554/live/ch00_1?token=AUTH_TOKEN` where the token is generated by the Aqara Home app. There are no default credentials -- authentication is handled via the URL token. **Can I use Aqara cameras with HomeKit and RTSP simultaneously?** Yes. HomeKit Secure Video and RTSP can run at the same time. Enabling RTSP does not disable HomeKit functionality. However, running both streams may slightly reduce camera performance. **Do Aqara cameras work as Zigbee hubs while streaming RTSP?** Yes. The Camera Hub G2H and G3 models serve as both Zigbee 3.0 gateways and cameras simultaneously. Enabling RTSP does not affect the hub functionality. **Do Aqara cameras support ONVIF?** No. Aqara cameras only support RTSP (with token auth) and HomeKit Secure Video. ONVIF discovery is not available. ## Related Resources - [All Camera Brands — RTSP URL Directory](../) - [EZVIZ Connection Guide](../ezviz/) — Another smart home camera brand - [TP-Link Connection Guide](../tp-link/) — Consumer cameras with RTSP - [IP Camera Preview Tutorial](../../videocapture/video-tutorials/ip-camera-preview/) - [SDK Installation & Samples](../#get-started) ---END OF PAGE--- ## How to Connect to Arecont Vision IP Camera in C# .NET **URL:** https://www.visioforge.com/help/docs/dotnet/camera-brands/arecont/ **Description:** Arecont Vision RTSP URL patterns for C# .NET. Integrate AV Series, MegaDome, and SurroundVideo panoramic cameras using VisioForge Video Capture SDK. **Tags:** Video Capture SDK, Media Blocks SDK, .NET, Windows, macOS, Linux, Android, iOS, Capture, Streaming, IP Camera, RTSP, ONVIF, H.264, MJPEG, C# # How to Connect to Arecont Vision IP Camera in C# .NET [Video Capture SDK .Net](https://www.visioforge.com/video-capture-sdk-net) [Media Blocks SDK .Net](https://www.visioforge.com/media-blocks-sdk-net) ## Brand Overview **Arecont Vision** (now part of Costar Group) is an American IP camera company originally founded in 2003 and based in Glendale, California. Arecont Vision was a pioneer of megapixel IP cameras and is known for high-resolution models (up to 20MP) and multi-sensor panoramic cameras. The company was acquired by **Costar Group** in 2019, which continues to support and manufacture Arecont Vision products. **Key facts:** - **Product lines:** AV Series (megapixel fixed), MegaDome, MegaBall, SurroundVideo (multi-sensor panoramic), MicroDome - **Protocol support:** RTSP, ONVIF (newer models), PSIA, HTTP/CGI - **Default RTSP port:** 554 - **Default credentials:** Varies by model (many ship with no default password) - **ONVIF support:** Yes (newer models), PSIA support on most models - **Video codecs:** H.264, MJPEG (older models MJPEG only) Arecont Vision and Costar Group Arecont Vision was acquired by Costar Group in 2019. Existing Arecont cameras continue to use the same RTSP and PSIA URL formats. Newer Costar-branded models may use updated firmware but maintain backward-compatible URL patterns. ## RTSP URL Patterns ### Standard URL Formats Arecont Vision cameras support multiple RTSP URL patterns depending on the model generation and configured protocol: ``` rtsp://[USERNAME]:[PASSWORD]@[IP]:554/h264.sdp ``` | URL Pattern | Protocol | Description | | --- | --- | --- | | `rtsp://IP:554/h264.sdp` | H.264 | Standard H.264 stream (most current models) | | `rtsp://IP:554/PSIA/Streaming/channels/0?videoCodecType=H.264` | PSIA | PSIA-based H.264 stream | | `rtsp://IP:554/cam1/mpeg4` | MPEG-4 | Legacy MPEG-4 stream (older models) | ### H.264 Stream with ROI Parameters Arecont cameras support optional Region of Interest (ROI) parameters for customizing the stream output: ``` rtsp://[USERNAME]:[PASSWORD]@[IP]:554/h264.sdp?res=half&x0=0&y0=0&x1=1600&y1=1200&quality=15&doublescan=0 ``` | Parameter | Values | Description | | --- | --- | --- | | `res` | `full`, `half` | Stream resolution (full or half of sensor resolution) | | `x0`, `y0` | 0 - max | Top-left corner of the region of interest | | `x1`, `y1` | 0 - max | Bottom-right corner of the region of interest | | `quality` | 1 - 21 | JPEG/H.264 quality factor (lower = higher quality) | | `doublescan` | 0, 1 | Enable double-scan mode for improved image quality | ROI Parameters Are Optional The ROI parameters (`res`, `x0`, `y0`, `x1`, `y1`, `quality`, `doublescan`) are optional and can be omitted entirely for full-frame streaming. Use `rtsp://IP:554/h264.sdp` without parameters for the simplest connection. ### Camera Models | Model Series | Resolution | Main Stream URL | Codec | | --- | --- | --- | --- | | AV Series (generic megapixel) | Varies | `rtsp://IP:554/h264.sdp` | H.264 | | AV2100 (2MP) | 1600x1200 | `rtsp://IP:554/cam1/mpeg4` | MPEG-4 | | AV5115/AV5125 | 2592x1944 | `rtsp://IP:554/h264.sdp` | H.264 | | AV8185DN (8MP multi-sensor) | 6400x1200 | `rtsp://IP:554/h264.sdp` | H.264 | | AV10005/AV10115 (10MP) | 3648x2752 | `rtsp://IP:554/PSIA/Streaming/channels/0?videoCodecType=H.264` | H.264 | | AV20185 (20MP multi-sensor) | 10240x1536 | `rtsp://IP:554/h264.sdp` | H.264 | | MegaDome Series | Varies | `rtsp://IP:554/h264.sdp` | H.264 | | MegaBall Series | Varies | `rtsp://IP:554/h264.sdp` | H.264 | | MicroDome Series | Varies | `rtsp://IP:554/h264.sdp` | H.264 | ### PSIA Streaming URLs Models that support the PSIA protocol can use the following URL format: | Channel | URL | | --- | --- | | Channel 0 (default) | `rtsp://IP:554/PSIA/Streaming/channels/0?videoCodecType=H.264` | | Channel 1 | `rtsp://IP:554/PSIA/Streaming/channels/1?videoCodecType=H.264` | ## Connecting with VisioForge SDK Use your Arecont Vision camera's RTSP URL with any of the three SDK approaches shown in the [Quick Start Guide](../#quick-start-code): ``` // Arecont Vision AV Series, H.264 main stream var uri = new Uri("rtsp://192.168.1.90:554/h264.sdp"); var username = "admin"; var password = "YourPassword"; ``` For PSIA-based streaming, use the PSIA URL instead: ``` // Arecont Vision via PSIA protocol var uri = new Uri("rtsp://192.168.1.90:554/PSIA/Streaming/channels/0?videoCodecType=H.264"); ``` ## Snapshot and MJPEG URLs | Type | URL Pattern | Notes | | --- | --- | --- | | JPEG Snapshot | `http://IP/img.jpg` | Most models, requires basic auth | | JPEG Snapshot (alt) | `http://IP/Jpeg/CamImg.jpg` | Alternative snapshot URL | | Configurable Snapshot | `http://IP/image?res=half&x0=0&y0=0&x1=1600&y1=1200&quality=15&doublescan=0` | Snapshot with ROI parameters | | MJPEG Stream | `http://IP/mjpeg?res=full&x0=0&y0=0&x1=100%&y1=100%&quality=12&doublescan=0` | Continuous MJPEG stream | ### Multi-Sensor (SurroundVideo) Snapshot URLs For SurroundVideo and other multi-sensor cameras, each sensor has its own snapshot URL: | Sensor | URL Pattern | Notes | | --- | --- | --- | | Channel 1 | `http://IP/image1?res=half&x1=0&y1=0` | First sensor | | Channel 2 | `http://IP/image2?res=half&x1=0&y1=0` | Second sensor | | Channel 3 | `http://IP/image3?res=half&x1=0&y1=0` | Third sensor | | Channel 4 | `http://IP/image4?res=half&x1=0&y1=0` | Fourth sensor | ## Troubleshooting ### ROI parameters causing issues Arecont cameras have unique Region of Interest parameters (`res`, `x0`, `y0`, `x1`, `y1`, `quality`, `doublescan`) embedded in their URLs. If you encounter connection problems: 1. Remove all ROI parameters and use the bare URL: `rtsp://IP:554/h264.sdp` 2. Verify the camera resolution supports the requested ROI coordinates 3. Use `res=full` for full-resolution streaming or `res=half` for reduced bandwidth ### MJPEG-only on older models Some older Arecont models (AV1300, AV2100, AV3100) only support MJPEG encoding and do not have H.264 capability. For these cameras: - Use the MPEG-4 RTSP URL: `rtsp://IP:554/cam1/mpeg4` - Or use the HTTP MJPEG stream: `http://IP/mjpeg` ### PSIA vs direct RTSP Arecont cameras support both direct RTSP and PSIA-based RTSP URLs. If one format does not work: - Try the alternative format (switch between `h264.sdp` and `PSIA/Streaming/channels/0`) - Verify the camera firmware version supports the chosen protocol - Check that PSIA is enabled in the camera's web interface ### Connection timeout Arecont cameras may take longer to establish an RTSP session than other brands, especially for high-resolution (10MP+) models: - Increase your connection timeout to at least 10 seconds - For multi-sensor models, connect to individual channels rather than the composite stream for lower latency ## FAQ **What RTSP URL format does Arecont Vision use?** The primary RTSP URL is `rtsp://IP:554/h264.sdp` for H.264 streaming. PSIA-based streaming uses `rtsp://IP:554/PSIA/Streaming/channels/0?videoCodecType=H.264`. Older models may use `rtsp://IP:554/cam1/mpeg4` for MPEG-4 streams. **Are Arecont Vision cameras still supported after the Costar acquisition?** Yes. Costar Group acquired Arecont Vision in 2019 and continues to manufacture and support Arecont Vision camera products. Existing cameras remain fully functional, and firmware updates are available through Costar's support channels. **How do I connect to a multi-sensor SurroundVideo camera?** SurroundVideo cameras expose individual sensor channels through numbered URLs. For snapshots, use `http://IP/image1`, `http://IP/image2`, etc. For RTSP, use the standard H.264 URL with the full panoramic composite, or PSIA channel-based URLs for individual sensors. **Do Arecont Vision cameras support ONVIF?** Newer Arecont Vision models support ONVIF Profile S. Older models rely on the PSIA protocol instead. Check your camera's specifications or web interface to confirm ONVIF availability. ## Related Resources - [All Camera Brands — RTSP URL Directory](../) - [GeoVision Connection Guide](../geovision/) — Professional surveillance cameras - [ONVIF Capture with Postprocessing](../../mediablocks/Guides/onvif-capture-with-postprocessing/) — Arecont ONVIF capture pipeline - [IP Camera Preview Tutorial](../../videocapture/video-tutorials/ip-camera-preview/) - [SDK Installation & Samples](../#get-started) ---END OF PAGE--- ## How to Connect to Arlo Camera in C# .NET - RTSP Workarounds **URL:** https://www.visioforge.com/help/docs/dotnet/camera-brands/arlo/ **Description:** Arlo camera RTSP limitations in C# .NET. No native RTSP support. Workaround options and alternative camera recommendations for developers. **Tags:** Video Capture SDK, Media Blocks SDK, .NET, MediaBlocksPipeline, Windows, macOS, Linux, Android, iOS, Capture, Streaming, Webcam, IP Camera, RTSP, ONVIF, C# **API:** MediaBlocksPipeline, SystemVideoSourceBlock, VideoRendererBlock # How to Connect to Arlo Camera in C# .NET [Video Capture SDK .Net](https://www.visioforge.com/video-capture-sdk-net) [Media Blocks SDK .Net](https://www.visioforge.com/media-blocks-sdk-net) ## Brand Overview **Arlo Technologies** is an American smart home security company headquartered in Carlsbad, California. Originally a Netgear brand, Arlo became independent in 2018. Arlo is one of the best-selling wireless security camera brands in North America and Europe, known for battery-powered outdoor cameras, doorbells, and floodlight cameras. **Key facts:** - **Product lines:** Pro (flagship), Ultra (4K), Essential (value), Go (cellular), Floodlight, Doorbell - **Architecture:** Cloud-first with optional local storage (Arlo SmartHub/Base Station) - **RTSP support:** No (removed from SmartHub in 2021) - **ONVIF support:** No - **Video codecs:** H.264, H.265 (select models) - **Cloud dependency:** High — all features require Arlo Secure subscription - **Power:** Battery, solar, or wired depending on model No RTSP Support Arlo cameras do **not** support RTSP. Arlo previously offered RTSP access through the SmartHub (VMB4540/VMB5000) for select camera models, but this feature was **removed** in a 2021 firmware update. There is currently no way to access Arlo camera streams via RTSP. ## RTSP History on Arlo Arlo had a brief period of RTSP support: | Period | Status | Details | | --- | --- | --- | | Before 2019 | No RTSP | Cloud-only access | | 2019-2021 | RTSP available (beta) | Via SmartHub for Ultra/Pro 3/Pro 4 only | | 2021-present | RTSP removed | Firmware update removed RTSP functionality | The RTSP feature was available on the **Arlo SmartHub (VMB5000)** for: - Arlo Ultra (VMC5040) - Arlo Pro 3 (VMC4040P) - Arlo Pro 4 (VMC4050P) It was never available for Arlo Essential, Go, or Doorbell models. ## Why No Direct Integration Arlo's architecture prevents direct SDK integration: 1. **Cloud-mandatory streaming:** All video routes through Arlo's cloud servers 2. **No local network access:** Cameras communicate with the SmartHub/base station using proprietary protocols 3. **No open ports:** Neither cameras nor base stations expose RTSP or HTTP video endpoints 4. **Subscription dependency:** Video access requires an active Arlo Secure plan ## Possible Workarounds ### Option 1: Arlo API (Unofficial) Community-developed libraries exist that interface with Arlo's cloud API to: - Retrieve snapshot images - Download recorded clips - Trigger camera actions These are unofficial and may break with Arlo service updates. They do not provide real-time RTSP streams. ### Option 2: HDMI Output from SmartHub The Arlo SmartHub (VMB5000) has an HDMI output that displays a live camera grid. You can capture this with an HDMI capture card: ``` // Capture HDMI output from Arlo SmartHub via USB capture card var pipeline = new MediaBlocksPipeline(); var captureDevice = new SystemVideoSourceBlock(captureDeviceSettings); var videoRenderer = new VideoRendererBlock(pipeline, VideoView1); pipeline.Connect(captureDevice.Output, videoRenderer.Input); await pipeline.StartAsync(); ``` This provides a composite view of all cameras, not individual streams. ## Recommended Alternatives For developers needing direct RTSP camera integration, these consumer cameras provide native RTSP support: | Alternative | Type | RTSP | Battery Option | Guide | | --- | --- | --- | --- | --- | | Reolink Argus 3 | Battery outdoor | Yes | Yes | [Connection Guide](../reolink/) | | Amcrest | Wired outdoor | Yes | No | [Connection Guide](../amcrest/) | | EZVIZ | Indoor/outdoor | Yes (enable required) | Limited | [Connection Guide](../ezviz/) | | TP-Link Tapo | Indoor/outdoor | Yes | No | [Connection Guide](../tp-link/) | | Eufy Security | Wired/battery | Yes (some models) | Yes | [Connection Guide](../eufy/) | ## FAQ **Do Arlo cameras support RTSP?** No. Arlo cameras do not currently support RTSP. A brief RTSP beta was available on the SmartHub (2019-2021) for select models, but it was removed in a firmware update. There is no current way to access Arlo streams via RTSP. **Can I use VisioForge SDK with Arlo cameras?** Not directly. Arlo cameras have no RTSP, ONVIF, or local streaming endpoints. The only integration option is capturing the HDMI output from the SmartHub using a capture card. For direct SDK integration, use cameras with native RTSP support. **Will Arlo bring back RTSP?** There has been no official announcement from Arlo about restoring RTSP support. Arlo's business model is subscription-based, and local streaming conflicts with this approach. **What battery cameras support RTSP?** For battery-powered cameras with RTSP support, consider [Reolink](../reolink/) (Argus series) or [Eufy Security](../eufy/) (select models). Most battery cameras from other brands are also cloud-only. ## Related Resources - [All Camera Brands — RTSP URL Directory](../) - [Reolink Connection Guide](../reolink/) — Consumer alternative with RTSP - [Eufy Security Connection Guide](../eufy/) — Consumer with partial RTSP - [Wyze Connection Guide](../wyze/) — Another cloud-first brand with limited RTSP - [SDK Installation & Samples](../#get-started) ---END OF PAGE--- ## Avigilon IP Camera RTSP URL Patterns and C# .NET Setup **URL:** https://www.visioforge.com/help/docs/dotnet/camera-brands/avigilon/ **Description:** Avigilon H5A, H5M, H5 Pro, H5SL, and Unity NVR RTSP URL patterns for C# .NET. Enterprise camera integration with VisioForge SDK code samples. **Tags:** Video Capture SDK, Media Blocks SDK, .NET, Windows, macOS, Linux, Android, iOS, Capture, Streaming, Decoding, IP Camera, RTSP, ONVIF, H.265, MJPEG, C# # How to Connect to Avigilon IP Camera in C# .NET [Video Capture SDK .Net](https://www.visioforge.com/video-capture-sdk-net) [Media Blocks SDK .Net](https://www.visioforge.com/media-blocks-sdk-net) ## Brand Overview **Avigilon** (Avigilon Corporation) is an enterprise security camera manufacturer originally based in Vancouver, Canada. Founded in 2004, Avigilon was acquired by **Motorola Solutions** in 2018 for approximately $1 billion. The company is known for high-resolution cameras (up to 61MP), AI-powered video analytics including Unusual Motion Detection (UMD) and Appearance Search, and proprietary HDSM (High Definition Stream Management) technology. Avigilon cameras are widely deployed in enterprise, government, and critical infrastructure environments. **Key facts:** - **Product lines:** H5A (bullet/dome), H5M (mini dome), H5 Pro (multi-sensor), H5SL (value line), Unity (NVRs) - **Previous lines:** HD Pro, HD Multisensor, HD Micro Dome, HD PTZ - **Protocol support:** RTSP, ONVIF (Profile S, Profile T), HTTP - **Default RTSP port:** 554 - **Default credentials:** admin / admin (must be changed on initial setup) - **ONVIF support:** Yes (Profile S, Profile T) - **Video codecs:** H.264, H.265, HDSM SmartCodec (H.265-based) - **Known for:** AI analytics (Unusual Motion Detection, Appearance Search), HDSM SmartCodec Avigilon is now part of Motorola Solutions Avigilon is now part of Motorola Solutions. The Avigilon camera line continues under the Motorola Solutions Video Security & Access Control division. See also our [Pelco guide](../pelco/) for another Motorola Solutions camera brand. ## RTSP URL Patterns ### Standard URL Format Avigilon cameras use the `defaultPrimary` / `defaultSecondary` URL pattern with a unicast stream type parameter: ``` rtsp://[USERNAME]:[PASSWORD]@[IP]:554/defaultPrimary?streamType=u ``` | Parameter | Value | Description | | --- | --- | --- | | `defaultPrimary` | Primary stream | Main stream (highest resolution) | | `defaultSecondary` | Secondary stream | Sub stream (lower resolution, less bandwidth) | | `streamType` | `u` | Unicast stream delivery | ### Camera Models | Model Series | Type | Main Stream URL | Notes | | --- | --- | --- | --- | | H5A Bullet | Fixed bullet | `rtsp://IP:554/defaultPrimary?streamType=u` | AI-enabled, up to 8MP | | H5A Dome | Fixed dome | `rtsp://IP:554/defaultPrimary?streamType=u` | AI-enabled, up to 8MP | | H5M Mini Dome | Mini dome | `rtsp://IP:554/defaultPrimary?streamType=u` | Compact form factor | | H5 Pro Multi-sensor | Multi-sensor | `rtsp://IP:554/defaultPrimary0?streamType=u` | See multi-sensor note below | | H5SL Bullet | Value bullet | `rtsp://IP:554/defaultPrimary?streamType=u` | Cost-effective line | | H5SL Dome | Value dome | `rtsp://IP:554/defaultPrimary?streamType=u` | Cost-effective line | | HD Pro | Legacy high-res | `rtsp://IP:554/defaultPrimary?streamType=u` | Up to 61MP | ### Multi-Sensor Camera URLs For Avigilon H5 Pro and other multi-sensor cameras, each sensor head has its own stream index: | Sensor | Main Stream | Sub Stream | | --- | --- | --- | | Sensor 1 | `rtsp://IP:554/defaultPrimary0?streamType=u` | `rtsp://IP:554/defaultSecondary0?streamType=u` | | Sensor 2 | `rtsp://IP:554/defaultPrimary1?streamType=u` | `rtsp://IP:554/defaultSecondary1?streamType=u` | | Sensor 3 | `rtsp://IP:554/defaultPrimary2?streamType=u` | `rtsp://IP:554/defaultSecondary2?streamType=u` | | Sensor 4 | `rtsp://IP:554/defaultPrimary3?streamType=u` | `rtsp://IP:554/defaultSecondary3?streamType=u` | ### Alternative URL Formats | URL Pattern | Notes | | --- | --- | | `rtsp://IP:554/defaultPrimary?streamType=u` | Standard primary (recommended) | | `rtsp://IP:554/defaultSecondary?streamType=u` | Secondary / sub stream | | `rtsp://IP:554/defaultPrimary0?streamType=u` | Primary stream alternate (also used for multi-sensor sensor 1) | ## Connecting with VisioForge SDK Use your Avigilon camera's RTSP URL with any of the three SDK approaches shown in the [Quick Start Guide](../#quick-start-code): ``` // Avigilon H5A dome, primary stream (unicast) var uri = new Uri("rtsp://192.168.1.100:554/defaultPrimary?streamType=u"); var username = "admin"; var password = "YourPassword"; ``` For sub-stream access, use `defaultSecondary` instead of `defaultPrimary`. ## Snapshot and MJPEG URLs | Type | URL Pattern | Notes | | --- | --- | --- | | JPEG Snapshot | `http://IP/snapshot.jpg` | Requires basic auth | ## Troubleshooting ### "401 Unauthorized" error Avigilon cameras require the default password to be changed during initial setup. If you have not configured the camera yet: 1. Access the camera at `http://CAMERA_IP` in a browser 2. Complete the initial setup wizard and set a strong password 3. Use those credentials in your RTSP URL ### HDSM SmartCodec streams Avigilon's HDSM SmartCodec is based on H.265. Ensure your decoder supports H.265 when connecting to cameras configured to use HDSM SmartCodec. If you experience decoding issues, try switching the camera to standard H.264 encoding in the camera's web interface. ### Stream type parameter The `streamType=u` parameter requests unicast delivery. If you omit this parameter, the camera may default to multicast, which can cause issues on networks not configured for multicast routing. ### Multi-sensor cameras show only one view For multi-sensor models (H5 Pro), each sensor is accessed as a separate stream. Use `defaultPrimary0`, `defaultPrimary1`, etc. to access individual sensor heads. See the multi-sensor URL table above. ## FAQ **What is the default RTSP URL for Avigilon cameras?** The URL is `rtsp://admin:password@CAMERA_IP:554/defaultPrimary?streamType=u` for the primary stream. Use `defaultSecondary` instead of `defaultPrimary` for the lower-resolution sub stream. **Do Avigilon cameras support ONVIF?** Yes. Avigilon cameras support ONVIF Profile S and Profile T. ONVIF can be enabled through the camera's web interface or Avigilon Control Center (ACC) software. **What is HDSM SmartCodec?** HDSM (High Definition Stream Management) SmartCodec is Avigilon's proprietary compression technology built on H.265. It reduces bandwidth and storage requirements by intelligently encoding different regions of the image at different quality levels while maintaining detail in areas of interest. Streams encoded with HDSM SmartCodec are compatible with standard H.265 decoders. **Can I use Avigilon cameras without Avigilon Control Center?** Yes. While Avigilon Control Center (ACC) is the recommended VMS, the cameras expose standard RTSP streams and support ONVIF, allowing integration with any RTSP-compatible application including VisioForge SDKs. **How do I access individual sensors on multi-sensor cameras?** Each sensor head on a multi-sensor camera (such as the H5 Pro) has its own stream URL. Use `defaultPrimary0` for sensor 1, `defaultPrimary1` for sensor 2, and so on. Each sensor can also have a secondary stream accessed via `defaultSecondary0`, `defaultSecondary1`, etc. ## Related Resources - [All Camera Brands — RTSP URL Directory](../) - [Pelco Connection Guide](../pelco/) — Also Motorola Solutions, enterprise cameras - [ONVIF Capture with Postprocessing](../../mediablocks/Guides/onvif-capture-with-postprocessing/) — Avigilon ONVIF capture pipeline - [IP Camera Preview Tutorial](../../videocapture/video-tutorials/ip-camera-preview/) - [SDK Installation & Samples](../#get-started) ---END OF PAGE--- ## AVTech IP Camera RTSP URL and C# .NET Connection Guide **URL:** https://www.visioforge.com/help/docs/dotnet/camera-brands/avtech/ **Description:** AVTech IP camera integration guide for C# .NET with RTSP URL patterns, DVR/NVR channel URLs, and code samples for AVM, AVN, AVC, and AVI models. **Tags:** Video Capture SDK, Media Blocks SDK, .NET, Windows, macOS, Linux, Android, iOS, Capture, Streaming, IP Camera, RTSP, ONVIF, AVI, H.264, MJPEG, C# # How to Connect to AVTech IP Camera in C# .NET [Video Capture SDK .Net](https://www.visioforge.com/video-capture-sdk-net) [Media Blocks SDK .Net](https://www.visioforge.com/media-blocks-sdk-net) ## Brand Overview **AVTech** (AVTech Corporation) is a Taiwanese surveillance equipment manufacturer based in Taipei, Taiwan, founded in 1996. AVTech is one of the largest DVR/NVR manufacturers globally, with a strong presence in Asia-Pacific, Middle East, and Latin American markets. The company produces a wide range of IP cameras, DVRs, NVRs, and the EagleEyes mobile viewing platform. AVTech is known for offering cost-effective surveillance solutions with broad model compatibility. **Key facts:** - **Product lines:** AVM (IP cameras), AVN (network cameras), AVC (DVRs), AVI (specialty cameras), EagleEyes (mobile app) - **Protocol support:** RTSP, ONVIF (newer models), HTTP/CGI, MJPEG - **Default RTSP port:** 554 (some models use port 88) - **Default credentials:** admin / admin - **ONVIF support:** Yes (newer models) - **Video codecs:** H.264, MPEG-4, MJPEG - **Guest access:** Many models allow unauthenticated JPEG snapshots via guest CGI Some AVTech models use port 88 Some newer AVTech models use port 88 instead of 554 for RTSP. If port 554 doesn't work, try port 88 with the URL pattern `rtsp://IP:88//live/h264_ulaw/VGA`. Guest access security Many AVTech cameras expose a guest CGI endpoint (`/cgi-bin/guest/Video.cgi`) that allows unauthenticated snapshot access. Ensure your camera's guest access settings are configured securely. ## RTSP URL Patterns ### Standard URL Format AVTech cameras use the `/live/` path-based URL pattern: ``` rtsp://[USERNAME]:[PASSWORD]@[IP]:554/live/h264 ``` | Parameter | Value | Description | | --- | --- | --- | | `/live/h264` | H.264 stream | Main H.264 video stream | | `/live/mpeg4` | MPEG-4 stream | Legacy MPEG-4 video stream | | `/live/h264/ch[N]` | Channel N | Channel-specific stream for DVRs/NVRs | ### Camera Models | Model | Type | Main Stream URL | Notes | | --- | --- | --- | --- | | AVM217 | IP camera | `rtsp://IP:554/live/h264` | H.264 main stream | | AVM328 | IP dome | `rtsp://IP:554/live/h264` | H.264 main stream | | AVM357 | IP dome | `rtsp://IP:554/live/h264` | H.264 main stream | | AVM457 | IP camera | `rtsp://IP:554/live/h264` | H.264 main stream | | AVM459 | IP camera | `rtsp://IP:554/live/h264` | H.264 main stream | | AVM552 | IP camera | `rtsp://IP:554/live/h264` | H.264 main stream | | AVM561 | IP dome | `rtsp://IP:554/live/h264` | H.264 main stream | | AVM571 | IP camera | `rtsp://IP:554/live/h264` | H.264 main stream | | AVN211 | Network camera | `rtsp://IP:554/live/h264` | H.264 main stream | | AVN252 | Network camera | `rtsp://IP:554/live/h264` | H.264 main stream | | AVN257 | Network camera | `rtsp://IP:554/live/h264` | H.264 main stream | | AVN304 | Network camera | `rtsp://IP:554/live/h264` | H.264 main stream | | AVN314 | Network camera | `rtsp://IP:554/live/h264` | H.264 main stream | | AVN362 | Network camera | `rtsp://IP:554/live/h264` | H.264 main stream | | AVN801 | Network camera | `rtsp://IP:554/live/h264` | H.264 main stream | | AVN812 | Network camera | `rtsp://IP:554/live/h264` | H.264 main stream | | AVN813 | Network camera | `rtsp://IP:554/live/h264` | H.264 main stream | | AVI201 | IP camera | `rtsp://IP:554/live/h264` | H.264 main stream | | AVI203 | IP camera | `rtsp://IP:554/live/h264` | H.264 main stream | ### DVR/NVR Channel URLs For AVTech DVRs and NVRs (AVC series and others): | Channel | Main Stream (H.264) | Main Stream (MPEG-4) | | --- | --- | --- | | Channel 1 | `rtsp://IP:554/live/h264/ch1` | `rtsp://IP:554/live/mpeg4/ch1` | | Channel 2 | `rtsp://IP:554/live/h264/ch2` | `rtsp://IP:554/live/mpeg4/ch2` | | Channel 3 | `rtsp://IP:554/live/h264/ch3` | `rtsp://IP:554/live/mpeg4/ch3` | | Channel N | `rtsp://IP:554/live/h264/chN` | `rtsp://IP:554/live/mpeg4/chN` | ### Alternative URL Formats Some AVTech models, particularly newer ones, use port 88 and different path formats: | URL Pattern | Notes | | --- | --- | | `rtsp://IP:554/live/h264` | Standard H.264 (recommended) | | `rtsp://IP:554/live/mpeg4` | MPEG-4 stream | | `rtsp://IP//live/h264` | Without explicit port (some models) | | `rtsp://IP:88//live/h264_ulaw/VGA` | Port 88, with audio, VGA resolution | | `rtsp://IP:88//live/video_audio/profile1` | Port 88 with profile selection | ## Connecting with VisioForge SDK Use your AVTech camera's RTSP URL with any of the three SDK approaches shown in the [Quick Start Guide](../#quick-start-code): ``` // AVTech AVM552, H.264 main stream var uri = new Uri("rtsp://192.168.1.80:554/live/h264"); var username = "admin"; var password = "YourPassword"; ``` For MPEG-4 stream access, use `/live/mpeg4` instead of `/live/h264`. ## Snapshot and MJPEG URLs | Type | URL Pattern | Notes | | --- | --- | --- | | JPEG Snapshot (guest) | `http://IP/cgi-bin/guest/Video.cgi?media=JPEG` | No authentication required (if guest access enabled) | | JPEG Snapshot (channel) | `http://IP/cgi-bin/guest/Video.cgi?media=JPEG&channel=CHANNEL` | Channel-specific snapshot | | MJPEG Live Stream | `http://IP/live/mjpeg` | Continuous MJPEG stream | ## Troubleshooting ### "401 Unauthorized" error If you receive an authentication error: 1. Verify your credentials - default is admin / admin 2. Access the camera at `http://CAMERA_IP` in a browser to confirm login works 3. Ensure RTSP is enabled in the camera's network settings 4. Try including credentials in the URL: `rtsp://admin:password@IP:554/live/h264` ### Port 554 vs port 88 Some newer AVTech models use port 88 instead of the standard RTSP port 554. If you cannot connect on port 554: 1. Try port 88: `rtsp://IP:88//live/h264_ulaw/VGA` 2. Note the double slash (`//`) in some port 88 URL patterns 3. Check the camera's web interface under network settings for the configured RTSP port ### MPEG-4 vs H.264 Older AVTech models may only support MPEG-4. If the H.264 stream URL does not work: - Try `rtsp://IP:554/live/mpeg4` instead - Check the camera's encoding settings in the web interface - Newer models support H.264; older models may be MPEG-4 only ### Double slash in URL Some AVTech URL patterns include a double slash (`//`) after the IP or port. This is intentional and required by certain firmware versions. If a single-slash URL does not work, try the double-slash variant. ### EagleEyes mobile app The EagleEyes app is AVTech's mobile viewing platform. RTSP access works independently of EagleEyes and does not require the app to be configured. ## FAQ **What is the default RTSP URL for AVTech cameras?** The URL is `rtsp://admin:password@CAMERA_IP:554/live/h264` for the main H.264 stream. For DVRs/NVRs, append the channel number: `rtsp://IP:554/live/h264/ch1` for channel 1. **Do AVTech cameras support ONVIF?** Newer AVTech models support ONVIF. Older models may not have ONVIF support and rely on proprietary protocols and RTSP for integration. **What is the difference between AVM and AVN series?** The AVM series are IP cameras designed for direct network connection, while the AVN series are network cameras that may include additional features such as built-in Wi-Fi or audio. Both series use the same RTSP URL format. **Can I access AVTech snapshots without authentication?** Many AVTech cameras have a guest CGI endpoint (`/cgi-bin/guest/Video.cgi?media=JPEG`) that allows unauthenticated JPEG snapshot access. This is a security concern if your camera is network-accessible. Check your camera's guest access settings and disable guest access if not needed. **Why do some AVTech URLs use port 88?** Some newer AVTech firmware versions default to port 88 for RTSP instead of the standard port 554. If you cannot connect on port 554, try port 88. The port setting can typically be verified and changed in the camera's web interface under network configuration. ## Related Resources - [All Camera Brands — RTSP URL Directory](../) - [LILIN Connection Guide](../lilin/) — Taiwanese industrial cameras - [BrickCom Connection Guide](../brickcom/) — Taiwanese industrial cameras - [ONVIF IP Camera Integration](../../videocapture/video-sources/ip-cameras/onvif/) — AVTech ONVIF device discovery - [IP Camera Preview Tutorial](../../videocapture/video-tutorials/ip-camera-preview/) - [SDK Installation & Samples](../#get-started) ---END OF PAGE--- ## Axis IP Camera RTSP URL Format and C# .NET Integration **URL:** https://www.visioforge.com/help/docs/dotnet/camera-brands/axis/ **Description:** Connect to Axis Communications cameras in C# .NET with RTSP URL patterns, VAPIX API, and code samples for M, P, Q, and F series models. **Tags:** Video Capture SDK, Media Blocks SDK, .NET, Windows, macOS, Linux, Android, iOS, Capture, Streaming, Encoding, IP Camera, RTSP, ONVIF, H.264, H.265, MJPEG, C# # How to Connect to Axis IP Camera in C# .NET [Video Capture SDK .Net](https://www.visioforge.com/video-capture-sdk-net) [Media Blocks SDK .Net](https://www.visioforge.com/media-blocks-sdk-net) ## Brand Overview **Axis Communications** is a Swedish manufacturer widely regarded as the pioneer of network cameras, having created the world's first IP camera in 1996. Headquartered in Lund, Sweden and now a subsidiary of Canon, Axis produces premium IP cameras, encoders, and network audio products primarily for the professional and enterprise surveillance market. **Key facts:** - **Product lines:** M-series (compact/mini), P-series (fixed), Q-series (professional), F-series (modular), V-series (vandal-resistant), PTZ cameras - **Protocol support:** ONVIF Profile S/G/T, RTSP, VAPIX (Axis proprietary HTTP API), HTTP/MJPEG - **Default RTSP port:** 554 - **Default credentials:** root / (set during initial setup; older firmware: root / pass) - **ONVIF support:** Full -- Axis was a founding member of ONVIF - **Video codecs:** H.264, H.265 (newer models), MJPEG - **Unique features:** VAPIX HTTP API for comprehensive camera control, ACAP (Axis Camera Application Platform) ## RTSP URL Patterns Axis cameras use the `axis-media/media.amp` RTSP path with optional parameters for resolution and codec control. ### URL Format ``` rtsp://[USERNAME]:[PASSWORD]@[IP]:[PORT]/axis-media/media.amp ``` ### Primary RTSP URLs | Model Series | RTSP URL | Codec | Audio | | --- | --- | --- | --- | | All modern models | `rtsp://IP:554/axis-media/media.amp` | H.264 (default) | Possible | | All modern models | `rtsp://IP:554/axis-media/media.amp?videocodec=h264` | H.264 (explicit) | Possible | | All modern models | `rtsp://IP:554/axis-media/media.amp?videocodec=h265` | H.265 | Possible | | ONVIF profile | `rtsp://IP:554/onvif-media/media.amp` | H.264 | Yes | | Legacy models | `rtsp://IP:554/mpeg4/media.amp` | MPEG-4 | Possible | ### Stream Profile Selection Axis cameras support named stream profiles that can be selected via URL parameter: | URL Pattern | Notes | | --- | --- | | `rtsp://IP:554/axis-media/media.amp?streamprofile=Quality` | High quality profile | | `rtsp://IP:554/axis-media/media.amp?streamprofile=Balanced` | Balanced profile | | `rtsp://IP:554/axis-media/media.amp?streamprofile=Bandwidth` | Low bandwidth profile | | `rtsp://IP:554/axis-media/media.amp?resolution=1920x1080` | Explicit resolution | | `rtsp://IP:554/axis-media/media.amp?resolution=640x480` | Lower resolution | | `rtsp://IP:554/axis-media/media.amp?fps=15` | Frame rate limit | ### Multi-Channel Models (Encoders, Multi-Sensor) For multi-channel devices like video encoders (M7001, P7214) and multi-sensor cameras: | Device | RTSP URL | Channel | | --- | --- | --- | | Channel 1 | `rtsp://IP:554/axis-media/media.amp?camera=1` | 1 | | Channel 2 | `rtsp://IP:554/axis-media/media.amp?camera=2` | 2 | | Channel 3 | `rtsp://IP:554/axis-media/media.amp?camera=3` | 3 | | Channel 4 | `rtsp://IP:554/axis-media/media.amp?camera=4` | 4 | ### Legacy URL Formats Older Axis cameras (200-series, early 1000-series) may require these formats: | URL Pattern | Models | Notes | | --- | --- | --- | | `rtsp://IP:554/mpeg4/media.amp` | 200, 205, 206, 207 | MPEG-4 stream | | `http://IP/axis-cgi/mjpg/video.cgi` | All models | MJPEG over HTTP | | `http://IP/mjpg/video.mjpg` | 200-series | Direct MJPEG stream | | `http://IP/axis-cgi/mjpg/video.cgi?camera=1` | Multi-channel | Specific channel | | `http://IP/axis-cgi/mjpg/video.cgi?resolution=640x480` | All models | Resolution-specific | ## Connecting with VisioForge SDK Use your Axis camera's RTSP URL with any of the three SDK approaches shown in the [Quick Start Guide](../#quick-start-code): ``` // Axis camera, H.264 main stream var uri = new Uri("rtsp://192.168.1.50:554/axis-media/media.amp"); var username = "root"; var password = "YourPassword"; ``` For sub-stream access, add `?resolution=640x480` parameter. ### ONVIF Discovery Axis was a founding member of ONVIF and has industry-leading ONVIF compliance. See the [ONVIF integration guide](../../mediablocks/Sources/) for discovery code examples. ## Snapshot and MJPEG URLs (VAPIX API) Axis cameras provide the VAPIX HTTP API, which is more feature-rich than most other brands: | Type | URL Pattern | Notes | | --- | --- | --- | | JPEG Snapshot | `http://IP/axis-cgi/jpg/image.cgi` | Current frame | | Snapshot (sized) | `http://IP/axis-cgi/jpg/image.cgi?resolution=1920x1080` | Specific resolution | | Snapshot (with overlay) | `http://IP/axis-cgi/jpg/image.cgi?date=1&clock=1` | Date/time overlay | | Snapshot (camera select) | `http://IP/axis-cgi/jpg/image.cgi?camera=1` | Multi-channel device | | Simple snapshot | `http://IP/jpg/image.jpg` | Basic JPEG capture | | Sized snapshot | `http://IP/jpg/image.jpg?size=3` | Predefined size (1-5) | | MJPEG stream | `http://IP/axis-cgi/mjpg/video.cgi` | Continuous MJPEG | | MJPEG (resolution) | `http://IP/axis-cgi/mjpg/video.cgi?resolution=640x480` | Sized MJPEG | | MJPEG (direct) | `http://IP/mjpg/video.mjpg` | Direct MJPEG (legacy) | ## Troubleshooting ### Audio "Possible" vs "Yes" Axis marks audio support as "Possible" on many RTSP streams because audio availability depends on the camera model having a built-in microphone or external audio input. The RTSP URL is the same whether audio is present or not -- the SDK will automatically detect and use audio if available. ### "401 Unauthorized" errors - Axis cameras default to digest authentication for RTSP - Ensure you're using the correct credentials (default username is `root`, not `admin`) - On newer firmware, password must meet complexity requirements (minimum 8 characters) ### MPEG-4 stream not available on newer models Modern Axis cameras (firmware 5.x+) have dropped MPEG-4 support. Use `/axis-media/media.amp` (H.264) instead of `/mpeg4/media.amp`. ### Resolution not matching expected output Axis cameras negotiate resolution dynamically. To force a specific resolution, add the `resolution` parameter: `rtsp://IP:554/axis-media/media.amp?resolution=1920x1080` ### Multi-channel encoder connections When connecting to an Axis encoder (M7001, P7214, etc.), you must specify the camera/channel parameter. Without it, you get channel 1 by default. ## FAQ **What is the default RTSP URL for Axis cameras?** The standard URL is `rtsp://root:password@CAMERA_IP:554/axis-media/media.amp`. This works for virtually all modern Axis cameras (M, P, Q, F, V series). The default username is `root` (not `admin` like most other brands). **How do I switch between H.264 and H.265 on Axis cameras?** Add the `videocodec` parameter to the RTSP URL: `rtsp://IP:554/axis-media/media.amp?videocodec=h265` for H.265, or `videocodec=h264` for H.264. Note that H.265 is only available on newer Axis models with Artpec-7 or newer chipsets. **Can I control stream quality via the RTSP URL?** Yes. Axis supports several URL parameters: `resolution` (e.g., `1920x1080`), `fps` (frame rate), `compression` (0-100), and `streamprofile` (named profiles configured in the camera). Example: `rtsp://IP:554/axis-media/media.amp?resolution=1280x720&fps=15`. **Why does Axis use "root" as the default username instead of "admin"?** Axis cameras run embedded Linux, and following Unix conventions, the administrative user is named `root`. This is different from most other camera brands that use `admin`. ## Related Resources - [All Camera Brands — RTSP URL Directory](../) - [Bosch Connection Guide](../bosch/) — Enterprise surveillance peer - [Hanwha Vision Connection Guide](../hanwha/) — Enterprise surveillance peer - [IP Camera Preview Tutorial](../../videocapture/video-tutorials/ip-camera-preview/) - [SDK Installation & Samples](../#get-started) ---END OF PAGE--- ## Basler IP Camera RTSP URL Connection Guide for C# .NET **URL:** https://www.visioforge.com/help/docs/dotnet/camera-brands/basler/ **Description:** Connect to Basler BIP2 IP cameras in C# .NET with RTSP URL patterns and code samples. Includes notes on machine vision vs IP security camera protocols. **Tags:** Video Capture SDK, Media Blocks SDK, .NET, Windows, macOS, Linux, Android, iOS, Capture, Streaming, IP Camera, USB3 Vision / GigE, RTSP, ONVIF, H.264, MJPEG, C# # How to Connect to Basler IP Camera in C# .NET [Video Capture SDK .Net](https://www.visioforge.com/video-capture-sdk-net) [Media Blocks SDK .Net](https://www.visioforge.com/media-blocks-sdk-net) ## Brand Overview **Basler** (Basler AG) is a German camera manufacturer headquartered in Ahrensburg, Germany, founded in 1988. Basler is a world leader in industrial machine vision cameras and also produces IP security cameras under the **BIP2** product line. While Basler's machine vision cameras use specialized industrial protocols, the BIP2 series provides standard RTSP and ONVIF connectivity for security and surveillance applications. **Key facts:** - **Product lines:** ace (machine vision), dart (compact), boost (high-speed), BIP2 (IP security) - **Protocol support:** RTSP, ONVIF, HTTP/CGI (BIP2 series); GigE Vision, USB3 Vision (machine vision) - **Default RTSP port:** 554 - **Default credentials:** admin / admin - **ONVIF support:** Yes (BIP2 series) - **Video codecs:** H.264, MPEG-4, MJPEG - **Primary use:** Industrial vision, factory automation, quality inspection, IP surveillance Machine Vision Cameras Use Different Protocols Basler's ace, dart, and boost machine vision cameras use GigE Vision or USB3 Vision protocols, not RTSP. These require Basler's Pylon SDK or a GenICam-compatible framework. The RTSP URLs on this page apply to Basler's BIP2 IP security camera line. ## RTSP URL Patterns ### Standard URL Format Basler BIP2 IP cameras use simple path-based RTSP URLs: ``` rtsp://[USERNAME]:[PASSWORD]@[IP]:554/h264 ``` | Stream | URL Pattern | Description | | --- | --- | --- | | H.264 main stream | `rtsp://IP:554/h264` | Primary stream, best quality | | MPEG-4 stream | `rtsp://IP:554/mpeg4` | Legacy MPEG-4 encoded stream | | JPEG over RTSP | `rtsp://IP:554/jpeg` | JPEG frames over RTSP | ### Camera Models | Model | Type | Main Stream URL | Codec | | --- | --- | --- | --- | | BIP2-1280c (720p) | IP bullet | `rtsp://IP:554/h264` | H.264 | | BIP2-1300c (1.3MP) | IP bullet | `rtsp://IP:554/h264` | H.264 | | BIP2-1920c (1080p) | IP bullet | `rtsp://IP:554/h264` | H.264 | | BIP2-1300c-dn | IP day/night | `rtsp://IP:554/h264` | H.264 | | BIP2-1920c-dn | IP day/night | `rtsp://IP:554/h264` | H.264 | ### Alternative URL Formats | URL Pattern | Notes | | --- | --- | | `rtsp://IP:554/h264` | H.264 stream (recommended) | | `rtsp://IP:554/mpeg4` | MPEG-4 stream (legacy) | | `rtsp://IP:554/jpeg` | JPEG over RTSP | ## Connecting with VisioForge SDK Use your Basler camera's RTSP URL with any of the three SDK approaches shown in the [Quick Start Guide](../#quick-start-code): ``` // Basler BIP2, H.264 main stream var uri = new Uri("rtsp://192.168.1.90:554/h264"); var username = "admin"; var password = "admin"; ``` For MPEG-4 streams, replace `/h264` with `/mpeg4` in the URL. ## Snapshot and MJPEG URLs | Type | URL Pattern | Notes | | --- | --- | --- | | MJPEG Stream | `http://IP/cgi-bin/mjpeg` | Continuous MJPEG stream | | JPEG Snapshot | `http://IP/cgi-bin/jpeg?stream=0` | Snapshot from channel 0 | | JPEG Snapshot (channel) | `http://IP/cgi-bin/jpeg?stream=CHANNEL` | Snapshot from specific channel | ## Troubleshooting ### Machine vision camera not connecting via RTSP Basler's ace, dart, and boost cameras do not support RTSP. These cameras use GigE Vision (Ethernet) or USB3 Vision (USB) protocols and require Basler's Pylon SDK or a GenICam-compatible library. Only the BIP2 IP camera series supports RTSP streaming. ### "401 Unauthorized" error Basler BIP2 cameras ship with default credentials `admin` / `admin`. If the credentials have been changed: 1. Access the camera web interface at `http://CAMERA_IP` 2. Log in and verify or reset the credentials 3. Use the updated credentials in your RTSP URL ### No video output on MPEG-4 stream Some newer Basler BIP2 firmware versions may default to H.264 only. If the MPEG-4 stream returns no data: 1. Open the camera web interface 2. Navigate to video stream settings 3. Ensure MPEG-4 encoding is enabled 4. Alternatively, use the `/h264` stream path instead ### ONVIF discovery not finding the camera ONVIF is supported on BIP2 series cameras only. Ensure: - The camera firmware is up to date - ONVIF is enabled in the camera's network settings - The camera and discovery client are on the same subnet ## FAQ **What is the default RTSP URL for Basler cameras?** For Basler BIP2 IP cameras, the default URL is `rtsp://admin:admin@CAMERA_IP:554/h264` for the H.264 main stream. Replace the credentials if they have been changed from the defaults. **Can I use VisioForge SDK with Basler machine vision cameras?** The RTSP-based connection described on this page applies to Basler BIP2 IP security cameras only. Basler's machine vision cameras (ace, dart, boost) use GigE Vision or USB3 Vision protocols and require Basler's Pylon SDK or a GenICam-compatible framework for direct integration. **Do Basler cameras support ONVIF?** Yes, but only the BIP2 IP security camera series supports ONVIF. Basler's machine vision cameras use industrial protocols (GigE Vision, USB3 Vision) instead. **What codecs do Basler IP cameras support?** Basler BIP2 cameras support H.264, MPEG-4, and MJPEG. H.264 is recommended for the best balance of quality and bandwidth efficiency. ## Related Resources - [All Camera Brands — RTSP URL Directory](../) - [Mobotix Connection Guide](../mobotix/) — German industrial cameras - [FLIR Connection Guide](../flir/) — Industrial and thermal imaging - [Building Camera Applications with Media Blocks](../../mediablocks/GettingStarted/camera/) - [SDK Installation & Samples](../#get-started) ---END OF PAGE--- ## Bosch IP Camera RTSP URL Patterns and C# .NET Setup **URL:** https://www.visioforge.com/help/docs/dotnet/camera-brands/bosch/ **Description:** Bosch Dinion, Flexidome, Autodome, and VIP encoder RTSP URL patterns for C# .NET. Integrate with VisioForge SDK for enterprise surveillance apps. **Tags:** Video Capture SDK, Media Blocks SDK, .NET, Windows, macOS, Linux, Android, iOS, Capture, Streaming, Encoding, IP Camera, RTSP, ONVIF, H.264, H.265, MJPEG, C# # How to Connect to Bosch IP Camera in C# .NET [Video Capture SDK .Net](https://www.visioforge.com/video-capture-sdk-net) [Media Blocks SDK .Net](https://www.visioforge.com/media-blocks-sdk-net) ## Brand Overview **Bosch Security and Safety Systems** (a division of Robert Bosch GmbH) is a German manufacturer of professional and enterprise video surveillance equipment. Headquartered in Grasbrunn near Munich, Bosch produces IP cameras, encoders, recording solutions, and video analytics primarily for critical infrastructure, transportation, and enterprise security markets. **Key facts:** - **Product lines:** Dinion (bullet/box), Flexidome (dome), Autodome (PTZ), MIC (ruggedized), NBN/NDN/NTC (legacy network), NWC (compact), VideoJet/VIP (encoders) - **Protocol support:** RTSP, ONVIF (Profile S/G/T), HTTP/CGI, Bosch VMS (BVMS), iSCSI direct recording - **Default RTSP port:** 554 - **Default credentials:** Varies by model and firmware version; many require setup via Bosch Configuration Manager - **ONVIF support:** Yes (all current IP cameras) - **Video codecs:** H.264, H.265, MJPEG - **Unique feature:** RTSP tunnel mode for firewall traversal ## RTSP URL Patterns Bosch cameras use several URL patterns depending on the model generation. The most common are the `/rtsp_tunnel` and `/video` paths. ### Current Models (Bosch CPP series firmware) | Stream | RTSP URL | Notes | | --- | --- | --- | | Video stream 1 | `rtsp://IP:554/video?inst=1` | Main stream | | Video stream 2 | `rtsp://IP:554/video?inst=2` | Sub stream | | RTSP tunnel | `rtsp://IP:554//rtsp_tunnel` | Firewall-friendly (note double slash) | | H.264 direct | `rtsp://IP:554/h264` | Direct H.264 stream | RTSP tunnel mode The `//rtsp_tunnel` URL (with double slash) is Bosch's proprietary RTSP tunneling mode that works better through firewalls and NAT. It encapsulates RTP data within the RTSP TCP connection. Use the standard `/video` URL for most integrations. ### Model-Specific URLs | Model Series | RTSP URL | Codec | Notes | | --- | --- | --- | --- | | Dinion IP 4000/5000/7000/8000 | `rtsp://IP:554/video?inst=1` | H.264/H.265 | Current | | Flexidome IP 4000/5000/7000/8000 | `rtsp://IP:554/video?inst=1` | H.264/H.265 | Current | | Autodome IP 4000/5000/7000 | `rtsp://IP:554/video?inst=1` | H.264/H.265 | Current PTZ | | MIC IP fusion/starlight/ultra | `rtsp://IP:554/video?inst=1` | H.264/H.265 | Ruggedized | | NDC-225-PI | `rtsp://IP:554//rtsp_tunnel` | H.264 | Legacy | | NDC-255-P | `rtsp://IP:554//rtsp_tunnel` | H.264 | Legacy | | NDC-265-P | `rtsp://IP:554/h264` | H.264 | Legacy | | NDN-832v | `rtsp://IP:554//rtsp_tunnel` | H.264 | Legacy dome | | NTC-255-PI | `rtsp://IP:554/video` | H.264 | Legacy thermal | | NTC-265-PI | `rtsp://IP:554/h264` | H.264 | Legacy thermal | | NTI-50022-V3 | `rtsp://IP:554/h264` | H.264 | IP bullet | | NWC-0455-20P | `rtsp://IP:554/h264` | H.264 | Compact | ### Encoder URLs Bosch video encoders (VideoJet, VIP series) allow connecting analog cameras to IP networks: | Encoder | RTSP URL | Notes | | --- | --- | --- | | VideoJet 10 | `rtsp://IP:554/video?inst=1` | Single channel | | VIP X1 | `rtsp://IP:554//rtsp_tunnel` | Single channel | | VIP X1600 | `rtsp://IP:554/video?inst=1` | Multi-channel | | VIP X2 | `rtsp://IP:554/video?inst=1` | Dual channel | ### DVR RTSP URLs | DVR Model | RTSP URL | Notes | | --- | --- | --- | | DVR 440/480/600 | `rtsp://IP:554/rtsp_tunnel` | Single slash | | DVR 440/480/600 | `rtsp://IP:554/video` | Alternative | | DVR (channel) | `rtsp://IP:554/cgi-bin/rtspStream/CHANNEL` | Channel-specific | | DVR (SDP) | `rtsp://IP:554/user=USER&password=PASS&channel=1&stream=0.sdp?` | SDP-based | ## Connecting with VisioForge SDK Use your Bosch camera's RTSP URL with any of the three SDK approaches shown in the [Quick Start Guide](../#quick-start-code): ``` // Bosch Dinion/Flexidome, main stream var uri = new Uri("rtsp://192.168.1.60:554/video?inst=1"); var username = "service"; var password = "YourPassword"; ``` For sub-stream access, use `?inst=2` instead of `?inst=1`. For legacy Bosch models, use the RTSP tunnel URL `//rtsp_tunnel` (note the double slash). ## Snapshot and MJPEG URLs | Type | URL Pattern | Notes | | --- | --- | --- | | JPEG Snapshot | `http://IP/snap.jpg` | Basic snapshot | | Snapshot (sized) | `http://IP/snap.jpg?JpegSize=XL` | XL, M sizes available | | Snapshot (channel) | `http://IP/snap.jpg?JpegCam=CHANNEL` | Multi-channel encoders | | Snapshot (auth) | `http://IP/snap.jpg?usr=USER&pwd=PASS` | URL-based auth | | MJPEG Stream | `http://IP/img/mjpeg.jpg` | Continuous MJPEG | | Image | `http://IP/img.jpg` | Single frame | | Image (alt) | `http://IP/image.jpg` | Alternative path | ## Troubleshooting ### Double slash in rtsp\_tunnel URL The `//rtsp_tunnel` URL (with double slash before `rtsp_tunnel`) is intentional for legacy Bosch cameras. This is not a typo: - Correct: `rtsp://IP:554//rtsp_tunnel` - Incorrect: `rtsp://IP:554/rtsp_tunnel` (may work on some models but not all) ### Bosch Configuration Manager required Many Bosch cameras require initial setup through the **Bosch Configuration Manager** desktop application before RTSP access works. The camera may not respond to RTSP connections until initial configuration is complete. ### Default username varies - **Current models:** `service` user with password set during setup - **Legacy models:** May use `admin`, `user`, or `service` depending on firmware - Check the Bosch Configuration Manager or camera's web interface for user settings ### inst parameter The `?inst=1` parameter selects the video stream instance: - `inst=1` = First video stream (main) - `inst=2` = Second video stream (sub) - Not all models support multiple instances ### Encoder channel selection For multi-channel encoders (VIP X1600, VideoJet X-series), use the `inst` parameter to select the channel: - `rtsp://IP:554/video?inst=1` = Channel 1 - `rtsp://IP:554/video?inst=2` = Channel 2 ## FAQ **What is the default RTSP URL for Bosch cameras?** For current Bosch cameras, the URL is `rtsp://service:password@CAMERA_IP:554/video?inst=1`. For legacy models, try `rtsp://CAMERA_IP:554//rtsp_tunnel` or `rtsp://CAMERA_IP:554/h264`. **What is Bosch RTSP tunnel mode?** RTSP tunnel (`//rtsp_tunnel`) is Bosch's proprietary mode that encapsulates RTP data within the RTSP TCP connection, making it easier to traverse firewalls. It's the default streaming mode on many legacy Bosch cameras. **Do Bosch cameras support H.265?** Current Bosch IP cameras (CPP13/CPP14 platform, including Dinion/Flexidome 7000/8000 series) support H.265. Legacy cameras support H.264 and MPEG-4. Check your specific model's datasheet for codec support. **Can I use Bosch encoders to connect analog cameras?** Yes. Bosch VideoJet and VIP encoders convert analog camera signals to IP streams accessible via RTSP. Use the same URL format (`/video?inst=1` or `//rtsp_tunnel`) as IP cameras. ## Related Resources - [All Camera Brands — RTSP URL Directory](../) - [Axis Connection Guide](../axis/) — Enterprise surveillance peer - [Honeywell Connection Guide](../honeywell/) — Enterprise / commercial segment - [IP Camera Preview Tutorial](../../videocapture/video-tutorials/ip-camera-preview/) - [SDK Installation & Samples](../#get-started) ---END OF PAGE--- ## BrickCom IP Camera RTSP URL Setup Guide for C# .NET **URL:** https://www.visioforge.com/help/docs/dotnet/camera-brands/brickcom/ **Description:** BrickCom CB, MB, OB, VD, and WCB series RTSP URL patterns for C# .NET. Stream and record using VisioForge Video Capture SDK integration code. **Tags:** Video Capture SDK, Media Blocks SDK, .NET, Windows, macOS, Linux, Android, iOS, Capture, Streaming, IP Camera, RTSP, ONVIF, H.264, MJPEG, C# # How to Connect to BrickCom IP Camera in C# .NET [Video Capture SDK .Net](https://www.visioforge.com/video-capture-sdk-net) [Media Blocks SDK .Net](https://www.visioforge.com/media-blocks-sdk-net) ## Brand Overview **BrickCom** (Brickcom Corporation) is a Taiwanese professional IP camera manufacturer headquartered in Taipei, Taiwan. Founded in 2004, BrickCom targets professional security and industrial surveillance markets with a wide range of form factors including bullet, dome, cube, and specialty cameras. The brand is known for its straightforward channel-based RTSP URL pattern across its product lines. **Key facts:** - **Product lines:** CB (cube), MB (mini bullet), OB (outdoor bullet), VD (vandal dome), FD (fixed dome), MD (multi-directional), WCB/WOB (wireless) - **Channel-based URL pattern:** `/channel1` for main stream, `/channel2` for sub stream - **Default RTSP port:** 554 - **Default credentials:** admin / admin - **ONVIF support:** Yes (most models) - **Video codecs:** H.264, MJPEG - **Primary RTSP URL:** `rtsp://IP:554/channel1` Channel numbering BrickCom uses simple channel-based URLs. Use `/channel1` for the primary (high-quality) stream and `/channel2` for the secondary (lower bandwidth) stream. ## RTSP URL Patterns ### Standard URL Format BrickCom cameras use a simple channel-based RTSP URL pattern: ``` rtsp://[USERNAME]:[PASSWORD]@[IP]:554/channel1 ``` | Parameter | Value | Description | | --- | --- | --- | | `channel1` | Main stream | Primary stream (highest resolution) | | `channel2` | Sub stream | Secondary stream (lower resolution, less bandwidth) | ### Camera Models | Model | Type | Main Stream URL | Notes | | --- | --- | --- | --- | | CB-100 (cube) | Cube | `rtsp://IP:554/channel1` | Indoor cube camera | | MB-300Ap (mini bullet) | Mini Bullet | `rtsp://IP:554/channel1` | Compact bullet form factor | | OB-100Ap (outdoor bullet) | Outdoor Bullet | `rtsp://IP:554/channel1` | Weatherproof bullet | | OB-300Af (outdoor bullet) | Outdoor Bullet | `rtsp://IP:554/channel1` | Auto-focus bullet | | VD-130Ae (vandal dome) | Vandal Dome | `rtsp://IP:554/channel1` | IK10-rated dome | | VD-301AF (vandal dome) | Vandal Dome | `rtsp://IP:554/channel1` | Auto-focus vandal dome | | VD-500Af (vandal dome) | Vandal Dome | `rtsp://IP:554/channel1` | 5MP vandal dome | | WCB-100Ap (wireless cube) | Wireless Cube | `rtsp://IP:554/channel1` | Wi-Fi cube camera | | WCB-300AP (wireless cube) | Wireless Cube | `rtsp://IP:554/channel1` | Wi-Fi cube, 3MP | | WOB-100Ae (wireless bullet) | Wireless Bullet | `rtsp://IP:554/channel1` | Wi-Fi outdoor bullet | | MD-500AP-360-A1 (multi-dome) | Multi-Directional | `rtsp://IP:554/channel1` | 360-degree multi-sensor | ### Alternative URL Formats Some BrickCom models and firmware versions support these additional RTSP URLs: | URL Pattern | Supported Models | Notes | | --- | --- | --- | | `rtsp://IP:554/channel1` | Most models | Standard (recommended) | | `rtsp://IP:554/h264` | Various | Direct H.264 stream | | `rtsp://IP//ONVIF/channel2` | VD-500Af, WCB-100Ap | ONVIF sub stream | | `rtsp://IP/stream/bidirect/channel1` | Select models | Bidirectional stream with audio | ## Connecting with VisioForge SDK Use your BrickCom camera's RTSP URL with any of the three SDK approaches shown in the [Quick Start Guide](../#quick-start-code): ``` // BrickCom OB-300Af, main stream var uri = new Uri("rtsp://192.168.1.90:554/channel1"); var username = "admin"; var password = "admin"; ``` For sub-stream access, use `/channel2` instead of `/channel1`. ## Snapshot and MJPEG URLs | Type | URL Pattern | Notes | | --- | --- | --- | | JPEG Snapshot | `http://IP/snapshot.jpg` | No authentication required | | JPEG Snapshot (auth) | `http://IP/snapshot.jpg?user=USER&pwd=PASS` | URL-based authentication | | Channel Snapshot | `http://IP/snapshot.jpg?user=USER&pwd=PASS&strm=1` | Specific channel with auth | | CGI Snapshot | `http://IP/cgi-bin/media.cgi?action=getSnapshot` | CGI-based snapshot | | HTTP Channel Stream | `http://IP/channel2` | HTTP sub stream | ## Troubleshooting ### "401 Unauthorized" error BrickCom cameras ship with default credentials of **admin / admin**. If you have changed the password via the web interface: 1. Access the camera at `http://CAMERA_IP` in a browser 2. Navigate to **Configuration > User Management** 3. Verify your credentials 4. Use those credentials in your RTSP URL ### Channel URL not connecting If `rtsp://IP:554/channel1` does not work, try the alternative H.264 URL: - `rtsp://IP:554/h264` -- direct H.264 stream without channel specification - Some older firmware versions may require the ONVIF format: `rtsp://IP//ONVIF/channel2` ### ONVIF discovery issues BrickCom cameras support ONVIF on most models. If ONVIF discovery fails: 1. Access the web interface at `http://CAMERA_IP` 2. Navigate to **Configuration > Network > ONVIF** 3. Ensure ONVIF is enabled 4. Verify the ONVIF port (default: 80 or 8080) ### Wireless models (WCB/WOB) connection drops Wireless BrickCom cameras (WCB and WOB series) may experience intermittent RTSP disconnections on congested Wi-Fi networks. Use the sub stream (`/channel2`) for lower bandwidth requirements, or connect via Ethernet for maximum reliability. ## FAQ **What is the default RTSP URL for BrickCom cameras?** The URL is `rtsp://admin:admin@CAMERA_IP:554/channel1` for the main stream. Use `/channel2` for the sub stream with lower resolution and bandwidth. **Do BrickCom cameras support ONVIF?** Yes. Most current BrickCom models support ONVIF. Some models also expose an ONVIF-specific RTSP path at `rtsp://IP//ONVIF/channel2`. **What is the difference between channel1 and channel2?** `/channel1` provides the primary high-resolution stream and `/channel2` provides a secondary lower-resolution stream suitable for thumbnails, mobile viewing, or bandwidth-constrained scenarios. **Can I access multiple streams simultaneously?** Yes. BrickCom cameras support concurrent connections to both `/channel1` and `/channel2`. The maximum number of simultaneous connections depends on the specific model. ## Related Resources - [All Camera Brands — RTSP URL Directory](../) - [AVTech Connection Guide](../avtech/) — Taiwanese industrial cameras - [LILIN Connection Guide](../lilin/) — Taiwanese professional cameras - [IP Camera Preview Tutorial](../../videocapture/video-tutorials/ip-camera-preview/) - [SDK Installation & Samples](../#get-started) ---END OF PAGE--- ## Canon IP Camera RTSP URL and C# .NET Connection Guide **URL:** https://www.visioforge.com/help/docs/dotnet/camera-brands/canon/ **Description:** Canon VB-H, VB-M, VB-S, VB-R camera RTSP URL patterns for C# .NET. Integrate with VisioForge SDK for streaming and recording in WPF, WinForms, MAUI. **Tags:** Video Capture SDK, Media Blocks SDK, .NET, Windows, macOS, Linux, Android, iOS, Capture, Streaming, IP Camera, RTSP, ONVIF, H.264, H.265, MJPEG, C# # How to Connect to Canon IP Camera in C# .NET [Video Capture SDK .Net](https://www.visioforge.com/video-capture-sdk-net) [Media Blocks SDK .Net](https://www.visioforge.com/media-blocks-sdk-net) ## Brand Overview **Canon Inc.** is a Japanese multinational corporation headquartered in Tokyo. Canon's IP camera division produces the **VB series** of network cameras targeting professional and enterprise surveillance markets. Canon cameras are known for their optical quality, leveraging Canon's expertise in lens manufacturing. Canon has been reducing its IP camera lineup in recent years, focusing on higher-end models. **Key facts:** - **Product lines:** VB-H series (box/PTZ, current), VB-M series (PTZ/compact), VB-S series (compact), VB-R series (PTZ), VB-C series (legacy PTZ) - **Protocol support:** RTSP, ONVIF (VB-H and VB-M series), HTTP/CGI with proprietary `-wvhttp-01-` path - **Default RTSP port:** 554 - **Default credentials:** root / (camera-specific) or admin / admin (varies by model) - **ONVIF support:** Yes (VB-H and VB-M series) - **Video codecs:** H.264, H.265 (VB-H47, VB-H761 series), MJPEG ## RTSP URL Patterns Canon cameras use profile-based streaming with channel and profile identifiers in the URL path. ### Current Models (VB-H / VB-M / VB-S / VB-R Series) | Stream | RTSP URL | Notes | | --- | --- | --- | | Channel-based | `rtsp://IP:554/cam1/h264` | Channel 1, H.264 | | Profile stream | `rtsp://IP:554//stream/profile1=r` | Profile 1, read mode (note double slash) | | Profile (short) | `rtsp://IP:554/profile1=r` | Profile 1, shorter variant | | Unicast profile | `rtsp://IP/profile1=u` | Unicast mode, no port | Profile-based streaming Canon cameras use profile identifiers with access modes: `profile1=r` for **read** (multicast-capable) and `profile1=u` for **unicast** (direct connection). Use `=r` for general access and `=u` when connecting directly without multicast. ### Model-Specific URLs | Model | RTSP URL | Type | Notes | | --- | --- | --- | --- | | VB-H41 | `rtsp://IP:554//stream/profile1=r` | Fixed box | Profile with double slash | | VB-H43 / VB-H45 | `rtsp://IP:554/cam1/h264` | Fixed box | Channel-based | | VB-H47 | `rtsp://IP:554/cam1/h264` | Fixed box | H.265 capable | | VB-H610D / VB-H610VE | `rtsp://IP:554/cam1/h264` | Fixed dome | Current | | VB-H730F | `rtsp://IP:554/cam1/h264` | Fixed dome | Fisheye | | VB-H751LE | `rtsp://IP:554/cam1/h264` | Fixed bullet | Outdoor | | VB-H761LVE | `rtsp://IP:554/cam1/h264` | Fixed bullet | H.265 capable | | VB-M40 | `rtsp://IP/profile1=u` | Compact PTZ | Unicast, no port specified | | VB-M42 / VB-M44 | `rtsp://IP:554/cam1/h264` | Compact PTZ | Channel-based | | VB-M600D | `rtsp://IP/profile1=r` | Compact dome | Read mode | | VB-M620D / VB-M640V | `rtsp://IP:554/cam1/h264` | Compact dome | Current | | VB-M741LE | `rtsp://IP:554/cam1/h264` | Compact PTZ | Outdoor | | VB-S30D / VB-S31D | `rtsp://IP:554/cam1/h264` | Compact | Indoor | | VB-S800D / VB-S900F | `rtsp://IP:554/cam1/h264` | Compact | Indoor | | VB-R11 / VB-R11VE | `rtsp://IP:554/cam1/h264` | PTZ dome | Current | | VB-R12VE | `rtsp://IP:554/cam1/h264` | PTZ dome | Outdoor | ### Legacy Models (VB-C Series -- HTTP Only) Legacy VB-C cameras do not support RTSP. They use Canon's proprietary `-wvhttp-01-` HTTP URLs: | Model | HTTP URL | Type | Notes | | --- | --- | --- | --- | | VB-C300 | `http://IP/-wvhttp-01-/GetLiveImage` | PTZ dome | HTTP only | | VB-C10 | `http://IP/-wvhttp-01-/GetLiveImage` | Compact | HTTP only | | VB-C50i | `http://IP/-wvhttp-01-/GetLiveImage` | PTZ dome | HTTP only | | VB-610 | `http://IP/-wvhttp-01-/video.cgi` | Fixed | HTTP only | ## Connecting with VisioForge SDK Use your Canon camera's RTSP URL with any of the three SDK approaches shown in the [Quick Start Guide](../#quick-start-code): ``` // Canon VB-H series camera, channel 1 var uri = new Uri("rtsp://192.168.1.70:554/cam1/h264"); var username = "root"; var password = "YourPassword"; ``` For profile-based access on older VB models, use `rtsp://IP:554/profile1=r` or `rtsp://IP/profile1=u` depending on the model. ## Snapshot and MJPEG URLs Canon uses a distinctive `-wvhttp-01-` path prefix for all HTTP-based image and video access: | Type | URL Pattern | Notes | | --- | --- | --- | | Live Image | `http://IP/-wvhttp-01-/GetLiveImage` | Current snapshot | | MJPEG Stream | `http://IP/-wvhttp-01-/video.cgi` | Continuous MJPEG | | Snapshot (sized) | `http://IP/-wvhttp-01-/GetOneShot?image_size=WIDTHxHEIGHT` | Custom resolution | | Snapshot (continuous) | `http://IP/-wvhttp-01-/GetOneShot?image_size=WIDTHxHEIGHT&frame_count=0` | Continuous capture | Canon `-wvhttp-01-` prefix The `-wvhttp-01-` path prefix is unique to Canon network cameras. All HTTP-based image and video URLs use this prefix. This distinctive path can help identify Canon cameras on a network. ## Troubleshooting ### RTSP must be enabled in the web interface Canon cameras may not have RTSP enabled by default. Access the camera's web interface and navigate to the streaming settings to enable RTSP. Without this, the camera will only respond to HTTP requests. ### Legacy VB-C series are HTTP only The VB-C series (VB-C300, VB-C10, VB-C50i) and VB-610 do not support RTSP at all. Use Canon's `-wvhttp-01-` HTTP URLs for video access from these models: - `http://IP/-wvhttp-01-/GetLiveImage` for snapshots - `http://IP/-wvhttp-01-/video.cgi` for MJPEG streaming ### Profile read vs unicast modes Canon profile URLs use two access modes: - `profile1=r` -- **Read mode**: Allows multicast distribution, suitable for multiple viewers - `profile1=u` -- **Unicast mode**: Direct connection, one viewer per stream If multicast is not configured on your network, use `profile1=u` for a direct unicast connection. ### Double slash in some URLs Some Canon models (notably VB-H41) require a **double forward slash** before the stream path: - VB-H41: `rtsp://IP:554//stream/profile1=r` (double slash) - Most others: `rtsp://IP:554/cam1/h264` (single slash) ### Default credentials vary Canon cameras do not have a universal default credential: - **Current models:** Often `root` with a password set during initial setup - **Older models:** May use `admin` / `admin` or `root` / `camera` - Check the camera label or setup guide for model-specific defaults ## FAQ **What is the default RTSP URL for Canon cameras?** For current Canon VB-H and VB-M series cameras, use `rtsp://root:password@CAMERA_IP:554/cam1/h264`. For older models, try `rtsp://CAMERA_IP:554/profile1=r` or `rtsp://CAMERA_IP/profile1=u`. **Do Canon cameras support H.265?** Select Canon models support H.265, including the VB-H47 and VB-H761 series. Most other VB-series cameras use H.264. Legacy VB-C models support only MJPEG over HTTP. **What is the `-wvhttp-01-` path in Canon URLs?** The `-wvhttp-01-` prefix is Canon's proprietary HTTP path used for all web-based image and video access on their network cameras. It is used for snapshots (`GetOneShot`, `GetLiveImage`), MJPEG streaming (`video.cgi`), and camera control. This path is unique to Canon cameras. **Can I connect to legacy Canon VB-C cameras?** Legacy VB-C cameras (VB-C300, VB-C10, VB-C50i) are HTTP-only and do not support RTSP. You can access their video using the HTTP URL `http://CAMERA_IP/-wvhttp-01-/GetLiveImage` for snapshots or `http://CAMERA_IP/-wvhttp-01-/video.cgi` for MJPEG streaming. ## Related Resources - [All Camera Brands — RTSP URL Directory](../) - [Sony Connection Guide](../sony/) — Japanese enterprise cameras - [Axis Connection Guide](../axis/) — Enterprise surveillance leader - [IP Camera Preview Tutorial](../../videocapture/video-tutorials/ip-camera-preview/) - [SDK Installation & Samples](../#get-started) ---END OF PAGE--- ## Cisco IP Camera RTSP URL Setup and C# .NET Integration **URL:** https://www.visioforge.com/help/docs/dotnet/camera-brands/cisco/ **Description:** Cisco CIVS and Meraki camera RTSP integration for C# .NET. URL patterns for enterprise PVC, VC models with VisioForge SDK code and ONVIF examples. **Tags:** Video Capture SDK, Media Blocks SDK, .NET, Windows, macOS, Linux, Android, iOS, Capture, Streaming, IP Camera, RTSP, ONVIF, H.264, MJPEG, C# # How to Connect to Cisco IP Camera in C# .NET [Video Capture SDK .Net](https://www.visioforge.com/video-capture-sdk-net) [Media Blocks SDK .Net](https://www.visioforge.com/media-blocks-sdk-net) ## Brand Overview **Cisco Systems** is the world's largest networking company, headquartered in San Jose, California, USA. Cisco produced IP cameras under both the **Cisco** and **Linksys** brands. The main camera lines were **Cisco Video Surveillance (CIVS/VC/PVC)** for enterprise deployments and the former **Linksys-branded (WVC)** series for consumer and small business markets. Cisco sold their video surveillance business to Verkada and discontinued most camera products, but many units remain deployed in the field. The **Meraki MV** line (cloud-managed) is the only current Cisco camera product. **Key facts:** - **Product lines:** CIVS (enterprise video surveillance), PVC (small business), VC (video camera), WVC (wireless video camera, Linksys legacy), WCS (wireless camera server), Meraki MV (cloud-managed, current) - **Protocol support:** RTSP, HTTP/CGI, MJPEG, ASF (WVC models); Meraki MV is cloud-only - **Default RTSP port:** 554 - **Default credentials:** admin / admin (varies by model) - **ONVIF support:** Limited (some newer CIVS models only; WVC series does not support ONVIF) - **Video codecs:** H.264, MPEG-4 (WVC series), MJPEG Meraki MV cameras Cisco Meraki MV cameras use cloud-only access and do **not** support direct RTSP streaming. They cannot be connected via local RTSP URLs. The information on this page applies to the legacy Cisco and Linksys camera product lines. ## RTSP URL Patterns ### Enterprise Cameras (CIVS / VC / PVC Series) Most Cisco enterprise IP cameras use the `/img/media.sav` path: | Stream | RTSP URL | Notes | | --- | --- | --- | | Main stream | `rtsp://IP:554/img/media.sav` | Most CIVS and WVC cameras | | Live SDP | `rtsp://IP:554/live.sdp` | VC240, PVC300, VC220 series | | Video SAV | `rtsp://IP:554/img/video.sav` | PVC2300 | | Access code | `rtsp://IP:554/[ACCESS_CODE]` | Code configured in camera web UI | | Root stream | `rtsp://IP:554/` | Fallback for PVC2300 and others | ### Model-Specific URLs | Model | RTSP URL | Type | | --- | --- | --- | | CIVS 2500 / 2521 / 2531 | `rtsp://IP:554/img/media.sav` | Enterprise dome/bullet | | PVC300 | `rtsp://IP:554/live.sdp` | Small business PTZ | | PVC2300 | `rtsp://IP:554/img/video.sav` | Small business box | | PVC2300 (alt) | `rtsp://IP:554/` | Fallback | | VC220 | `rtsp://IP:554/live.sdp` | Dome camera | | VC240 | `rtsp://IP:554/live.sdp` | Dome camera | | WVC80N | `rtsp://IP:554/img/media.sav` | Linksys wireless | | WVC210 | `rtsp://IP:554/img/media.sav` | Linksys wireless | | WVC54GCA | `rtsp://IP:554/img/media.sav` | Linksys wireless | | WCS-1130 | `rtsp://IP:554/play1.sdp` | Wireless camera server | Unusual file extension Cisco and Linksys cameras use the `/img/media.sav` path, which has an unusual `.sav` file extension. This is not a standard media format -- it is a Cisco-specific RTSP endpoint. Do not confuse it with a file download URL. ### WVC Series (Linksys Legacy) The Linksys WVC (Wireless Video Camera) series was a popular consumer camera line before Cisco rebranded and eventually discontinued it: | Model | RTSP URL | Resolution | Notes | | --- | --- | --- | --- | | WVC54GCA | `rtsp://IP:554/img/media.sav` | 640x480 | Wi-Fi, MPEG-4 | | WVC80N | `rtsp://IP:554/img/media.sav` | 640x480 | Wireless-N | | WVC210 | `rtsp://IP:554/img/media.sav` | 640x480 | Wireless-G PTZ | ## Connecting with VisioForge SDK Use your Cisco camera's RTSP URL with any of the three SDK approaches shown in the [Quick Start Guide](../#quick-start-code): ``` // Cisco enterprise camera (CIVS/WVC), main stream var uri = new Uri("rtsp://192.168.1.50:554/img/media.sav"); var username = "admin"; var password = "YourPassword"; ``` For VC240 or PVC300 cameras, use `/live.sdp` instead of `/img/media.sav`. ## Snapshot and MJPEG URLs | Type | URL Pattern | Notes | | --- | --- | --- | | JPEG Snapshot | `http://IP/img/snapshot.cgi?size=3` | Most Cisco cameras (size: 1=QQVGA, 2=QVGA, 3=VGA) | | JPEG Snapshot (VGA) | `http://IP/img/snapshot.cgi?img=vga` | Named resolution | | MJPEG Stream | `http://IP/img/video.mjpeg` | Continuous MJPEG stream | | MJPEG (alt) | `http://IP/img/mjpeg.jpg` | Alternative MJPEG endpoint | | ASF Stream | `http://IP/img/video.asf` | WVC series ASF stream | | PVC300 Snapshot | `http://IP/cgi-bin/viewer/snapshot.jpg?resolution=640x480` | Resolution parameter required | ## Troubleshooting ### `/img/media.sav` not responding The `.sav` extension is a Cisco-specific RTSP endpoint. If the URL does not work: 1. Verify the camera IP address and that port 554 is open 2. Confirm RTSP is enabled in the camera's web UI 3. Some models require an access code to be configured before RTSP access works -- check the camera's streaming settings 4. Try the fallback URL `rtsp://IP:554/` if the specific path does not respond ### WVC series returns MPEG-4 only The Linksys WVC cameras (WVC54GCA, WVC80N, WVC210) support MPEG-4 but not H.264. The VisioForge SDK handles MPEG-4 streams automatically. If you see artifacts, ensure you are not forcing H.264 decoding. ### Access code authentication Some Cisco cameras use an access code instead of traditional username/password for RTSP. The access code is configured in the camera's web interface under streaming settings and is appended to the URL: ``` rtsp://IP:554/[YOUR_ACCESS_CODE] ``` ### HTTP streams for legacy cameras Older Cisco/Linksys cameras may work better with HTTP-based ASF or MJPEG streams than RTSP. Use the ASF URL (`http://IP/img/video.asf`) as a fallback if RTSP is unreliable. ### Meraki MV cameras not accessible Meraki MV cameras are cloud-managed only and do not support local RTSP access. There is no local RTSP URL available for these cameras. Video can only be accessed through the Meraki Dashboard cloud interface. ## FAQ **What is the default RTSP URL for Cisco cameras?** For most Cisco and Linksys IP cameras, use `rtsp://admin:password@CAMERA_IP:554/img/media.sav`. For VC/PVC series cameras, try `rtsp://admin:password@CAMERA_IP:554/live.sdp` instead. **Do Cisco cameras support ONVIF?** Only some newer CIVS-series enterprise cameras have limited ONVIF support. The Linksys WVC consumer cameras and Meraki MV cameras do not support ONVIF. **Are Cisco cameras still being manufactured?** Cisco sold their video surveillance business (CIVS line) to Verkada and discontinued the Linksys WVC cameras. The only current Cisco camera product is the Meraki MV series, which is cloud-managed and does not support RTSP. However, many legacy Cisco cameras remain deployed and operational. **What codecs do Cisco cameras use?** Newer CIVS enterprise cameras support H.264. The Linksys WVC series primarily uses MPEG-4 and MJPEG. The codec depends on the model and firmware version. ## Related Resources - [All Camera Brands — RTSP URL Directory](../) - [Linksys Connection Guide](../linksys/) — Same URL patterns, Cisco subsidiary - [IP Camera Preview Tutorial](../../videocapture/video-tutorials/ip-camera-preview/) - [SDK Installation & Samples](../#get-started) ---END OF PAGE--- ## CP Plus IP Camera RTSP URL and C# .NET Connection Guide **URL:** https://www.visioforge.com/help/docs/dotnet/camera-brands/cp-plus/ **Description:** CP Plus UNC, NC, RNP, Guard+, and Cosmic series RTSP URL patterns for C# .NET. Integrate with VisioForge SDK for IP camera streaming and recording. **Tags:** Video Capture SDK, Media Blocks SDK, .NET, Windows, macOS, Linux, Android, iOS, Capture, Streaming, IP Camera, RTSP, ONVIF, MJPEG, C# # How to Connect to CP Plus IP Camera in C# .NET [Video Capture SDK .Net](https://www.visioforge.com/video-capture-sdk-net) [Media Blocks SDK .Net](https://www.visioforge.com/media-blocks-sdk-net) ## Brand Overview **CP Plus** (Aditya Infotech Ltd.) is India's #1 security camera brand and one of the largest surveillance manufacturers in the world, headquartered in Delhi, India. CP Plus cameras are primarily **Dahua OEM** products, meaning most models run Dahua firmware and share identical RTSP URL patterns. Some models use alternative chipsets with different URL formats. CP Plus dominates the Indian, Middle Eastern, and Southeast Asian markets with a comprehensive range of IP cameras, NVRs, and analog systems. **Key facts:** - **Product lines:** UNC (IP cameras), RNP (NVRs), VAC (analog), Guard+ (wireless), E series (entry-level), Cosmic (value) - **OEM base:** Dahua (most models use Dahua firmware and URL patterns) - **Protocol support:** RTSP, ONVIF, HTTP/CGI - **Default RTSP port:** 554 - **Default credentials:** admin / admin - **ONVIF support:** Yes (most models) - **Video codecs:** H.264, H.265 (newer models) - **Dominant market:** India (#1), Middle East, Southeast Asia CP Plus = Dahua OEM CP Plus cameras are primarily Dahua OEM products and use the same RTSP URL patterns. See our [Dahua connection guide](../dahua/) for additional details. Some CP Plus models use the `/VideoInput/` URL format instead. ## RTSP URL Patterns ### Standard URL Format (Dahua-style) Most CP Plus cameras use the Dahua `cam/realmonitor` URL pattern: ``` rtsp://[USERNAME]:[PASSWORD]@[IP]:554/cam/realmonitor?channel=1&subtype=1 ``` | Parameter | Value | Description | | --- | --- | --- | | `channel` | 1, 2, 3... | Camera channel (1 for standalone cameras) | | `subtype` | 0 | Main stream (highest resolution) | | `subtype` | 1 | Sub stream (lower resolution, less bandwidth) | ### Camera Models | Model | Type | Main Stream URL | Notes | | --- | --- | --- | --- | | CP-UNC-DP10L2C | IP dome | `rtsp://IP:554/cam/realmonitor?channel=1&subtype=0` | Dahua-style URL | | CP-UNC-TY20FL2C | IP turret | `rtsp://IP:554/cam/realmonitor?channel=1&subtype=0` | Dahua-style URL | | CP-NC9W-K | Network camera | `rtsp://IP:554/VideoInput/1/mpeg4/1` | VideoInput format | | B series | Basic | `rtsp://IP:554/cam/realmonitor?channel=1&subtype=0` | Dahua-style URL | ### NVR Channel URLs For CP Plus NVRs (CP-RNP-36D, CN-RNP-36D, etc.): | Channel | Main Stream | Sub Stream | | --- | --- | --- | | Camera 1 | `rtsp://IP:554/cam/realmonitor?channel=1&subtype=0` | `rtsp://IP:554/cam/realmonitor?channel=1&subtype=1` | | Camera 2 | `rtsp://IP:554/cam/realmonitor?channel=2&subtype=0` | `rtsp://IP:554/cam/realmonitor?channel=2&subtype=1` | | Camera N | `rtsp://IP:554/cam/realmonitor?channel=N&subtype=0` | `rtsp://IP:554/cam/realmonitor?channel=N&subtype=1` | ### Alternative URL Formats Some CP Plus models use different URL patterns depending on firmware and chipset: | URL Pattern | Notes | | --- | --- | | `rtsp://IP:554/cam/realmonitor?channel=1&subtype=1` | Standard Dahua-style (most models) | | `rtsp://IP:554//cam/realmonitor` | Dahua-style alternate (double slash) | | `rtsp://IP:554/VideoInput/1/mpeg4/1` | VideoInput format (CP-NC9W-K, CP-UNC-DP10L2C on some firmware) | | `rtsp://IP:554//cam/realmonitor?channel=1&subtype=00&authbasic=AUTH` | With base64-encoded authentication | ## Connecting with VisioForge SDK Use your CP Plus camera's RTSP URL with any of the three SDK approaches shown in the [Quick Start Guide](../#quick-start-code): ``` // CP Plus CP-UNC-DP10L2C, main stream var uri = new Uri("rtsp://192.168.1.90:554/cam/realmonitor?channel=1&subtype=0"); var username = "admin"; var password = "YourPassword"; ``` For sub-stream access, use `subtype=1` instead of `subtype=0`. ## Snapshot and MJPEG URLs | Type | URL Pattern | Notes | | --- | --- | --- | | JPEG Snapshot | `http://IP/cgi-bin/snapshot.cgi?1` | Requires basic auth (CP-UNC-TY20FL2C) | | JPEG Snapshot (legacy) | `http://IP/cgi-bin/snapshot.cgi?loginuse=USER&loginpas=PASS` | URL-based auth for older models | | JPEG Image | `http://IP/cgi-bin/jpg/image.cgi` | Alternative JPEG endpoint | | MJPEG Stream | `http://IP/api/mjpegvideo.cgi?InputNumber=1&StreamNumber=CHANNEL` | Continuous MJPEG stream | | Direct HTTP Stream | `http://IP:8008/` | Some NVR models (CN-RNP-36D, CP-RNP-36D) | ## Troubleshooting ### "401 Unauthorized" error CP Plus cameras ship with default credentials (`admin` / `admin`). If you've changed the password via the web interface or mobile app, ensure your RTSP URL uses the updated credentials. 1. Access the camera at `http://CAMERA_IP` in a browser 2. Log in with your credentials 3. Verify RTSP is enabled under **Setup > Network > Port** 4. Use those credentials in your RTSP URL ### Dahua-style URL not working Some CP Plus models (particularly the CP-NC series) use the `/VideoInput/` URL format instead of the Dahua `cam/realmonitor` pattern. Try: ``` rtsp://admin:password@IP:554/VideoInput/1/mpeg4/1 ``` ### Port 554 vs custom port Check the RTSP port setting at: - Web interface: **Setup > Network > Port > RTSP Port** - Default is 554 ### Stream type confusion - `subtype=0` = Main stream (full resolution, higher bandwidth) - `subtype=1` = Sub stream (reduced resolution, lower bandwidth) ### Direct HTTP stream on port 8008 Some CP Plus NVR models (CP-RNP-36D, CN-RNP-36D) expose a direct HTTP stream on port 8008. Try accessing `http://CAMERA_IP:8008/` if standard RTSP is unavailable. ## FAQ **Are CP Plus cameras the same as Dahua?** Most CP Plus cameras are manufactured by Dahua and use Dahua firmware. The RTSP URL format (`cam/realmonitor?channel=1&subtype=0`) is identical for the majority of models. However, some CP Plus models use different chipsets with the `/VideoInput/` URL format. Any code written for Dahua cameras generally works with CP Plus and vice versa. **What is the default RTSP URL for CP Plus cameras?** The URL is `rtsp://admin:password@CAMERA_IP:554/cam/realmonitor?channel=1&subtype=1` for the sub stream. Replace `subtype=1` with `subtype=0` for the main stream. For NVR setups, change `channel=1` to the appropriate channel number. **Do CP Plus cameras support ONVIF?** Yes. Most current CP Plus IP cameras support ONVIF, which provides a standardized way to discover and connect to cameras regardless of the specific URL format. **What if my CP Plus camera uses a different URL format?** Some CP Plus models (especially the CP-NC series) use `rtsp://IP:554/VideoInput/1/mpeg4/1` instead of the Dahua-style URL. If the standard URL does not work, try the VideoInput format. You can also use ONVIF discovery to automatically detect the correct URL. ## Related Resources - [All Camera Brands — RTSP URL Directory](../) - [Dahua Connection Guide](../dahua/) — Same URL format for most models - [Amcrest Connection Guide](../amcrest/) — Another Dahua OEM - [IP Camera Preview Tutorial](../../videocapture/video-tutorials/ip-camera-preview/) - [SDK Installation & Samples](../#get-started) ---END OF PAGE--- ## Dahua IP Camera RTSP URL Patterns and C# .NET Guide **URL:** https://www.visioforge.com/help/docs/dotnet/camera-brands/dahua/ **Description:** Integrate Dahua IPC-HDW, IPC-HFW, NVR, and DVR cameras into C# .NET apps. RTSP URL format, ONVIF auto-discovery, and VisioForge SDK code included. **Tags:** Video Capture SDK, Media Blocks SDK, .NET, Windows, macOS, Linux, Android, iOS, Capture, Streaming, IP Camera, RTSP, ONVIF, MJPEG, C# # How to Connect to Dahua IP Camera in C# .NET [Video Capture SDK .Net](https://www.visioforge.com/video-capture-sdk-net) [Media Blocks SDK .Net](https://www.visioforge.com/media-blocks-sdk-net) ## Brand Overview **Dahua Technology** (Zhejiang Dahua Technology Co., Ltd.) is the world's second-largest video surveillance manufacturer. Founded in 2001 and headquartered in Hangzhou, China, Dahua produces IP cameras, NVRs, DVRs, access control systems, and video intercoms. Dahua cameras are also widely sold under OEM brands including Amcrest, Lorex, and others. **Key facts:** - **Product lines:** IPC-HDW (dome), IPC-HFW (bullet), IPC-HDBW (dome vandal-proof), SD (PTZ), NVR4xxx/5xxx (NVRs), XVR (DVRs) - **Protocol support:** ONVIF Profile S/G/T, RTSP, HTTP, Dahua proprietary (DHIP) - **Default RTSP port:** 554 (some models use 1554) - **Default credentials:** admin / admin (older firmware); admin / (set during setup on newer firmware) - **ONVIF support:** Full - **Video codecs:** H.264, H.265, H.265+, MJPEG ## RTSP URL Patterns Dahua cameras use a `cam/realmonitor` URL structure with channel and subtype parameters. ### URL Format ``` rtsp://[USERNAME]:[PASSWORD]@[IP]:[PORT]/cam/realmonitor?channel=[CH]&subtype=[ST] ``` **Parameters:** - `channel` = camera channel number (1 for single-channel cameras, 1-N for NVR/DVR) - `subtype` = stream type: 0 = main stream, 1 = sub stream, 2 = third stream ### IP Cameras (Single Channel) | Model Series | RTSP URL | Stream | Audio | | --- | --- | --- | --- | | IPC-HDW (dome) | `rtsp://IP:554/cam/realmonitor?channel=1&subtype=0` | Main | Yes | | IPC-HDW (dome) | `rtsp://IP:554/cam/realmonitor?channel=1&subtype=1` | Sub | Yes | | IPC-HFW (bullet) | `rtsp://IP:554/cam/realmonitor?channel=1&subtype=0` | Main | Yes | | IPC-HDBW (vandal dome) | `rtsp://IP:554/cam/realmonitor?channel=1&subtype=0` | Main | Yes | | SD (PTZ) | `rtsp://IP:554/cam/realmonitor?channel=1&subtype=0` | Main | Yes | | DH-IPC-HF2100P | `rtsp://IP:1554/cam/realmonitor?channel=1&subtype=0` | Main | Yes | ### Simplified URL Format Many Dahua cameras also accept a shorter URL format: | URL Pattern | Stream | Notes | | --- | --- | --- | | `rtsp://IP:554/cam/realmonitor` | Main (ch1) | Defaults to channel 1, main stream | | `rtsp://IP:554/` | Main | Bare URL, some models only | | `rtsp://IP:554/live` | Main | Legacy format | ### NVR / DVR Channels | Device | Channel | RTSP URL | Stream | | --- | --- | --- | --- | | NVR Camera 1 | 1 | `rtsp://IP:554/cam/realmonitor?channel=1&subtype=0` | Main | | NVR Camera 1 | 1 | `rtsp://IP:554/cam/realmonitor?channel=1&subtype=1` | Sub | | NVR Camera 2 | 2 | `rtsp://IP:554/cam/realmonitor?channel=2&subtype=0` | Main | | NVR Camera 4 | 4 | `rtsp://IP:554/cam/realmonitor?channel=4&subtype=0` | Main | | DVR Channel 1 | 1 | `rtsp://IP:554/cam/realmonitor?channel=1&subtype=01` | Sub | ### Amcrest / Lorex (Dahua OEM) Amcrest and Lorex cameras use the same Dahua RTSP URL format: | Brand | RTSP URL | Notes | | --- | --- | --- | | Amcrest | `rtsp://IP:554/cam/realmonitor?channel=1&subtype=0` | Identical to Dahua | | Lorex | `rtsp://IP:554/cam/realmonitor?channel=1&subtype=0` | Identical to Dahua | ## Connecting with VisioForge SDK Use your Dahua camera's RTSP URL with any of the three SDK approaches shown in the [Quick Start Guide](../#quick-start-code): ``` // Dahua IPC-HDW series, main stream var uri = new Uri("rtsp://192.168.1.108:554/cam/realmonitor?channel=1&subtype=0"); var username = "admin"; var password = "YourPassword"; ``` For sub-stream access, use `subtype=1` instead. ### ONVIF Discovery Dahua cameras provide strong ONVIF support. See the [ONVIF integration guide](../../mediablocks/Sources/) for discovery code examples. ## Snapshot and MJPEG URLs | Type | URL Pattern | Notes | | --- | --- | --- | | JPEG Snapshot | `http://IP/cgi-bin/snapshot.cgi?channel=1` | Requires basic auth | | JPEG Snapshot (legacy) | `http://IP/cgi-bin/snapshot.cgi?loginuse=USER&loginpas=PASS` | URL-based auth | | MJPEG Stream | `http://IP/cgi-bin/mjpg/video.cgi?channel=1` | Continuous MJPEG | | Axis-compatible MJPEG | `http://IP/axis-cgi/mjpg/video.cgi?camera=1` | Emulated Axis API | | CGI Snapshot | `http://IP/cgi-bin/video.jpg` | Simple snapshot | | Image CGI | `http://IP/cgi-bin/jpg/image.cgi` | Alternative snapshot | ## Troubleshooting ### Port 554 vs 1554 Some Dahua models (especially the DH-IPC-HF series) use port **1554** instead of the standard 554. If connection fails on port 554, try 1554. ### Authentication methods - Dahua supports both **basic** and **digest** RTSP authentication - Newer firmware defaults to digest authentication - VisioForge SDK handles both methods automatically - If using HTTP snapshot URLs, some require URL-embedded credentials (`loginuse`/`loginpas` parameters) while newer firmware uses standard HTTP basic/digest auth ### Connection drops - Dahua cameras can be sensitive to network congestion. Use TCP transport for reliability. - Reduce main stream resolution or switch to sub stream (`subtype=1`) to lower bandwidth - Check the camera's **Max User Connections** setting (Configuration > Network > Connection) -- the default is typically 10 ### Amcrest/Lorex cameras not connecting If you have an Amcrest or Lorex camera (Dahua OEM), use the exact same RTSP URL patterns listed above. The default ports and paths are identical to Dahua. The only difference may be in default credentials: - **Amcrest default:** admin / admin - **Lorex default:** admin / (set during setup) ### DVR extra stream format When connecting to DVR channels, note that `subtype=00` and `subtype=0` are equivalent for the main stream. Some older firmware requires the two-digit format (`01` instead of `1`). ## FAQ **What is the default RTSP URL for Dahua cameras?** The standard URL is `rtsp://admin:password@CAMERA_IP:554/cam/realmonitor?channel=1&subtype=0` for the main stream. Use `subtype=1` for the sub stream (lower resolution, less bandwidth). **Do Amcrest cameras use the same RTSP URLs as Dahua?** Yes. Amcrest cameras are manufactured by Dahua and use identical RTSP URL patterns, authentication, and port configurations. Any RTSP URL that works for a Dahua camera will work for the corresponding Amcrest model. **How do I access multiple cameras on a Dahua NVR?** Change the `channel` parameter in the RTSP URL. Channel 1 is the first camera, channel 2 is the second, and so on. For example, `rtsp://IP:554/cam/realmonitor?channel=3&subtype=0` connects to the third camera on the NVR's main stream. **Why does my Dahua camera use port 1554 instead of 554?** Some older Dahua models, particularly the DH-IPC-HF series, default to RTSP port 1554. You can change this in the camera's web interface under Configuration > Network > Port. Newer models default to port 554. ## Related Resources - [All Camera Brands — RTSP URL Directory](../) - [Amcrest Connection Guide](../amcrest/) — Dahua OEM, identical URL format - [Lorex Connection Guide](../lorex/) — Uses Dahua URL format for many models - [IP Camera Preview Tutorial](../../videocapture/video-tutorials/ip-camera-preview/) - [SDK Installation & Samples](../#get-started) ---END OF PAGE--- ## D-Link DCS IP Camera RTSP URLs and C# .NET Code Samples **URL:** https://www.visioforge.com/help/docs/dotnet/camera-brands/dlink/ **Description:** D-Link DCS camera RTSP URL patterns for C# .NET integration. Covers DCS-930, DCS-2130, DCS-5222 with VisioForge SDK code and authentication setup. **Tags:** Video Capture SDK, Media Blocks SDK, .NET, Windows, macOS, Linux, Android, iOS, Capture, Streaming, IP Camera, RTSP, ONVIF, H.264, MJPEG, C# # How to Connect to D-Link IP Camera in C# .NET [Video Capture SDK .Net](https://www.visioforge.com/video-capture-sdk-net) [Media Blocks SDK .Net](https://www.visioforge.com/media-blocks-sdk-net) ## Brand Overview **D-Link Corporation** is a Taiwanese networking equipment manufacturer headquartered in Taipei. D-Link produces IP cameras under the **DCS (D-Link Cloud Security)** product line, targeting consumer and small business markets. D-Link cameras are widely available through retail channels and are popular for home security and small office deployments. **Key facts:** - **Product lines:** DCS-930/932/933/934 (consumer Wi-Fi), DCS-2130/2132/2230/2310/2330/2332 (prosumer), DCS-5020/5222/5615 (PTZ), DCS-6010/6113/6818 (enterprise), DCS-7010/7110/7410 (outdoor professional) - **Protocol support:** RTSP, ONVIF (some models), HTTP/CGI, MJPEG, D-Link mydlink cloud - **Default RTSP port:** 554 - **Default credentials:** admin / (empty password); some models: admin / admin - **ONVIF support:** Select models only (typically DCS-2xxx and higher) - **Video codecs:** H.264, MJPEG, MPEG-4 (legacy) ## RTSP URL Patterns ### Current and Recent Models D-Link cameras use the `live.sdp` or `play.sdp` URL format: | Stream | RTSP URL | Quality | Notes | | --- | --- | --- | --- | | Main stream (H.264) | `rtsp://IP:554/live1.sdp` | High | Main H.264 stream | | Sub stream (H.264) | `rtsp://IP:554/live2.sdp` | Medium | Second stream | | Third stream | `rtsp://IP:554/live3.sdp` | Low | Third stream (some models) | | Main stream (alt) | `rtsp://IP:554/play1.sdp` | High | Alternative URL | | Sub stream (alt) | `rtsp://IP:554/play2.sdp` | Medium | Alternative URL | ### Model-Specific URLs | Model | RTSP URL | Resolution | Type | | --- | --- | --- | --- | | DCS-930L | `rtsp://IP:554/play1.sdp` | 640x480 | Consumer Wi-Fi | | DCS-932L | `rtsp://IP:554/play1.sdp` | 640x480 | Consumer Wi-Fi IR | | DCS-933L | `rtsp://IP:554/play1.sdp` | 640x480 | Consumer Wi-Fi | | DCS-934L | `rtsp://IP:554/play1.sdp` | 1280x720 | Consumer HD | | DCS-942L | `rtsp://IP:554/play1.sdp` | 640x480 | Consumer IR | | DCS-2100+ | `rtsp://IP:554/live.sdp` | 640x480 | Legacy | | DCS-2121 | `rtsp://IP:554/play1.sdp` | 640x480 | Prosumer | | DCS-2130 | `rtsp://IP:554//live1.sdp` | 1280x720 | Prosumer HD | | DCS-2132L | `rtsp://IP:554//live1.sdp` | 1280x720 | Prosumer HD | | DCS-2230 | `rtsp://IP:554//live1.sdp` | 1920x1080 | Prosumer FHD | | DCS-2310L | `rtsp://IP:554/live1.sdp` | 1280x720 | Outdoor HD | | DCS-2332L | `rtsp://IP:554//live1.sdp` | 1280x720 | Outdoor HD | | DCS-5020L | `rtsp://IP:554/play1.sdp` | 640x480 | PTZ consumer | | DCS-5222L | `rtsp://IP:554//live1.sdp` | 1280x720 | PTZ HD | | DCS-6010L | `rtsp://IP:554/live1.sdp` | 1600x1200 | Panoramic | | DCS-6113 | `rtsp://IP:554/live1.sdp` | 1920x1080 | Box camera | | DCS-6818 | `rtsp://IP:554/live3.sdp` | 1920x1080 | Enterprise | | DCS-7010L | `rtsp://IP:554/live1.sdp` | 1280x720 | Outdoor PoE | | DCS-7110 | `rtsp://IP:554/live1.sdp` | 1280x800 | Outdoor HD | | DCS-7410 | `rtsp://IP:554/live1.sdp` | 1280x720 | Outdoor enterprise | Double slash in some URLs Some D-Link models use a double slash before the path: `rtsp://IP:554//live1.sdp`. This is common on DCS-2130, DCS-2132L, DCS-2230, DCS-2332L, and DCS-5222L models. Try both single and double slash if one format doesn't work. ### Legacy Models (HTTP Only) Very old D-Link DCS cameras only support HTTP: | Model | URL | Notes | | --- | --- | --- | | DCS-900 | `http://IP/cgi-bin/video.jpg` | JPEG only | | DCS-910 | `http://IP/video.cgi` | MJPEG | | DCS-920 | `http://IP/video.cgi` | MJPEG | | DCS-2100 | `http://IP/cgi-bin/video.jpg?size=2` | JPEG only | ## Connecting with VisioForge SDK Use your D-Link camera's RTSP URL with any of the three SDK approaches shown in the [Quick Start Guide](../#quick-start-code): ``` // D-Link DCS camera, main stream var uri = new Uri("rtsp://192.168.1.45:554/live1.sdp"); var username = "admin"; var password = "YourPassword"; ``` For sub-stream access, use `/live2.sdp` instead. ## Snapshot and MJPEG URLs | Type | URL Pattern | Notes | | --- | --- | --- | | JPEG Snapshot | `http://IP/image/jpeg.cgi` | Most current DCS models | | MJPEG Stream | `http://IP/video/mjpg.cgi` | Continuous MJPEG | | MJPEG (alt) | `http://IP/video.cgi` | Older models | | MJPEG (auth) | `http://IP/mjpeg.cgi?user=USER&password=PASS&channel=1` | With authentication | | DMS Snapshot | `http://IP/dms.jpg` | DCS-2130/2132/2230/2310/2332 | | DMS Stream | `http://IP/dms?nowprofileid=2` | Profile-based | | ipcam stream | `http://IP/ipcam/stream.cgi?nowprofileid=2` | Some models | | Legacy JPEG | `http://IP/cgi-bin/video.jpg` | Very old DCS models | ## Troubleshooting ### live vs play URL format D-Link cameras use two URL naming conventions: - **Current models (DCS-2xxx+):** `live1.sdp`, `live2.sdp`, `live3.sdp` - **Consumer models (DCS-930/932/933/942):** `play1.sdp`, `play2.sdp`, `play3.sdp` If one format doesn't work, try the other. ### Default password is empty Many D-Link cameras ship with `admin` as the username and an **empty password**. You may need to set a password through the web interface or D-Link Setup Wizard before RTSP works properly. ### mydlink cloud cameras Some newer D-Link cameras are designed primarily for the mydlink cloud ecosystem and may have limited or no RTSP support. Check the camera's specifications for "RTSP" or "third-party integration" support. ### Port configuration D-Link cameras use port 554 by default for RTSP. The HTTP interface is typically on port 80. Both can be changed in the camera's web interface under Network Settings. ## FAQ **What is the default RTSP URL for D-Link cameras?** For most D-Link DCS cameras, try `rtsp://admin:password@CAMERA_IP:554/live1.sdp` or `rtsp://admin:password@CAMERA_IP:554/play1.sdp`. The `live` format is used by newer models, while `play` is used by consumer models. **Do D-Link cameras support ONVIF?** Select models support ONVIF (typically DCS-2xxx and higher-end models). Consumer cameras like the DCS-930L and DCS-932L generally do not support ONVIF. **What is the difference between live1.sdp and play1.sdp?** Both serve the same purpose (main video stream) but are used by different D-Link camera generations. `live1.sdp` is more common on newer prosumer/professional models, while `play1.sdp` is used on older consumer models. **Can I connect to D-Link cameras without the mydlink app?** Yes. D-Link cameras with RTSP support can be accessed directly via their IP address without the mydlink cloud service. The mydlink cloud is optional for remote access. ## Related Resources - [All Camera Brands — RTSP URL Directory](../) - [Foscam Connection Guide](../foscam/) — Consumer IP camera peer - [TP-Link Connection Guide](../tp-link/) — Consumer cameras with RTSP - [IP Camera Preview Tutorial](../../videocapture/video-tutorials/ip-camera-preview/) - [SDK Installation & Samples](../#get-started) ---END OF PAGE--- ## Edimax IP Camera RTSP URL and C# .NET Connection Guide **URL:** https://www.visioforge.com/help/docs/dotnet/camera-brands/edimax/ **Description:** Learn how to connect to Edimax IP cameras using C# .NET with RTSP URL patterns, authentication tips, and code samples for IC, IR, PT, and VS series models. **Tags:** Video Capture SDK, Media Blocks SDK, .NET, Windows, macOS, Linux, Android, iOS, Capture, Streaming, Encoding, IP Camera, RTSP, ONVIF, H.264, MJPEG, C# # How to Connect to Edimax IP Camera in C# .NET [Video Capture SDK .Net](https://www.visioforge.com/video-capture-sdk-net) [Media Blocks SDK .Net](https://www.visioforge.com/media-blocks-sdk-net) ## Brand Overview **Edimax** (Edimax Technology Co.) is a Taiwanese networking equipment manufacturer headquartered in Taipei, Taiwan. Founded in 1986, Edimax is known primarily for networking products such as routers, switches, and Wi-Fi adapters, but also manufactures a range of consumer and small-to-medium business IP cameras under the IC series. Over the years, Edimax cameras have evolved through several URL format generations. **Key facts:** - **Product lines:** IC (IP camera), IR (infrared), PT (pan/tilt), VS (video server) - **Multiple URL format generations:** older models use `/ipcam.sdp`, newer models use `/stream1` - **Default RTSP port:** 554 (some models use 8000) - **Default credentials:** admin / 1234 - **ONVIF support:** Yes (newer models) - **Video codecs:** H.264, MJPEG - **Primary RTSP URL:** `rtsp://IP:554/ipcam_h264.sdp` URL format generations Edimax cameras have evolved through several URL format generations. Older IC-1500/IC-3000 series use `/ipcam.sdp` or `/ipcam_h264.sdp`, while newer IR/PT series use `/stream1`. Try both formats if one doesn't work. Dual authentication styles Edimax cameras use two different authentication parameter styles in HTTP URLs: `account=USER&password=PASS` (older firmware) and `user=USER&pwd=PASS` (newer firmware). Check which format your camera supports. ## RTSP URL Patterns ### Standard URL Format Edimax cameras primarily use an SDP-based RTSP URL: ``` rtsp://[USERNAME]:[PASSWORD]@[IP]:554/ipcam_h264.sdp ``` | URL Pattern | Description | | --- | --- | | `/ipcam.sdp` | SDP-based stream (older IC series) | | `/ipcam_h264.sdp` | H.264 SDP stream (recommended for most models) | | `/stream1` | Primary stream (newer IR/PT series) | | `/stream2` | Secondary stream (newer IR/PT series) | | `/live1.sdp` | Live SDP stream (PT series) | ### Camera Models | Model | Type | Main Stream URL | Notes | | --- | --- | --- | --- | | IC-1500WG (VGA wireless) | VGA | `rtsp://IP:554/ipcam.sdp` | Older SDP format | | IC-3010 (HD) | HD | `rtsp://IP:554/ipcam.sdp` | Older SDP format | | IC-3015WN (HD wireless) | HD Wireless | `rtsp://IP:554/ipcam.sdp` | Wi-Fi, SDP format | | IC-3030WN (HD wireless) | HD Wireless | `rtsp://IP:554/ipcam.sdp` | Wi-Fi, SDP format | | IC-3030IWN (HD wireless) | HD Wireless | `rtsp://IP:554/ipcam.sdp` | Indoor Wi-Fi | | IC-3100W (HD wireless) | HD Wireless | `rtsp://IP:554/ipcam_h264.sdp` | H.264 SDP format | | IC-3110W (HD wireless) | HD Wireless | `rtsp://IP:554/ipcam_h264.sdp` | H.264 SDP format | | IC-3116W (HD wireless) | HD Wireless | `rtsp://IP:554/ipcam_h264.sdp` | H.264 SDP format | | IC-7000 (HD PTZ) | HD PTZ | `rtsp://IP:554/ipcam.sdp` | Pan/tilt/zoom | | IC-7010PTN (HD PTZ) | HD PTZ | `rtsp://IP:554/ipcam.sdp` | Network PTZ | | IC-7100 (HD PTZ) | HD PTZ | `rtsp://IP:554/ipcam_h264.sdp` | H.264 PTZ | | IC-7110P (HD PTZ PoE) | HD PTZ | `rtsp://IP:554/ipcam_h264.sdp` | PoE PTZ | | IC-7110W (HD PTZ wireless) | HD PTZ | `rtsp://IP:554/ipcam_h264.sdp` | Wi-Fi PTZ | | IC-9000 (outdoor) | Outdoor | `rtsp://IP:554/CHANNEL/USERNAME:PASSWORD/main` | Credential-in-URL | | IR-112E (infrared) | Infrared | `rtsp://IP:554//stream2` | Newer stream format | | IR-113E (infrared) | Infrared | `rtsp://IP:554//stream1` | Newer stream format | | PT-112E (pan/tilt) | Pan/Tilt | `rtsp://IP:554/live1.sdp` | Live SDP format | | PT-31E (pan/tilt) | Pan/Tilt | `rtsp://IP:8000//stream1` | Port 8000 | | VS100 (video server) | Video Server | `rtsp://IP:554//stream1` | Encoder/server | ### Alternative URL Formats Some Edimax models and firmware versions support these additional RTSP URLs: | URL Pattern | Supported Models | Notes | | --- | --- | --- | | `rtsp://IP:554/ipcam.sdp` | IC-1500, IC-3010, IC-3015WN, IC-3030WN, IC-7000, IC-7010PTN | Older SDP format | | `rtsp://IP:554/ipcam_h264.sdp` | IC-3100W, IC-3110W, IC-3116W, IC-7100, IC-7110P, IC-7110W | H.264 SDP (recommended) | | `rtsp://IP:554//stream1` | IR-113E, VS100 | Newer stream format (note double slash) | | `rtsp://IP:554//stream2` | IR-112E | Sub stream (double slash) | | `rtsp://IP:554/stream1` | Select newer models | Stream without double slash | | `rtsp://IP:554/live1.sdp` | PT-112E | Live SDP for pan/tilt | | `rtsp://IP:8000//stream1` | PT-31E | Non-standard port 8000 | ## Connecting with VisioForge SDK Use your Edimax camera's RTSP URL with any of the three SDK approaches shown in the [Quick Start Guide](../#quick-start-code): ``` // Edimax IC-3116W, H.264 main stream var uri = new Uri("rtsp://192.168.1.90:554/ipcam_h264.sdp"); var username = "admin"; var password = "1234"; ``` For newer IR/PT series models, use `/stream1` or `//stream1` instead of `/ipcam_h264.sdp`. ## Snapshot and MJPEG URLs | Type | URL Pattern | Notes | | --- | --- | --- | | JPEG Snapshot | `http://IP/snapshot.jpg` | Basic snapshot, may require auth | | Snapshot (account auth) | `http://IP/snapshot.jpg?account=USER&password=PASS` | Older firmware auth style | | Snapshot (user auth) | `http://IP/snapshot.jpg?user=USER&pwd=PASS` | Newer firmware auth style | | JPEG Image | `http://IP/jpg/image.jpg` | Direct JPEG | | Channel JPEG | `http://IP/jpg/1/image.jpg` | Channel-specific JPEG | | MJPEG Stream | `http://IP/mjpg/video.mjpg` | Continuous MJPEG stream | | Channel MJPEG | `http://IP/mjpg/1/video.mjpg` | Channel-specific MJPEG | | CGI Snapshot | `http://IP/snapshot.cgi` | CGI-based snapshot | | CGI MJPEG | `http://IP/cgi/mjpg/mjpeg.cgi` | CGI MJPEG stream | | Stream CGI | `http://IP/cgi-bin/Stream?Video` | Alternative video stream | ## Troubleshooting ### "401 Unauthorized" error Edimax cameras ship with default credentials of **admin / 1234**. If authentication fails: 1. Access the camera at `http://CAMERA_IP` in a browser 2. Log in with the default credentials or the ones you configured 3. Navigate to **Configuration > Security** to verify or reset credentials 4. Use those credentials in your RTSP URL ### URL format not working Edimax has used several different RTSP URL formats across model generations. If your URL does not connect: 1. Try `/ipcam_h264.sdp` first (works with most mid-generation models) 2. Try `/ipcam.sdp` for older IC-1500 and IC-3000 series 3. Try `//stream1` (with double slash) for newer IR and PT series 4. Try `/stream1` (single slash) if double slash fails 5. Check if your model uses port 8000 instead of 554 (e.g., PT-31E) ### Double-slash URLs Some newer Edimax models use a double-slash in the RTSP path (e.g., `rtsp://IP:554//stream1`). This is intentional and not a typo. If `/stream1` does not work, try `//stream1`. ### Port 554 vs port 8000 Most Edimax cameras use the standard RTSP port 554, but some models (such as the PT-31E) use port 8000. Check your camera's web interface under **Configuration > Network > RTSP** for the correct port setting. ### Snapshot authentication style If snapshot URLs return 401 errors even with correct credentials, try switching between the two authentication parameter styles: - Older firmware: `?account=USER&password=PASS` - Newer firmware: `?user=USER&pwd=PASS` ## FAQ **What is the default RTSP URL for Edimax cameras?** For most Edimax IC series cameras, the URL is `rtsp://admin:1234@CAMERA_IP:554/ipcam_h264.sdp`. For newer IR and PT series, use `rtsp://admin:1234@CAMERA_IP:554//stream1`. The exact format depends on the model and firmware version. **Do Edimax cameras support ONVIF?** Newer Edimax models support ONVIF. Older IC-1500 and IC-3000 series models may not have ONVIF support. Check your camera's specifications or web interface for ONVIF settings. **Why does my Edimax camera use a double slash in the URL?** Some newer Edimax models (IR and PT series) use a double-slash path format like `//stream1`. This is the correct format for those models and is not a typo. Both `//stream1` and `/stream1` may work depending on the firmware version. **What is the difference between ipcam.sdp and ipcam\_h264.sdp?** `/ipcam.sdp` is the generic SDP stream used by older models and may deliver either MJPEG or H.264 depending on the camera configuration. `/ipcam_h264.sdp` explicitly requests the H.264 encoded stream and is recommended for better compression and quality. **Can I use both snapshot authentication styles?** No. Each camera firmware version supports only one authentication style for HTTP URLs. Older firmware uses `account=USER&password=PASS` while newer firmware uses `user=USER&pwd=PASS`. Try both to determine which your camera expects. ## Related Resources - [All Camera Brands — RTSP URL Directory](../) - [Zavio Connection Guide](../zavio/) — Taiwanese SMB cameras - [RTSP Video Streaming Guide](../../general/network-streaming/rtsp/) — Edimax RTSP network streaming - [IP Camera Preview Tutorial](../../videocapture/video-tutorials/ip-camera-preview/) - [SDK Installation & Samples](../#get-started) ---END OF PAGE--- ## Eufy Security Camera RTSP Connection Guide for C# .NET **URL:** https://www.visioforge.com/help/docs/dotnet/camera-brands/eufy/ **Description:** Eufy camera RTSP integration for C# .NET developers. Which eufyCam, SoloCam, and Indoor Cam models support RTSP/ONVIF, plus VisioForge SDK code samples. **Tags:** Video Capture SDK, Media Blocks SDK, .NET, Windows, macOS, Linux, Android, iOS, Capture, Streaming, IP Camera, RTSP, ONVIF, C# # How to Connect to Eufy Security Camera in C# .NET [Video Capture SDK .Net](https://www.visioforge.com/video-capture-sdk-net) [Media Blocks SDK .Net](https://www.visioforge.com/media-blocks-sdk-net) ## Brand Overview **Eufy Security** is a smart home security brand owned by **Anker Innovations**, headquartered in Changsha, China. Eufy is known for local storage (no mandatory cloud subscription), AI-powered detection, and a wide range of indoor, outdoor, battery, and doorbell cameras. RTSP and ONVIF support varies significantly by model and firmware version. **Key facts:** - **Product lines:** eufyCam (battery), SoloCam (standalone), Indoor Cam, Floodlight Cam, Video Doorbell, HomeBase - **Protocol support:** RTSP (select models, must be enabled), ONVIF (newer firmware), Eufy Security app - **Default RTSP port:** 554 - **Default credentials:** No standard defaults — set during RTSP enablement - **ONVIF support:** Added in recent firmware updates for many models - **Video codecs:** H.264, H.265 (select models) - **Local storage:** Yes — HomeBase or camera microSD (no cloud required for recording) RTSP/ONVIF Support Varies by Model Eufy has been gradually adding RTSP and ONVIF support across its product line through firmware updates. Not all models support these features. Check the Eufy Security app settings for your specific camera to see if RTSP is available. ## RTSP Support by Model | Model | RTSP | ONVIF | Notes | | --- | --- | --- | --- | | eufyCam 2 / 2 Pro | Yes (via HomeBase) | Yes | Requires HomeBase 2 | | eufyCam 2C / 2C Pro | Yes (via HomeBase) | Yes | Requires HomeBase 2 | | eufyCam 3 / 3C | Yes (via HomeBase 3) | Yes | Requires HomeBase 3 | | eufyCam S330 | Yes (via HomeBase 3) | Yes | 4K model | | SoloCam S340 | Yes | Yes | Dual-lens, standalone RTSP | | SoloCam C210 | Yes | Yes | Standalone with RTSP | | Indoor Cam 2K | Yes | Yes | WiFi, firmware-dependent | | Indoor Cam Pan & Tilt | Yes | Yes | WiFi, firmware-dependent | | Floodlight Cam 2 Pro | Yes | Yes | Wired | | Video Doorbell 2K | Limited | No | Via HomeBase only | | Video Doorbell Dual | Limited | No | Via HomeBase only | ## Enabling RTSP ### For HomeBase-Connected Cameras (eufyCam series) 1. Open the **Eufy Security** app 2. Go to **HomeBase Settings > Storage > NAS** or **RTSP** 3. Enable RTSP streaming 4. Set an RTSP username and password 5. Note the RTSP URL displayed for each camera ### For Standalone Cameras (SoloCam, Indoor Cam, Floodlight) 1. Open the **Eufy Security** app 2. Select your camera → **Settings** (gear icon) 3. Look for **RTSP** or **Advanced > RTSP Stream** 4. Enable RTSP and set credentials 5. Note the RTSP URL provided ## RTSP URL Patterns ### Standard URL Format ``` rtsp://[USERNAME]:[PASSWORD]@[IP]:554/live0 ``` | Stream | URL Pattern | Description | | --- | --- | --- | | Main stream | `rtsp://IP:554/live0` | Full resolution | | Sub stream | `rtsp://IP:554/live1` | Lower resolution | ### HomeBase RTSP URLs When connected through a HomeBase, the RTSP URL points to the HomeBase IP: ``` rtsp://[USERNAME]:[PASSWORD]@[HOMEBASE_IP]:554/live0 ``` For multiple cameras on one HomeBase, each camera gets a unique stream path shown in the app. ### Alternative URL Formats | URL Pattern | Notes | | --- | --- | | `rtsp://IP:554/live0` | Main stream (common) | | `rtsp://IP:554/live1` | Sub stream | | `rtsp://IP:554/stream1` | Alternative format (some models) | | `rtsp://IP:554/h264_stream` | H.264 explicit (some firmware) | ## Connecting with VisioForge SDK Use your Eufy camera's RTSP URL with any of the three SDK approaches shown in the [Quick Start Guide](../#quick-start-code): ``` // Eufy SoloCam S340, main stream var uri = new Uri("rtsp://192.168.1.90:554/live0"); var username = "rtsp_user"; // set in Eufy Security app var password = "rtsp_pass"; ``` For sub-stream access, use `/live1` instead of `/live0`. ## Troubleshooting ### RTSP option not visible in app RTSP support requires specific firmware versions. Update your camera and HomeBase firmware through the Eufy Security app. If RTSP still does not appear, your model may not yet support it. ### HomeBase vs standalone RTSP - **HomeBase cameras** (eufyCam series): RTSP streams come from the **HomeBase IP**, not the camera IP. The HomeBase acts as a proxy. - **Standalone cameras** (SoloCam, Indoor Cam): RTSP streams come directly from the **camera IP**. ### Stream drops on battery cameras Battery-powered eufyCam models may stop RTSP streaming when in standby mode. The camera must be actively recording or in "always streaming" mode for continuous RTSP access. This significantly impacts battery life. ### ONVIF discovery Newer Eufy firmware supports ONVIF discovery. Use ONVIF to automatically find cameras on your network instead of manually configuring RTSP URLs. ### Firmware inconsistencies Eufy has been rolling out RTSP/ONVIF support gradually. Different cameras in your setup may have different capabilities depending on their firmware version. Always update all devices to the latest firmware. ## FAQ **Do Eufy cameras support RTSP?** Many Eufy cameras now support RTSP, but it must be enabled in the Eufy Security app and varies by model. HomeBase-connected cameras stream RTSP through the HomeBase, while standalone cameras stream directly. Check your specific model's capabilities in the app settings. **Do Eufy cameras require a cloud subscription for RTSP?** No. RTSP streaming works locally without any cloud subscription. Eufy cameras store footage on the HomeBase or camera microSD card. The cloud subscription (Eufy Security Plan) is optional and provides additional cloud storage and features. **Can I use Eufy cameras without the Eufy app?** Initial setup requires the Eufy Security app. After setup and RTSP enablement, you can access the RTSP stream without the app. However, firmware updates and configuration changes still require the app. **What is the difference between HomeBase RTSP and standalone RTSP?** HomeBase RTSP streams all connected cameras through the HomeBase's IP address. The HomeBase acts as a gateway. Standalone cameras (SoloCam, Indoor Cam, Floodlight) stream directly from their own IP. HomeBase RTSP may have slightly higher latency. ## Related Resources - [All Camera Brands — RTSP URL Directory](../) - [Arlo Connection Guide](../arlo/) — Consumer alternative (no RTSP) - [Reolink Connection Guide](../reolink/) — Consumer with native RTSP - [EZVIZ Connection Guide](../ezviz/) — Smart home cameras with RTSP - [IP Camera Preview Tutorial](../../videocapture/video-tutorials/ip-camera-preview/) - [SDK Installation & Samples](../#get-started) ---END OF PAGE--- ## EverFocus IP Camera RTSP URL Connection Guide for C# .NET **URL:** https://www.visioforge.com/help/docs/dotnet/camera-brands/everfocus/ **Description:** EverFocus EAN, EHN, EMN, EPN, and EQN series RTSP URL patterns for C# .NET. Stream and record using VisioForge Video Capture SDK integration. **Tags:** Video Capture SDK, Media Blocks SDK, .NET, Windows, macOS, Linux, Android, iOS, Capture, Streaming, IP Camera, RTSP, ONVIF, MJPEG, C# # How to Connect to EverFocus IP Camera in C# .NET [Video Capture SDK .Net](https://www.visioforge.com/video-capture-sdk-net) [Media Blocks SDK .Net](https://www.visioforge.com/media-blocks-sdk-net) ## Brand Overview **EverFocus Electronics** is a Taiwanese professional surveillance company headquartered in New Taipei City, Taiwan, with US operations based in Duarte, California. Founded in 1995, EverFocus manufactures IP cameras, DVRs, and mobile surveillance solutions designed for professional security integrators. The company is well-known in the commercial and industrial surveillance market. **Key facts:** - **Product lines:** EAN (bullet), EHN (dome), EMN (mini dome), EPN (PTZ), EZN (compact), EQN (turret), ECOR/EPARA (DVRs) - **Protocol support:** RTSP, ONVIF, HTTP/CGI - **Default RTSP port:** 554 - **Default credentials:** admin / admin - **ONVIF support:** Yes (all current IP cameras) - **Video codecs:** H.264 (all current models) EverFocus RTSP URL Format EverFocus cameras use a unique `rtspStreamOvf` path in their RTSP URLs. This format is specific to EverFocus and should not be confused with other manufacturers' URL patterns. Note the required double-slash (`//`) before `cgi-bin`. ## RTSP URL Patterns ### Standard URL Format EverFocus cameras use the `rtspStreamOvf` CGI path for RTSP streaming: ``` rtsp://[USERNAME]:[PASSWORD]@[IP]:554//cgi-bin/rtspStreamOvf/0 ``` | Parameter | Value | Description | | --- | --- | --- | | Stream index | `/0` | Main stream (highest resolution) | | Stream index | `/1` | Sub stream (lower resolution, less bandwidth) | Double-Slash Required The URL path must include a double-slash before `cgi-bin` (i.e., `//cgi-bin/rtspStreamOvf/...`). Omitting the leading slash will cause the connection to fail. ### Primary URL Format (rtspStreamOvf) Most EverFocus IP cameras use the `rtspStreamOvf` format: | Model | Series | Main Stream URL | Sub Stream URL | | --- | --- | --- | --- | | EAN3220 | EAN (bullet) | `rtsp://IP:554//cgi-bin/rtspStreamOvf/0` | `rtsp://IP:554//cgi-bin/rtspStreamOvf/1` | | EHN3260 | EHN (dome) | `rtsp://IP:554//cgi-bin/rtspStreamOvf/0` | `rtsp://IP:554//cgi-bin/rtspStreamOvf/1` | | EMN2220 | EMN (mini dome) | `rtsp://IP:554//cgi-bin/rtspStreamOvf/0` | `rtsp://IP:554//cgi-bin/rtspStreamOvf/1` | | EMN1360 | EMN (mini dome) | `rtsp://IP:554//cgi-bin/rtspStreamOvf/0` | `rtsp://IP:554//cgi-bin/rtspStreamOvf/1` | | EMN3260 | EMN (mini dome) | `rtsp://IP:554//cgi-bin/rtspStreamOvf/0` | `rtsp://IP:554//cgi-bin/rtspStreamOvf/1` | | EPN4220 | EPN (PTZ) | `rtsp://IP:554//cgi-bin/rtspStreamOvf/0` | `rtsp://IP:554//cgi-bin/rtspStreamOvf/1` | | EZN3160 | EZN (compact) | `rtsp://IP:554//cgi-bin/rtspStreamOvf/0` | `rtsp://IP:554//cgi-bin/rtspStreamOvf/1` | ### Alternative URL Format (streaming/channels) Some newer EverFocus models also support the `streaming/channels` format: | Model | Series | Main Stream URL | | --- | --- | --- | | EPN4220 | EPN (PTZ) | `rtsp://IP:554/streaming/channels/0` | | EZN3240 | EZN (compact) | `rtsp://IP:554/streaming/channels/0` | | EHN3260 | EHN (dome) | `rtsp://IP:554/streaming/channels/0` | Which Format to Use Try the `rtspStreamOvf` format first, as it is supported across all EverFocus IP camera product lines. The `streaming/channels` format is an alternative available on select newer models. ## Connecting with VisioForge SDK Use your EverFocus camera's RTSP URL with any of the three SDK approaches shown in the [Quick Start Guide](../#quick-start-code): ``` // EverFocus EHN3260, main stream var uri = new Uri("rtsp://192.168.1.90:554//cgi-bin/rtspStreamOvf/0"); var username = "admin"; var password = "admin"; ``` For sub-stream access, use `/1` instead of `/0` at the end of the URL. ## Snapshot and MJPEG URLs | Type | URL Pattern | Supported Models | | --- | --- | --- | | Snapshot (with auth) | `http://IP/snapshot.jpg?user=USER&pwd=PASS&strm=CHANNEL` | EQN2101 | | Snapshot (simple) | `http://IP/snapshot.jpg?user=USER&pwd=PASS` | General IP cameras | | Mobile snapshot | `http://IP/m/camera[CHANNEL].jpg` | ECOR/EPARA DVRs | DVR Snapshots For ECOR and EPARA DVR models, replace `[CHANNEL]` with the camera channel number (e.g., `camera1.jpg` for channel 1). ## Troubleshooting ### Connection refused or timeout EverFocus cameras use the `rtspStreamOvf` CGI path which is unique to this brand. Make sure you are not accidentally using a URL format from another manufacturer: 1. Verify the URL includes the double-slash: `//cgi-bin/rtspStreamOvf/0` 2. Confirm the RTSP port is 554 (or check the camera's network settings for a custom port) 3. Ensure the camera is accessible on the network by pinging its IP address ### Stream index starts at 0 Unlike some other camera brands where channels start at 1, EverFocus stream indices start at **0**: - `/0` = Main stream (full resolution) - `/1` = Sub stream (reduced resolution) Using `/1` expecting the main stream will return the sub stream instead. ### Alternative URL format not working The `streaming/channels/0` URL format is only available on certain newer models (EPN4220, EZN3240, EHN3260). If this format does not work, fall back to the standard `//cgi-bin/rtspStreamOvf/0` format. ### Authentication issues EverFocus cameras default to `admin` / `admin`. If you have changed the password via the web interface and forgotten it, a hardware reset button on the camera will restore factory defaults. ## FAQ **What is the default RTSP URL for EverFocus cameras?** The default URL is `rtsp://admin:admin@CAMERA_IP:554//cgi-bin/rtspStreamOvf/0` for the main stream. Use `/1` at the end for the sub stream. Note the double-slash before `cgi-bin` which is required. **Why does the EverFocus RTSP URL look different from other cameras?** EverFocus uses a proprietary `rtspStreamOvf` CGI path that is unique to their camera firmware. This is different from the more common formats used by Hikvision, Dahua, or ONVIF generic paths. The double-slash (`//cgi-bin/...`) is intentional and required. **Do EverFocus cameras support ONVIF?** Yes. All current EverFocus IP cameras support ONVIF, which provides a standardized way to discover and connect to the camera. You can use ONVIF as an alternative to the proprietary RTSP URL format. **Can I connect to EverFocus DVRs (ECOR/EPARA) via RTSP?** EverFocus DVRs primarily expose HTTP-based snapshot URLs for individual channels (`http://IP/m/camera[CHANNEL].jpg`). For RTSP streaming from DVR channels, consult your specific DVR model's documentation or use ONVIF discovery. ## Related Resources - [All Camera Brands — RTSP URL Directory](../) - [Speco Connection Guide](../speco/) — Professional surveillance cameras - [RTSP Video Streaming Guide](../../general/network-streaming/rtsp/) — EverFocus RTSP streaming setup - [IP Camera Preview Tutorial](../../videocapture/video-tutorials/ip-camera-preview/) - [SDK Installation & Samples](../#get-started) ---END OF PAGE--- ## EZVIZ IP Camera RTSP URL and Connection Guide for C# .NET **URL:** https://www.visioforge.com/help/docs/dotnet/camera-brands/ezviz/ **Description:** Connect to EZVIZ cameras in C# .NET with RTSP URL patterns for C1C, C3W, C6N, BC1C and other models. Enable RTSP on cloud-first cameras. **Tags:** Video Capture SDK, Media Blocks SDK, .NET, Windows, macOS, Linux, Android, iOS, Capture, Streaming, IP Camera, RTSP, ONVIF, C# # How to Connect to EZVIZ IP Camera in C# .NET [Video Capture SDK .Net](https://www.visioforge.com/video-capture-sdk-net) [Media Blocks SDK .Net](https://www.visioforge.com/media-blocks-sdk-net) ## Brand Overview **EZVIZ** is a consumer smart home and security camera brand owned by **Hikvision**. Originally launched as Hikvision's consumer division, EZVIZ became an independent brand focused on home cameras, doorbells, smart locks, and IoT devices. EZVIZ cameras are designed primarily for cloud-based use via the EZVIZ app, but many models support local RTSP streaming when enabled. **Key facts:** - **Product lines:** C-series (indoor/outdoor), BC-series (battery), DB-series (doorbells), H-series (pan/tilt) - **Protocol support:** RTSP (must be enabled), ONVIF (limited models), EZVIZ Cloud (default) - **Default RTSP port:** 554 - **Default credentials:** admin / verification code (printed on camera label) - **ONVIF support:** Limited (some newer models only) - **Video codecs:** H.264, H.265 (select models) - **Parent company:** Hikvision RTSP Must Be Enabled Manually EZVIZ cameras are cloud-first devices. **RTSP is disabled by default** on most models. You must enable RTSP through the EZVIZ mobile app or web portal before connecting with the VisioForge SDK. Some budget and battery-powered models do not support RTSP at all. ## Enabling RTSP on EZVIZ Cameras Before connecting, enable RTSP access: 1. Open the **EZVIZ app** on your phone 2. Select your camera → **Settings** (gear icon) 3. Navigate to **Local Network** or **LAN access** 4. Enable **RTSP** or **Third-party access** 5. Note the verification code (usually printed on the camera label or shown in app) Alternatively, use the EZVIZ web portal at `https://www.ezvizlife.com` to manage camera settings. ## RTSP URL Patterns ### Standard URL Format EZVIZ cameras use Hikvision-derived RTSP URL patterns: ``` rtsp://admin:[VERIFICATION_CODE]@[IP]:554/h264/ch1/main/av_stream ``` | Stream | URL Pattern | Description | | --- | --- | --- | | Main stream | `rtsp://IP:554/h264/ch1/main/av_stream` | Full resolution | | Sub stream | `rtsp://IP:554/h264/ch1/sub/av_stream` | Lower resolution | Verification Code as Password EZVIZ cameras use the **verification code** (printed on the camera label) as the RTSP password. The username is always `admin`. This is different from the EZVIZ cloud account password. ### Alternative URL Formats Some EZVIZ models support additional URL patterns: | URL Pattern | Notes | | --- | --- | | `rtsp://IP:554/h264/ch1/main/av_stream` | Standard (recommended) | | `rtsp://IP:554/h264/ch1/sub/av_stream` | Sub stream | | `rtsp://IP:554/Streaming/Channels/101` | Hikvision-style (some models) | | `rtsp://IP:554/Streaming/Channels/102` | Hikvision-style sub stream | | `rtsp://IP:554/live` | Simple path (older models) | ### Camera Models | Model | Type | RTSP Support | Main Stream URL | | --- | --- | --- | --- | | C6N (indoor pan/tilt) | Indoor | Yes | `rtsp://IP:554/h264/ch1/main/av_stream` | | C6W (4MP indoor PT) | Indoor | Yes | `rtsp://IP:554/h264/ch1/main/av_stream` | | C1C (1080p indoor) | Indoor | Yes | `rtsp://IP:554/h264/ch1/main/av_stream` | | H6c (pan/tilt) | Indoor | Yes | `rtsp://IP:554/h264/ch1/main/av_stream` | | H8c (outdoor PT) | Outdoor | Yes | `rtsp://IP:554/h264/ch1/main/av_stream` | | C3W (outdoor bullet) | Outdoor | Yes | `rtsp://IP:554/h264/ch1/main/av_stream` | | C3WN (outdoor bullet) | Outdoor | Yes | `rtsp://IP:554/h264/ch1/main/av_stream` | | C3X (dual-lens outdoor) | Outdoor | Yes | `rtsp://IP:554/h264/ch1/main/av_stream` | | BC1C (battery cam) | Battery | No | N/A — cloud-only | | DB1C (doorbell) | Doorbell | No | N/A — cloud-only | Battery and Doorbell Models EZVIZ battery-powered cameras (BC series) and video doorbells (DB series) generally do **not** support RTSP. These devices only stream through the EZVIZ cloud. Only AC-powered cameras with wired network or stable WiFi connections support RTSP. ## Connecting with VisioForge SDK Use your EZVIZ camera's RTSP URL with any of the three SDK approaches shown in the [Quick Start Guide](../#quick-start-code): ``` // EZVIZ C6N, main stream (verification code from label) var uri = new Uri("rtsp://192.168.1.90:554/h264/ch1/main/av_stream"); var username = "admin"; var password = "ABCDEF"; // verification code from camera label ``` For sub-stream access, use `/h264/ch1/sub/av_stream` instead. ## Snapshot URLs | Type | URL Pattern | Notes | | --- | --- | --- | | JPEG Snapshot | `http://IP/cgi-bin/snapshot.cgi` | Requires basic auth with verification code | ## Troubleshooting ### "Connection refused" or no response RTSP is disabled by default on EZVIZ cameras. You must enable it through the EZVIZ app first. Check **Settings > Local Network > Third-party access**. ### Wrong password EZVIZ cameras use the **verification code** (6 uppercase letters printed on the camera label) as the RTSP password, **not** your EZVIZ cloud account password. The username is always `admin`. ### Camera not on local network EZVIZ cameras connect to the cloud via WiFi. To use RTSP, the camera and your application must be on the same local network. The camera's local IP can be found in the EZVIZ app under **Device Info** or in your router's DHCP client list. ### RTSP option not available in app Some EZVIZ models and firmware versions do not expose RTSP settings. In this case: 1. Update the camera firmware through the EZVIZ app 2. If RTSP still does not appear, the model may not support local streaming 3. Battery-powered and doorbell models typically do not support RTSP ### Hikvision URL format works on some models Since EZVIZ cameras use Hikvision firmware, some models also accept the Hikvision URL format (`/Streaming/Channels/101`). Try this if the standard EZVIZ URL does not work. ## FAQ **What is the default RTSP URL for EZVIZ cameras?** The standard URL is `rtsp://admin:VERIFICATION_CODE@CAMERA_IP:554/h264/ch1/main/av_stream`. The VERIFICATION\_CODE is the 6-character code printed on your camera's label. RTSP must be enabled in the EZVIZ app first. **Is EZVIZ related to Hikvision?** Yes. EZVIZ is a brand owned by Hikvision, focused on the consumer smart home market. EZVIZ cameras use Hikvision-derived firmware, which is why similar RTSP URL patterns work. However, EZVIZ cameras are designed primarily for cloud-based use. **Can I use EZVIZ cameras without the cloud?** Partially. You can access RTSP streams locally without the EZVIZ cloud for live viewing and recording. However, initial camera setup, firmware updates, and enabling RTSP require the EZVIZ app (which uses the cloud). Features like motion alerts and clip storage require an EZVIZ cloud subscription. **Do EZVIZ cameras support ONVIF?** Some newer EZVIZ models support ONVIF, but it is not available on all cameras. Check your camera's specifications or the EZVIZ app settings for ONVIF support. For most EZVIZ cameras, direct RTSP connection is more reliable than ONVIF. ## Related Resources - [All Camera Brands — RTSP URL Directory](../) - [Hikvision Connection Guide](../hikvision/) — Parent company, similar URL format - [Imou Connection Guide](../imou/) — Dahua consumer brand, similar market - [IP Camera Preview Tutorial](../../videocapture/video-tutorials/ip-camera-preview/) - [SDK Installation & Samples](../#get-started) ---END OF PAGE--- ## FLIR IP Camera RTSP Connection Guide in C# .NET SDK **URL:** https://www.visioforge.com/help/docs/dotnet/camera-brands/flir/ **Description:** FLIR Quasar, Saros, and Elara thermal camera RTSP URL patterns for C# .NET. Teledyne FLIR integration with VisioForge Video Capture SDK code. **Tags:** Video Capture SDK, Media Blocks SDK, .NET, Windows, macOS, Linux, Android, iOS, Capture, Streaming, IP Camera, USB3 Vision / GigE, RTSP, ONVIF, H.265, MJPEG, C# # How to Connect to FLIR IP Camera in C# .NET [Video Capture SDK .Net](https://www.visioforge.com/video-capture-sdk-net) [Media Blocks SDK .Net](https://www.visioforge.com/media-blocks-sdk-net) ## Brand Overview **FLIR Systems** (now **Teledyne FLIR** following the 2021 acquisition by Teledyne Technologies) is a leading manufacturer of thermal imaging cameras and visible-light security cameras. Headquartered in Wilsonville, Oregon, USA, FLIR serves enterprise, critical infrastructure, and government markets. FLIR is best known for thermal imaging but also produces a full range of visible-light IP cameras for professional surveillance. FLIR previously acquired **Lorex** and **DVTEL** (now FLIR Latitude VMS). **Key facts:** - **Product lines:** Quasar (premium multi-sensor/mini-dome), Saros (perimeter detection), Elara (thermal+visible dual-sensor), CM (compact mini dome), CF (compact fixed), PT/PTZ (pan-tilt-zoom), FC (thermal-only), FLIR FX (consumer, discontinued) - **Protocol support:** RTSP, ONVIF (Quasar, Saros, Elara series), HTTP/CGI - **Default RTSP port:** 554 - **Default credentials:** admin / admin (most models), admin / fliradmin (some Quasar models) - **ONVIF support:** Yes (Quasar, Saros, Elara series) - **Video codecs:** H.264, H.265 (Quasar series), MJPEG - **Thermal specialization:** FLIR thermal cameras output radiometric data in addition to visible-light video, with separate RTSP streams for each sensor Thermal cameras have separate streams FLIR dual-sensor cameras (Elara, PT-series) provide separate RTSP streams for visible and thermal channels. Typically `ch0` is the visible channel and `ch1` is the thermal channel. ## RTSP URL Patterns ### Current Models (Quasar, Saros, Elara) | Stream | RTSP URL | Notes | | --- | --- | --- | | Visible channel | `rtsp://IP:554/ch0` | Primary visible stream | | Thermal channel | `rtsp://IP:554/ch1` | Thermal stream (dual-sensor models) | | Visible (alt) | `rtsp://IP:554/vis` | Visible on PT-series | | Wide FOV thermal | `rtsp://IP:554/wfov` | PT-series, wide field of view | | Auth stream | `rtsp://IP:554/0/USERNAME:PASSWORD/main` | With embedded credentials | ### Model-Specific URLs | Model Series | RTSP URL | Type | Notes | | --- | --- | --- | --- | | Quasar CM-3308 | `rtsp://IP:554/ch0` | Mini dome | Compact multi-sensor | | Quasar CM-6208 | `rtsp://IP:554/ch0` | Mini dome | Compact multi-sensor | | D-series (fixed dome) | `rtsp://IP:554/ch0` | Fixed dome | Visible stream | | F-series (fixed) | `rtsp://IP:554/ch0` | Fixed | Visible stream | | PT-series (PTZ-35x140) | `rtsp://IP:554/vis` | PTZ | Visible channel | | PT-series (PTZ-35x140) | `rtsp://IP:554/wfov` | PTZ | Wide FOV thermal | | Elara (visible) | `rtsp://IP:554/ch0` | Thermal+visible | Visible channel | | Elara (thermal) | `rtsp://IP:554/ch1` | Thermal+visible | Thermal channel | | FC-series (thermal) | `rtsp://IP:554/ch0` | Thermal only | Thermal stream | ### Dual-Sensor Thermal Cameras FLIR dual-sensor cameras provide both visible and thermal video on separate channels: | Stream | RTSP URL | Notes | | --- | --- | --- | | Elara visible | `rtsp://IP:554/ch0` | Visible-light sensor | | Elara thermal | `rtsp://IP:554/ch1` | Thermal sensor | | PT visible | `rtsp://IP:554/vis` | Visible-light sensor | | PT wide thermal | `rtsp://IP:554/wfov` | Wide FOV thermal sensor | ## Connecting with VisioForge SDK Use your FLIR camera's RTSP URL with any of the three SDK approaches shown in the [Quick Start Guide](../#quick-start-code): ``` // FLIR Quasar mini-dome, visible stream var uri = new Uri("rtsp://192.168.1.70:554/ch0"); var username = "admin"; var password = "admin"; ``` For dual-sensor cameras, use `ch1` to access the thermal stream. For PT-series cameras, use `/vis` for the visible channel or `/wfov` for the wide FOV thermal channel. ## Snapshot and MJPEG URLs | Type | URL Pattern | Notes | | --- | --- | --- | | JPEG Snapshot | `http://IP/jpg/image.jpg` | Some models | | Snapshot (alt) | `http://IP/snapshot.jpg` | Alternative path | ## Troubleshooting ### Thermal vs. visible channels FLIR dual-sensor cameras (Elara, PT-series) expose separate RTSP streams for each sensor: - `ch0` = visible-light channel (most models) - `ch1` = thermal channel (most models) - `/vis` = visible channel (PT-series) - `/wfov` = wide FOV thermal (PT-series) If you connect to the wrong channel, you may receive thermal imagery when you expected visible or vice versa. Check your camera's documentation for channel assignments. ### Default credentials differ by model - **Most FLIR cameras:** admin / admin - **Some Quasar models:** admin / fliradmin - **Current Teledyne FLIR firmware:** Password may need to be set during initial configuration Always change default credentials before deploying cameras on a production network. ### Teledyne FLIR rebranding Teledyne Technologies acquired FLIR Systems in 2021. Current firmware versions may display Teledyne FLIR branding, and newer cameras may ship with updated web interfaces and configuration tools. RTSP URL patterns remain consistent with legacy FLIR cameras. ### FLIR FX consumer cameras The discontinued FLIR FX consumer camera line used cloud-only access and does not support RTSP streaming. These cameras cannot be connected via direct RTSP URLs. ### FLIR Lorex cameras FLIR acquired Lorex, but Lorex cameras use their own RTSP URL patterns (based on Dahua firmware). Do not use FLIR URL patterns for Lorex cameras. See the [Lorex](../lorex/) page for Lorex-specific URLs. ### ONVIF availability ONVIF is supported on current-generation cameras (Quasar, Saros, Elara). Older FLIR cameras and consumer models (FLIR FX) do not support ONVIF. For ONVIF-supported models, use ONVIF discovery as an alternative to manual RTSP URL configuration. ## FAQ **What is the default RTSP URL for FLIR cameras?** For most FLIR cameras, use `rtsp://admin:admin@CAMERA_IP:554/ch0` for the visible stream. For dual-sensor thermal cameras, use `ch1` for the thermal stream. For PT-series cameras, use `/vis` (visible) or `/wfov` (wide FOV thermal). **Does FLIR support H.265?** Quasar-series cameras support H.265 encoding. Other FLIR camera lines primarily use H.264 and MJPEG. Check your specific model's datasheet for codec support. **How do I access the thermal stream on a FLIR dual-sensor camera?** Dual-sensor cameras provide separate RTSP streams for visible and thermal channels. On Elara models, `ch0` is visible and `ch1` is thermal. On PT-series models, `/vis` is visible and `/wfov` is the wide FOV thermal stream. Connect to the appropriate URL for the desired sensor. **Are FLIR and Teledyne FLIR the same company?** Yes. Teledyne Technologies acquired FLIR Systems in 2021. The company now operates as Teledyne FLIR. Existing FLIR cameras continue to work with the same RTSP URL patterns. Newer products may carry Teledyne FLIR branding. **Can I use FLIR URL patterns for Lorex cameras?** No. Although FLIR acquired Lorex, Lorex cameras use Dahua-based firmware with different RTSP URL patterns. See the [Lorex](../lorex/) camera connection guide for the correct URLs. ## Related Resources - [All Camera Brands — RTSP URL Directory](../) - [Basler Connection Guide](../basler/) — Industrial / machine vision cameras - [Mobotix Connection Guide](../mobotix/) — German industrial cameras - [IP Camera Preview Tutorial](../../videocapture/video-tutorials/ip-camera-preview/) - [SDK Installation & Samples](../#get-started) ---END OF PAGE--- ## Foscam IP Camera RTSP URL Guide and C# .NET Integration **URL:** https://www.visioforge.com/help/docs/dotnet/camera-brands/foscam/ **Description:** Connect to Foscam cameras in C# .NET with RTSP and HTTP URL patterns, CGI API access, and code samples for FI, C1, C2, R2, and R4 models. **Tags:** Video Capture SDK, Media Blocks SDK, .NET, Windows, macOS, Linux, Android, iOS, Capture, Streaming, IP Camera, RTSP, ONVIF, H.264, MJPEG, C# # How to Connect to Foscam IP Camera in C# .NET [Video Capture SDK .Net](https://www.visioforge.com/video-capture-sdk-net) [Media Blocks SDK .Net](https://www.visioforge.com/media-blocks-sdk-net) ## Brand Overview **Foscam** (Shenzhen Foscam Intelligent Technology Co., Ltd.) is a Chinese manufacturer specializing in consumer and small business IP cameras. Founded in 2007 and headquartered in Shenzhen, China, Foscam gained popularity for affordable Wi-Fi cameras and was one of the first brands to bring low-cost IP cameras to the consumer market. **Key facts:** - **Product lines:** FI-series (legacy pan/tilt), C1/C2 (indoor HD), R2/R4 (indoor pan/tilt), SD (outdoor), G-series (battery), VZ-series (doorbell) - **Protocol support:** RTSP, HTTP/CGI, ONVIF (newer models), P2P - **Default RTSP port:** 88 (not 554 -- this is unique to Foscam) - **Default HTTP port:** 88 - **Default credentials:** admin / (blank password on older models); admin / (set during setup on newer models) - **ONVIF support:** Partial (newer HD models only, e.g., C1, C2, R2, R4) - **Video codecs:** H.264 (HD models), MJPEG (legacy models) ## RTSP URL Patterns Foscam cameras use a non-standard port (88) and simple stream path names. ### URL Format ``` rtsp://[USERNAME]:[PASSWORD]@[IP]:88/videoMain ``` Non-standard port Foscam cameras typically use **port 88** for both RTSP and HTTP, not the standard port 554. This is the most common connection issue. ### HD Models (H.264) | Model Series | RTSP URL | Stream | Audio | | --- | --- | --- | --- | | C1 / C1 Lite (indoor) | `rtsp://IP:88/videoMain` | Main (720p) | Yes | | C1 / C1 Lite (indoor) | `rtsp://IP:88/videoSub` | Sub (VGA) | Yes | | C2 (indoor 1080p) | `rtsp://IP:88/videoMain` | Main (1080p) | Yes | | C2 (indoor 1080p) | `rtsp://IP:88/videoSub` | Sub (VGA) | Yes | | R2 (pan/tilt 1080p) | `rtsp://IP:88/videoMain` | Main (1080p) | Yes | | R4 (pan/tilt 1440p) | `rtsp://IP:88/videoMain` | Main (2560x1440) | Yes | | FI9821W V2 (pan/tilt) | `rtsp://IP:88/videoMain` | Main (720p) | Yes | | FI9826W (pan/tilt/zoom) | `rtsp://IP:88/videoMain` | Main (960p) | Yes | | FI9828P (outdoor PTZ) | `rtsp://IP:88/videoMain` | Main (960p) | Yes | | FI9900P (outdoor bullet) | `rtsp://IP:88/videoMain` | Main (1080p) | Yes | | SD2 (outdoor pan/tilt) | `rtsp://IP:88/videoMain` | Main (1080p) | Yes | ### Legacy Models (MJPEG only) Older Foscam models (FI8904W, FI8910W, FI8918W, FI8919W) do not support RTSP. They use HTTP streaming only: | Model | HTTP URL | Type | Audio | | --- | --- | --- | --- | | FI8904W | `http://IP:88/videostream.asf?user=USER&pwd=PASS` | ASF stream | Yes | | FI8910W | `http://IP:88/videostream.asf?user=USER&pwd=PASS` | ASF stream | Yes | | FI8918W | `http://IP:88/videostream.asf?user=USER&pwd=PASS` | ASF stream | Yes | | FI8919W | `http://IP:88/videostream.asf?user=USER&pwd=PASS` | ASF stream | Yes | | FI8904W | `http://IP:88/videostream.cgi?user=USER&pwd=PASS&resolution=32` | MJPEG | No | ### Alternative RTSP Ports Some Foscam models can be configured for alternative ports: | URL Pattern | Port | Notes | | --- | --- | --- | | `rtsp://IP:88/videoMain` | 88 | Default for most models | | `rtsp://IP:554/videoMain` | 554 | If reconfigured in settings | | `rtsp://IP:554/cam1/mpeg4` | 554 | Some OEM variants | | `rtsp://IP:554/live1.sdp` | 554 | DCS-compatible firmware | ## Connecting with VisioForge SDK Use your Foscam camera's RTSP URL with any of the three SDK approaches shown in the [Quick Start Guide](../#quick-start-code): ``` // Foscam R2, main stream -- note port 88, not 554! var uri = new Uri("rtsp://192.168.1.30:88/videoMain"); var username = "admin"; var password = "YourPassword"; ``` For sub-stream access, use `/videoSub` instead. ## Snapshot and MJPEG URLs Foscam provides a CGI API for snapshots and control: | Type | URL Pattern | Notes | | --- | --- | --- | | CGI Snapshot (HD) | `http://IP:88/cgi-bin/CGIProxy.fcgi?cmd=snapPicture2&usr=USER&pwd=PASS` | HD models | | Legacy Snapshot | `http://IP:88/snapshot.cgi?user=USER&pwd=PASS` | Legacy models | | Snapshot (count) | `http://IP:88/snapshot.cgi?user=USER&pwd=PASS&count=0` | Single frame | | MJPEG Stream (legacy) | `http://IP:88/videostream.cgi?user=USER&pwd=PASS&resolution=32` | VGA MJPEG | | ASF Stream (legacy) | `http://IP:88/videostream.asf?user=USER&pwd=PASS` | ASF container | | Video CGI | `http://IP:88/video.cgi?resolution=VGA` | Direct video | ## Troubleshooting ### Wrong port -- must use 88, not 554 The most common Foscam connection issue is using port 554. Foscam cameras default to **port 88** for all services (RTSP, HTTP, and CGI). If your connection times out, check the port number first. ### Legacy vs HD models Foscam has two fundamentally different product generations: - **Legacy (FI89xx):** MJPEG only, HTTP streaming via `videostream.asf` or `videostream.cgi`, no RTSP - **HD (C1, C2, R2, R4, FI99xx):** H.264, RTSP via `videoMain`/`videoSub`, ONVIF support If `rtsp://IP:88/videoMain` doesn't work, your camera is likely a legacy model -- use the HTTP streaming URLs instead. ### Blank/empty password Older Foscam cameras ship with a blank password (username: `admin`, password: empty string). Newer firmware requires setting a password during initial setup. If authentication fails with a password, try an empty password for legacy models. ### Wi-Fi connection instability Foscam Wi-Fi cameras can experience stream dropouts. Recommendations: - Use TCP transport mode for reliability - Position camera closer to the Wi-Fi router - Use 2.4GHz Wi-Fi (better range) instead of 5GHz - Reduce stream resolution to sub stream: `rtsp://IP:88/videoSub` ### ONVIF not available ONVIF is only supported on newer HD models (C1, C2, R2, R4, FI99xx). Legacy FI89xx cameras do not support ONVIF. For legacy models, use direct HTTP/RTSP URLs instead. ## FAQ **What is the default RTSP URL for Foscam cameras?** For HD models, the URL is `rtsp://admin:password@CAMERA_IP:88/videoMain`. Note the non-standard port 88 (not 554). For legacy models (FI89xx series), use HTTP: `http://CAMERA_IP:88/videostream.asf?user=admin&pwd=password`. **Why does Foscam use port 88 instead of the standard 554?** Foscam chose port 88 as their default for all camera services to avoid conflicts with other network devices. You can change this in the camera's web interface under Settings > Network > Port, but the default is 88. **Can I change the Foscam RTSP port to 554?** Yes. Access the camera's web interface at `http://CAMERA_IP:88`, go to Settings > Network > Port, and change the RTSP port to 554. After saving and rebooting, you can use the standard port 554 in your RTSP URLs. **Does Foscam support pan/tilt/zoom control via the SDK?** Foscam PTZ models (R2, R4, FI9821, FI9826) support pan/tilt via their CGI API and ONVIF (HD models). You can send PTZ commands through ONVIF using the VisioForge SDK's PTZ control features. ## Related Resources - [All Camera Brands — RTSP URL Directory](../) - [TP-Link Connection Guide](../tp-link/) — Consumer cameras with RTSP - [D-Link Connection Guide](../dlink/) — Consumer segment peer - [IP Camera Preview Tutorial](../../videocapture/video-tutorials/ip-camera-preview/) - [SDK Installation & Samples](../#get-started) ---END OF PAGE--- ## GeoVision IP Camera RTSP URL Setup and C# .NET Guide **URL:** https://www.visioforge.com/help/docs/dotnet/camera-brands/geovision/ **Description:** GeoVision GV-BL, GV-FD, GV-VD, GV-FE, and GV-DVR RTSP URL patterns for C# .NET. Integrate with VisioForge SDK for multi-channel surveillance apps. **Tags:** Video Capture SDK, Media Blocks SDK, .NET, Windows, macOS, Linux, Android, iOS, Capture, Streaming, IP Camera, RTSP, ONVIF, MJPEG, C# # How to Connect to GeoVision IP Camera in C# .NET [Video Capture SDK .Net](https://www.visioforge.com/video-capture-sdk-net) [Media Blocks SDK .Net](https://www.visioforge.com/media-blocks-sdk-net) ## Brand Overview **GeoVision** (GeoVision Inc.) is a Taiwanese manufacturer of IP cameras, network video recorders, and video management software, headquartered in Taipei, Taiwan. GeoVision is a well-established brand in the enterprise and professional surveillance market, known for their GV-series IP cameras and the GeoVision VMS platform. **Key facts:** - **Product lines:** GV-BL (bullet), GV-FD (fixed dome), GV-VD (vandal dome), GV-FE (fisheye), GV-CB (cube), GV-CA (camera), GV-DVR (digital video recorder), GV-NVR - **Protocol support:** RTSP, ONVIF, PSIA, HTTP/CGI - **Default RTSP port:** 8554 (IP cameras), 554 (DVR/Server) - **Default credentials:** admin / admin - **ONVIF support:** Yes (current models) - **Video codecs:** H.264, H.265 (current models), MPEG-4 (legacy) Non-standard RTSP port GeoVision IP cameras use **port 8554** by default, not the standard 554. Make sure to specify the correct port when constructing your RTSP URL. GeoVision DVR/Server software uses the standard port 554. ## RTSP URL Patterns ### IP Camera Standard Format GeoVision IP cameras use a channel-based SDP URL pattern on port 8554: ``` rtsp://[USERNAME]:[PASSWORD]@[IP]:8554//CH001.sdp ``` | Parameter | Value | Description | | --- | --- | --- | | Port | 8554 | Default for GeoVision IP cameras | | `CH001` | CH001, CH002... | Channel number (zero-padded 3 digits) | | `.sdp` | Required | SDP session descriptor suffix | Double slash Some GeoVision models require a double slash (`//`) before the channel identifier. If a single slash does not work, try `//CH001.sdp`. ### IP Camera Streams | Stream | URL | Notes | | --- | --- | --- | | Main stream | `rtsp://IP:8554//CH001.sdp` | Full resolution, port 8554 | | Sub stream | `rtsp://IP:8554//CH002.sdp` | Lower resolution | ### DVR / GeoVision Server GeoVision DVR and GV-Server software use port 554: ``` rtsp://[USERNAME]:[PASSWORD]@[IP]:554/CH001.sdp ``` | Channel | Main Stream URL | Notes | | --- | --- | --- | | Channel 1 | `rtsp://IP:554/CH001.sdp` | Port 554 on DVR/Server | | Channel 2 | `rtsp://IP:554/CH002.sdp` | Port 554 on DVR/Server | | Channel N | `rtsp://IP:554/CH00N.sdp` | Zero-pad to 3 digits | ### PSIA Streaming GeoVision also supports PSIA-compatible RTSP URLs: ``` rtsp://[USERNAME]:[PASSWORD]@[IP]:554/PSIA/Streaming/channels/1?videoCodecType=MPEG4 ``` ### URL Summary Table | Device Type | Main Stream URL | Default Port | Notes | | --- | --- | --- | --- | | GV-BL (bullet) | `rtsp://IP:8554//CH001.sdp` | 8554 | Standard IP camera | | GV-FD (fixed dome) | `rtsp://IP:8554//CH001.sdp` | 8554 | Standard IP camera | | GV-VD (vandal dome) | `rtsp://IP:8554//CH001.sdp` | 8554 | Standard IP camera | | GV-FE (fisheye) | `rtsp://IP:8554//CH001.sdp` | 8554 | Standard IP camera | | GV-CB (cube) | `rtsp://IP:8554//CH001.sdp` | 8554 | Standard IP camera | | GV-DVR | `rtsp://IP:554/CH001.sdp` | 554 | DVR software | | GV-NVR | `rtsp://IP:554/CH001.sdp` | 554 | NVR software | | PSIA stream | `rtsp://IP:554/PSIA/Streaming/channels/1` | 554 | PSIA compatible | ## Connecting with VisioForge SDK Use your GeoVision camera's RTSP URL with any of the three SDK approaches shown in the [Quick Start Guide](../#quick-start-code): ``` // GeoVision GV-BL2702, main stream (note port 8554) var uri = new Uri("rtsp://192.168.1.90:8554//CH001.sdp"); var username = "admin"; var password = "YourPassword"; ``` For sub-stream access, use `CH002.sdp` instead of `CH001.sdp`. ## Snapshot and MJPEG URLs | Type | URL Pattern | Notes | | --- | --- | --- | | JPEG Snapshot | `http://IP/cgi-bin/snapshot.cgi` | Requires basic auth | | JPEG Snapshot (alt) | `http://IP/GetImage.cgi` | Some models | | JPEG Snapshot (alt) | `http://IP/cgi-bin/getimage` | Some models | | JPEG Snapshot (viewer) | `http://IP/cgi-bin/viewer/video.jpg` | Web viewer interface | | Static image (alt) | `http://IP/cgi-bin/jpg/image.cgi` | Some models | | Legacy snapshot | `http://IP/cam1.jpg` | Firmware 6.0-8.x, channel 1 | | Legacy snapshot (ch N) | `http://IP/camN.jpg` | Firmware 6.0-8.x, channel N | ## Troubleshooting ### Wrong port — 554 vs 8554 The most common connection issue with GeoVision cameras is using the wrong port: - **IP cameras** (GV-BL, GV-FD, GV-VD, GV-FE, GV-CB): Use **port 8554** - **DVR / GV-Server software**: Use **port 554** If you get a connection timeout, check that you are using the correct port for your device type. ### Double slash in URL path Some GeoVision IP camera models require a double slash before the channel identifier (`//CH001.sdp`). If a single slash (`/CH001.sdp`) returns an error, add the extra slash. ### Channel numbering format GeoVision uses zero-padded three-digit channel numbers: `CH001`, `CH002`, `CH003`, etc. Using `CH1` instead of `CH001` will not work. ### Firmware version differences Older GeoVision firmware versions (6.x-8.x) may use different snapshot URL formats. If the CGI-based snapshot URL does not work, try the legacy format (`http://IP/cam1.jpg`). ## FAQ **What port does GeoVision use for RTSP?** GeoVision IP cameras use **port 8554** by default, which differs from the industry-standard port 554. GeoVision DVR and GV-Server software use the standard port 554. **What is the default RTSP URL for GeoVision IP cameras?** The URL is `rtsp://admin:password@CAMERA_IP:8554//CH001.sdp` for the main stream. Use `CH002.sdp` for the sub stream. Note the double slash before `CH001` and port 8554. **Do GeoVision cameras support ONVIF?** Yes. All current GeoVision IP camera models support ONVIF Profile S. ONVIF discovery can be used as an alternative to manual RTSP URL configuration. **Can I connect to a GeoVision DVR and IP camera at the same time?** Yes. Connect to the DVR on port 554 and individual IP cameras on port 8554. Each device has its own IP address and RTSP endpoint. ## Related Resources - [All Camera Brands — RTSP URL Directory](../) - [Vivotek Connection Guide](../vivotek/) — Taiwanese enterprise cameras - [ACTi Connection Guide](../acti/) — Taiwanese professional cameras - [RTSP Camera Integration Guide](../../videocapture/video-sources/ip-cameras/rtsp/) — GeoVision RTSP stream setup - [IP Camera Preview Tutorial](../../videocapture/video-tutorials/ip-camera-preview/) - [SDK Installation & Samples](../#get-started) ---END OF PAGE--- ## How to Connect to Grandstream IP Camera in C# .NET **URL:** https://www.visioforge.com/help/docs/dotnet/camera-brands/grandstream/ **Description:** Integrate Grandstream GXV and GSC cameras into C# .NET apps via RTSP. URL patterns for GXV3500, GXV3610, GSC3610, plus VisioForge SDK examples. **Tags:** Video Capture SDK, Media Blocks SDK, .NET, Windows, macOS, Linux, Android, iOS, Capture, Streaming, Encoding, IP Camera, RTSP, ONVIF, H.264, MJPEG, C# # How to Connect to Grandstream IP Camera in C# .NET [Video Capture SDK .Net](https://www.visioforge.com/video-capture-sdk-net) [Media Blocks SDK .Net](https://www.visioforge.com/media-blocks-sdk-net) ## Brand Overview **Grandstream Networks** is an American company headquartered in Boston, Massachusetts, USA, known for VoIP phones and IP surveillance products. Grandstream offers IP cameras and video encoders under the **GXV** (legacy) and **GSC** (current generation) product lines, targeting SMB and professional markets. Their cameras are often deployed alongside Grandstream VoIP and UCM (Unified Communications Manager) systems. **Key facts:** - **Product lines:** GXV (IP cameras and video encoders, legacy), GSC (current generation smart cameras) - **Protocol support:** RTSP, ONVIF (GXV36xx and newer GSC series), HTTP/CGI, SIP (video calling) - **Default RTSP port:** 554 - **Default credentials:** admin / admin - **ONVIF support:** Yes (GXV36xx and newer GSC models) - **Video codecs:** H.264, H.265 (current GSC models), MPEG-4 (legacy GXV models) ## RTSP URL Patterns ### Current GSC-Series Cameras Current generation Grandstream GSC cameras use a channel-based URL format: | Stream | RTSP URL | Notes | | --- | --- | --- | | Primary stream | `rtsp://IP:554/live/ch00_0` | Main stream, channel 0 | | Secondary stream | `rtsp://IP:554/live/ch00_1` | Sub stream | ### GXV-Series (Legacy) Older GXV cameras support multiple URL formats depending on the model: | Stream | RTSP URL | Notes | | --- | --- | --- | | Primary stream | `rtsp://IP:554//0` | Main stream (channel 0) | | Secondary stream | `rtsp://IP:554//4` | Sub stream (channel 4) | | H.264 SDP | `rtsp://IP:554/ipcam_h264.sdp` | SDP file-based access | | Live H.264 | `rtsp://IP:554/live/h264` | Named stream | | Channel-based | `rtsp://IP:554/[CHANNEL]` | Direct channel number | | Auth stream | `rtsp://IP:554//0/888888:888888/main` | With embedded credentials | | MPEG-4 (legacy) | `rtsp://IP:554/cam1/mpeg4?user=USER&pwd=PASS` | Legacy MPEG-4 stream | Unusual channel numbering Grandstream uses a non-standard channel numbering scheme. For single-channel cameras, channel **0** is the primary stream and channel **4** is the secondary stream. This differs from most other brands that use sequential numbering. ### Model-Specific URLs | Model | Primary Stream | Secondary Stream | Type | | --- | --- | --- | --- | | GXV3500 | `rtsp://IP:554/0` | `rtsp://IP:554/4` | Video encoder | | GXV3504 (ch 1) | `rtsp://IP:554/0` | `rtsp://IP:554/4` | 4-channel encoder | | GXV3504 (ch 2) | `rtsp://IP:554/1` | `rtsp://IP:554/5` | 4-channel encoder | | GXV3504 (ch 3) | `rtsp://IP:554/2` | `rtsp://IP:554/6` | 4-channel encoder | | GXV3504 (ch 4) | `rtsp://IP:554/3` | `rtsp://IP:554/7` | 4-channel encoder | | GXV3601 / GXV3611 | `rtsp://IP:554//4` | -- | Dome camera | | GXV3601 (alt) | `rtsp://IP:554/ipcam_h264.sdp` | -- | SDP-based | | GXV3610 | `rtsp://IP:554/0` | `rtsp://IP:554/4` | Dome HD | | GXV3651 / GXV3661 / GXV3662 | `rtsp://IP:554/0` | `rtsp://IP:554/4` | FHD cameras | | GXV3672 | `rtsp://IP:554//0` | `rtsp://IP:554/live/ch00_0` | HD/FHD outdoor | | GSC3610 / GSC3615 | `rtsp://IP:554/live/ch00_0` | `rtsp://IP:554/live/ch00_1` | Current dome | | GSC3620 | `rtsp://IP:554/live/ch00_0` | `rtsp://IP:554/live/ch00_1` | Current outdoor | ### Multi-Channel Encoder (GXV3504) Channel Map The GXV3504 is a 4-channel video encoder with the following channel numbering: | Input | Primary Channel | Secondary Channel | | --- | --- | --- | | Input 1 | 0 | 4 | | Input 2 | 1 | 5 | | Input 3 | 2 | 6 | | Input 4 | 3 | 7 | ## Connecting with VisioForge SDK Use your Grandstream camera's RTSP URL with any of the three SDK approaches shown in the [Quick Start Guide](../#quick-start-code): ``` // Grandstream GSC-series camera, main stream var uri = new Uri("rtsp://192.168.1.60:554/live/ch00_0"); var username = "admin"; var password = "YourPassword"; ``` For legacy GXV models, use `rtsp://IP:554//0` for the primary stream or `rtsp://IP:554//4` for the secondary stream. ## Snapshot and MJPEG URLs | Type | URL Pattern | Notes | | --- | --- | --- | | JPEG Snapshot | `http://IP/snapshot/view0.jpg` | Channel 0 snapshot | | JPEG Snapshot (ch 1) | `http://IP/snapshot/view1.jpg` | Channel 1 (multi-channel) | | HTTP Stream | `http://IP/goform/stream?cmd=get&channel=0` | Channel-based HTTP stream | ## Troubleshooting ### Channel numbering confusion Grandstream channel numbering is unconventional: - **Single-channel cameras:** Channel 0 = primary stream, Channel 4 = secondary stream - **GXV3504 (4-channel encoder):** Channels 0-3 are primary streams for inputs 1-4; Channels 4-7 are secondary streams for inputs 1-4 If you get a blank stream or error, double-check you are using the correct channel number for your desired stream quality. ### Factory default credential `888888` Some older Grandstream GXV models use `888888` as the default password (or embedded in the RTSP URL as `888888:888888`). If `admin` / `admin` does not work, try `888888` as the password. ### RTSP not enabled On some older GXV models, RTSP streaming must be explicitly enabled in the camera's web interface. Navigate to the streaming or media settings page and confirm that RTSP is turned on and set to port 554. ### Multiple URL formats per model Many GXV cameras support several RTSP URL formats simultaneously. If one format does not work, try the alternatives: 1. `rtsp://IP:554//0` (channel number with double slash) 2. `rtsp://IP:554/live/ch00_0` (named channel) 3. `rtsp://IP:554/ipcam_h264.sdp` (SDP file) 4. `rtsp://IP:554/live/h264` (named stream) ### Codec compatibility Current GSC-series cameras support H.265 and H.264. Legacy GXV models may default to MPEG-4. If you experience decoding issues with a legacy model, check the camera's web interface and switch the codec to H.264 if available. ## FAQ **What is the default RTSP URL for Grandstream cameras?** For current GSC-series cameras, use `rtsp://admin:password@CAMERA_IP:554/live/ch00_0`. For older GXV-series cameras, try `rtsp://admin:password@CAMERA_IP:554//0` for the primary stream. **Do Grandstream cameras support ONVIF?** Yes, the GXV36xx series and current GSC-series cameras support ONVIF. Older GXV35xx models and video encoders generally do not support ONVIF. **What is the difference between channel 0 and channel 4?** On single-channel Grandstream cameras, channel 0 is the primary (high quality) stream and channel 4 is the secondary (lower quality) stream. This is a Grandstream-specific convention that differs from most other camera brands. **Can I use Grandstream cameras with a UCM system?** Yes. Grandstream cameras integrate natively with Grandstream UCM (Unified Communications Manager) systems. However, RTSP access works independently of the UCM and can be used with any third-party software including VisioForge SDKs. ## Related Resources - [All Camera Brands — RTSP URL Directory](../) - [Milesight Connection Guide](../milesight/) — SMB / professional camera segment - [ONVIF IP Camera Integration](../../videocapture/video-sources/ip-cameras/onvif/) — Grandstream ONVIF device setup - [IP Camera Preview Tutorial](../../videocapture/video-tutorials/ip-camera-preview/) - [SDK Installation & Samples](../#get-started) ---END OF PAGE--- ## How to Connect to Hanwha Vision IP Camera in C# .NET **URL:** https://www.visioforge.com/help/docs/dotnet/camera-brands/hanwha/ **Description:** Hanwha Vision X, Q, P, L series and Wisenet NVR RTSP URL patterns for C# .NET. ONVIF-compatible integration with VisioForge SDK code samples. **Tags:** Video Capture SDK, Media Blocks SDK, .NET, Windows, macOS, Linux, Android, iOS, Capture, Streaming, Decoding, IP Camera, RTSP, ONVIF, MJPEG, C# # How to Connect to Hanwha Vision IP Camera in C# .NET [Video Capture SDK .Net](https://www.visioforge.com/video-capture-sdk-net) [Media Blocks SDK .Net](https://www.visioforge.com/media-blocks-sdk-net) ## Brand Overview **Hanwha Vision** (formerly Hanwha Techwin, formerly Samsung Techwin) is a South Korean video surveillance manufacturer and a subsidiary of Hanwha Group. Hanwha acquired Samsung's security division in 2015 and rebranded to Hanwha Vision in 2023. All cameras are sold under the **Wisenet** product brand. Hanwha Vision is a top-5 global surveillance manufacturer with strong enterprise and government market presence. **Key facts:** - **Product lines:** Wisenet X (premium), Wisenet P (AI/4K), Wisenet Q (mainstream), Wisenet L (value), Wisenet T (thermal) - **Protocol support:** RTSP, ONVIF Profile S/G/T, HTTP/CGI, SUNAPI (proprietary) - **Default RTSP port:** 554 - **Default credentials:** admin / (set during initial setup; older models: admin / 4321) - **ONVIF support:** Yes (all current models) - **Video codecs:** H.264, H.265 (WiseStream II), MJPEG - **Product brand:** Wisenet (see also our [Samsung/Hanwha guide](../samsung/) for legacy Samsung Techwin URLs) Hanwha Vision vs Samsung vs Wisenet **Hanwha Vision** is the company name (since 2023). **Wisenet** is the product brand for all cameras and NVRs. **Samsung Techwin** was the previous company name (before 2015). Our [Samsung/Hanwha guide](../samsung/) covers legacy Samsung-branded models. This page covers current Hanwha Vision / Wisenet products. ## RTSP URL Patterns ### Standard URL Format Hanwha Vision cameras use a profile-based RTSP URL structure: ``` rtsp://[USERNAME]:[PASSWORD]@[IP]:554/profile[N]/media.smp ``` | Parameter | Value | Description | | --- | --- | --- | | `profile1` | Profile 1 | Typically configured as main stream | | `profile2` | Profile 2 | Typically configured as sub stream | | `profile3` | Profile 3 | Third stream (if configured) | ### Camera Models | Model Series | Resolution | Main Stream URL | Audio | | --- | --- | --- | --- | | XNO-6080R (X 2MP bullet) | 1920x1080 | `rtsp://IP:554/profile2/media.smp` | Yes | | XNO-8080R (X 5MP bullet) | 2560x1920 | `rtsp://IP:554/profile2/media.smp` | Yes | | XNO-9080R (X 4K bullet) | 3840x2160 | `rtsp://IP:554/profile2/media.smp` | Yes | | XND-6080 (X 2MP dome) | 1920x1080 | `rtsp://IP:554/profile2/media.smp` | Yes | | XND-8080RV (X 5MP dome) | 2560x1920 | `rtsp://IP:554/profile2/media.smp` | Yes | | XNP-6120H (X 2MP PTZ) | 1920x1080 | `rtsp://IP:554/profile2/media.smp` | Yes | | PNO-A9081R (P 4K AI bullet) | 3840x2160 | `rtsp://IP:554/profile2/media.smp` | Yes | | QNO-8080R (Q 5MP bullet) | 2560x1920 | `rtsp://IP:554/profile2/media.smp` | Yes | | QND-8080R (Q 5MP dome) | 2560x1920 | `rtsp://IP:554/profile2/media.smp` | Yes | | LNO-6032R (L 2MP bullet) | 1920x1080 | `rtsp://IP:554/profile2/media.smp` | No | Profile Numbering On most Hanwha Vision cameras, `profile2` is the main stream and `profile1` is reserved for internal use. If `profile2` does not work, try `profile1` or `profile3`. You can verify profile assignments in the camera's web interface under **Video Profile**. ### NVR Channel URLs For Wisenet NVRs (XRN, QRN, LRN series): | Channel | Main Stream | Sub Stream | | --- | --- | --- | | Camera 1 | `rtsp://IP:554/profile2/media.smp/trackID=channel1` | `rtsp://IP:554/profile3/media.smp/trackID=channel1` | | Camera 2 | `rtsp://IP:554/profile2/media.smp/trackID=channel2` | `rtsp://IP:554/profile3/media.smp/trackID=channel2` | | Camera N | `rtsp://IP:554/profile2/media.smp/trackID=channelN` | `rtsp://IP:554/profile3/media.smp/trackID=channelN` | ### Alternative URL Formats | URL Pattern | Notes | | --- | --- | | `rtsp://IP:554/profile2/media.smp` | Standard (recommended) | | `rtsp://IP:554/profile1/media.smp` | First profile | | `rtsp://IP:554/onvif-media/media.amp` | ONVIF media service | | `rtsp://IP:554/cam/realmonitor?channel=1&subtype=0` | Some OEM variants | ## Connecting with VisioForge SDK Use your Hanwha Vision camera's RTSP URL with any of the three SDK approaches shown in the [Quick Start Guide](../#quick-start-code): ``` // Hanwha Vision XNO-8080R (Wisenet X 5MP), main stream var uri = new Uri("rtsp://192.168.1.90:554/profile2/media.smp"); var username = "admin"; var password = "YourPassword"; ``` For sub-stream access, use `/profile3/media.smp` instead of `/profile2/media.smp`. ## Snapshot and MJPEG URLs | Type | URL Pattern | Notes | | --- | --- | --- | | JPEG Snapshot | `http://IP/cgi-bin/video.cgi?msubmenu=jpg&action=view&Resolution=1920x1080&Quality=5&Channel=0` | Full resolution snapshot | | JPEG Snapshot (simple) | `http://IP/cgi-bin/snapshot.cgi` | Requires digest auth | | MJPEG Stream | `http://IP/cgi-bin/video.cgi?msubmenu=mjpeg&action=view&Channel=0&Stream=0` | Continuous MJPEG | ## Troubleshooting ### profile2 vs profile1 confusion Hanwha Vision cameras typically assign `profile2` as the main (highest quality) stream, which differs from most other brands that use profile/channel 1. If you get no video or low resolution from `profile2`, check the profile configuration in the camera's web interface under **Video Profile**. ### Password activation required Current Hanwha Vision cameras ship without a default password. You must activate the camera and set a password through: 1. Wisenet Installation Wizard (IP Installer tool) 2. Web browser at `http://CAMERA_IP` 3. Wisenet mobile app Older Samsung Techwin models used `admin` / `4321` as defaults. ### WiseStream II codec WiseStream II is Hanwha's dynamic encoding technology that adjusts compression per-region in the frame. It produces standard H.265 or H.264 streams that are compatible with any decoder. No special codec is required. ### SUNAPI vs ONVIF Hanwha Vision cameras support both their proprietary SUNAPI and standard ONVIF. For VisioForge SDK integration, use either the RTSP URLs above or ONVIF discovery. SUNAPI is primarily used by Hanwha's own VMS (SSM/Wisenet WAVE). ## FAQ **What is the default RTSP URL for Hanwha Vision (Wisenet) cameras?** The standard URL is `rtsp://admin:password@CAMERA_IP:554/profile2/media.smp` for the main stream. Use `profile3` for the sub stream. The profile numbers can be customized in the camera's web interface. **Are Hanwha Vision and Samsung cameras the same?** Hanwha Vision acquired Samsung's security camera division in 2015 (then called Samsung Techwin, later Hanwha Techwin, now Hanwha Vision). Current cameras are sold under the **Wisenet** brand. Legacy Samsung-branded cameras may use different URL patterns -- see our [Samsung/Hanwha guide](../samsung/). **What is the difference between Wisenet X, P, Q, and L series?** **X** = premium enterprise (best low-light, WDR). **P** = AI-powered (deep learning analytics). **Q** = mainstream business (good balance of features and price). **L** = value/entry-level (basic features, competitive pricing). **T** = thermal imaging. **Do Hanwha Vision cameras support ONVIF?** Yes. All current Hanwha Vision cameras support ONVIF Profile S, G, and T. ONVIF provides standardized discovery, streaming, and PTZ control. ## Related Resources - [All Camera Brands — RTSP URL Directory](../) - [Samsung/Hanwha Legacy Guide](../samsung/) — Older Samsung Techwin models - [Wisenet Product Guide](../wisenet/) — Wisenet product family details - [IP Camera Preview Tutorial](../../videocapture/video-tutorials/ip-camera-preview/) - [SDK Installation & Samples](../#get-started) ---END OF PAGE--- ## Hikvision RTSP URL in C# .NET — IP Camera and NVR Guide **URL:** https://www.visioforge.com/help/docs/dotnet/camera-brands/hikvision/ **Description:** Hikvision RTSP URL format for DS-2CD, DS-2DE, and NVR models in C# .NET. ONVIF discovery, multi-channel streams, and VisioForge SDK integration guide. **Tags:** Video Capture SDK, Media Blocks SDK, .NET, Windows, macOS, Linux, Android, iOS, Capture, Streaming, Decoding, IP Camera, RTSP, ONVIF, H.265, MJPEG, C# **API:** RTSPSourceProtocol # How to Connect to Hikvision IP Camera in C# .NET [Video Capture SDK .Net](https://www.visioforge.com/video-capture-sdk-net) [Media Blocks SDK .Net](https://www.visioforge.com/media-blocks-sdk-net) ## Brand Overview **Hikvision** (Hangzhou Hikvision Digital Technology Co., Ltd.) is the world's largest manufacturer of video surveillance equipment by market share. Founded in 2001 and headquartered in Hangzhou, China, Hikvision produces IP cameras, DVRs, NVRs, and video management software used across enterprise, government, and consumer markets. **Key facts:** - **Product lines:** DS-2CD (fixed cameras), DS-2DE (PTZ cameras), DS-76/77/96 (NVRs), DS-7200/7300/7600 (DVRs) - **Protocol support:** ONVIF Profile S/G/T, RTSP, HTTP, ISAPI - **Default RTSP port:** 554 - **Default credentials:** admin / (set during initial setup; older firmware: admin / 12345) - **ONVIF support:** Full -- recommended for automatic discovery and configuration - **Video codecs:** H.264, H.265 (Smart Codec), MJPEG ## RTSP URL Patterns Hikvision cameras use a channel-based URL structure. Channel numbers encode both the camera channel and the stream type. ### URL Format ``` rtsp://[USERNAME]:[PASSWORD]@[IP]:[PORT]/Streaming/Channels/[CHANNEL_ID] ``` **Channel ID encoding:** - Channel ID = (camera\_number \* 100) + stream\_number - Stream 1 = main stream, Stream 2 = sub stream, Stream 3 = third stream - Example: Camera 1, main stream = **101**; Camera 1, sub stream = **102** ### IP Cameras (Single Channel) | Model Series | RTSP URL | Stream | Audio | | --- | --- | --- | --- | | DS-2CD2xx2 (2MP fixed) | `rtsp://IP:554/Streaming/Channels/101` | Main (1080p) | Yes | | DS-2CD2xx2 (2MP fixed) | `rtsp://IP:554/Streaming/Channels/102` | Sub (CIF/D1) | Yes | | DS-2CD2x32 (3MP fixed) | `rtsp://IP:554/Streaming/Channels/101` | Main (2048x1536) | Yes | | DS-2CD2x32 (3MP fixed) | `rtsp://IP:554/Streaming/Channels/102` | Sub | Yes | | DS-2CD21xx-I (value series) | `rtsp://IP:554/Streaming/Channels/1` | Main | Yes | | DS-2CD21xx-I (value series) | `rtsp://IP:554/Streaming/Channels/2` | Sub | Yes | | DS-2DE series (PTZ) | `rtsp://IP:554/Streaming/Channels/101` | Main | Yes | | DS-2CD6362F (fisheye) | `rtsp://IP:554/Streaming/Channels/101` | Main (3072x2048) | Yes | ### NVR / DVR Channels For NVR and DVR devices, change the camera number in the channel ID: | Device | Channel | RTSP URL | Stream | | --- | --- | --- | --- | | NVR Camera 1 | 1 | `rtsp://IP:554/Streaming/Channels/101` | Main | | NVR Camera 1 | 1 | `rtsp://IP:554/Streaming/Channels/102` | Sub | | NVR Camera 2 | 2 | `rtsp://IP:554/Streaming/Channels/201` | Main | | NVR Camera 2 | 2 | `rtsp://IP:554/Streaming/Channels/202` | Sub | | NVR Camera 8 | 8 | `rtsp://IP:554/Streaming/Channels/801` | Main | | DVR Channel 1 | 1 | `rtsp://IP:554/Streaming/Channels/101` | Main | ### Alternative URL Formats Some older Hikvision models and OEM variants use different URL patterns: | URL Pattern | Notes | | --- | --- | | `rtsp://IP:554/h264/ch1/main/av_stream` | Older firmware versions | | `rtsp://IP:554/h264/ch1/sub/av_stream` | Older firmware, sub stream | | `rtsp://IP:554/PSIA/Streaming/channels/101` | PSIA protocol (legacy) | | `rtsp://IP:554/video.h264` | Some OEM models | | `rtsp://IP:554/live.sdp` | Some older models | | `rtsp://IP:554/cam/realmonitor?channel=1&subtype=1` | Dahua-compatible OEM | | `rtsp://IP:554/mpeg4` | MPEG4 stream (legacy) | ## Connecting with VisioForge SDK Use your Hikvision camera's RTSP URL with any of the three SDK approaches shown in the [Quick Start Guide](../#quick-start-code): ``` // Hikvision DS-2CD2032-I, main stream var uri = new Uri("rtsp://192.168.1.64:554/Streaming/Channels/101"); var username = "admin"; var password = "YourPassword"; ``` For sub-stream access, use `/Streaming/Channels/102` instead. ### ONVIF Discovery Hikvision cameras have excellent ONVIF support. Use ONVIF to automatically discover cameras on your network and retrieve their stream URIs without manually constructing RTSP URLs. See the [ONVIF integration guide](../../mediablocks/Sources/) for discovery code examples. ## Snapshot and MJPEG URLs Hikvision cameras also provide HTTP endpoints for snapshots and MJPEG streams: | Type | URL Pattern | Notes | | --- | --- | --- | | JPEG Snapshot | `http://IP/ISAPI/Streaming/channels/101/picture` | Requires authentication | | MJPEG Stream | `http://IP/ISAPI/Streaming/channels/102/httpPreview` | Sub stream as MJPEG | | Legacy Snapshot | `http://IP/Streaming/channels/1/picture` | Older firmware | | CGI Snapshot | `http://IP/cgi-bin/snapshot.cgi` | Basic authentication | ## Troubleshooting ### "Double slash" in URL path Hikvision RTSP URLs use a path starting with `/Streaming/Channels/`. Some tools or code generate `//Streaming/Channels/` (double slash). Both work with Hikvision cameras, but use a single slash for correctness. ### Connection refused on port 554 - Verify RTSP is enabled in the camera's web interface: **Configuration > Network > Advanced Settings > RTSP** - Check that the RTSP port hasn't been changed from the default (554) - Ensure no firewall is blocking the port between your application and the camera ### Authentication failures - Hikvision cameras require **digest authentication** by default. VisioForge SDK handles this automatically. - On newer firmware, the default `admin/12345` credentials are disabled. You must set a strong password during initial setup via the Hikvision SADP tool or web interface. - If connecting to an NVR, use the NVR credentials, not the individual camera credentials. ### H.265 stream not playing - Ensure you have the HEVC decoder redistributable installed - Alternatively, configure the camera to use H.264 encoding in its video settings - Use `rtspSettings.UseGPUDecoder = true` for hardware-accelerated H.265 decoding ### High latency - Use TCP transport: `rtspSettings.AllowedProtocols = RTSPSourceProtocol.TCP` - Reduce buffer latency: `rtspSettings.Latency = TimeSpan.FromMilliseconds(200)` - Switch to the sub stream (channel 102) for lower bandwidth requirements - Disable audio if not needed: `audioEnabled: false` Combined on a single `RTSPSourceSettings` instance (constructed via the async factory): ``` var rtspSettings = await RTSPSourceSettings.CreateAsync( uri: new Uri("rtsp://192.168.1.100:554/Streaming/Channels/102"), // sub stream login: "admin", password: "password", audioEnabled: false); rtspSettings.UseGPUDecoder = true; // hardware-accelerated H.265 rtspSettings.AllowedProtocols = RTSPSourceProtocol.TCP; // TCP transport rtspSettings.Latency = TimeSpan.FromMilliseconds(200); ``` ## FAQ **What is the default RTSP URL for Hikvision cameras?** The standard RTSP URL for Hikvision cameras is `rtsp://admin:password@CAMERA_IP:554/Streaming/Channels/101` for the main stream. Replace `admin` and `password` with your camera credentials, and `CAMERA_IP` with the camera's IP address. Use channel `102` for the sub stream. **How do I find my Hikvision camera's IP address?** Use the Hikvision SADP (Search Active Devices Protocol) tool, which is a free utility that discovers all Hikvision devices on your local network. Alternatively, check your router's DHCP client list or use ONVIF device discovery with the VisioForge SDK. **Can I connect to a Hikvision NVR and view individual camera channels?** Yes. Use the same RTSP URL format but change the channel number. Camera 1 is channel 101 (main) or 102 (sub), camera 2 is channel 201/202, and so on. The formula is: channel ID = (camera\_number x 100) + stream\_number. **Does VisioForge SDK support Hikvision's H.265+ (Smart Codec)?** Yes. The SDK supports standard H.265/HEVC decoding. Hikvision's H.265+ is a proprietary compression optimization that produces standard H.265 streams, so it works with any H.265-capable decoder. ## Related Resources - [All Camera Brands — RTSP URL Directory](../) - [LTS Connection Guide](../lts/) — Hikvision OEM, uses same URL format - [EZVIZ Connection Guide](../ezviz/) — Hikvision consumer brand - [IP Camera Preview Tutorial](../../videocapture/video-tutorials/ip-camera-preview/) - [SDK Installation & Samples](../#get-started) ---END OF PAGE--- ## Honeywell IP Camera RTSP URL Guide for C# .NET Apps **URL:** https://www.visioforge.com/help/docs/dotnet/camera-brands/honeywell/ **Description:** Connect to Honeywell Performance Series and equIP cameras in C# .NET with RTSP URL patterns and code samples for HD, HDZ, HBD, HBW, and PSIA models. **Tags:** Video Capture SDK, Media Blocks SDK, .NET, Windows, macOS, Linux, Android, iOS, Capture, Streaming, IP Camera, RTSP, ONVIF, H.264, H.265, MJPEG, C# # How to Connect to Honeywell IP Camera in C# .NET [Video Capture SDK .Net](https://www.visioforge.com/video-capture-sdk-net) [Media Blocks SDK .Net](https://www.visioforge.com/media-blocks-sdk-net) ## Brand Overview **Honeywell Commercial Security** (part of Honeywell Building Technologies) is a major manufacturer of enterprise video surveillance equipment. Honeywell cameras are widely deployed in commercial buildings, critical infrastructure, government facilities, and transportation systems worldwide. Honeywell acquired several camera brands over the years including **Samsung Techwin** (briefly) and markets cameras under the **Performance Series**, **30 Series**, and **60 Series** product lines. **Key facts:** - **Product lines:** Performance Series (equIP, H-series), 30 Series (HC30W, HC35W), 60 Series (HC60W), HDZ/HD (legacy equIP), HBD/HBW (bullet/dome), IPCAM (consumer) - **Protocol support:** RTSP, ONVIF (Profile S/G/T), PSIA, HTTP/CGI - **Default RTSP port:** 554 - **Default credentials:** admin / 1234 (Performance Series); admin / admin (legacy models); varies by model and firmware - **ONVIF support:** Yes (all current Performance Series and 30/60 Series models) - **Video codecs:** H.264, H.265 (current models), MPEG-4 (legacy) ## RTSP URL Patterns ### Current Models (Performance Series, 30/60 Series) | Stream | RTSP URL | Codec | Notes | | --- | --- | --- | --- | | Main stream (H.264) | `rtsp://IP:554/h264` | H.264 | Primary stream | | Main stream (H.265) | `rtsp://IP:554/h265` | H.265 | Current models only | | Channel stream (H.264) | `rtsp://IP:554/cam1/h264` | H.264 | Channel-specific | | Channel stream (MPEG-4) | `rtsp://IP:554/cam1/mpeg4` | MPEG-4 | Legacy fallback | | PSIA stream | `rtsp://IP:554/PSIA/Streaming/channels/1` | H.264 | PSIA-compatible | ### Model-Specific URLs | Model Series | RTSP URL | Resolution | Notes | | --- | --- | --- | --- | | HC30W/HC35W (30 Series) | `rtsp://IP:554/h264` | Up to 5MP | Current Wi-Fi | | HC60W (60 Series) | `rtsp://IP:554/h264` | Up to 4K | Current wired | | HD45IP | `rtsp://IP:554/h264` | 1080p | equIP dome | | HD54IP | `rtsp://IP:554/h264` | 1080p | equIP box | | HD55IPX | `rtsp://IP:554/h264` | 1080p+ | equIP box | | HDZ20HDEX/HDZ20HDX | `rtsp://IP:554/h264` | 1080p | equIP PTZ | | HD4MDIP | `rtsp://IP:554/cam1/mpeg4` | 720p | Multi-channel | | HDM3DIP | `rtsp://IP:554/cam1/mpeg4` | 720p | Mini dome | | HBD/HBW series | `rtsp://IP:554/h264` | Up to 4MP | Bullet/dome | ### PSIA Streaming Honeywell cameras that support **PSIA (Physical Security Interoperability Alliance)** use a different URL format: | Stream | RTSP URL | Notes | | --- | --- | --- | | Channel 1 | `rtsp://IP:554/PSIA/Streaming/channels/1` | First channel | | Channel 2 | `rtsp://IP:554/PSIA/Streaming/channels/2` | Second channel | ### Legacy Models (HTTP Only) Older Honeywell consumer cameras (IPCAM series) use HTTP: | Model | URL | Notes | | --- | --- | --- | | IPCAM / IPCAM-PT | `http://IP/img/snapshot.cgi?size=3` | JPEG snapshot | | IPCAM-PT | `http://IP/img/video.mjpeg` | MJPEG stream | | IPCAM-PT | `http://IP/img/video.asf` | ASF stream (audio) | | IPCAM-OD / IPCAM-W12 | `http://IP/img/video.mjpeg` | MJPEG stream | | IPCAM-OD / IPCAM-W12 | `http://IP/img/video.asf` | ASF stream (audio) | ## Connecting with VisioForge SDK Use your Honeywell camera's RTSP URL with any of the three SDK approaches shown in the [Quick Start Guide](../#quick-start-code): ``` // Honeywell Performance Series camera, main stream var uri = new Uri("rtsp://192.168.1.75:554/h264"); var username = "admin"; var password = "YourPassword"; ``` For PSIA channel streams, use `/PSIA/Streaming/channels/1` instead. For multi-channel models, use `/cam1/h264` format. ## Snapshot and MJPEG URLs | Type | URL Pattern | Notes | | --- | --- | --- | | JPEG Snapshot | `http://IP/img/snapshot.cgi?size=3` | Most models | | MJPEG Stream | `http://IP/img/video.mjpeg` | Continuous MJPEG | | ASF Stream | `http://IP/img/video.asf` | ASF with audio | | HREP Snapshot | `http://IP/cgi-bin/webra_fcgi.fcgi?api=get_jpeg_raw&chno=1` | NVR channel snapshot | ## Troubleshooting ### RTSP URL format Honeywell cameras use a simple RTSP URL format compared to other brands: - Primary: `rtsp://IP:554/h264` (no complex paths) - Multi-channel: `rtsp://IP:554/cam1/h264` (channel number in path) - PSIA: `rtsp://IP:554/PSIA/Streaming/channels/1` (PSIA standard) If `/h264` doesn't work, try `/cam1/h264` or the PSIA URL. ### Default credentials vary Honeywell has used different default credentials across product lines: - **Performance Series:** admin / 1234 (must be changed on first login) - **30/60 Series:** Set during initial setup (no default) - **Legacy equIP:** admin / admin - **IPCAM series:** admin / (empty) or admin / admin ### PSIA vs ONVIF Honeywell cameras support both PSIA and ONVIF protocols: - **ONVIF** is recommended for new integrations (wider compatibility) - **PSIA** is Honeywell's legacy interoperability standard, still supported on most models - Both provide the same video streams via different discovery and configuration mechanisms ## FAQ **What is the default RTSP URL for Honeywell cameras?** For most current Honeywell cameras, use `rtsp://admin:password@CAMERA_IP:554/h264`. For multi-channel models, use `rtsp://admin:password@CAMERA_IP:554/cam1/h264`. PSIA-compatible cameras also respond to `/PSIA/Streaming/channels/1`. **Do Honeywell cameras support ONVIF?** Yes. All current Honeywell Performance Series, 30 Series, and 60 Series cameras support ONVIF Profile S (streaming), Profile G (recording), and Profile T (advanced streaming). Legacy equIP models may only support ONVIF Profile S. **What is PSIA on Honeywell cameras?** PSIA (Physical Security Interoperability Alliance) is an alternative to ONVIF for device interoperability. Honeywell has historically supported PSIA alongside ONVIF. PSIA streams use the URL format `rtsp://IP:554/PSIA/Streaming/channels/1`. **Are Honeywell IPCAM models still supported?** The IPCAM consumer series is discontinued. These cameras only support HTTP MJPEG/JPEG and do not have RTSP. For IPCAM models, use the HTTP snapshot URL `http://IP/img/snapshot.cgi?size=3` or MJPEG stream `http://IP/img/video.mjpeg`. ## Related Resources - [All Camera Brands — RTSP URL Directory](../) - [Bosch Connection Guide](../bosch/) — Enterprise / commercial segment peer - [IP Camera Preview Tutorial](../../videocapture/video-tutorials/ip-camera-preview/) - [SDK Installation & Samples](../#get-started) ---END OF PAGE--- ## Imou IP Camera in C# .NET — RTSP & ONVIF Setup Guide **URL:** https://www.visioforge.com/help/docs/dotnet/camera-brands/imou/ **Description:** Connect Imou cameras (Cruiser, Ranger, Bullet, Cell) to C# / .NET apps via RTSP/ONVIF. Default credentials, stream URLs, H.264/H.265 configs. Sample code. **Tags:** Video Capture SDK, Media Blocks SDK, .NET, Windows, macOS, Linux, Android, iOS, Capture, Streaming, IP Camera, RTSP, ONVIF, H.264, H.265, MJPEG, C# # How to Connect to Imou IP Camera in C# .NET [Video Capture SDK .Net](https://www.visioforge.com/video-capture-sdk-net) [Media Blocks SDK .Net](https://www.visioforge.com/media-blocks-sdk-net) ## Brand Overview **Imou** (pronounced "ee-moo") is a consumer smart home and security camera brand owned by **Dahua Technology**. Launched in 2019, Imou targets the consumer and small business market with WiFi cameras, battery cameras, doorbells, and home security kits. Imou cameras use Dahua firmware and RTSP URL patterns. **Key facts:** - **Product lines:** Cruiser (outdoor PT), Ranger (indoor PT), Bullet (fixed outdoor), Cell (battery), Versa (versatile), Rex (indoor) - **Protocol support:** RTSP (must be enabled on some models), ONVIF (select models), Imou Life cloud - **Default RTSP port:** 554 - **Default credentials:** admin / admin (or admin / imou + serial number suffix) - **ONVIF support:** Yes (most wired models) - **Video codecs:** H.264, H.265 (select models) - **Parent company:** Dahua Technology Imou = Dahua Consumer Brand Imou cameras use Dahua firmware and the same `cam/realmonitor` RTSP URL format as Dahua cameras. See our [Dahua connection guide](../dahua/) for additional details. ## RTSP URL Patterns ### Standard URL Format Imou cameras use the Dahua `cam/realmonitor` URL pattern: ``` rtsp://[USERNAME]:[PASSWORD]@[IP]:554/cam/realmonitor?channel=1&subtype=0 ``` | Parameter | Value | Description | | --- | --- | --- | | `channel` | 1 | Camera channel (always 1 for standalone cameras) | | `subtype` | 0 | Main stream (highest resolution) | | `subtype` | 1 | Sub stream (lower resolution, less bandwidth) | ### Camera Models | Model | Type | Main Stream URL | Audio | | --- | --- | --- | --- | | Cruiser SE+ 4MP | Outdoor PTZ | `rtsp://IP:554/cam/realmonitor?channel=1&subtype=0` | Yes | | Cruiser 2E 4MP | Outdoor PTZ | `rtsp://IP:554/cam/realmonitor?channel=1&subtype=0` | Yes | | Ranger 2 (IPC-A22EP) | Indoor PTZ | `rtsp://IP:554/cam/realmonitor?channel=1&subtype=0` | Yes | | Ranger SE 4MP | Indoor PTZ | `rtsp://IP:554/cam/realmonitor?channel=1&subtype=0` | Yes | | Rex 3D (IPC-GS7EP) | Indoor PTZ | `rtsp://IP:554/cam/realmonitor?channel=1&subtype=0` | Yes | | Bullet 2E (IPC-F22FP) | Outdoor fixed | `rtsp://IP:554/cam/realmonitor?channel=1&subtype=0` | Yes | | Bullet 2S (IPC-F26FP) | Outdoor fixed | `rtsp://IP:554/cam/realmonitor?channel=1&subtype=0` | Yes | | Versa 4MP | Indoor/outdoor | `rtsp://IP:554/cam/realmonitor?channel=1&subtype=0` | Yes | | Cell 2 | Battery outdoor | Limited — see note | Yes | | Cell Go | Battery mini | No RTSP | No | Battery Models Imou battery-powered cameras (Cell series) have limited or no RTSP support. The Cell 2 may support RTSP when connected to the Imou Base Station, but the Cell Go and other battery mini cameras are cloud-only devices. ### Alternative URL Formats | URL Pattern | Notes | | --- | --- | | `rtsp://IP:554/cam/realmonitor?channel=1&subtype=0` | Standard (recommended) | | `rtsp://IP:554/cam/realmonitor?channel=1&subtype=0&unicast=true` | Force unicast | | `rtsp://IP:554/live` | Simple path (some models) | ## Connecting with VisioForge SDK Use your Imou camera's RTSP URL with any of the three SDK approaches shown in the [Quick Start Guide](../#quick-start-code): ``` // Imou Cruiser SE+ 4MP, main stream var uri = new Uri("rtsp://192.168.1.90:554/cam/realmonitor?channel=1&subtype=0"); var username = "admin"; var password = "YourPassword"; ``` For sub-stream access, use `subtype=1` instead of `subtype=0`. ## Snapshot and MJPEG URLs | Type | URL Pattern | Notes | | --- | --- | --- | | JPEG Snapshot | `http://IP/cgi-bin/snapshot.cgi?channel=1` | Requires basic auth | | MJPEG Stream | `http://IP/cgi-bin/mjpg/video.cgi?channel=1&subtype=1` | Continuous MJPEG | ## Troubleshooting ### RTSP not accessible Some Imou cameras require RTSP to be enabled through the Imou Life app: 1. Open **Imou Life** app → select your camera 2. Go to **Settings > Advanced Settings > RTSP** 3. Enable RTSP and note the password (may differ from app password) ### Default credentials Imou password defaults vary by model and firmware: - `admin` / `admin` (common on older models) - `admin` / specific code (check camera label) - Custom password set during Imou Life app setup If RTSP login fails, check the RTSP password in the Imou Life app settings. ### WiFi camera IP address Imou WiFi cameras get their IP from your router via DHCP. Find the camera's local IP in: 1. The Imou Life app → Device Info 2. Your router's DHCP client list 3. ONVIF discovery (if supported) ### Dahua web interface Some Imou cameras expose the Dahua web interface at `http://CAMERA_IP`. This provides additional configuration options beyond the Imou Life app, including RTSP settings, video encoding, and network configuration. ## FAQ **What is the default RTSP URL for Imou cameras?** The standard URL is `rtsp://admin:password@CAMERA_IP:554/cam/realmonitor?channel=1&subtype=0` for the main stream. This is the same format as Dahua cameras. RTSP may need to be enabled in the Imou Life app first. **Is Imou the same as Dahua?** Imou is a consumer brand owned by Dahua Technology. Imou cameras use Dahua firmware and the same RTSP URL format (`cam/realmonitor`). The main differences are branding, consumer-focused features, and cloud service integration. **Can I use Imou cameras without the cloud?** Partially. You can access RTSP streams locally without the Imou cloud for live viewing and recording. However, initial camera setup requires the Imou Life app. Cloud-dependent features like smart alerts, cloud storage, and remote access require an Imou subscription. **Do Imou cameras support ONVIF?** Most wired and WiFi-connected Imou cameras support ONVIF. Battery-powered models generally do not. Check your camera's specifications in the Imou Life app. ## Related Resources - [All Camera Brands — RTSP URL Directory](../) - [Dahua Connection Guide](../dahua/) — Parent company, identical URL format - [Amcrest Connection Guide](../amcrest/) — Another Dahua OEM brand - [IP Camera Preview Tutorial](../../videocapture/video-tutorials/ip-camera-preview/) - [SDK Installation & Samples](../#get-started) ---END OF PAGE--- ## IP Camera RTSP URL Directory - Connect Any Camera in C# .NET **URL:** https://www.visioforge.com/help/docs/dotnet/camera-brands/ **Description:** Complete RTSP URL directory for 62 IP camera brands. Connect Hikvision, Dahua, Axis, Uniview, EZVIZ, Wisenet, Arlo and more using VisioForge .NET SDK. **Tags:** Video Capture SDK, Media Blocks SDK, .NET, Windows, macOS, Linux, Android, iOS, Capture, Streaming **API:** VideoCaptureCoreX, VideoCaptureCore, RTSPSourceSettings, IVideoView, IPCameraSourceSettings # IP Camera Connection Guide by Brand [Video Capture SDK .Net](https://www.visioforge.com/video-capture-sdk-net) [Media Blocks SDK .Net](https://www.visioforge.com/media-blocks-sdk-net) Connecting to IP cameras in C# .NET is straightforward when you know the right RTSP URL pattern for your camera brand. Each manufacturer uses slightly different URL formats, ports, and authentication methods. This directory provides **brand-specific RTSP URL patterns**, connection code samples using VisioForge SDK, and troubleshooting tips for the most popular IP camera manufacturers. ## How RTSP Camera Connections Work Most modern IP cameras expose video streams via the **RTSP (Real-Time Streaming Protocol)** on port 554. The general connection flow is: 1. Determine your camera's IP address (via ONVIF discovery, DHCP lease table, or manufacturer utility) 2. Construct the RTSP URL using the brand-specific pattern 3. Authenticate with camera credentials 4. Connect and render the video stream ### Quick Start Code Connect to any RTSP camera using one of three VisioForge SDK approaches: VideoCaptureCoreXVideoCaptureCoreMedia Blocks ``` // Initialize SDK (call once at app startup) await VisioForgeX.InitSDKAsync(); var videoCapture = new VideoCaptureCoreX(VideoView1); // Create RTSP source var rtsp = await RTSPSourceSettings.CreateAsync( new Uri("rtsp://192.168.1.100:554/stream1"), "admin", "password", true); // capture audio videoCapture.Video_Source = rtsp; await videoCapture.StartAsync(); ``` ``` var videoCapture = new VideoCaptureCore(VideoView1 as IVideoView); videoCapture.IP_Camera_Source = new IPCameraSourceSettings() { URL = new Uri("rtsp://admin:password@192.168.1.100:554/stream1"), Type = IPSourceEngine.Auto_LAV }; videoCapture.Audio_PlayAudio = true; videoCapture.Audio_RecordAudio = false; videoCapture.Mode = VideoCaptureMode.IPPreview; await videoCapture.StartAsync(); ``` ``` var pipeline = new MediaBlocksPipeline(); var rtspSettings = await RTSPSourceSettings.CreateAsync( new Uri("rtsp://192.168.1.100:554/stream1"), "admin", "password", audioEnabled: true); rtspSettings.AllowedProtocols = RTSPSourceProtocol.TCP; var rtspSource = new RTSPSourceBlock(rtspSettings); var videoRenderer = new VideoRendererBlock(pipeline, VideoView1); var audioRenderer = new AudioRendererBlock(); pipeline.Connect(rtspSource.VideoOutput, videoRenderer.Input); pipeline.Connect(rtspSource.AudioOutput, audioRenderer.Input); await pipeline.StartAsync(); ``` Replace the RTSP URL with your brand-specific pattern from the pages below. ### Which SDK Should I Choose? | SDK | Best For | Platforms | | --- | --- | --- | | **VideoCaptureCoreX** | New cross-platform projects, modern .NET | Windows, macOS, Linux, Android, iOS | | **VideoCaptureCore** | Windows-only projects, legacy .NET Framework | Windows | | **Media Blocks** | Advanced pipelines, custom processing chains | Windows, macOS, Linux, Android, iOS | **VideoCaptureCoreX** is recommended for most new projects. Use **Media Blocks** when you need to build custom processing pipelines with multiple sources, filters, or outputs. ## Camera Brands ### Featured Brands (Full Guides) | Brand | Headquarters | Market Segment | Guide | | --- | --- | --- | --- | | **Hikvision** | Hangzhou, China | Enterprise / Consumer | [Connection Guide](hikvision/) | | **Dahua** | Hangzhou, China | Enterprise / Consumer | [Connection Guide](dahua/) | | **Axis** | Lund, Sweden | Enterprise / Professional | [Connection Guide](axis/) | | **Reolink** | Hong Kong | Consumer / Prosumer | [Connection Guide](reolink/) | | **Amcrest** | Houston, USA | Consumer / SMB | [Connection Guide](amcrest/) | | **Samsung/Hanwha** | Grasbrunn, Germany / Seoul, South Korea | Enterprise / Professional | [Connection Guide](samsung/) | | **Bosch** | Grasbrunn, Germany | Enterprise / Critical Infrastructure | [Connection Guide](bosch/) | | **Ubiquiti** | New York, USA | Prosumer / SMB | [Connection Guide](ubiquiti/) | | **Foscam** | Shenzhen, China | Consumer / SMB | [Connection Guide](foscam/) | | **TP-Link** | Shenzhen, China | Consumer / SMB | [Connection Guide](tp-link/) | | **Vivotek** | New Taipei City, Taiwan | Enterprise / Professional | [Connection Guide](vivotek/) | | **Panasonic/i-PRO** | Tokyo, Japan | Enterprise / Government | [Connection Guide](panasonic/) | | **Sony** | Tokyo, Japan | Enterprise (discontinued 2020) | [Connection Guide](sony/) | | **Lorex** | Markham, Canada | Consumer / Prosumer | [Connection Guide](lorex/) | | **D-Link** | Taipei, Taiwan | Consumer / SMB | [Connection Guide](dlink/) | | **Honeywell** | Charlotte, USA | Enterprise / Commercial | [Connection Guide](honeywell/) | | **Pelco** | Fresno, USA (Motorola Solutions) | Enterprise / Government | [Connection Guide](pelco/) | | **Cisco** | San Jose, USA | Enterprise / Consumer-SMB (legacy) | [Connection Guide](cisco/) | | **Grandstream** | Boston, USA | SMB / Professional | [Connection Guide](grandstream/) | | **Swann** | Melbourne, Australia | Consumer / Prosumer | [Connection Guide](swann/) | | **GeoVision** | Taipei, Taiwan | Enterprise / Professional | [Connection Guide](geovision/) | | **ACTi** | Taipei, Taiwan | Professional / Enterprise | [Connection Guide](acti/) | | **Canon** | Tokyo, Japan | Professional / Enterprise | [Connection Guide](canon/) | | **FLIR (Teledyne)** | Wilsonville, USA | Enterprise / Thermal | [Connection Guide](flir/) | | **Milesight** | Xiamen, China | Professional / SMB | [Connection Guide](milesight/) | | **INSTAR** | Hanau, Germany | Consumer / Smart Home | [Connection Guide](instar/) | | **Zmodo** | Shenzhen, China | Consumer / Budget | [Connection Guide](zmodo/) | | **Arecont Vision** | Glendale, USA (Costar Group) | Professional / Enterprise | [Connection Guide](arecont/) | | **JVC** | Yokohama, Japan | Professional (discontinued ~2015) | [Connection Guide](jvc/) | | **Toshiba** | Tokyo, Japan | Enterprise (discontinued) | [Connection Guide](toshiba/) | | **LG** | Seoul, South Korea | Enterprise (discontinued) | [Connection Guide](lg/) | | **Linksys** | Irvine, USA | Consumer (discontinued ~2014) | [Connection Guide](linksys/) | | **LTS** | City of Industry, USA | Professional (Hikvision OEM) | [Connection Guide](lts/) | | **Q-See** | Anaheim, USA | Consumer (defunct ~2020) | [Connection Guide](q-see/) | | **Speco Technologies** | Amityville, USA | Professional | [Connection Guide](speco/) | | **EverFocus** | New Taipei City, Taiwan | Professional | [Connection Guide](everfocus/) | | **ABUS** | Wetter, Germany | Consumer / Professional | [Connection Guide](abus/) | | **Basler** | Ahrensburg, Germany | Machine Vision / Industrial | [Connection Guide](basler/) | | **Mobotix** | Langmeil, Germany (Konica Minolta) | Industrial / Critical Infrastructure | [Connection Guide](mobotix/) | | **Avigilon** | Vancouver, Canada (Motorola Solutions) | Enterprise / Critical Infrastructure | [Connection Guide](avigilon/) | | **AVTech** | Taipei, Taiwan | Commercial / Industrial | [Connection Guide](avtech/) | | **LILIN** | New Taipei City, Taiwan | Professional / Enterprise | [Connection Guide](lilin/) | | **Zavio** | Hsinchu, Taiwan | Professional / SMB | [Connection Guide](zavio/) | | **CP Plus** | Delhi, India | Enterprise / Commercial | [Connection Guide](cp-plus/) | | **Sanyo** | Osaka, Japan (now Panasonic) | Professional (discontinued) | [Connection Guide](sanyo/) | | **BrickCom** | Taipei, Taiwan | Professional / Industrial | [Connection Guide](brickcom/) | | **Edimax** | Taipei, Taiwan | Consumer / SMB | [Connection Guide](edimax/) | | **Uniview (UNV)** | Hangzhou, China | Enterprise / Government | [Connection Guide](uniview/) | | **Hanwha Vision** | Seoul, South Korea | Enterprise / Professional | [Connection Guide](hanwha/) | | **Tiandy** | Tianjin, China | Enterprise / SMB | [Connection Guide](tiandy/) | | **EZVIZ** | Hangzhou, China (Hikvision) | Consumer / Smart Home | [Connection Guide](ezviz/) | | **Wisenet** | Seoul, South Korea (Hanwha Vision) | Enterprise / Professional | [Connection Guide](wisenet/) | | **Annke** | Hong Kong | Consumer / Prosumer | [Connection Guide](annke/) | | **Imou** | Hangzhou, China (Dahua) | Consumer / Smart Home | [Connection Guide](imou/) | | **Wyze** | Kirkland, USA | Consumer (limited RTSP) | [Connection Guide](wyze/) | | **Aqara** | Shenzhen, China | Smart Home / HomeKit | [Connection Guide](aqara/) | | **Verkada** | San Mateo, USA | Enterprise / Cloud-managed | [Connection Guide](verkada/) | | **Rhombus** | Sacramento, USA | Enterprise / Cloud-managed | [Connection Guide](rhombus/) | | **Arlo** | Carlsbad, USA | Consumer (no RTSP) | [Connection Guide](arlo/) | | **Eufy Security** | Changsha, China (Anker) | Consumer / Smart Home | [Connection Guide](eufy/) | | **Tenda** | Shenzhen, China | Consumer / Budget | [Connection Guide](tenda/) | | **Mercusys** | Shenzhen, China (TP-Link) | Consumer / Budget | [Connection Guide](mercusys/) | ### Common RTSP URL Patterns by Brand For quick reference, here are the primary RTSP URL patterns for popular camera brands: | Brand | Primary RTSP URL Pattern | Default Port | | --- | --- | --- | | Hikvision | `rtsp://IP:554/Streaming/Channels/101` | 554 | | Dahua | `rtsp://IP:554/cam/realmonitor?channel=1&subtype=0` | 554 | | Axis | `rtsp://IP:554/axis-media/media.amp` | 554 | | Foscam | `rtsp://IP:88/videoMain` | 88 | | TP-Link (Tapo) | `rtsp://IP:554/stream1` | 554 | | Amcrest | `rtsp://IP:554/cam/realmonitor?channel=1&subtype=0` | 554 | | Reolink | `rtsp://IP:554/h264Preview_01_main` | 554 | | Ubiquiti | `rtsp://IP:7447/STREAM_TOKEN` | 7447 | | Samsung/Hanwha | `rtsp://IP:554/profile2/media.smp` | 554 | | Bosch | `rtsp://IP:554/video?inst=1` | 554 | | Vivotek | `rtsp://IP:554/live.sdp` | 554 | | Panasonic/i-PRO | `rtsp://IP:554/MediaInput/h264` | 554 | | Sony | `rtsp://IP:554/media/video1` | 554 | | Lorex | `rtsp://IP:554/cam/realmonitor?channel=1&subtype=0` | 554 | | D-Link | `rtsp://IP:554/live1.sdp` | 554 | | Honeywell | `rtsp://IP:554/h264` | 554 | | Pelco | `rtsp://IP:554//stream1` | 554 | | Cisco | `rtsp://IP:554/img/media.sav` | 554 | | Grandstream | `rtsp://IP:554/live/ch00_0` | 554 | | Swann | `rtsp://IP:554/live/h264` | 554 | | GeoVision | `rtsp://IP:8554//CH001.sdp` | 8554 | | ACTi | `rtsp://IP:7070//stream1` | 7070 | | Canon | `rtsp://IP:554/cam1/h264` | 554 | | FLIR (Teledyne) | `rtsp://IP:554/ch0` | 554 | | Milesight | `rtsp://IP:554//main` | 554 | | INSTAR | `rtsp://IP:554//11` | 554 | | Zmodo | `rtsp://IP:10554//tcp/av0_0` | 10554 | | Arecont Vision | `rtsp://IP:554/h264.sdp` | 554 | | JVC | `rtsp://IP:554/PSIA/Streaming/channels/0` | 554 | | Toshiba | `rtsp://IP:554/live.sdp` | 554 | | LG | `rtsp://IP:554/video1+audio1` | 554 | | Linksys | `rtsp://IP:554/img/media.sav` | 554 | | LTS | `rtsp://IP:554//Streaming/Channels/1` | 554 | | Q-See | `rtsp://IP:554/cam/realmonitor?channel=1&subtype=1` | 554 | | Speco | `rtsp://IP:554/1/stream1` | 554 | | EverFocus | `rtsp://IP:554//cgi-bin/rtspStreamOvf/0` | 554 | | ABUS | `rtsp://IP:554/video.mp4` | 554 | | Basler | `rtsp://IP:554/h264` | 554 | | Mobotix | `rtsp://IP:554/mobotix.h264` | 554 | | Avigilon | `rtsp://IP:554/defaultPrimary?streamType=u` | 554 | | AVTech | `rtsp://IP:554/live/h264` | 554 | | LILIN | `rtsp://IP:554/rtsph2641080p` | 554 | | Zavio | `rtsp://IP:554/video.mp4` | 554 | | CP Plus | `rtsp://IP:554/cam/realmonitor?channel=1&subtype=1` | 554 | | Sanyo | `rtsp://IP:554/VideoInput/1/h264/1` | 554 | | BrickCom | `rtsp://IP:554/channel1` | 554 | | Edimax | `rtsp://IP:554/ipcam_h264.sdp` | 554 | | Uniview (UNV) | `rtsp://IP:554/media/video1` | 554 | | Hanwha Vision | `rtsp://IP:554/profile2/media.smp` | 554 | | Tiandy | `rtsp://IP:554/cam/realmonitor?channel=1&subtype=0` | 554 | | EZVIZ | `rtsp://IP:554/h264/ch1/main/av_stream` | 554 | | Wisenet | `rtsp://IP:554/profile2/media.smp` | 554 | | Annke | `rtsp://IP:554/Streaming/Channels/101` | 554 | | Imou | `rtsp://IP:554/cam/realmonitor?channel=1&subtype=0` | 554 | | Wyze | `rtsp://IP:8554/live` | 8554 | | Aqara | `rtsp://IP:554/live/ch00_1` | 554 | | Verkada | N/A (cloud-only) | N/A | | Rhombus | `rtsp://IP:554/live` (if enabled) | 554 | | Arlo | N/A (no RTSP) | N/A | | Eufy Security | `rtsp://IP:554/live0` | 554 | | Tenda | `rtsp://IP:554/stream1` | 554 | | Mercusys | `rtsp://IP:554/stream1` | 554 | ## ONVIF Discovery Most modern IP cameras support **ONVIF (Open Network Video Interface Forum)**, which allows automatic camera discovery on your network. VisioForge SDK supports ONVIF discovery -- see our [ONVIF integration guide](../mediablocks/Sources/) for details. ## Get Started ### Install via NuGet Cross-platform (recommended)Windows-only (legacy DirectShow engine) ``` dotnet add package VisioForge.DotNet.VideoCapture dotnet add package VisioForge.CrossPlatform.Core.Windows.x64 ``` Swap the second package for the native runtime of your target OS — `VisioForge.CrossPlatform.Core.Linux.x64`, `.macOS`, `.Android` or `.iOS`. ``` dotnet add package VisioForge.DotNet.VideoCapture dotnet add package VisioForge.DotNet.Core.Redist.VideoCapture.x64 ``` ### Sample Projects Complete working examples for IP camera integration: - [IP Camera Preview (WinForms)](https://github.com/visioforge/.Net-SDK-s-samples/tree/master/Video%20Capture%20SDK/_CodeSnippets/ip-camera-preview) — Live camera view - [IP Camera Recording to MP4](https://github.com/visioforge/.Net-SDK-s-samples/tree/master/Video%20Capture%20SDK/_CodeSnippets/ip-camera-capture-mp4) — Record streams to file - [All .NET SDK Samples](https://github.com/visioforge/.Net-SDK-s-samples) — Full sample repository ## Related Resources - [RTSP Source Block Documentation](../mediablocks/Sources/) - [IP Camera Preview Tutorial](../videocapture/video-tutorials/ip-camera-preview/) - [IP Camera Recording to MP4](../videocapture/video-tutorials/ip-camera-capture-mp4/) - [Building Camera Applications with Media Blocks](../mediablocks/GettingStarted/camera/) - [Device Enumeration Guide](../mediablocks/GettingStarted/device-enum/) ---END OF PAGE--- ## INSTAR IP Camera RTSP URL and C# .NET Connection Guide **URL:** https://www.visioforge.com/help/docs/dotnet/camera-brands/instar/ **Description:** INSTAR IN-6xxx, IN-7xxx, IN-8xxx, IN-9xxx HD camera RTSP URL patterns for C# .NET. Stream and record with VisioForge Video Capture SDK integration. **Tags:** Video Capture SDK, Media Blocks SDK, .NET, Windows, macOS, Linux, Android, iOS, Capture, Streaming, IP Camera, RTSP, ONVIF, MJPEG, C# # How to Connect to INSTAR IP Camera in C# .NET [Video Capture SDK .Net](https://www.visioforge.com/video-capture-sdk-net) [Media Blocks SDK .Net](https://www.visioforge.com/media-blocks-sdk-net) ## Brand Overview **INSTAR** (INSTAR Deutschland GmbH) is a German IP camera manufacturer headquartered in Hanau, Germany. INSTAR specializes in affordable indoor and outdoor IP cameras for the consumer and small business market, with a strong presence in Europe, particularly Germany. INSTAR cameras are known for local storage options, MQTT smart home integration (Home Assistant, ioBroker, Node-RED), and straightforward setup. **Key facts:** - **Product lines:** IN-2xxx/3xxx/4xxx (legacy VGA), IN-5xxx (720p), IN-6xxx (720p HD), IN-7xxx (1080p Full HD), IN-8xxx (current 1080p+), IN-9xxx (current 4K/WQHD) - **Protocol support:** RTSP, HTTP, ONVIF (IN-6xxx and newer), MQTT - **Default RTSP port:** 554 - **Default credentials:** admin / instar (varies by model) - **ONVIF support:** Yes (IN-6xxx, IN-7xxx, IN-8xxx, IN-9xxx series) - **Video codecs:** H.265 (IN-9xxx), H.264 (IN-6xxx/7xxx/8xxx), MPEG-4 (IN-5xxx), MJPEG (legacy IN-2xxx/3xxx/4xxx) ## RTSP URL Patterns INSTAR cameras use a distinctive URL format with a **double forward slash** before the stream number. ### URL Format (HD Models) ``` rtsp://[USERNAME]:[PASSWORD]@[IP]:554//11 ``` Double forward slash INSTAR HD cameras use a **double forward slash** (`//`) before the stream number. Using a single slash will result in a connection failure. ### HD Models (IN-6xxx / IN-7xxx / IN-8xxx / IN-9xxx) | Stream | RTSP URL | Resolution | Notes | | --- | --- | --- | --- | | Main stream | `rtsp://IP:554//11` | Full resolution | H.264 / H.265 | | Sub stream | `rtsp://IP:554//12` | Lower resolution | Bandwidth-friendly | | Third stream | `rtsp://IP:554//13` | Mobile optimized | Lowest resolution | ### Model-Specific URLs | Model | RTSP URL | Resolution | Type | | --- | --- | --- | --- | | IN-6012 HD | `rtsp://IP:554//11` | 720p | Indoor pan/tilt | | IN-6014 HD | `rtsp://IP:554//11` | 720p | Indoor | | IN-7011 HD | `rtsp://IP:554//11` | 1080p | Indoor pan/tilt | | IN-8015 Full HD | `rtsp://IP:554//11` | 1080p | Indoor/Outdoor | | IN-9008 Full HD | `rtsp://IP:554//11` | 1080p+ | Outdoor PoE | | IN-9020 Full HD | `rtsp://IP:554//11` | WQHD/4K | Outdoor PoE | ### Older 720p Models (IN-5xxx -- MPEG-4) IN-5xxx cameras use a different RTSP path with MPEG-4 encoding: | Model | RTSP URL | Resolution | Notes | | --- | --- | --- | --- | | IN-5905 HD | `rtsp://IP:554/MediaInput/mpeg4` | 720p | Outdoor | | IN-5907 HD | `rtsp://IP:554/MediaInput/mpeg4` | 720p | Outdoor | ### Legacy Models (IN-2xxx / IN-3xxx / IN-4xxx -- HTTP Only) Legacy VGA-resolution INSTAR cameras do not support RTSP. They use HTTP-based streaming only: | Model Series | HTTP URL | Type | Notes | | --- | --- | --- | --- | | IN-2xxx/3xxx/4xxx | `http://IP/videostream.asf?user=USER&pwd=PASS&resolution=32&rate=0` | ASF stream | VGA resolution | | IN-2xxx/3xxx/4xxx | `http://IP/videostream.cgi?rate=11` | MJPEG | No audio | | IN-2xxx/3xxx/4xxx | `http://IP//iphone/11?USER:PASS&` | Mobile stream | iPhone-compatible | ## Connecting with VisioForge SDK Use your INSTAR camera's RTSP URL with any of the three SDK approaches shown in the [Quick Start Guide](../#quick-start-code): ``` // INSTAR IN-8015 Full HD, main stream -- note the double forward slash! var uri = new Uri("rtsp://192.168.1.50:554//11"); var username = "admin"; var password = "instar"; ``` For sub-stream access, use `//12` instead of `//11`. ## Snapshot and MJPEG URLs | Type | URL Pattern | Notes | | --- | --- | --- | | Snapshot (HD) | `http://IP/tmpfs/auto.jpg` | IN-6xxx/7xxx/8xxx/9xxx | | Snapshot (HD, auth) | `http://IP/snap.jpg?usr=USER&pwd=PASS` | With credentials | | Snapshot (legacy) | `http://IP/snapshot.cgi` | IN-2xxx/3xxx/4xxx | | Snapshot (legacy, auth) | `http://IP/snapshot.jpg?user=USER&pwd=PASS` | Legacy with credentials | | ASF Stream (legacy) | `http://IP/videostream.asf?user=USER&pwd=PASS&resolution=32&rate=0` | VGA ASF | | MJPEG Stream (legacy) | `http://IP/videostream.cgi?rate=11` | Legacy MJPEG | ## Troubleshooting ### Double forward slash is required The most common INSTAR connection issue is forgetting the **double forward slash** before the stream number. The correct URL is `rtsp://IP:554//11` (two slashes), not `rtsp://IP:554/11` (one slash). ### Legacy cameras have no RTSP support IN-2xxx, IN-3xxx, and IN-4xxx cameras are HTTP-only. They do not support RTSP at all. Use the ASF or MJPEG HTTP streaming URLs for these models. ### IN-5xxx uses a different RTSP path IN-5xxx cameras use `rtsp://IP:554/MediaInput/mpeg4` instead of the `//11` path used by newer HD models. If the `//11` URL fails on a 720p INSTAR camera, check whether your model is from the IN-5xxx series. ### MQTT and smart home integration INSTAR cameras support MQTT for integration with Home Assistant, ioBroker, and Node-RED. MQTT is used for camera control and event notifications, not for video streaming. For video integration with smart home platforms, use the RTSP URL. ### PoE availability IN-8xxx and IN-9xxx outdoor models support Power over Ethernet (PoE), allowing a single cable for both power and data. Indoor models typically require a separate power adapter. ### Credentials vary by model While the common default credentials are admin / instar, some models may use different defaults. Check the camera's documentation or label for the factory credentials. INSTAR cameras typically require changing the default password during initial setup. ## FAQ **What is the default RTSP URL for INSTAR cameras?** For current HD models (IN-6xxx, IN-7xxx, IN-8xxx, IN-9xxx), the URL is `rtsp://admin:instar@CAMERA_IP:554//11`. Note the double forward slash before `11`. For IN-5xxx models, use `rtsp://admin:instar@CAMERA_IP:554/MediaInput/mpeg4`. **Do all INSTAR cameras support RTSP?** No. Legacy models (IN-2xxx, IN-3xxx, IN-4xxx) are VGA-resolution cameras that only support HTTP-based streaming in ASF or MJPEG format. All IN-5xxx and newer cameras support RTSP. **What is the difference between stream //11, //12, and //13?** Stream `//11` is the main (highest quality) stream, `//12` is a lower-resolution sub stream suitable for remote viewing over limited bandwidth, and `//13` is a mobile-optimized third stream with the lowest resolution. **Do INSTAR cameras support ONVIF?** Yes. ONVIF is supported on IN-6xxx, IN-7xxx, IN-8xxx, and IN-9xxx series cameras. Legacy models do not support ONVIF. You can use the VisioForge SDK's ONVIF features for camera discovery and PTZ control on supported models. **Can I integrate INSTAR cameras with Home Assistant?** Yes. INSTAR cameras support MQTT, making them easy to integrate with Home Assistant, ioBroker, and Node-RED for automation and event-driven actions. For video streaming in Home Assistant, use the RTSP URL in a generic camera integration. ## Related Resources - [All Camera Brands — RTSP URL Directory](../) - [ABUS Connection Guide](../abus/) — German consumer / smart home cameras - [Save Original RTSP Stream](../../mediablocks/Guides/rtsp-save-original-stream/) — Record INSTAR streams without re-encoding - [IP Camera Preview Tutorial](../../videocapture/video-tutorials/ip-camera-preview/) - [SDK Installation & Samples](../#get-started) ---END OF PAGE--- ## JVC IP Camera RTSP URL and C# .NET Integration Guide **URL:** https://www.visioforge.com/help/docs/dotnet/camera-brands/jvc/ **Description:** JVC VN-H, VN-T, VN-C, and VN-X network camera RTSP URL patterns for C# .NET. Stream and record with VisioForge Video Capture SDK integration code. **Tags:** Video Capture SDK, Media Blocks SDK, .NET, Windows, macOS, Linux, Android, iOS, Capture, Streaming, IP Camera, RTSP, ONVIF, H.264, MJPEG, C# # How to Connect to JVC IP Camera in C# .NET [Video Capture SDK .Net](https://www.visioforge.com/video-capture-sdk-net) [Media Blocks SDK .Net](https://www.visioforge.com/media-blocks-sdk-net) ## Brand Overview **JVC** (JVCKENWOOD Corporation) is a Japanese electronics company headquartered in Yokohama, Japan. JVC's Professional Systems Division produced the VN-series IP cameras for surveillance applications. JVC exited the standalone IP camera market around 2015, but many VN-series cameras remain in active service across enterprise and government installations. These cameras are known for their robust PSIA protocol support and reliable performance. **Key facts:** - **Product lines:** VN-H Series (VN-H37, VN-H137, VN-H237, VN-H657), VN-T Series (VN-T216U), VN-X Series (VN-X35U, VN-X235U), VN-C Series (VN-C20U) - **Protocol support:** RTSP, ONVIF (VN-H/VN-T series), PSIA, HTTP/CGI - **Default RTSP port:** 554 - **Default credentials:** admin / jvc (varies by model) - **ONVIF support:** Yes (VN-H and VN-T series) - **Video codecs:** H.264 (VN-H/VN-T series), MPEG-4 (older VN-C models) Discontinued Product Line JVC exited the IP camera market around 2015. While VN-series cameras remain widely deployed, firmware updates are no longer available. Consider network segmentation and firewall rules to protect these cameras, as they will not receive security patches. ## RTSP URL Patterns ### Standard URL Formats JVC cameras support multiple RTSP URL patterns depending on the model series: ``` rtsp://[USERNAME]:[PASSWORD]@[IP]:554/PSIA/Streaming/channels/0?videoCodecType=H.264 ``` | URL Pattern | Protocol | Description | | --- | --- | --- | | `rtsp://IP:554/PSIA/Streaming/channels/0?videoCodecType=H.264` | PSIA | Primary H.264 stream (most VN-H models) | | `rtsp://IP:554/PSIA/Streaming/channels/CHANNEL` | PSIA | PSIA stream by channel number | | `rtsp://IP:554/video.h264` | H.264 | Direct H.264 stream (VN Series general) | | `rtsp://IP:554/1/stream1` | H.264 | Alternative stream URL (VN-T216U) | | `rtsp://IP:554//livestream` | H.264 | Live stream URL (VN-H57) | PSIA Channel Numbering JVC cameras use zero-based channel numbering for PSIA URLs. Channel 0 is the first (and usually only) video channel. This differs from most other brands that start channel numbering at 1. ### PSIA Channel URLs | Channel | URL | Description | | --- | --- | --- | | Channel 0 (primary) | `rtsp://IP:554/PSIA/Streaming/channels/0?videoCodecType=H.264` | First video channel (main stream) | | Channel 1 | `rtsp://IP:554/PSIA/Streaming/channels/1?videoCodecType=H.264` | Second video channel (sub stream, if available) | ### Camera Models | Model Series | Resolution | Main Stream URL | Codec | | --- | --- | --- | --- | | VN-H37 (HD dome) | 1920x1080 | `rtsp://IP:554/PSIA/Streaming/channels/0?videoCodecType=H.264` | H.264 | | VN-H137 (HD bullet) | 1920x1080 | `rtsp://IP:554/PSIA/Streaming/channels/0?videoCodecType=H.264` | H.264 | | VN-H237 (HD dome) | 1920x1080 | `rtsp://IP:554/PSIA/Streaming/channels/0?videoCodecType=H.264` | H.264 | | VN-H657 (HD PTZ) | 1920x1080 | `rtsp://IP:554/PSIA/Streaming/channels/0?videoCodecType=H.264` | H.264 | | VN-T216U (HD box) | 1920x1080 | `rtsp://IP:554/1/stream1` | H.264 | | VN-X35U (network camera) | 1280x960 | `rtsp://IP:554/video.h264` | H.264 | | VN-X235U (network camera) | 1920x1080 | `rtsp://IP:554/video.h264` | H.264 | | VN-C20U (legacy network) | 640x480 | N/A (HTTP snapshot only) | MJPEG | ## Connecting with VisioForge SDK Use your JVC camera's RTSP URL with any of the three SDK approaches shown in the [Quick Start Guide](../#quick-start-code): ``` // JVC VN-H Series, PSIA H.264 main stream var uri = new Uri("rtsp://192.168.1.90:554/PSIA/Streaming/channels/0?videoCodecType=H.264"); var username = "admin"; var password = "jvc"; ``` For VN-T series cameras using the alternative URL format: ``` // JVC VN-T216U, alternative stream URL var uri = new Uri("rtsp://192.168.1.90:554/1/stream1"); ``` ## Snapshot and MJPEG URLs | Type | URL Pattern | Notes | | --- | --- | --- | | JPEG Snapshot | `http://IP/cgi-bin/video.jpg` | Standard snapshot (most models) | | Java Applet Snapshot | `http://IP/java.jpg` | Java-based snapshot (legacy) | | API Snapshot | `http://IP/api/video?encode=jpeg` | API-based JPEG capture (VN-X series) | | MJPEG Stream | `http://IP/api/video?encode=jpeg&framerate=15&boundary=on` | Continuous MJPEG via API | ### Model-Specific Snapshot URLs | Model Series | Snapshot URL | Notes | | --- | --- | --- | | VN-H Series | `http://IP/cgi-bin/video.jpg` | CGI-based snapshot | | VN-T Series | `http://IP/cgi-bin/video.jpg` | CGI-based snapshot | | VN-C Series (VN-C20U) | `http://IP/cgi-bin/video.jpg` | CGI-based snapshot | | VN-X Series (VN-X35U/X235U) | `http://IP/api/video?encode=jpeg` | API-based snapshot | ## Troubleshooting ### PSIA channel numbering starts at 0 Unlike most camera brands where channel numbering starts at 1, JVC uses **zero-based** PSIA channel numbering. If you are porting code from another brand: - Channel 0 = First video channel (equivalent to Channel 1 on other brands) - Channel 1 = Second video channel (sub stream or secondary sensor) ### Default credentials not working JVC cameras ship with different default credentials depending on the model and firmware version: 1. Try `admin` / `jvc` (most common) 2. Try `admin` / `admin` 3. Try accessing the web interface at `http://CAMERA_IP` to reset or verify credentials 4. Some models ship with no default password - access the web interface first to set one ### Firmware updates unavailable Since JVC discontinued its IP camera line around 2015, firmware updates are no longer available. To mitigate security risks: - Place cameras on an isolated VLAN or network segment - Use firewall rules to restrict access to camera ports - Disable UPnP and any cloud connectivity features - Consider replacing end-of-life cameras with currently supported models ### VN-C series HTTP-only access The older VN-C series cameras (such as VN-C20U) do not support RTSP streaming and only provide HTTP-based MJPEG access. Use the HTTP snapshot or MJPEG stream URLs for these models instead of RTSP. ### Multiple URL formats on VN-T series The VN-T216U supports multiple RTSP URL formats. If one does not work, try alternatives: 1. `rtsp://IP:554/1/stream1` (preferred) 2. `rtsp://IP:554/PSIA/Streaming/channels/0?videoCodecType=H.264` (PSIA) 3. `rtsp://IP:554/video.h264` (direct H.264) ## FAQ **What is the default RTSP URL for JVC cameras?** For most VN-H series cameras, the primary RTSP URL is `rtsp://admin:jvc@CAMERA_IP:554/PSIA/Streaming/channels/0?videoCodecType=H.264`. The VN-T series uses `rtsp://IP:554/1/stream1` as an alternative. VN-X series models use `rtsp://IP:554/video.h264`. **Are JVC IP cameras still supported?** JVC exited the standalone IP camera market around 2015. The cameras remain functional but no longer receive firmware updates or official support. Many VN-series cameras are still actively deployed in surveillance systems worldwide. **Do JVC cameras support ONVIF?** The VN-H and VN-T series cameras support ONVIF Profile S. Older VN-C and some VN-X models do not support ONVIF and rely on PSIA or proprietary CGI interfaces instead. **Why does PSIA channel numbering start at 0?** JVC implements zero-based PSIA channel numbering, meaning the first video channel is channel 0 rather than channel 1. This is specific to JVC's PSIA implementation and differs from most other camera manufacturers. When migrating from another brand, adjust your channel numbers accordingly. ## Related Resources - [All Camera Brands — RTSP URL Directory](../) - [Sony Connection Guide](../sony/) — Japanese enterprise cameras - [Canon Connection Guide](../canon/) — Japanese professional cameras - [IP Camera Preview Tutorial](../../videocapture/video-tutorials/ip-camera-preview/) - [SDK Installation & Samples](../#get-started) ---END OF PAGE--- ## LG IP Camera RTSP URL Setup and Streaming in C# .NET **URL:** https://www.visioforge.com/help/docs/dotnet/camera-brands/lg/ **Description:** LG SmartIP, LW, and LV series camera RTSP URL patterns for C# .NET. Stream wireless and wired models using VisioForge Video Capture SDK integration. **Tags:** Video Capture SDK, Media Blocks SDK, .NET, Windows, macOS, Linux, Android, iOS, Capture, Streaming, Webcam, IP Camera, RTSP, ONVIF, H.264, MJPEG, C# # How to Connect to LG IP Camera in C# .NET [Video Capture SDK .Net](https://www.visioforge.com/video-capture-sdk-net) [Media Blocks SDK .Net](https://www.visioforge.com/media-blocks-sdk-net) ## Brand Overview **LG Electronics** is a South Korean multinational electronics company headquartered in Seoul, South Korea. LG produced IP cameras under the **SmartIP** brand and the **LW/LV series** for the professional security market. LG has since largely exited the IP camera business and sold its security division. A limited number of LG cameras remain deployed in commercial and enterprise installations. **Key facts:** - **Product lines:** LW Series (wireless dome/bullet), LV Series (wired), SmartIP (enterprise) - **Protocol support:** RTSP, HTTP/CGI, ONVIF (SmartIP series), PSIA (select models) - **Default RTSP port:** 554 - **Default credentials:** admin / admin - **ONVIF support:** Yes (SmartIP series), limited or absent on LW/LV series - **Video codecs:** H.264 (LW130W, LW332, SmartIP series), MJPEG (older models) Discontinued Product Line LG has exited the IP camera market and sold its security division. No new firmware updates or official support are available. Many database entries labeled "LG" are actually LG smartphones used as IP cameras via third-party apps -- only actual LG camera models (LW, LV, SmartIP, 7210R) are covered here. ## RTSP URL Patterns ### Standard URL Formats LG cameras use several different RTSP URL patterns depending on the model series: ``` rtsp://[USERNAME]:[PASSWORD]@[IP]:554/video1+audio1 ``` | URL Pattern | Description | | --- | --- | | `video1+audio1` | H.264 video with audio (LW series, 7210R) | | `/` (root) | Root stream (LV series) | | `//Master-0` | Master stream (LW130W alternate) | | `camera.stm` | Camera stream (LW332) | | `live1.sdp` | Live SDP stream (LW332 alternate) | | PSIA channel URL | Enterprise PSIA streaming (SmartIP) | ### Camera Models - RTSP Streams | Model | Type | Main Stream URL | Notes | | --- | --- | --- | --- | | LW130W | Wireless Dome | `rtsp://IP:554/video1+audio1` | H.264 + audio | | LW130W | Wireless Dome | `rtsp://IP//Master-0` | Alternate Master stream | | LW332 | Wireless Bullet | `rtsp://IP:554/camera.stm` | Camera stream | | LW332 | Wireless Bullet | `rtsp://IP:554/live1.sdp` | Alternate SDP stream | | LVW700 | Wired Dome | `rtsp://IP:554/` | Root stream | | LVW701 | Wired Dome | `rtsp://IP:554/` | Root stream | | 7210R | IP Camera | `rtsp://IP:554/video1+audio1` | H.264 + audio | | SmartIP | Enterprise | `rtsp://IP:554/PSIA/Streaming/channels/2?videoCodecType=H.264` | PSIA H.264 stream | ### Models by Series #### LW Series (Wireless Cameras) | Model | Streaming URLs | Protocol | | --- | --- | --- | | LW130W | `video1+audio1` or `//Master-0` | RTSP + HTTP | | LW332 | `camera.stm` or `live1.sdp` | RTSP + HTTP | #### LV Series (Wired Cameras) | Model | Streaming URLs | Protocol | | --- | --- | --- | | LVW700 | Root stream (`rtsp://IP:554/`) | RTSP | | LVW701 | Root stream (`rtsp://IP:554/`) | RTSP | #### SmartIP Series (Enterprise Cameras) | Model | Streaming URLs | Protocol | | --- | --- | --- | | SmartIP models | PSIA channel URL | RTSP + PSIA + ONVIF | #### Standalone Models | Model | Streaming URLs | Protocol | | --- | --- | --- | | 7210R | `video1+audio1` | RTSP | ### Alternative URL Formats | URL Pattern | Models | Notes | | --- | --- | --- | | `rtsp://IP:554/video1+audio1` | LW130W, 7210R | Standard (recommended for these models) | | `rtsp://IP//Master-0` | LW130W | Alternate; note double-slash, no port | | `rtsp://IP:554/camera.stm` | LW332 | Standard for LW332 | | `rtsp://IP:554/live1.sdp` | LW332 | Alternate SDP format | | `rtsp://IP:554/` | LVW700, LVW701 | Root stream (unusual but valid) | | `rtsp://IP:554/PSIA/Streaming/channels/2?videoCodecType=H.264` | SmartIP | PSIA enterprise streaming | Root Stream URL The LVW700 and LVW701 use a root RTSP URL (`rtsp://IP:554/`) with no path component. This is unusual but valid. Make sure your RTSP client does not strip the trailing slash or add a default path. ## Connecting with VisioForge SDK Use your LG camera's RTSP URL with any of the three SDK approaches shown in the [Quick Start Guide](../#quick-start-code): ``` // LG LW130W, H.264 + audio stream var uri = new Uri("rtsp://192.168.1.90:554/video1+audio1"); var username = "admin"; var password = "admin"; ``` For LW332 cameras, use `camera.stm` or `live1.sdp` as the stream path instead. ## Snapshot and MJPEG URLs | Type | URL Pattern | Notes | | --- | --- | --- | | CGI Snapshot | `http://IP/snapshot.cgi` | Standard CGI snapshot | | JPEG Snapshot | `http://IP/snapshot.jpg` | Direct JPEG (LW130W) | | Video Feed | `http://IP/videofeed` | Live video feed | | MJPEG Stream | `http://IP/video?submenu=mjpg` | Continuous MJPEG stream | | Profile Video | `http://IP/video?profile=CHANNEL` | Profile-based video selection | ## Troubleshooting ### Confusing LG cameras with LG smartphones Many RTSP camera databases contain entries labeled "LG" that are actually **LG smartphones** (P350, P509, P970, Nexus 4, Optimus V, LS670) running third-party IP camera apps like "IP Webcam." These are not actual LG IP cameras. Look for model numbers starting with **LW**, **LV**, **SmartIP**, or **7210R** to identify genuine LG security cameras. ### Root stream URL not connecting The LVW700 and LVW701 cameras use a bare root URL (`rtsp://IP:554/`) with no stream path. Some RTSP client libraries may not handle this correctly. If you experience connection issues: 1. Ensure the trailing slash is included 2. Try specifying the URL as `rtsp://admin:admin@192.168.1.90:554/` 3. Verify the camera is responding on port 554 using a network scanner ### Multiple URL formats per model Some LG cameras (particularly the LW130W and LW332) support multiple RTSP URL formats. If one format fails, try the alternate: - **LW130W:** Try `video1+audio1` first, then `//Master-0` - **LW332:** Try `camera.stm` first, then `live1.sdp` ### PSIA streaming on SmartIP models SmartIP enterprise cameras support PSIA (Physical Security Interoperability Alliance) streaming. The PSIA URL format is: ``` rtsp://admin:admin@192.168.1.90:554/PSIA/Streaming/channels/2?videoCodecType=H.264 ``` Change the channel number to select different streams. PSIA requires authentication via the URL or HTTP digest. ### No firmware updates available LG has exited the security camera market. No new firmware, patches, or official support channels are available. If you encounter bugs or security vulnerabilities, consider replacing the camera with a currently supported model. ## FAQ **What is the default RTSP URL for LG IP cameras?** It depends on the model series. For LW130W and 7210R cameras, use `rtsp://admin:admin@CAMERA_IP:554/video1+audio1`. For LW332, use `rtsp://admin:admin@CAMERA_IP:554/camera.stm`. For LVW700/LVW701, use `rtsp://admin:admin@CAMERA_IP:554/`. Each model series has a different URL pattern. **Are LG IP cameras still supported?** No. LG sold its security division and exited the IP camera market. No firmware updates, new models, or official technical support are available. Existing cameras continue to function but will not receive security patches or feature updates. **Do LG cameras support ONVIF?** Only the SmartIP enterprise series supports ONVIF. The consumer LW and LV series cameras have limited or no ONVIF support. SmartIP cameras also support PSIA as an alternative interoperability protocol. **Why do I see LG phone models in IP camera databases?** Many RTSP URL databases list LG smartphone models (Nexus 4, Optimus V, P509, etc.) as "LG cameras." These are actually phones running third-party apps like "IP Webcam" that turn the phone into a makeshift security camera. They are not actual LG IP camera products and use completely different URL patterns determined by the app. ## Related Resources - [All Camera Brands — RTSP URL Directory](../) - [Samsung Connection Guide](../samsung/) — Korean enterprise cameras - [IP Camera Preview Tutorial](../../videocapture/video-tutorials/ip-camera-preview/) - [SDK Installation & Samples](../#get-started) ---END OF PAGE--- ## LILIN IP Camera RTSP URL Patterns and C# .NET Setup **URL:** https://www.visioforge.com/help/docs/dotnet/camera-brands/lilin/ **Description:** LILIN LR, Z, D, S, and P series camera RTSP URL patterns for C# .NET. Includes snapshot endpoints and VisioForge SDK streaming integration code. **Tags:** Video Capture SDK, Media Blocks SDK, .NET, Windows, macOS, Linux, Android, iOS, Capture, Streaming, IP Camera, RTSP, ONVIF, H.264, MJPEG, C# # How to Connect to LILIN IP Camera in C# .NET [Video Capture SDK .Net](https://www.visioforge.com/video-capture-sdk-net) [Media Blocks SDK .Net](https://www.visioforge.com/media-blocks-sdk-net) ## Brand Overview **LILIN** (Merit LILIN Co., Ltd.) is a Taiwanese professional security camera manufacturer headquartered in New Taipei City, Taiwan. Founded in 1980, LILIN is one of the oldest IP camera manufacturers in the world. The company is known for professional-grade surveillance cameras with distinctive RTSP URL patterns that encode the resolution directly in the URL path. **Key facts:** - **Product lines:** Z Series (bullet), S Series (speed dome), D Series (dome), LR Series (IR), P Series (panoramic) - **Protocol support:** RTSP, ONVIF, HTTP/CGI - **Default RTSP port:** 554 - **Default credentials:** admin / pass - **ONVIF support:** Yes (most current models) - **Video codecs:** H.264, MJPEG - **Unique URL pattern:** Resolution encoded in RTSP path (e.g., `rtsph264720p`, `rtsph2641080p`) Resolution-Based RTSP Paths LILIN uses a unique URL pattern where the resolution is encoded directly in the RTSP path (e.g., `rtsph264720p` for 720p, `rtsph2641080p` for 1080p). Make sure to use the correct resolution suffix for your camera model. ## RTSP URL Patterns ### Standard URL Format LILIN cameras use a resolution-based RTSP path format: ``` rtsp://[USERNAME]:[PASSWORD]@[IP]:554/rtsph2641080p ``` | Parameter | Value | Description | | --- | --- | --- | | `rtsph264720p` | 720p stream | H.264 at 1280x720 resolution | | `rtsph2641080p` | 1080p stream | H.264 at 1920x1080 resolution | | `rtsph2641024p` | 1024p stream | H.264 at 1280x1024 resolution (note: double-slash in some models) | ### Camera Models | Model | Resolution | Main Stream URL | Notes | | --- | --- | --- | --- | | LR7022E4 (IR bullet) | 1920x1080 | `rtsp://IP:554/rtsph2641080p` | LR series, 1080p | | LR7722X (IR bullet) | 1920x1080 | `rtsp://IP:554/rtsph2641080p` | LR series, 1080p | | IPR712M4.3 (PTZ) | 1280x1024 | `rtsp://IP:554//rtsph2641024p` | IPR series, double-slash path | | Z Series (bullet) | 1920x1080 | `rtsp://IP:554/rtsph2641080p` | Outdoor bullet cameras | | D Series (dome) | 1920x1080 | `rtsp://IP:554/rtsph2641080p` | Indoor/outdoor dome | | S Series (speed dome) | 1920x1080 | `rtsp://IP:554/rtsph2641080p` | PTZ speed dome | ### Alternative URL Formats Some LILIN models or firmware versions support these alternative URLs: | URL Pattern | Notes | | --- | --- | | `rtsp://IP:554/rtsph2641080p` | Standard 1080p (recommended) | | `rtsp://IP:554/rtsph264720p` | 720p stream | | `rtsp://IP:554//rtsph2641024p` | 1024p stream (double-slash, some PTZ models) | ## Connecting with VisioForge SDK Use your LILIN camera's RTSP URL with any of the three SDK approaches shown in the [Quick Start Guide](../#quick-start-code): ``` // LILIN LR7022E4, 1080p main stream var uri = new Uri("rtsp://192.168.1.90:554/rtsph2641080p"); var username = "admin"; var password = "pass"; ``` For 720p access, use `rtsph264720p` instead of `rtsph2641080p`. ## Snapshot and MJPEG URLs | Type | URL Pattern | Notes | | --- | --- | --- | | JPEG Snapshot (VGA) | `http://IP/getimage?camera=CHANNEL&fmt=vga` | VGA resolution snapshot | | Snapshot by Channel | `http://IP/getimage[CHANNEL]` | Replace CHANNEL with camera number | | Quick Snapshot | `http://IP/snap` | Simple snapshot URL | | CGI Snapshot | `http://IP/cgi-bin/net_jpeg.cgi?ch=CHANNEL` | CGI-based snapshot | | Auth Snapshot | `http://IP/snapshot.jpg?user=USER&pwd=PASS` | URL-based authentication | | Direct Image | `http://IP/image/CHANNEL.jpg` | Direct JPEG image by channel | ## Troubleshooting ### "401 Unauthorized" error LILIN cameras ship with default credentials of `admin` / `pass`. If you have changed the password through the web interface, ensure you update the credentials in your RTSP URL. 1. Access the camera at `http://CAMERA_IP` in a browser 2. Log in with your credentials 3. Verify the RTSP settings under the network configuration section ### Double-slash in RTSP path Some LILIN models, particularly the IPR PTZ series, require a double-slash (`//`) before the resolution path. If a single-slash URL fails: - Try `rtsp://IP:554//rtsph2641024p` instead of `rtsp://IP:554/rtsph2641024p` - This is commonly seen with 1024p resolution models ### Choosing the correct resolution suffix LILIN cameras do not use `subtype=0/1` like many other brands. Instead, the stream resolution is selected by changing the URL path: - `rtsph264720p` for 720p (1280x720) - `rtsph2641080p` for 1080p (1920x1080) - `rtsph2641024p` for 1024p (1280x1024) If you specify a resolution your camera does not support, the connection will fail. ### Port 554 connection refused Verify that RTSP is enabled on the camera: - Web interface: Check **Network > RTSP** settings - Confirm port 554 is not blocked by a firewall - Default RTSP port is 554 ## FAQ **What is the default RTSP URL for LILIN cameras?** The most common URL is `rtsp://admin:pass@CAMERA_IP:554/rtsph2641080p` for the 1080p main stream. Replace the resolution suffix (`rtsph2641080p`) with the appropriate value for your camera's resolution. **Do LILIN cameras support ONVIF?** Yes. Most current LILIN models support ONVIF, which provides an alternative method for discovering and connecting to the camera without needing brand-specific URL patterns. **Why does LILIN use a different RTSP URL format?** LILIN encodes the resolution directly in the RTSP path rather than using channel/subtype parameters like Dahua or Hikvision. This is a proprietary design choice. The format is straightforward once you know which resolution suffix your camera model supports. **What are the default login credentials for LILIN cameras?** The default username is `admin` and the default password is `pass`. It is recommended to change these credentials after initial setup for security purposes. ## Related Resources - [All Camera Brands — RTSP URL Directory](../) - [AVTech Connection Guide](../avtech/) — Taiwanese industrial cameras - [BrickCom Connection Guide](../brickcom/) — Taiwanese industrial cameras - [RTSP Camera Integration Guide](../../videocapture/video-sources/ip-cameras/rtsp/) — LILIN RTSP stream configuration - [IP Camera Preview Tutorial](../../videocapture/video-tutorials/ip-camera-preview/) - [SDK Installation & Samples](../#get-started) ---END OF PAGE--- ## Linksys IP Camera RTSP URL Patterns and C# .NET Setup **URL:** https://www.visioforge.com/help/docs/dotnet/camera-brands/linksys/ **Description:** Connect to Linksys WVC, PVC, and LCAB cameras in C# .NET with RTSP URL patterns, ASF/MJPEG streams, and code samples for discontinued WVC series models. **Tags:** Video Capture SDK, Media Blocks SDK, .NET, Windows, macOS, Linux, Android, iOS, Capture, Streaming, IP Camera, RTSP, ONVIF, MP4, H.264, MJPEG, C# # How to Connect to Linksys IP Camera in C# .NET [Video Capture SDK .Net](https://www.visioforge.com/video-capture-sdk-net) [Media Blocks SDK .Net](https://www.visioforge.com/media-blocks-sdk-net) ## Brand Overview **Linksys** is an American networking company based in Irvine, California. Originally acquired by Cisco Systems in 2003, the brand was sold to Belkin (a Foxconn subsidiary) in 2013. During the Cisco ownership years, Linksys produced the popular **WVC (Wireless Video Camera)** series of IP cameras for the consumer and prosumer market. The camera product line was discontinued around 2014, but many units remain deployed and operational. Because Linksys was a Cisco brand, its cameras share identical URL patterns and firmware with Cisco consumer camera products. The `.sav` extension in RTSP URLs is a proprietary Cisco/Linksys endpoint format. **Key facts:** - **Product lines:** WVC Series (WVC54G, WVC54GC, WVC54GCA, WVC80N, WVC200, WVC210, WVC2300), PVC Series (PVC2300), LCAB Series - **Protocol support:** RTSP, HTTP/ASF, MJPEG, MMS (Windows Media) - **Default RTSP port:** 554 - **Default credentials:** admin / admin - **ONVIF support:** Limited (LCAB series only) - **Video codecs:** MPEG-4/ASF (WVC series), H.264 (newer models), MJPEG Discontinued product line Linksys IP cameras were discontinued around 2014. No new firmware updates or official support are available. The information on this page is provided for legacy deployments. Many WVC models require Internet Explorer with ActiveX for their web interface. Linksys = Cisco consumer cameras Linksys cameras use the same URL patterns as Cisco consumer cameras since Linksys was a Cisco brand. See our [Cisco connection guide](../cisco/) for additional details and enterprise Cisco camera models. ## RTSP URL Patterns ### Standard URL Format Most Linksys cameras use the Cisco `/img/media.sav` RTSP path: ``` rtsp://[USERNAME]:[PASSWORD]@[IP]:554/img/media.sav ``` Unusual `.sav` extension The `.sav` extension is a proprietary Cisco/Linksys RTSP endpoint -- it is not a standard media file format. Do not confuse it with a file download URL. ### RTSP URLs by Model | Model | RTSP URL | Codec | Notes | | --- | --- | --- | --- | | WVC54GCA | `rtsp://IP:554/img/media.sav` | MPEG-4 | Wireless-G, 640x480 | | WVC80N | `rtsp://IP:554/img/media.sav` | MPEG-4 | Wireless-N, 640x480 | | WVC80N (alt) | `rtsp://IP:554/img/video.sav` | MPEG-4 | Alternative video endpoint | | WVC210 | `rtsp://IP:554/img/media.sav` | MPEG-4 | Wireless-G PTZ | | WVC200 | `rtsp://IP:554/img/media.sav` | MPEG-4 | Wireless-G | | PVC2300 | `rtsp://IP:554/video.mp4` | MPEG-4/H.264 | Small business box camera | | LCAB03VLNOD | `rtsp://IP:554//ONVIF/channel2` | H.264 | ONVIF-enabled outdoor camera | ### Model Family Summary | Model Family | RTSP Stream | HTTP ASF | MJPEG | Snapshot CGI | | --- | --- | --- | --- | --- | | WVC54G / WVC54GC / WVC54GCA | `/img/media.sav` | Yes | Yes | Yes | | WVC80N | `/img/media.sav`, `/img/video.sav` | Yes | Yes | -- | | WVC200 / WVC210 | `/img/media.sav` | Yes | Yes | Yes | | WVC2300 | `/img/media.sav` | Yes | -- | -- | | PVC2300 | `/video.mp4` | Yes | -- | -- | | LCAB series | `//ONVIF/channel2` | -- | -- | -- | ## Connecting with VisioForge SDK Use your Linksys camera's RTSP URL with any of the three SDK approaches shown in the [Quick Start Guide](../#quick-start-code): ``` // Linksys WVC80N, primary RTSP stream var uri = new Uri("rtsp://192.168.1.60:554/img/media.sav"); var username = "admin"; var password = "admin"; ``` For PVC2300 cameras, use `/video.mp4` instead of `/img/media.sav`. ## Snapshot and MJPEG URLs | Type | URL Pattern | Compatible Models | | --- | --- | --- | | ASF Video Stream | `http://IP/img/video.asf` | WVC54G, WVC54GC, WVC54GCA, WVC80N, WVC200, WVC210, WVC11b | | MJPEG Stream | `http://IP/img/video.mjpeg` | WVC54GC, WVC54GCA, WVC80N, WVC200, WVC210 | | MJPEG Single Frame | `http://IP/img/mjpeg.jpg` | Most WVC models | | MJPEG CGI | `http://IP/img/mjpeg.cgi` | Most WVC models | | MJPEG (uppercase) | `http://IP/MJPEG.CGI` | Some WVC models | | High-Res Snapshot | `http://IP/img/snapshot.cgi?size=3` | WVC54GCA, WVC200, WVC210 | | Medium Snapshot | `http://IP/img/snapshot.cgi?size=2` | WVC54GCA, WVC200, WVC210 | | VGA Snapshot | `http://IP/img/snapshot.cgi?img=vga` | WVC54GCA, WVC200, WVC210 | | Alternative ASF | `http://IP/videostream.asf` | WVC54GC, WVC80N | | MMS Stream | `mms://IP/img/video.asf` | Legacy Windows Media (all WVC models) | HTTP streams as RTSP fallback Many Linksys WVC cameras work more reliably with HTTP-based ASF or MJPEG streams than with RTSP. If the RTSP URL is unresponsive, try the ASF stream at `http://IP/img/video.asf` as a fallback. ## Troubleshooting ### RTSP stream not connecting Linksys WVC cameras have limited RTSP support. Many models primarily serve video over HTTP using ASF (Advanced Streaming Format) rather than true RTSP: 1. Verify the camera IP address and that port 554 is open 2. Confirm RTSP is enabled in the camera's web interface 3. Try the HTTP ASF stream (`http://IP/img/video.asf`) as an alternative 4. Some models require the web interface to be accessed first (via Internet Explorer with ActiveX) before RTSP becomes available ### ASF stream requires specific handling The ASF (Advanced Streaming Format) streams from WVC cameras use a Microsoft proprietary container. The VisioForge SDK handles ASF streams automatically. If you encounter issues: - Ensure you are connecting via HTTP, not RTSP, for ASF URLs - ASF streams may require Windows Media components or LAV filters on some systems ### MMS protocol streams The `mms://` protocol URLs are Windows Media-specific and only work with Windows Media Player or compatible decoders. For modern applications, use the HTTP ASF URL (`http://IP/img/video.asf`) instead of the MMS equivalent. ### Web interface requires Internet Explorer Many WVC models require Internet Explorer with ActiveX controls for their web configuration interface. Use Internet Explorer or an ActiveX-compatible browser to access camera settings. The RTSP and HTTP streams themselves work with any client. ### Camera not discoverable on network Linksys cameras do not support modern discovery protocols (except LCAB series with ONVIF). To find the camera: 1. Check your router's DHCP lease table for the camera's IP address 2. Use the Linksys Camera Utility (if still available) for discovery 3. Try the default IP address assigned by the camera (check the model's manual) 4. Use a network scanner such as Advanced IP Scanner ## FAQ **What is the default RTSP URL for Linksys cameras?** For most Linksys WVC cameras, use `rtsp://admin:admin@CAMERA_IP:554/img/media.sav`. For the PVC2300, use `rtsp://admin:admin@CAMERA_IP:554/video.mp4` instead. If RTSP does not work, try the HTTP ASF stream at `http://CAMERA_IP/img/video.asf`. **Are Linksys cameras still available for purchase?** No. Linksys discontinued its entire IP camera product line around 2014, shortly after the brand was sold from Cisco to Belkin/Foxconn. No firmware updates or official support are available. However, many WVC and PVC cameras remain in use and functional. **Do Linksys cameras support ONVIF?** Only the LCAB series cameras have ONVIF support. The WVC and PVC series do not support ONVIF. For WVC cameras, use the direct RTSP or HTTP URL patterns listed above. **Are Linksys and Cisco camera URLs the same?** Yes. Linksys cameras were produced during Cisco's ownership of the brand and share the same firmware and URL patterns as Cisco consumer cameras. The `/img/media.sav` RTSP path and `/img/video.asf` HTTP path are identical across both brands. See our [Cisco connection guide](../cisco/) for more details. ## Related Resources - [All Camera Brands — RTSP URL Directory](../) - [Cisco Connection Guide](../cisco/) — Same URL patterns, parent company - [IP Camera Preview Tutorial](../../videocapture/video-tutorials/ip-camera-preview/) - [SDK Installation & Samples](../#get-started) ---END OF PAGE--- ## Lorex IP Camera RTSP URL Connection Guide for C# .NET **URL:** https://www.visioforge.com/help/docs/dotnet/camera-brands/lorex/ **Description:** Lorex LNB, LNE, LNZ, DVR, and NVR RTSP URL patterns for C# .NET. Stream and record Lorex cameras using VisioForge Video Capture SDK integration. **Tags:** Video Capture SDK, Media Blocks SDK, .NET, Windows, macOS, Linux, Android, iOS, Capture, Streaming, IP Camera, RTSP, ONVIF, MP4, H.264, C# # How to Connect to Lorex IP Camera in C# .NET [Video Capture SDK .Net](https://www.visioforge.com/video-capture-sdk-net) [Media Blocks SDK .Net](https://www.visioforge.com/media-blocks-sdk-net) ## Brand Overview **Lorex Technology** (a subsidiary of Dahua Technology through FLIR/Lorex) is a major consumer and prosumer security camera brand in North America. Lorex cameras are primarily manufactured by **Dahua Technology** and sold under the Lorex brand through retail channels including Amazon, Costco, and Best Buy. Lorex is one of the top-selling security camera brands in the United States and Canada. **Key facts:** - **Product lines:** LNB (bullet IP), LNE (dome/turret IP), LNZ (PTZ IP), LNC (consumer Wi-Fi), IPSC (legacy), L-series (legacy) - **Protocol support:** RTSP, ONVIF, HTTP/CGI - **Default RTSP port:** 554 - **Default credentials:** admin / (set during NVR/camera setup); some older models: admin / admin - **ONVIF support:** Yes (most current models) - **Video codecs:** H.264, H.265 (newer models) - **OEM base:** Dahua Technology (some models use Hikvision firmware) Lorex uses multiple OEM sources Most Lorex IP cameras are manufactured by Dahua and use Dahua's RTSP URL format. However, some Lorex models (particularly LNB2153 and MCNB2153) use Hikvision-based firmware with `/Streaming/Channels/` URLs. Check both URL formats if one doesn't work. ## RTSP URL Patterns ### Dahua-Based Models (Most Lorex IP Cameras) Most Lorex IP cameras use Dahua's URL format: | Stream | RTSP URL | Notes | | --- | --- | --- | | Main stream | `rtsp://IP:554/cam/realmonitor?channel=1&subtype=0` | Full resolution | | Sub stream | `rtsp://IP:554/cam/realmonitor?channel=1&subtype=1` | Lower resolution | ### Hikvision-Based Models Some Lorex models use Hikvision firmware: | Stream | RTSP URL | Notes | | --- | --- | --- | | Main stream | `rtsp://IP:554//Streaming/Channels/1` | Full resolution (note double slash) | | Sub stream | `rtsp://IP:554//Streaming/Channels/2` | Lower resolution | | H.264 direct | `rtsp://IP:554/ch0_0.h264` | Direct H.264 stream | ### Model-Specific URLs | Model | RTSP URL | OEM Base | Notes | | --- | --- | --- | --- | | LNB2153 | `rtsp://IP:554//Streaming/Channels/1` | Hikvision | 1080p bullet | | LNB2184 | `rtsp://IP:554/video.mp4` | Dahua | 4MP bullet | | LNE1001 | `rtsp://IP:554/` | Dahua | 1080p dome | | LNE3003 | `rtsp://IP:554/video.mp4` | Dahua | 2K dome | | LNZ4001 | `rtsp://IP:554/video.mp4` | Dahua | PTZ | | MCNB2153 | `rtsp://IP:554//Streaming/Channels/1` | Hikvision | 1080p bullet | ### Alternative URL Formats Some Lorex cameras also respond to these URLs: | URL Pattern | Notes | | --- | --- | | `rtsp://IP:554/` | Root path (some models) | | `rtsp://IP:554/video.mp4` | Video stream | | `rtsp://IP:554/ch0_0.h264` | Direct H.264 | ### Legacy Models | Model | URL | Notes | | --- | --- | --- | | IPSC Series | `rtsp://IP:554/` | Legacy IP cameras | | L23WD | `rtsp://IP:554/` | Legacy wireless | | IP1240 | `http://IP/GetData.cgi` | HTTP only | | LNC104/116/204 | `http://IP/snapshot.jpg?user=USER&pwd=PASS` | Wi-Fi cameras, HTTP only | ## Connecting with VisioForge SDK Use your Lorex camera's RTSP URL with any of the three SDK approaches shown in the [Quick Start Guide](../#quick-start-code). ### Dahua-Based Models (Most Lorex Cameras) ``` // Lorex camera (Dahua-based), main stream var uri = new Uri("rtsp://192.168.1.65:554/cam/realmonitor?channel=1&subtype=0"); var username = "admin"; var password = "YourPassword"; ``` ### Hikvision-Based Lorex Models ``` // Lorex LNB2153 (Hikvision-based), main stream var uri = new Uri("rtsp://192.168.1.65:554//Streaming/Channels/1"); var username = "admin"; var password = "YourPassword"; ``` See the [OEM identification guide](#determine-your-oem-base) in Troubleshooting to determine which URL format your Lorex camera uses. ## Snapshot URLs | Type | URL Pattern | Notes | | --- | --- | --- | | JPEG Snapshot | `http://IP/jpg/image.jpg` | Most Lorex IP cameras | | Snapshot (auth) | `http://IP/snapshot.jpg?user=USER&pwd=PASS` | Consumer Wi-Fi cameras | | Snapshot (account) | `http://IP/snapshot.jpg?account=USER&password=PASS` | Alternative auth | | GetData | `http://IP/GetData.cgi` | Legacy models | | MJPEG Stream | `http://IP/video.mjpg` | Continuous MJPEG | ## Troubleshooting ### Determine your OEM base Lorex cameras use firmware from different manufacturers. To determine which URL format to use: 1. Try the **Dahua format** first: `rtsp://IP:554/cam/realmonitor?channel=1&subtype=0` 2. If that fails, try the **Hikvision format**: `rtsp://IP:554//Streaming/Channels/1` 3. Check the camera's web interface -- Dahua-based cameras have a blue/white web UI, while Hikvision-based ones have a dark gray/black UI ### NVR vs direct camera access - When connecting through a Lorex NVR, use `channel=N` in the Dahua URL format to select the camera - When connecting directly to an IP camera, always use `channel=1` ### Lorex consumer Wi-Fi cameras (LNC series) The LNC series (LNC104, LNC116, LNC204) are consumer Wi-Fi cameras that typically don't support RTSP. They provide HTTP snapshot URLs only and are primarily designed for use with the Lorex app. ### Port 9000 Some very old Lorex cameras used port 9000 for streaming instead of 554. If standard port 554 doesn't work on an older model, try: `rtsp://IP:9000/` ## FAQ **Are Lorex cameras the same as Dahua?** Most Lorex IP cameras are manufactured by Dahua and use identical firmware. The RTSP URL format (`cam/realmonitor?channel=1&subtype=0`) is the same. However, some Lorex models use Hikvision firmware. See our [Dahua connection guide](../dahua/) for additional details. **What is the default RTSP URL for Lorex cameras?** Try `rtsp://admin:password@CAMERA_IP:554/cam/realmonitor?channel=1&subtype=0` first (Dahua-based). If that fails, try `rtsp://admin:password@CAMERA_IP:554//Streaming/Channels/1` (Hikvision-based). **Can I use Lorex cameras without the Lorex NVR?** Yes. Lorex IP cameras with RTSP support can be connected directly using their individual IP addresses. You don't need the Lorex NVR for third-party software integration. **Do Lorex cameras support ONVIF?** Most current Lorex IP cameras support ONVIF. Consumer Wi-Fi cameras (LNC series) generally do not. ## Related Resources - [All Camera Brands — RTSP URL Directory](../) - [Dahua Connection Guide](../dahua/) — Same URL format for most models - [Amcrest Connection Guide](../amcrest/) — Another Dahua OEM - [Swann Connection Guide](../swann/) — Consumer/prosumer segment peer - [IP Camera Preview Tutorial](../../videocapture/video-tutorials/ip-camera-preview/) - [SDK Installation & Samples](../#get-started) ---END OF PAGE--- ## LTS IP Camera RTSP URL and C# .NET Connection Guide **URL:** https://www.visioforge.com/help/docs/dotnet/camera-brands/lts/ **Description:** Connect to LTS (LT Security) cameras in C# .NET with RTSP URL patterns and code samples for CMIP, CMHR series and NVR models. LTS uses Hikvision firmware. **Tags:** Video Capture SDK, Media Blocks SDK, .NET, Windows, macOS, Linux, Android, iOS, Capture, Streaming, IP Camera, RTSP, ONVIF, H.264, MJPEG, C# # How to Connect to LTS IP Camera in C# .NET [Video Capture SDK .Net](https://www.visioforge.com/video-capture-sdk-net) [Media Blocks SDK .Net](https://www.visioforge.com/media-blocks-sdk-net) ## Brand Overview **LTS (LT Security Inc.)** is an American security company based in City of Industry, California. LTS cameras are manufactured by **Hikvision** and use Hikvision firmware, protocols, and web interfaces. LTS rebrands Hikvision hardware with US-based technical support and competitive pricing, making it a popular choice in the professional installation market. Because LTS cameras run Hikvision firmware, they use the same RTSP URL format, ONVIF implementation, and API endpoints as Hikvision cameras. Any integration code written for Hikvision works with LTS and vice versa. **Key facts:** - **Product lines:** CMIP (IP cameras), CMHR (HD-TVI analog), LTD (DVRs), LTN (NVRs) - **Protocol support:** RTSP, ONVIF Profile S/G/T, HTTP/ISAPI - **Default RTSP port:** 554 - **Default credentials:** admin / 123456 (some models: admin / admin) - **ONVIF support:** Yes (all current models) - **Video codecs:** H.264, H.265 (CMIP4xxx and newer) - **OEM base:** Hikvision (identical RTSP URL format) LTS = Hikvision OEM LTS cameras use Hikvision firmware and the exact same RTSP URL format as Hikvision cameras. Any code written for Hikvision cameras works with LTS. See our [Hikvision connection guide](../hikvision/) for additional details. ## RTSP URL Patterns ### Standard URL Format (Hikvision) Most current LTS cameras use the standard Hikvision `Streaming/Channels` URL pattern: ``` rtsp://[USERNAME]:[PASSWORD]@[IP]:554/Streaming/Channels/[CHANNEL_ID] ``` | Parameter | Value | Description | | --- | --- | --- | | `CHANNEL_ID` | 101 | Channel 1, main stream | | `CHANNEL_ID` | 102 | Channel 1, sub stream | | `CHANNEL_ID` | 201 | Channel 2, main stream (NVR) | | `CHANNEL_ID` | 202 | Channel 2, sub stream (NVR) | Double-slash in URL Some LTS/Hikvision cameras use `//Streaming/Channels/1` (with a double forward slash before `Streaming`). Both single-slash and double-slash variants typically work, but try the double-slash version if the single-slash URL fails. ### RTSP URLs by Model | Model | RTSP URL | Resolution | Notes | | --- | --- | --- | --- | | CMIP3122 | `rtsp://IP:554/Streaming/Channels/101` | 3MP | Hikvision standard format | | CMIP3132-28 | `rtsp://IP:554/Streaming/Channels/101` | 3MP | Hikvision standard format | | CMIP3432 | `rtsp://IP:554/Streaming/Channels/101` | 4MP | Hikvision standard format | | CMIP3243 | `rtsp://IP:554/live.h264` | 3MP | Alternative H.264 stream | | CMIP3412-28 | `rtsp://IP:554/live.h264` | 4MP | Alternative H.264 stream | | CMIP8232 | `rtsp://IP:554/live.sdp` | 8MP/4K | SDP live stream | | CMIP8232 (alt) | `rtsp://IP:554/HighResolutionVideo` | 8MP/4K | High resolution stream | | CMIP8232 (sub) | `rtsp://IP:554/h264/ch1/sub/` | 8MP/4K | H.264 sub stream | | CMIP series (low-res) | `rtsp://IP:554/LowResolutionVideo` | Varies | Low resolution sub stream | ### Alternative URL Formats Some older LTS models or specific firmware versions support these alternative URLs: | URL Pattern | Notes | | --- | --- | | `rtsp://IP:554/Streaming/Channels/101` | Standard Hikvision (recommended) | | `rtsp://IP:554//Streaming/Channels/1` | Double-slash variant | | `rtsp://IP:554/live.h264` | H.264 live stream (older CMIP3xxx) | | `rtsp://IP:554/live.sdp` | SDP live stream (CMIP8xxx) | | `rtsp://IP:554/HighResolutionVideo` | Named high-resolution stream | | `rtsp://IP:554/LowResolutionVideo` | Named low-resolution stream | | `rtsp://IP:554/h264/ch1/sub/` | H.264 sub stream by channel | | `rtsp://IP:554/cam1/mpeg4?user=USER&pwd=PASS` | MPEG-4 with URL-based auth | ### NVR Channel URLs (LTN Series) For LTS NVRs (LTN8704, LTN8708, LTN8716, etc.): | Channel | Main Stream | Sub Stream | | --- | --- | --- | | Camera 1 | `rtsp://IP:554/Streaming/Channels/101` | `rtsp://IP:554/Streaming/Channels/102` | | Camera 2 | `rtsp://IP:554/Streaming/Channels/201` | `rtsp://IP:554/Streaming/Channels/202` | | Camera N | `rtsp://IP:554/Streaming/Channels/N01` | `rtsp://IP:554/Streaming/Channels/N02` | ### Model Series Summary | Model Series | Primary RTSP URL | Alternative URLs | | --- | --- | --- | | CMIP3xxx (3MP) | `/Streaming/Channels/101` | `/live.h264` (some models) | | CMIP4xxx (4MP) | `/Streaming/Channels/101` | `/live.h264` (some models) | | CMIP8xxx (8MP/4K) | `/Streaming/Channels/101` | `/live.sdp`, `/HighResolutionVideo`, `/h264/ch1/sub/` | | LTN NVRs | `/Streaming/Channels/N01` | Channel-based | | LTD DVRs | `/Streaming/Channels/N01` | Channel-based | ## Connecting with VisioForge SDK Use your LTS camera's RTSP URL with any of the three SDK approaches shown in the [Quick Start Guide](../#quick-start-code): ``` // LTS CMIP3432, main stream (Hikvision format) var uri = new Uri("rtsp://192.168.1.80:554/Streaming/Channels/101"); var username = "admin"; var password = "123456"; ``` For sub-stream access, use channel ID `102` instead of `101`. ## Snapshot and MJPEG URLs | Type | URL Pattern | Notes | | --- | --- | --- | | JPEG Snapshot | `http://IP/snapshot.jpg` | Standard snapshot | | 3GP Snapshot | `http://IP/snapshot_3gp.jpg` | 3GP format (mobile-optimized) | | Stream Snapshot | `http://IP/stream.jpg` | Stream-based snapshot | | DVR Channel Snapshot | `http://IP/stillimg[CHANNEL].jpg` | Replace `[CHANNEL]` with channel number (LTD DVRs) | | ISAPI Snapshot | `http://IP/ISAPI/Streaming/channels/101/picture` | Hikvision ISAPI (requires auth) | ## Troubleshooting ### Identifying the correct URL format LTS cameras span multiple generations with different URL formats. To determine which URL your camera uses: 1. Try the standard Hikvision format first: `rtsp://IP:554/Streaming/Channels/101` 2. If that fails, try the double-slash variant: `rtsp://IP:554//Streaming/Channels/1` 3. For older CMIP3xxx models, try `rtsp://IP:554/live.h264` 4. For CMIP8xxx (4K) models, try `rtsp://IP:554/live.sdp` ### Default credentials and activation - Older LTS cameras: default password is `123456` or `admin` - Newer LTS cameras (with Hikvision 5.3+ firmware): require password activation on first use, similar to Hikvision - If you cannot log in with default credentials, the camera may need to be activated via the LTS Discovery Tool or Hikvision SADP Tool ### Using Hikvision tools with LTS cameras Since LTS cameras run Hikvision firmware, you can use Hikvision utilities for network discovery and configuration: - **Hikvision SADP Tool** -- discovers LTS cameras on the local network and can activate/reset them - **LTS Discovery Tool** -- LTS-branded version of SADP with identical functionality - **iVMS-4200** -- Hikvision's free VMS software works with LTS cameras ### "401 Unauthorized" error 1. Verify your credentials are correct (default: admin / 123456) 2. On newer firmware, ensure the camera has been activated and you are using the password set during activation 3. Check if the camera has a lockout policy -- too many failed login attempts may temporarily block access 4. Some models require digest authentication rather than basic authentication for RTSP ### Double-slash URL issue The `//Streaming/Channels/1` URL with a double forward slash at the beginning is a known Hikvision pattern. Some HTTP clients or RTSP libraries may normalize this to a single slash. If your connection fails: - Ensure your URL string preserves the double slash - Try both `//Streaming/Channels/1` and `/Streaming/Channels/101` variants ## FAQ **Are LTS cameras the same as Hikvision?** LTS cameras are manufactured by Hikvision and run Hikvision firmware. The RTSP URL format (`/Streaming/Channels/101`), ONVIF implementation, and ISAPI interface are identical. The main differences are branding, pricing, and US-based technical support from LTS. Any code written for Hikvision cameras works with LTS cameras. **What is the default RTSP URL for LTS cameras?** For most current LTS cameras, use `rtsp://admin:123456@CAMERA_IP:554/Streaming/Channels/101` for the main stream. Use channel ID `102` for the sub stream. Older models may use `/live.h264` or `/live.sdp` instead. **Do LTS cameras support ONVIF?** Yes. All current LTS IP cameras (CMIP series) support ONVIF Profile S and Profile T. ONVIF can be used for automatic discovery and configuration alongside direct RTSP URLs. **What is the difference between CMIP and CMHR series?** CMIP cameras are IP (network) cameras that support RTSP streaming. CMHR cameras are HD-TVI analog cameras that connect directly to DVRs via coaxial cable and do not have network RTSP capability. Only CMIP series cameras can be connected to via RTSP URLs in software. ## Related Resources - [All Camera Brands — RTSP URL Directory](../) - [Hikvision Connection Guide](../hikvision/) — Same URL format (OEM base) - [Annke Connection Guide](../annke/) — Another Hikvision OEM - [RTSP Camera Integration Guide](../../videocapture/video-sources/ip-cameras/rtsp/) — LTS RTSP stream configuration - [IP Camera Preview Tutorial](../../videocapture/video-tutorials/ip-camera-preview/) - [SDK Installation & Samples](../#get-started) ---END OF PAGE--- ## Mercusys IP Camera RTSP URL and C# .NET Integration **URL:** https://www.visioforge.com/help/docs/dotnet/camera-brands/mercusys/ **Description:** Mercusys MC and MB series indoor/outdoor camera RTSP URL patterns for C# .NET. Stream and record using VisioForge Video Capture SDK integration code. **Tags:** Video Capture SDK, Media Blocks SDK, .NET, Windows, macOS, Linux, Android, iOS, Capture, Streaming, IP Camera, RTSP, ONVIF, C# # How to Connect to Mercusys IP Camera in C# .NET [Video Capture SDK .Net](https://www.visioforge.com/video-capture-sdk-net) [Media Blocks SDK .Net](https://www.visioforge.com/media-blocks-sdk-net) ## Brand Overview **Mercusys** is a networking and smart home brand owned by **TP-Link**. Mercusys targets the budget-conscious segment with affordable routers, mesh systems, and security cameras. Mercusys cameras share design and firmware similarities with TP-Link Tapo cameras, offering standard RTSP support at lower price points. **Key facts:** - **Product lines:** MC (indoor cameras), MB (outdoor cameras) - **Protocol support:** RTSP, ONVIF (select models), HTTP - **Default RTSP port:** 554 - **Default credentials:** Set during app setup (no factory defaults) - **ONVIF support:** Yes (newer models, must be enabled) - **Video codecs:** H.264 - **Parent company:** TP-Link - **Companion app:** Mercusys Security app Mercusys and TP-Link Tapo Mercusys cameras share firmware architecture with TP-Link Tapo cameras. The RTSP URL format (`/stream1`, `/stream2`) is similar. If you are familiar with Tapo integration, the same approach works with Mercusys. See our [TP-Link connection guide](../tp-link/) for additional details. ## RTSP URL Patterns ### Standard URL Format Mercusys cameras use a stream-number-based RTSP URL: ``` rtsp://[USERNAME]:[PASSWORD]@[IP]:554/stream1 ``` | Stream | URL Pattern | Description | | --- | --- | --- | | Main stream | `rtsp://IP:554/stream1` | Full resolution | | Sub stream | `rtsp://IP:554/stream2` | Lower resolution, less bandwidth | ### Camera Models | Model | Type | Resolution | Main Stream URL | Audio | | --- | --- | --- | --- | --- | | MC50 (indoor PT) | Indoor pan/tilt | 1920x1080 | `rtsp://IP:554/stream1` | Yes | | MC60 (2K indoor PT) | Indoor pan/tilt | 2304x1296 | `rtsp://IP:554/stream1` | Yes | | MC70 (4MP indoor PT) | Indoor pan/tilt | 2560x1440 | `rtsp://IP:554/stream1` | Yes | | MB50 (outdoor bullet) | Outdoor | 1920x1080 | `rtsp://IP:554/stream1` | Yes | | MB60 (2K outdoor) | Outdoor | 2304x1296 | `rtsp://IP:554/stream1` | Yes | | MB70 (4MP outdoor) | Outdoor | 2560x1440 | `rtsp://IP:554/stream1` | Yes | ### Enabling RTSP / ONVIF RTSP and ONVIF may need to be enabled in the camera settings: 1. Open the **Mercusys Security** app 2. Select your camera → **Settings** 3. Navigate to **Advanced Settings** 4. Enable **RTSP** and/or **ONVIF** 5. Set a username and password for RTSP access ## Connecting with VisioForge SDK Use your Mercusys camera's RTSP URL with any of the three SDK approaches shown in the [Quick Start Guide](../#quick-start-code): ``` // Mercusys MC70 (4MP indoor pan/tilt), main stream var uri = new Uri("rtsp://192.168.1.90:554/stream1"); var username = "rtsp_user"; // set in Mercusys Security app var password = "rtsp_pass"; ``` For sub-stream access, use `/stream2` instead of `/stream1`. ## Snapshot URLs | Type | URL Pattern | Notes | | --- | --- | --- | | JPEG Snapshot | `http://IP/cgi-bin/snapshot.cgi` | Requires basic auth | ## Troubleshooting ### RTSP not accessible Mercusys cameras require initial setup through the Mercusys Security app. RTSP may also need to be explicitly enabled in the advanced settings. After enabling RTSP, the credentials set in the app must be used for RTSP authentication. ### Camera IP discovery Find your Mercusys camera's IP address in: 1. The Mercusys Security app → Device Info 2. Your router's DHCP client list 3. ONVIF discovery (if enabled) ### Similar to TP-Link Tapo If standard Mercusys troubleshooting does not resolve your issue, check our [TP-Link Tapo guide](../tp-link/) for additional troubleshooting steps, as the firmware is similar. ## FAQ **What is the default RTSP URL for Mercusys cameras?** Mercusys cameras use `rtsp://username:password@CAMERA_IP:554/stream1` for the main stream and `/stream2` for the sub stream. The username and password are set during RTSP enablement in the Mercusys Security app. **Is Mercusys the same as TP-Link?** Mercusys is a brand owned by TP-Link that targets the budget segment. Mercusys cameras share firmware architecture with TP-Link Tapo cameras and use similar RTSP URL formats. **Do Mercusys cameras support ONVIF?** Newer Mercusys camera models support ONVIF, but it must be enabled through the Mercusys Security app. Older models may not include ONVIF support. **How do Mercusys cameras compare to TP-Link Tapo?** Mercusys cameras are positioned as a more affordable alternative to Tapo. They share similar firmware and RTSP URL patterns. Tapo cameras generally have more model options and broader community support. ## Related Resources - [All Camera Brands — RTSP URL Directory](../) - [TP-Link Connection Guide](../tp-link/) — Parent company, similar firmware - [Tenda Connection Guide](../tenda/) — Budget camera alternative - [IP Camera Preview Tutorial](../../videocapture/video-tutorials/ip-camera-preview/) - [SDK Installation & Samples](../#get-started) ---END OF PAGE--- ## Milesight IP Camera RTSP URL and C# .NET Connection Guide **URL:** https://www.visioforge.com/help/docs/dotnet/camera-brands/milesight/ **Description:** Milesight MS-C, MS-A, MS-V series RTSP URL patterns for C# .NET. ONVIF-compliant integration with VisioForge Video Capture SDK code samples. **Tags:** Video Capture SDK, Media Blocks SDK, .NET, Windows, macOS, Linux, Android, iOS, Capture, Streaming, IP Camera, RTSP, ONVIF, H.265, MJPEG, C# # How to Connect to Milesight IP Camera in C# .NET [Video Capture SDK .Net](https://www.visioforge.com/video-capture-sdk-net) [Media Blocks SDK .Net](https://www.visioforge.com/media-blocks-sdk-net) ## Brand Overview **Milesight Technology** is a Chinese manufacturer of IP cameras and IoT devices, headquartered in Xiamen, China. Milesight targets professional and SMB markets with a rapidly growing lineup of AI-enabled cameras at competitive price points. The brand is known for strong ONVIF compliance, built-in AI analytics (face detection, LPR, people counting), and straightforward integration with third-party VMS platforms. **Key facts:** - **Product lines:** MS-C (mini dome/bullet), MS-A (PTZ/speed dome), MS-V (vandal dome), MS-F (fisheye), MS-B (box), MS-N (NVR) - **Protocol support:** RTSP, ONVIF (Profile S/G/T on all current models), HTTP/CGI - **Default RTSP port:** 554 - **Default credentials:** admin / ms1234 (must be changed on first login) - **ONVIF support:** Yes (all current models, Profile S/G/T) - **Video codecs:** H.264, H.265, MJPEG Double slash in RTSP URLs Milesight cameras use a **double forward slash** before `main` and `sub` in their RTSP URLs: `rtsp://IP:554//main`. This is intentional and required for all current Milesight models. ## RTSP URL Patterns ### Current Models (All Series) | Stream | RTSP URL | Notes | | --- | --- | --- | | Main stream | `rtsp://IP:554//main` | Full resolution (note double slash) | | Sub stream | `rtsp://IP:554//sub` | Lower resolution | | Root stream | `rtsp://IP:554/` | Fallback | ### Model-Specific URLs All current Milesight camera models use the same RTSP URL pattern: | Model Series | RTSP URL | Type | Notes | | --- | --- | --- | --- | | MS-C2672-P | `rtsp://IP:554//main` | Mini dome | 2MP | | MS-C3366-FP | `rtsp://IP:554//main` | Bullet | 3MP, AI | | MS-C3366-FPH | `rtsp://IP:554//main` | Bullet | 3MP, AI, heater | | MS-C2363 | `rtsp://IP:554//main` | Mini dome | 2MP | | MS-2681 | `rtsp://IP:554//main` | Dome | 8MP | | MS-3672 | `rtsp://IP:554//main` | Bullet | 3MP | | MS-A series (PTZ) | `rtsp://IP:554//main` | PTZ | Speed dome | | MS-V series (vandal) | `rtsp://IP:554//main` | Vandal dome | IK10 rated | | MS-F series (fisheye) | `rtsp://IP:554//main` | Fisheye | 360-degree | | MS-B series (box) | `rtsp://IP:554//main` | Box | Professional | ### NVR Channel Streams For Milesight MS-N series NVRs, use the `channel` parameter to select individual camera streams: | Stream | RTSP URL | Notes | | --- | --- | --- | | Channel 1, main | `rtsp://IP:554//main?channel=1` | NVR channel 1 | | Channel 2, main | `rtsp://IP:554//main?channel=2` | NVR channel 2 | | Channel 1, sub | `rtsp://IP:554//sub?channel=1` | NVR channel 1, low-res | | Channel 2, sub | `rtsp://IP:554//sub?channel=2` | NVR channel 2, low-res | ## Connecting with VisioForge SDK Use your Milesight camera's RTSP URL with any of the three SDK approaches shown in the [Quick Start Guide](../#quick-start-code): ``` // Milesight camera, main stream -- note the double slash before "main" var uri = new Uri("rtsp://192.168.1.90:554//main"); var username = "admin"; var password = "ms1234"; ``` For sub-stream access, use `//sub` instead of `//main`. For NVR channel selection, append `?channel=N` to the URL. ## Snapshot and MJPEG URLs | Type | URL Pattern | Notes | | --- | --- | --- | | CGI Snapshot | `http://IP/cgi-bin/snapshot.cgi` | Basic auth required | ## Troubleshooting ### Double slash is required Milesight cameras require a **double forward slash** before the stream path: - Correct: `rtsp://IP:554//main` - May not work: `rtsp://IP:554/main` If your connection fails, verify that you are using the double-slash URL format. This pattern is similar to Pelco and ACTi cameras. ### Default password must be changed The factory default password is `ms1234`, but Milesight cameras require this password to be changed during first login through the web interface or Milesight CMS. If the default password does not work, the camera has likely been configured with a new password. ### AI features are independent of RTSP Milesight AI features (face detection, license plate recognition, people counting, intrusion detection) run on the camera's built-in processor and do not affect RTSP streaming. AI metadata and events are delivered through ONVIF events or the Milesight API, not through the RTSP stream itself. ### Milesight CMS is optional Milesight CMS (Central Management Software) is Milesight's proprietary VMS. It is not required for RTSP streaming. Milesight cameras work with any ONVIF-compatible VMS or any application that supports standard RTSP connections. ### NVR channel numbering When connecting through a Milesight MS-N NVR, channel numbers start at 1 and correspond to the physical camera input or network camera order configured in the NVR. Use `?channel=1` for the first camera, `?channel=2` for the second, and so on. ### ONVIF discovery All current Milesight cameras support ONVIF Profile S, G, and T. If you prefer automatic discovery over manual RTSP URL configuration, use ONVIF device discovery to find cameras on your network and retrieve their streaming URLs automatically. ## FAQ **What is the default RTSP URL for Milesight cameras?** For all current Milesight cameras, use `rtsp://admin:ms1234@CAMERA_IP:554//main` (note the double slash). For the sub-stream, use `//sub`. For NVR access, append `?channel=N` to select the desired camera channel. **Do all Milesight models use the same RTSP URL?** Yes. All current Milesight camera models (MS-C, MS-A, MS-V, MS-F, MS-B series) use the same `//main` and `//sub` URL pattern. This makes Milesight one of the most consistent brands for RTSP integration. **Does Milesight support H.265?** Yes. All current Milesight cameras support H.264, H.265, and MJPEG encoding. H.265 can be enabled through the camera's web interface or Milesight CMS to reduce bandwidth and storage requirements. **Why does the double slash matter in Milesight URLs?** The double slash (`//main` instead of `/main`) is part of Milesight's RTSP URL specification. Omitting the extra slash may cause connection failures. This convention is shared with a few other camera brands (Pelco, ACTi) but is not universal across the industry. **Can I access Milesight AI analytics through RTSP?** No. RTSP delivers the video stream only. AI analytics results (face detection events, license plate data, people counting statistics) are accessible through ONVIF events, the Milesight HTTP API, or Milesight CMS. The video stream itself does not contain embedded AI metadata. ## Related Resources - [All Camera Brands — RTSP URL Directory](../) - [Grandstream Connection Guide](../grandstream/) — SMB / professional camera segment - [IP Camera Capture to MP4](../../videocapture/video-tutorials/ip-camera-capture-mp4/) — Record Milesight streams to file - [IP Camera Preview Tutorial](../../videocapture/video-tutorials/ip-camera-preview/) - [SDK Installation & Samples](../#get-started) ---END OF PAGE--- ## Mobotix RTSP URL Patterns for IP Camera Access in C# **URL:** https://www.visioforge.com/help/docs/dotnet/camera-brands/mobotix/ **Description:** Connect to MOBOTIX cameras in C# .NET with RTSP URL patterns for classic Mx and MOVE series. Includes MxPEG, MJPEG, and H.264 stream options. **Tags:** Video Capture SDK, Media Blocks SDK, .NET, Windows, macOS, Linux, Android, iOS, Capture, Streaming, IP Camera, USB3 Vision / GigE, RTSP, ONVIF, H.264, MJPEG, C# # How to Connect to Mobotix IP Camera in C# .NET [Video Capture SDK .Net](https://www.visioforge.com/video-capture-sdk-net) [Media Blocks SDK .Net](https://www.visioforge.com/media-blocks-sdk-net) ## Brand Overview **MOBOTIX** (MOBOTIX AG) is a German IP camera manufacturer headquartered in Langmeil, Germany, founded in 1999. MOBOTIX pioneered the concept of decentralized IP video systems where intelligent processing, recording, and analytics happen directly inside the camera rather than on a central server. The company was acquired by **Konica Minolta** in 2016. MOBOTIX cameras are known for their rugged construction, long operational lifespan, and suitability for industrial, outdoor, and critical infrastructure environments. **Key facts:** - **Product lines:** M-series (outdoor), D-series (dome), S-series (hemispheric), Q-series (panoramic), T-series (door station), MOVE (newer ONVIF line) - **Protocol support:** RTSP, HTTP/CGI, MxPEG (proprietary); ONVIF (MOVE series only) - **Default RTSP port:** 554 - **Default credentials:** admin / meinsm - **ONVIF support:** MOVE series only (classic Mx cameras do not support ONVIF) - **Video codecs:** MxPEG (proprietary), MJPEG, H.264 (newer models) - **Architecture:** Decentralized, in-camera recording and processing Classic vs MOVE Series Classic Mobotix cameras (M/D/S/Q series) primarily use the proprietary MxPEG codec and do not support ONVIF. For ONVIF and standard H.264/H.265 RTSP, use the newer MOBOTIX MOVE series. About MxPEG MxPEG is a proprietary video codec developed by MOBOTIX for efficient bandwidth usage with their decentralized architecture. If your application cannot decode MxPEG natively, use the MJPEG fallback stream via HTTP (`/cgi-bin/faststream.jpg`) or configure the camera to output standard MJPEG or H.264 where supported. VisioForge SDK can connect to MOBOTIX cameras using the MJPEG HTTP stream or the H.264 RTSP stream on supported models. ## RTSP URL Patterns ### Standard URL Format MOBOTIX cameras use branded path-based RTSP URLs: ``` rtsp://[USERNAME]:[PASSWORD]@[IP]:554/mobotix.h264 ``` | Stream | URL Pattern | Description | | --- | --- | --- | | H.264 main stream | `rtsp://IP:554/mobotix.h264` | Primary H.264 stream (newer models) | | MJPEG stream | `rtsp://IP:554/mobotix.mjpeg` | MJPEG over RTSP | ### Camera Series and URLs | Series | Type | Recommended URL | Codec | | --- | --- | --- | --- | | MOVE Bullet | IP bullet | `rtsp://IP:554/mobotix.h264` | H.264 | | MOVE Dome | IP dome | `rtsp://IP:554/mobotix.h264` | H.264 | | MOVE Vandal Dome | IP vandal-proof | `rtsp://IP:554/mobotix.h264` | H.264 | | M-series (M73, M16) | Outdoor | `rtsp://IP:554/mobotix.mjpeg` | MJPEG | | D-series (D16, D26) | Dome | `rtsp://IP:554/mobotix.mjpeg` | MJPEG | | S-series (S16, S26) | Hemispheric | `rtsp://IP:554/mobotix.mjpeg` | MJPEG | | Q-series (Q26) | Panoramic 360 | `rtsp://IP:554/mobotix.mjpeg` | MJPEG | | T-series (T26) | Door station | `rtsp://IP:554/mobotix.mjpeg` | MJPEG | ### MOVE Series ONVIF URLs MOBOTIX MOVE cameras support standard ONVIF and provide conventional RTSP streams: | Stream | URL Pattern | Notes | | --- | --- | --- | | Main stream | `rtsp://IP:554/mobotix.h264` | H.264 primary stream | | Sub stream | `rtsp://IP:554/mobotix.mjpeg` | MJPEG secondary stream | ## Connecting with VisioForge SDK Use your MOBOTIX camera's RTSP URL with any of the three SDK approaches shown in the [Quick Start Guide](../#quick-start-code): ``` // MOBOTIX MOVE or classic Mx camera, H.264 stream var uri = new Uri("rtsp://192.168.1.90:554/mobotix.h264"); var username = "admin"; var password = "meinsm"; ``` For classic Mx cameras that only support MxPEG, use the MJPEG HTTP stream URL instead (see below). ## Snapshot and MJPEG URLs | Type | URL Pattern | Notes | | --- | --- | --- | | MJPEG Full Resolution | `http://IP/cgi-bin/faststream.jpg?stream=full` | Full resolution continuous MJPEG | | MxPEG Stream | `http://IP/cgi-bin/faststream.jpg?stream=MxPEG&needlength&fps=6` | Proprietary MxPEG at 6 fps | | Controlled FPS MJPEG | `http://IP/control/faststream.jpg?stream=full&fps=10` | MJPEG capped at 10 fps | | Current Snapshot | `http://IP/record/current.jpg` | Single JPEG snapshot | ## Troubleshooting ### Classic Mx camera not connecting via RTSP Classic MOBOTIX cameras (M, D, S, Q, T series) primarily use the proprietary MxPEG codec. If the RTSP stream fails: 1. Try the MJPEG RTSP URL: `rtsp://IP:554/mobotix.mjpeg` 2. If RTSP is not available, use the HTTP MJPEG stream: `http://IP/cgi-bin/faststream.jpg?stream=full` 3. Check that RTSP is enabled in the camera's web interface under **Admin Menu > Network Setup > RTSP Server** ### "401 Unauthorized" error MOBOTIX cameras use the default credentials `admin` / `meinsm`. If authentication fails: 1. Access the camera web interface at `http://CAMERA_IP` 2. Log in with the default or configured credentials 3. Verify the user account has streaming access permissions 4. Use the correct credentials in your RTSP URL ### MxPEG stream not decoding MxPEG is a proprietary codec that standard media players and libraries may not support. Workarounds: - Use the MJPEG fallback stream via `http://IP/cgi-bin/faststream.jpg?stream=full` - Configure the camera to output H.264 if the model and firmware support it - For MOVE series cameras, H.264 RTSP is natively supported ### ONVIF discovery not finding the camera Only MOBOTIX MOVE series cameras support ONVIF. Classic Mx cameras (M, D, S, Q, T series) do not implement the ONVIF protocol. For classic cameras, connect directly using the RTSP or HTTP URLs listed above. ### Low frame rate on MJPEG streams MOBOTIX classic cameras may default to low frame rates to conserve bandwidth. To adjust: 1. Open the camera web interface 2. Navigate to **Admin Menu > Image Control > Frame Rate** 3. Increase the maximum frame rate 4. For HTTP streams, specify the desired fps in the URL: `http://IP/control/faststream.jpg?stream=full&fps=15` ## FAQ **What is the default RTSP URL for MOBOTIX cameras?** For newer MOBOTIX MOVE cameras, the default URL is `rtsp://admin:meinsm@CAMERA_IP:554/mobotix.h264`. For classic Mx cameras, use `rtsp://admin:meinsm@CAMERA_IP:554/mobotix.mjpeg` or the HTTP MJPEG stream at `http://CAMERA_IP/cgi-bin/faststream.jpg?stream=full`. **What is MxPEG and do I need it?** MxPEG is a proprietary video codec developed by MOBOTIX for bandwidth-efficient streaming in their decentralized camera architecture. You do not need MxPEG support to use MOBOTIX cameras with VisioForge SDK. Instead, use the standard MJPEG HTTP stream or H.264 RTSP stream (on supported models) as described on this page. **Do MOBOTIX cameras support ONVIF?** Only the MOBOTIX MOVE series supports ONVIF. Classic MOBOTIX cameras (M, D, S, Q, T series) use a proprietary web interface and do not support ONVIF discovery or profiles. **What is the difference between MOBOTIX classic and MOVE cameras?** Classic MOBOTIX cameras (M, D, S, Q, T series) use a decentralized architecture with in-camera recording and the proprietary MxPEG codec. MOVE series cameras are MOBOTIX's newer product line that follows industry-standard protocols including ONVIF, H.264, and H.265, making them easier to integrate with third-party VMS and SDK solutions. **Can I connect to MOBOTIX cameras without ONVIF?** Yes. All MOBOTIX cameras support direct RTSP or HTTP connections using the URLs listed on this page. ONVIF is not required for basic video streaming. ## Related Resources - [All Camera Brands — RTSP URL Directory](../) - [Basler Connection Guide](../basler/) — Industrial / machine vision cameras - [FLIR Connection Guide](../flir/) — Industrial and thermal imaging - [IP Camera Preview Tutorial](../../videocapture/video-tutorials/ip-camera-preview/) - [SDK Installation & Samples](../#get-started) ---END OF PAGE--- ## How to Connect to Panasonic (i-PRO) IP Camera in C# .NET **URL:** https://www.visioforge.com/help/docs/dotnet/camera-brands/panasonic/ **Description:** Panasonic i-PRO and legacy WV/BL/BB camera RTSP URL patterns for C# .NET. ONVIF-compatible integration with VisioForge SDK for all generations. **Tags:** Video Capture SDK, Media Blocks SDK, .NET, Windows, macOS, Linux, Android, iOS, Capture, Streaming, Encoding, IP Camera, RTSP, ONVIF, H.264, H.265, MJPEG, C# # How to Connect to Panasonic (i-PRO) IP Camera in C# .NET [Video Capture SDK .Net](https://www.visioforge.com/video-capture-sdk-net) [Media Blocks SDK .Net](https://www.visioforge.com/media-blocks-sdk-net) ## Brand Overview **Panasonic i-PRO** (formerly Panasonic Security Systems, now operating as i-PRO Co., Ltd.) is a Japanese manufacturer of professional video surveillance equipment. Originally part of Panasonic Corporation, the security division was spun off as **i-PRO** in 2019. Panasonic/i-PRO cameras are widely deployed in enterprise, government, transportation, and retail environments worldwide. **Key facts:** - **Product lines:** WV-S (current S-series), WV-X (X-series AI), WV-SF/SC/SP/SW (mid-generation), WV-NP/NS/NW (legacy professional), BL (consumer/SMB), BB/KX-HCM (legacy consumer) - **Protocol support:** RTSP, ONVIF (Profile S/G/T), HTTP/CGI, MJPEG, Panasonic proprietary - **Default RTSP port:** 554 - **Default credentials:** admin / 12345 (current models require password change on first login); legacy BB/BL models often had no default password - **ONVIF support:** Yes (all current WV-S/WV-X models) - **Video codecs:** H.264, H.265 (current models), MPEG-4 (legacy), MJPEG ## RTSP URL Patterns ### Current Models (WV-S/WV-X Series, i-PRO) Current Panasonic i-PRO cameras use the `MediaInput` URL format: | Stream | RTSP URL | Codec | Notes | | --- | --- | --- | --- | | H.264 stream | `rtsp://IP:554/MediaInput/h264` | H.264 | Primary RTSP stream | | H.265 stream | `rtsp://IP:554/MediaInput/h265` | H.265 | Current models only | | MPEG-4 stream | `rtsp://IP:554/MediaInput/mpeg4` | MPEG-4 | Legacy fallback | | ONVIF stream | `rtsp://IP//ONVIF/MediaInput` | H.264 | ONVIF-compatible (note double slash) | Double slash in ONVIF URLs Panasonic ONVIF URLs use a double slash before `ONVIF`: `rtsp://IP//ONVIF/MediaInput`. This is intentional and required for ONVIF-based connections. ### Model-Specific URLs | Model Series | RTSP URL | Generation | | --- | --- | --- | | WV-S1131/S1132 | `rtsp://IP:554/MediaInput/h264` | Current (i-PRO) | | WV-S2131L/S2231L | `rtsp://IP:554/MediaInput/h264` | Current (i-PRO) | | WV-X1551L/X2251L | `rtsp://IP:554/MediaInput/h264` | Current AI series | | WV-SF132/SF135/SF138 | `rtsp://IP:554/MediaInput/h264` | Mid-generation | | WV-SF332/SF335/SF346 | `rtsp://IP:554/MediaInput/h264` | Mid-generation | | WV-SC384/SC385/SC386 | `rtsp://IP:554/MediaInput/h264` | Mid-generation | | WV-SP105/SP306/SP508 | `rtsp://IP:554/MediaInput/h264` | Mid-generation | | WV-SW115/SW155/SW175 | `rtsp://IP:554/MediaInput/h264` | Mid-generation outdoor | | WV-SW316/SW352/SW355 | `rtsp://IP:554/MediaInput/h264` | Mid-generation outdoor | | WV-SW395/SW396/SW458 | `rtsp://IP:554/MediaInput/h264` | Mid-generation outdoor | | WV-SW558/SW559/SW598 | `rtsp://IP:554/MediaInput/h264` | Mid-generation outdoor | | WV-ST162/ST165 | `rtsp://IP:554/MediaInput/h264` | Mid-generation PTZ | | WV-NP240/NP244/NP304 | `rtsp://IP:554/MediaInput/mpeg4` | Legacy professional | | WV-NP502/NP1000/NP1004 | `rtsp://IP:554/MediaInput/mpeg4` | Legacy professional | | WV-NS202/NS324/NS954 | `rtsp://IP:554/MediaInput/mpeg4` | Legacy PTZ | | WV-NW484/NW502/NW960/NW964 | `rtsp://IP:554/MediaInput/mpeg4` | Legacy outdoor | ### Legacy Consumer Models (BB/BL/KX Series) Older Panasonic consumer cameras used different URL patterns: | Model Series | RTSP URL | Codec | Notes | | --- | --- | --- | --- | | BL-C210/C230 | `rtsp://IP:554/MediaInput/h264` | H.264 | Late consumer models | | BL-C210/C230 | `rtsp://IP:554/MediaInput/mpeg4` | MPEG-4 | MPEG-4 fallback | | BL-VP101/VP104 | `rtsp://IP:554/MediaInput/h264` | H.264 | Compact | | BB-HCM531A/735 | `rtsp://IP/nphMpeg4/g726-640x48` | MPEG-4 | Very old format | | BB/BL/KX (HTTP only) | `http://IP/nphMotionJpeg?Resolution=640x480&Quality=Standard` | MJPEG | HTTP MJPEG stream | Legacy BB/BL cameras Many older Panasonic BB and BL series cameras do not support RTSP at all. They only provide HTTP-based MJPEG and JPEG snapshot streams. Current i-PRO cameras fully support RTSP. ### Encoder/DVR URLs | Device | RTSP URL | Notes | | --- | --- | --- | | WJ-GXE500 encoder | `http://IP/cgi-bin/camera` | MJPEG via HTTP | | WJ-HD220 DVR | `http://IP/cgi-bin/jpeg` | Snapshot from DVR | | WJ-ND400 NVR | `http://IP/cgi-bin/jpeg` | Snapshot from NVR | | WJ-NV200 NVR | `http://IP/cgi-bin/checkimage.cgi?UID=USER&CAM=CHANNEL` | Channel snapshot | ## Connecting with VisioForge SDK Use your Panasonic camera's RTSP URL with any of the three SDK approaches shown in the [Quick Start Guide](../#quick-start-code): ``` // Panasonic i-PRO camera, H.264 stream var uri = new Uri("rtsp://192.168.1.80:554/MediaInput/h264"); var username = "admin"; var password = "YourPassword"; ``` For H.265, use `/MediaInput/h265` instead. ## Snapshot and MJPEG URLs | Type | URL Pattern | Notes | | --- | --- | --- | | MJPEG Stream (current) | `http://IP/cgi-bin/mjpeg?stream=1` | Current WV-S/WV-X models | | JPEG Snapshot | `http://IP/cgi-bin/camera` | Current models | | Snapshot (sized) | `http://IP/SnapshotJPEG?Resolution=640x480` | Mid-generation models | | Snapshot (quality) | `http://IP/SnapShotJPEG?Resolution=320x240&Quality=Motion` | Legacy models | | MJPEG Stream (legacy) | `http://IP/nphMotionJpeg?Resolution=640x480&Quality=Standard` | BB/BL/KX models | | Server push | `http://IP/cgi-bin/nphContinuousServerPush` | Continuous JPEG push | ## Troubleshooting ### Brand name confusion The Panasonic security camera brand has evolved: - **Panasonic** (before 2019): Full Panasonic branding - **i-PRO** (2019-present): Spun off from Panasonic as i-PRO Co., Ltd. - Current products are branded **i-PRO** but many users still search for "Panasonic camera" All use compatible RTSP URL patterns within their generation. ### MediaInput/h264 vs ONVIF/MediaInput - Use `rtsp://IP:554/MediaInput/h264` for direct RTSP connections (recommended) - Use `rtsp://IP//ONVIF/MediaInput` for ONVIF-compatible connections (note the double slash) - Both provide the same video stream but use different authentication mechanisms ### Legacy cameras without RTSP Many older Panasonic BB-series and BL-series cameras (particularly BL-C1, BL-C10, BL-C30, BL-C101, BL-C111, BL-C131 and earlier) do not support RTSP. These cameras only provide: - HTTP MJPEG: `http://IP/nphMotionJpeg?Resolution=640x480&Quality=Standard` - HTTP Snapshot: `http://IP/SnapshotJPEG?Resolution=320x240` ### MPEG-4 vs H.264 Legacy WV-NP/NS/NW series cameras may only support MPEG-4 over RTSP. Try `MediaInput/mpeg4` if `MediaInput/h264` fails on older models. ## FAQ **What is the default RTSP URL for Panasonic/i-PRO cameras?** For current i-PRO cameras, use `rtsp://admin:password@CAMERA_IP:554/MediaInput/h264`. For ONVIF connections, use `rtsp://CAMERA_IP//ONVIF/MediaInput`. Legacy models may need `MediaInput/mpeg4`. **Is Panasonic the same as i-PRO?** Yes. Panasonic's security camera division was spun off as i-PRO Co., Ltd. in 2019. Current cameras are branded i-PRO, but use the same RTSP URL patterns as late-generation Panasonic WV-series cameras. **Do Panasonic cameras support H.265?** Current i-PRO cameras (WV-S and WV-X series) support H.265. Use `rtsp://IP:554/MediaInput/h265` for the H.265 stream. Mid-generation and older models support H.264 and MPEG-4 only. **Can I connect to legacy Panasonic BB/BL cameras?** Many older BB and BL series cameras don't support RTSP and only provide HTTP MJPEG streams. Use the HTTP MJPEG URL `http://IP/nphMotionJpeg?Resolution=640x480&Quality=Standard` with an HTTP source instead of RTSP. ## Related Resources - [All Camera Brands — RTSP URL Directory](../) - [Sanyo Connection Guide](../sanyo/) — Acquired by Panasonic, predecessor product line - [IP Camera Preview Tutorial](../../videocapture/video-tutorials/ip-camera-preview/) - [SDK Installation & Samples](../#get-started) ---END OF PAGE--- ## Pelco IP Camera RTSP URL Patterns and C# .NET Setup **URL:** https://www.visioforge.com/help/docs/dotnet/camera-brands/pelco/ **Description:** Pelco Sarix and Spectra PTZ camera RTSP integration for C# .NET. URL patterns for IX, IMP, IME models with ONVIF support and VisioForge SDK code. **Tags:** Video Capture SDK, Media Blocks SDK, .NET, Windows, macOS, Linux, Android, iOS, Capture, Streaming, IP Camera, RTSP, ONVIF, MJPEG, C# # How to Connect to Pelco IP Camera in C# .NET [Video Capture SDK .Net](https://www.visioforge.com/video-capture-sdk-net) [Media Blocks SDK .Net](https://www.visioforge.com/media-blocks-sdk-net) ## Brand Overview **Pelco** (now part of **Motorola Solutions**) is a leading manufacturer of professional video surveillance equipment, headquartered in Fresno, California. Pelco is particularly strong in enterprise, government, and critical infrastructure markets. The brand is known for its **Sarix** fixed camera line and **Spectra** PTZ camera line. Motorola Solutions acquired Pelco in 2020. **Key facts:** - **Product lines:** Sarix (Professional/Enhanced/Value fixed cameras), Spectra (Professional PTZ), IX (fixed box), IMP/IME (mini dome), D-series (dome PTZ) - **Protocol support:** RTSP, ONVIF (Profile S/G/T), HTTP/CGI, Pelco D/P serial protocol - **Default RTSP port:** 554 - **Default credentials:** admin / admin (must be changed on first login for current models) - **ONVIF support:** Yes (all current Sarix and Spectra models) - **Video codecs:** H.264, H.265 (Sarix Professional), MJPEG Double slash in RTSP URLs Pelco cameras consistently use a **double forward slash** before the stream path: `rtsp://IP:554//stream1`. This is intentional and required for most Pelco models. ## RTSP URL Patterns ### Current Models (Sarix Professional/Enhanced/Value) | Stream | RTSP URL | Notes | | --- | --- | --- | | Main stream | `rtsp://IP:554//stream1` | Full resolution (note double slash) | | Sub stream | `rtsp://IP:554//stream2` | Lower resolution | | Low-res stream | `rtsp://IP:554/LowResolutionVideo` | Lowest quality | | Channel stream | `rtsp://IP:554/stream1` | Single slash (some models) | | Numbered channel | `rtsp://IP:554/1/stream1` | Channel-specific | ### Model-Specific URLs | Model Series | RTSP URL | Type | Notes | | --- | --- | --- | --- | | Sarix Pro (IMP/IME) | `rtsp://IP:554//stream1` | Fixed dome | Current generation | | Sarix Enhanced (IX) | `rtsp://IP:554//stream1` | Fixed box | Mid-range | | Sarix Value | `rtsp://IP:554//stream1` | Fixed | Entry-level | | IX10 | `rtsp://IP:554//stream1` | Fixed box | Professional | | IX30C / IX30DN | `rtsp://IP:554//stream1` | Fixed box | Day/night | | IXDN30 | `rtsp://IP:554//stream1` | Fixed box | Day/night | | IXE10LW | `rtsp://IP:554//stream1` | Fixed dome | Wireless | | IXE20DN | `rtsp://IP:554//stream1` | Fixed dome | Day/night | | IXP31 | `rtsp://IP:554//stream1` | Fixed dome | Professional | | IMP519 | `rtsp://IP:554//stream1` | Mini dome | 5MP | | IMP1110-1 / IMP1110-1E | `rtsp://IP:554//stream1` | Mini dome | Sarix Pro | | IM10C10 | `rtsp://IP:554//stream1` | Multi-sensor | Sarix IMM | | IM10DN10-1E | `rtsp://IP:554//stream1` | Multi-sensor | Day/night | | D5230-ADFRZ28 | `rtsp://IP:554//stream1` | PTZ dome | Spectra | | Spectra IV | `rtsp://IP:554//stream1` | PTZ dome | Legacy PTZ | | Spectra Professional | `rtsp://IP:554//stream1` | PTZ dome | Current PTZ | ### Multi-Channel / Multi-Sensor For multi-channel Pelco devices: | Stream | RTSP URL | Notes | | --- | --- | --- | | Channel 1, main | `rtsp://IP:554/1/stream1` | First sensor/channel | | Channel 2, main | `rtsp://IP:554/2/stream1` | Second sensor/channel | | Channel stream (alt) | `rtsp://IP:554/stream1` | Single channel (some models) | ### Legacy Models | Model | URL | Notes | | --- | --- | --- | | IP110 / IP-110 | `http://IP/api/jpegControl.php?frameRate=10` | JPEG stream | | Spectra IV (HTTP) | `http://IP/jpeg` | JPEG snapshot | | Spectra IV (pull) | `http://IP/jpeg/pull` | Continuous JPEG | | Spectra IV (API) | `http://IP/api/jpegControl.php?frameRate=10` | Frame-rate JPEG | ## Connecting with VisioForge SDK Use your Pelco camera's RTSP URL with any of the three SDK approaches shown in the [Quick Start Guide](../#quick-start-code): ``` // Pelco Sarix camera, main stream var uri = new Uri("rtsp://192.168.1.85:554//stream1"); var username = "admin"; var password = "YourPassword"; ``` For sub-stream access, use `//stream2` instead. For multi-sensor cameras, use `/1/stream1` for channel selection. ## Snapshot and MJPEG URLs | Type | URL Pattern | Notes | | --- | --- | --- | | JPEG Snapshot | `http://IP/jpeg` | Most current models | | JPEG (channel) | `http://IP/jpeg?id=1` | Channel-specific | | JPEG (API) | `http://IP/api/jpegControl.php?frameRate=10` | Legacy models | | JPEG (tmpfs) | `http://IP/tmpfs/auto.jpg` | Auto-capture | | Image file | `http://IP/img.jpg` | Simple snapshot | ## Troubleshooting ### Double slash is required Most Pelco cameras require a **double forward slash** before the stream path: - Correct: `rtsp://IP:554//stream1` - May not work: `rtsp://IP:554/stream1` If a single-slash URL fails, always try the double-slash variant first. ### Channel numbering for multi-sensor Pelco multi-sensor cameras (IM10-series, Sarix IMM) use numbered channel paths: - `rtsp://IP:554/1/stream1` — first sensor - `rtsp://IP:554/2/stream1` — second sensor Single-sensor cameras should use `//stream1` without a channel number. ### Pelco D/P protocol vs RTSP Pelco is also known for the **Pelco D** and **Pelco P** serial communication protocols used to control PTZ cameras. These are serial protocols for PTZ control, not video streaming. Video streaming always uses RTSP or HTTP regardless of which PTZ control protocol is used. ### Spectra PTZ cameras Pelco Spectra PTZ cameras use the same RTSP URL format (`//stream1`) as fixed cameras. PTZ control is handled separately via ONVIF PTZ commands or Pelco D/P serial protocol, not through the RTSP URL. ## FAQ **What is the default RTSP URL for Pelco cameras?** For most Pelco cameras, use `rtsp://admin:password@CAMERA_IP:554//stream1` (note the double slash). For the sub-stream, use `//stream2`. Multi-sensor models use `/1/stream1` for channel-specific access. **Is Pelco still an independent company?** No. Pelco was acquired by Motorola Solutions in 2020. Current Pelco cameras are manufactured and supported by Motorola Solutions. The Pelco brand and product lines (Sarix, Spectra) continue under Motorola Solutions' video security portfolio. **Do Pelco cameras support ONVIF?** Yes. All current Pelco Sarix and Spectra cameras support ONVIF Profile S, G, and T. ONVIF is the recommended discovery and configuration method for new Pelco integrations. **What is the difference between Pelco D and RTSP?** Pelco D (and Pelco P) are serial protocols for PTZ camera control (pan, tilt, zoom commands). RTSP is the video streaming protocol. You use RTSP for video and Pelco D/ONVIF for PTZ control — they serve different purposes and are not interchangeable. ## Related Resources - [All Camera Brands — RTSP URL Directory](../) - [Avigilon Connection Guide](../avigilon/) — Also Motorola Solutions, enterprise cameras - [Honeywell Connection Guide](../honeywell/) — Enterprise surveillance cameras - [IP Camera Preview Tutorial](../../videocapture/video-tutorials/ip-camera-preview/) - [SDK Installation & Samples](../#get-started) ---END OF PAGE--- ## How to Connect to Q-See IP Camera & DVR in C# .NET **URL:** https://www.visioforge.com/help/docs/dotnet/camera-brands/q-see/ **Description:** Q-See QC, QCN, and QS series camera and DVR RTSP URL patterns for C# .NET. Default credentials, channel setup, and VisioForge SDK integration code. **Tags:** Video Capture SDK, Media Blocks SDK, .NET, Windows, macOS, Linux, Android, iOS, Capture, Streaming, IP Camera, RTSP, ONVIF, H.264, MJPEG, C# # How to Connect to Q-See IP Camera & DVR in C# .NET [Video Capture SDK .Net](https://www.visioforge.com/video-capture-sdk-net) [Media Blocks SDK .Net](https://www.visioforge.com/media-blocks-sdk-net) ## Brand Overview **Q-See** was an American consumer surveillance brand based in Anaheim, California. Q-See DVRs and IP cameras were popular budget surveillance systems sold through major US retailers including Costco and Amazon. The company became essentially defunct by 2020, but a large number of Q-See systems remain deployed in homes and businesses. Q-See products used a mix of **Dahua OEM cameras** and components from other Chinese manufacturers, meaning most Q-See devices follow Dahua RTSP URL conventions. **Key facts:** - **Product lines:** QC Series (DVRs), QCN Series (IP cameras), QS Series (DVR kits) - **Protocol support:** RTSP, HTTP/CGI, ONVIF (some IP camera models) - **Default RTSP port:** 554 - **Default credentials:** admin / admin or admin / 123456 - **ONVIF support:** Some IP camera models (QCN series) - **Video codecs:** H.264 (most models), MPEG-4 (older DVRs) - **OEM base:** Mix of Dahua and other manufacturers Q-See Is Defunct Q-See ceased operations around 2020. No firmware updates, technical support, or cloud services are available. If you are integrating Q-See hardware, treat it as Dahua-compatible equipment and try Dahua URL patterns first. See our [Dahua connection guide](../dahua/) for additional details. ## RTSP URL Patterns ### Standard URL Format (Dahua-Based) Most Q-See devices use the Dahua `cam/realmonitor` URL pattern: ``` rtsp://[USERNAME]:[PASSWORD]@[IP]:554/cam/realmonitor?channel=1&subtype=0 ``` | Parameter | Value | Description | | --- | --- | --- | | `channel` | 1, 2, 3... | Camera channel (1 for standalone cameras, 1-N for DVR channels) | | `subtype` | 0 | Main stream (highest resolution) | | `subtype` | 1 | Sub stream (lower resolution, less bandwidth) | ### DVR Models (QC Series, QS Series) | Model / Series | Main Stream URL | Notes | | --- | --- | --- | | QC-804 (4-ch DVR) | `rtsp://IP:554/cam/realmonitor?channel=1&subtype=0` | Dahua format, change `channel` for each input | | QS408 / QS411 (DVR kits) | `rtsp://IP:554/cam/realmonitor?channel=1&subtype=0` | Dahua format | | Various DVRs | `rtsp://IP:554/` | Root stream (fallback) | | Various DVRs | `rtsp://IP:554/live.sdp` | Live SDP stream | | Various DVRs | `rtsp://IP:554/ch0_unicast_firststream` | Unicast first stream | ### IP Camera Models (QCN Series) | Model | Resolution | URL | Notes | | --- | --- | --- | --- | | QCN7001B | 1080p | `rtsp://IP:554/cam/realmonitor?channel=1&subtype=0` | Dahua format (recommended) | | QCN7001B | 1080p | `rtsp://IP:554/PSIA/Streaming/channels/0?videoCodecType=H.264` | PSIA format | | QCN7001B | 1080p | `rtsp://IP:554/VideoInput/1/h264/1` | VideoInput H.264 | | QCN7001B | 1080p | `rtsp://IP:554/VideoInput/1/mpeg4/1` | VideoInput MPEG-4 | | QCN7005B | 1080p | `rtsp://IP:554/` | Root stream | ### Alternative URL Formats Some Q-See devices support additional URL patterns: | URL Pattern | Notes | | --- | --- | | `rtsp://IP:554/cam/realmonitor?channel=1&subtype=0` | Standard Dahua format (recommended) | | `rtsp://IP:554/cam/realmonitor?channel=1&subtype=1` | Sub stream (lower bandwidth) | | `rtsp://IP:554/cam/realmonitor?channel=1&subtype=00&authbasic=BASE64` | With base64-encoded credentials | | `rtsp://IP:554/` | Root stream (fallback for many models) | | `rtsp://IP:554/live.sdp` | Live SDP format | | `rtsp://IP:554/ch0_unicast_firststream` | Unicast first stream | Base64 Authentication The `authbasic=` parameter used in some Q-See URLs takes base64-encoded credentials in the format `username:password`. For example, `admin:admin` encodes to `YWRtaW46YWRtaW4=`. ### DVR Channel URLs For Q-See multi-channel DVRs (QC-804, QS408, QS411, etc.): | Channel | Main Stream | Sub Stream | | --- | --- | --- | | Camera 1 | `rtsp://IP:554/cam/realmonitor?channel=1&subtype=0` | `rtsp://IP:554/cam/realmonitor?channel=1&subtype=1` | | Camera 2 | `rtsp://IP:554/cam/realmonitor?channel=2&subtype=0` | `rtsp://IP:554/cam/realmonitor?channel=2&subtype=1` | | Camera N | `rtsp://IP:554/cam/realmonitor?channel=N&subtype=0` | `rtsp://IP:554/cam/realmonitor?channel=N&subtype=1` | ## Connecting with VisioForge SDK Use your Q-See camera's RTSP URL with any of the three SDK approaches shown in the [Quick Start Guide](../#quick-start-code): ``` // Q-See QC-804 DVR, channel 1 main stream var uri = new Uri("rtsp://192.168.1.100:554/cam/realmonitor?channel=1&subtype=0"); var username = "admin"; var password = "admin"; ``` For sub-stream access, use `subtype=1` instead of `subtype=0`. ## Snapshot and MJPEG URLs | Type | URL Pattern | Notes | | --- | --- | --- | | CGI Snapshot | `http://IP/cgi-bin/snapshot.cgi?chn=1&u=USER&p=PASS` | Channel-based snapshot with credentials | | Login-Based Snapshot | `http://IP/cgi-bin/snapshot.cgi?loginuse=USER&loginpas=PASS` | Login parameter-based snapshot | | Still Image | `http://IP/stillimg1.jpg` | Replace `1` with channel number | | Stream Image | `http://IP/images/stream_1.jpg` | Replace `1` with channel number | | Fast Stream (QS Series) | `http://IP/control/faststream.jpg?stream=MxPEG&needlength&fps=6` | Continuous fast stream | ## Troubleshooting ### No firmware updates or support Q-See ceased operations around 2020. There are no firmware updates, no technical support, and no replacement parts available. If your Q-See device has a security vulnerability or bug, it cannot be patched. Consider upgrading to a currently supported camera brand. ### Try Dahua URL patterns first Most Q-See DVRs and many IP cameras use Dahua firmware internally. If the Q-See-specific URLs listed above do not work, try the standard Dahua `cam/realmonitor` format. See our [Dahua connection guide](../dahua/) for the full set of Dahua URL patterns. ### Base64 authentication parameter Some Q-See devices use an `authbasic=` parameter in the RTSP URL instead of embedding credentials in the URI. Encode `username:password` as base64: - `admin:admin` = `YWRtaW46YWRtaW4=` - `admin:123456` = `YWRtaW46MTIzNDU2` ### Port forwarding for remote access Q-See DVRs typically require manual port forwarding for remote RTSP access. Forward port **554** (RTSP) and optionally port **80** or **8080** (HTTP) on your router to the DVR's local IP address. ### Default credentials Q-See devices commonly ship with one of these credential pairs: - `admin` / `admin` - `admin` / `123456` If neither works, the password may have been changed by the previous owner or installer. ## FAQ **What RTSP URL format do Q-See cameras use?** Most Q-See devices use the Dahua `cam/realmonitor` format: `rtsp://admin:password@CAMERA_IP:554/cam/realmonitor?channel=1&subtype=0`. This is because Q-See cameras and DVRs were primarily OEM versions of Dahua hardware. Use `channel=1` for standalone cameras or the appropriate channel number for DVR inputs. **Are Q-See cameras still supported?** No. Q-See ceased operations around 2020. No firmware updates, cloud services, or technical support are available. The hardware still functions, but there will be no future patches or improvements. Many users have migrated to other brands like Amcrest or Reolink that use similar Dahua-based protocols. **Can I use Q-See cameras with ONVIF?** Some Q-See IP cameras (QCN series) support ONVIF, but most Q-See DVRs do not. If ONVIF discovery fails, use the direct RTSP URL patterns listed above instead. **What is the default password for Q-See cameras?** The default credentials are typically `admin` / `admin` or `admin` / `123456`. Since Q-See is no longer available, there is no official password reset tool. A factory reset (usually a pinhole button on the device) will restore default credentials on most models. ## Related Resources - [All Camera Brands — RTSP URL Directory](../) - [Dahua Connection Guide](../dahua/) — Same URL format for most Q-See devices - [IP Camera Preview Tutorial](../../videocapture/video-tutorials/ip-camera-preview/) - [SDK Installation & Samples](../#get-started) ---END OF PAGE--- ## Reolink IP Camera RTSP Connection Guide for C# .NET **URL:** https://www.visioforge.com/help/docs/dotnet/camera-brands/reolink/ **Description:** Reolink RLC, E1, Argus, CX, and Duo series RTSP URL patterns for C# .NET. Stream and record using VisioForge SDK with ONVIF discovery support. **Tags:** Video Capture SDK, Media Blocks SDK, .NET, Windows, macOS, Linux, Android, iOS, Capture, Streaming, IP Camera, RTSP, ONVIF, H.264, H.265, C# # How to Connect to Reolink IP Camera in C# .NET [Video Capture SDK .Net](https://www.visioforge.com/video-capture-sdk-net) [Media Blocks SDK .Net](https://www.visioforge.com/media-blocks-sdk-net) ## Brand Overview **Reolink** (Reolink Digital Technology Co., Ltd.) is a consumer and prosumer IP camera manufacturer headquartered in Hong Kong. Founded in 2009, Reolink has grown rapidly through direct-to-consumer sales on Amazon and their own website, offering competitively priced cameras with straightforward RTSP access. Reolink is notable for clear documentation of RTSP URLs and easy integration with third-party software. **Key facts:** - **Product lines:** RLC series (PoE wired), RLN series (NVRs), E1 series (Wi-Fi pan/tilt), Argus series (battery/solar), CX series (ColorX night vision), Duo series (dual-lens), TrackMix (auto-tracking) - **Protocol support:** RTSP, ONVIF, HTTP/HTTPS, proprietary Reolink protocol - **Default RTSP port:** 554 - **Default credentials:** admin / (blank password or set during setup) - **ONVIF support:** Yes (most current models, may require enabling in camera settings) - **Video codecs:** H.264 (all models), H.265 (most current models) ## RTSP URL Patterns Reolink uses a consistent URL pattern across most models. The main difference is between cameras and NVRs (which use channel numbers). ### Camera RTSP URLs | Stream | RTSP URL | Resolution | Notes | | --- | --- | --- | --- | | Main (clear) | `rtsp://IP:554/h264Preview_01_main` | Full (up to 4K/8MP) | H.264 main stream | | Sub (fluent) | `rtsp://IP:554/h264Preview_01_sub` | Reduced (640x360) | Lower bandwidth | H.265 streams For cameras with H.265 enabled, the URL remains the same (`h264Preview_01_main`). The `h264` in the URL path is not codec-specific -- it works for both H.264 and H.265 streams. ### NVR Channel URLs For Reolink NVRs (RLN8-410, RLN16-410, RLN36, etc.), append the channel number: | Channel | Main Stream URL | Sub Stream URL | | --- | --- | --- | | Channel 1 | `rtsp://IP:554/h264Preview_01_main` | `rtsp://IP:554/h264Preview_01_sub` | | Channel 2 | `rtsp://IP:554/h264Preview_02_main` | `rtsp://IP:554/h264Preview_02_sub` | | Channel 3 | `rtsp://IP:554/h264Preview_03_main` | `rtsp://IP:554/h264Preview_03_sub` | | Channel N | `rtsp://IP:554/h264Preview_0N_main` | `rtsp://IP:554/h264Preview_0N_sub` | ### Models and Resolutions | Model | Resolution | Codec | Wi-Fi | RTSP | | --- | --- | --- | --- | --- | | RLC-410 | 2560x1440 (4MP) | H.264/H.265 | No (PoE) | Yes | | RLC-510A | 2560x1920 (5MP) | H.264/H.265 | No (PoE) | Yes | | RLC-520A | 2560x1920 (5MP) | H.264/H.265 | No (PoE) | Yes | | RLC-810A | 3840x2160 (8MP) | H.264/H.265 | No (PoE) | Yes | | RLC-811A | 3840x2160 (8MP) | H.264/H.265 | No (PoE) | Yes | | RLC-820A | 3840x2160 (8MP) | H.264/H.265 | No (PoE) | Yes | | RLC-1212A | 4512x2512 (12MP) | H.264/H.265 | No (PoE) | Yes | | E1 Zoom | 2560x1920 (5MP) | H.264/H.265 | Yes | Yes | | E1 Pro | 2560x1440 (4MP) | H.264 | Yes | Yes | | E1 Outdoor | 2560x1920 (5MP) | H.264/H.265 | Yes | Yes | | CX410 | 2560x1440 (4MP) | H.264/H.265 | No (PoE) | Yes | | CX810 | 3840x2160 (8MP) | H.264/H.265 | No (PoE) | Yes | | TrackMix PoE | 3840x2160 (8MP) | H.264/H.265 | No (PoE) | Yes | | Duo 2 PoE | 4608x1728 (8MP) | H.264/H.265 | No (PoE) | Yes | | Argus 3 Pro | 2560x1440 (4MP) | H.264 | Yes (battery) | Yes | Argus battery cameras Argus series battery-powered cameras support RTSP but drain the battery quickly when streaming continuously. Use RTSP only for testing or event-triggered recording, not 24/7 monitoring. ## Connecting with VisioForge SDK Use your Reolink camera's RTSP URL with any of the three SDK approaches shown in the [Quick Start Guide](../#quick-start-code): ``` // Reolink RLC-810A, main stream var uri = new Uri("rtsp://192.168.1.88:554/h264Preview_01_main"); var username = "admin"; var password = "YourPassword"; ``` For sub-stream access, use `h264Preview_01_sub` instead of `h264Preview_01_main`. For NVR channels, change the channel number (e.g., `h264Preview_03_main` for channel 3). ## Snapshot URLs | Type | URL Pattern | Notes | | --- | --- | --- | | JPEG Snapshot | `http://IP/cgi-bin/api.cgi?cmd=Snap&channel=0&rs=abc123&user=USER&password=PASS` | API-based snapshot | ## Troubleshooting ### RTSP not working -- "Connection refused" RTSP may need to be enabled on some Reolink models: 1. Open the **Reolink app** or web interface 2. Go to **Settings > Network > Advanced > Port Settings** 3. Ensure **RTSP port** is enabled and set to 554 4. Some older firmware versions have RTSP disabled by default ### H.265 stream not decoding If your Reolink camera is configured for H.265 and the stream fails to decode: - The SDK supports H.265 natively, but ensure you're using a recent SDK version - Try switching the camera to H.264 in **Settings > Display > Encode** as a workaround - The RTSP URL path (`h264Preview`) remains the same regardless of the actual codec ### Sub stream shows low quality The sub stream (`h264Preview_01_sub`) is intentionally lower resolution (typically 640x360) to reduce bandwidth. Use `h264Preview_01_main` for full resolution. You can adjust sub stream quality in the Reolink app under Display settings. ### NVR channel numbering Reolink NVR channels are 1-indexed with zero-padded two-digit format: `01`, `02`, `03`... `16`. Channel 0 does not exist. ## FAQ **What is the default RTSP URL for Reolink cameras?** The URL is `rtsp://admin:password@CAMERA_IP:554/h264Preview_01_main` for the main stream and `h264Preview_01_sub` for the sub stream. The password is whatever you set during camera setup. **Does the RTSP URL change when using H.265?** No. The URL path `h264Preview_01_main` is used for both H.264 and H.265 streams. The `h264` in the path is a legacy naming convention, not a codec selector. **Can I access Reolink cameras remotely via RTSP?** RTSP is designed for local network access. For remote access, you would need to set up port forwarding on your router (forward port 554 to the camera's IP) or use a VPN. Reolink's cloud/P2P access uses a proprietary protocol, not RTSP. **Do Reolink Duo cameras have separate RTSP streams for each lens?** Yes. Reolink Duo cameras expose the wide-angle lens on the standard channel and may provide additional streams. Check your specific model's documentation for dual-lens stream access. ## Related Resources - [All Camera Brands — RTSP URL Directory](../) - [Amcrest Connection Guide](../amcrest/) — Consumer alternative with RTSP - [TP-Link Connection Guide](../tp-link/) — Budget cameras with native RTSP - [IP Camera Preview Tutorial](../../videocapture/video-tutorials/ip-camera-preview/) - [SDK Installation & Samples](../#get-started) ---END OF PAGE--- ## Rhombus Camera RTSP URL and Cloud API C# Integration **URL:** https://www.visioforge.com/help/docs/dotnet/camera-brands/rhombus/ **Description:** Rhombus camera integration options in C# .NET. Cloud-managed architecture, API access, and alternative approaches for Rhombus Systems cameras. **Tags:** Video Capture SDK, Media Blocks SDK, .NET, Windows, macOS, Linux, Android, iOS, Capture, Streaming, IP Camera, RTSP, ONVIF, C# # How to Connect to Rhombus Camera in C# .NET [Video Capture SDK .Net](https://www.visioforge.com/video-capture-sdk-net) [Media Blocks SDK .Net](https://www.visioforge.com/media-blocks-sdk-net) ## Brand Overview **Rhombus Systems** (Rhombus, Inc.) is an American cloud-managed video security company headquartered in Sacramento, California. Founded in 2016, Rhombus provides enterprise cameras, sensors, and access control with a cloud-first management platform. Similar to Verkada, Rhombus cameras are managed through a centralized cloud console. **Key facts:** - **Product lines:** R-series (dome), R-series Pro (advanced), R-series Mini (compact) - **Architecture:** Cloud-managed with on-camera AI processing - **RTSP support:** Limited — available on some models via LAN configuration - **ONVIF support:** No - **Video codecs:** H.264, H.265 - **API access:** Rhombus API (REST, requires subscription) - **On-camera storage:** Yes (local SD card for edge storage) Limited Local Streaming Some Rhombus camera models support RTSP for local LAN streaming, but this feature must be enabled through the Rhombus console and is not available on all models or subscription tiers. Check your Rhombus account settings for RTSP availability. ## RTSP Access (Where Available) ### Enabling RTSP On supported Rhombus cameras: 1. Log in to the **Rhombus Console** (console.rhombus.com) 2. Navigate to your camera's settings 3. Look for **Local Streaming** or **RTSP** settings 4. Enable RTSP and note the provided URL ### RTSP URL Format When RTSP is available: ``` rtsp://[IP]:554/live ``` The exact URL format and authentication method depend on the camera model and firmware version. The Rhombus console will provide the specific URL when RTSP is enabled. ## Connecting with VisioForge SDK If RTSP is available on your Rhombus camera, use the URL with any of the three SDK approaches shown in the [Quick Start Guide](../#quick-start-code): ``` // Rhombus camera with RTSP enabled var uri = new Uri("rtsp://192.168.1.90:554/live"); var username = "admin"; var password = "YourPassword"; // from Rhombus console ``` ## Integration via Rhombus API For cameras without RTSP access, Rhombus provides a REST API that offers: - Camera listing and status - Video clip export and download - Snapshot/thumbnail retrieval - Event and analytics data - Webhook notifications The API does not provide real-time RTSP streams. It is designed for clip retrieval, metadata access, and automation workflows. ## Troubleshooting ### RTSP not available on my camera Not all Rhombus cameras or subscription tiers support RTSP. Contact Rhombus support to verify RTSP availability for your specific camera model and plan. ### RTSP stream disconnects Rhombus cameras prioritize cloud connectivity. If the local RTSP stream is unstable: 1. Ensure the camera has sufficient network bandwidth for both cloud and local streams 2. Use the sub stream for lower bandwidth requirements 3. Check the Rhombus console for firmware updates ## FAQ **Do Rhombus cameras support RTSP?** Some Rhombus cameras support RTSP for local LAN streaming, but it must be enabled through the Rhombus console and may not be available on all models or subscription tiers. Contact Rhombus support for specifics. **Can I use VisioForge SDK with Rhombus cameras?** If your Rhombus camera has RTSP enabled, yes. Use the RTSP URL from the Rhombus console with VisioForge SDK's RTSP source. For cameras without RTSP, you would need to use the Rhombus REST API separately for clip and snapshot access. **How does Rhombus compare to Verkada?** Both are cloud-managed platforms. Rhombus offers RTSP on some models, while Verkada does not support RTSP at all. Both provide REST APIs for clip/snapshot access. See our [Verkada guide](../verkada/) for comparison. **What are good alternatives to Rhombus with full RTSP support?** For enterprise cameras with native RTSP and ONVIF support, consider [Axis](../axis/), [Bosch](../bosch/), [Hanwha Vision](../hanwha/), or [Avigilon](../avigilon/). ## Related Resources - [All Camera Brands — RTSP URL Directory](../) - [Verkada Connection Guide](../verkada/) — Another cloud-managed platform - [Axis Connection Guide](../axis/) — Enterprise alternative with full RTSP - [Hanwha Vision Connection Guide](../hanwha/) — Enterprise alternative with RTSP - [SDK Installation & Samples](../#get-started) ---END OF PAGE--- ## How to Connect to Samsung (Hanwha) IP Camera in C# .NET **URL:** https://www.visioforge.com/help/docs/dotnet/camera-brands/samsung/ **Description:** Samsung Wisenet SNO, SND, XNO, XND, and PNO camera RTSP URL patterns for C# .NET. Hanwha Vision integration with VisioForge SDK code samples. **Tags:** Video Capture SDK, Media Blocks SDK, .NET, Windows, macOS, Linux, Android, iOS, Capture, Streaming, IP Camera, RTSP, ONVIF, H.264, H.265, MJPEG, C# # How to Connect to Samsung (Hanwha) IP Camera in C# .NET [Video Capture SDK .Net](https://www.visioforge.com/video-capture-sdk-net) [Media Blocks SDK .Net](https://www.visioforge.com/media-blocks-sdk-net) ## Brand Overview **Hanwha Vision** (formerly Samsung Techwin, then Hanwha Techwin) is a South Korean manufacturer of professional and enterprise-grade video surveillance equipment. The Samsung security camera brand was rebranded to **Wisenet** after Hanwha Group acquired Samsung Techwin in 2015. Hanwha Vision cameras are widely deployed in enterprise, government, and critical infrastructure installations worldwide. **Key facts:** - **Product lines:** XNO/XND/XNV (X-series, current flagship), PNO/PND/PNV (P-series, mainstream), QNO/QND/QNV (Q-series, value), SNO/SND/SNV/SNB (S-series, legacy Samsung) - **Naming convention:** First letter = series, N = network, O = outdoor, D = dome, V = vandal-resistant, B = box, P = PTZ - **Protocol support:** RTSP, ONVIF (Profile S/G/T), HTTP/CGI, Wisenet WAVE VMS - **Default RTSP port:** 554 - **Default credentials:** admin / (set during initial setup); legacy Samsung models: admin / 4321 - **ONVIF support:** Yes (all current and most legacy models) - **Video codecs:** H.264, H.265, MJPEG ## RTSP URL Patterns ### Current Models (Wisenet X/P/Q Series) Current Hanwha Vision cameras use a profile-based URL format: | Stream | RTSP URL | Notes | | --- | --- | --- | | Profile 1 (main) | `rtsp://IP:554/profile2/media.smp` | Main stream, H.264/H.265 | | Profile 2 (sub) | `rtsp://IP:554/profile3/media.smp` | Sub stream | | ONVIF Profile 1 | `rtsp://IP:554//onvif/profile1/media.smp` | ONVIF-compatible (note double slash) | | ONVIF Profile 2 | `rtsp://IP:554//onvif/profile2/media.smp` | ONVIF sub stream | Double slash in ONVIF URLs Samsung/Hanwha ONVIF URLs use a double slash (`//onvif/`). This is intentional and required. Using a single slash will fail. ### Legacy Samsung S-Series | Model Series | RTSP URL | Codec | | --- | --- | --- | | SNB-xxxx (box) | `rtsp://IP:554/profile2/media.smp` | H.264 | | SND-xxxx (dome) | `rtsp://IP:554/profile2/media.smp` | H.264 | | SNO-xxxx (outdoor) | `rtsp://IP:554/profile2/media.smp` | H.264 | | SNV-xxxx (vandal) | `rtsp://IP:554/profile2/media.smp` | H.264 | | SNP-xxxx (PTZ) | `rtsp://IP:554/profile2/media.smp` | H.264 | ### Older Samsung Models (Pre-Wisenet) Older Samsung cameras used different URL formats: | URL Pattern | Models | Codec | | --- | --- | --- | | `rtsp://IP:554/mpeg4unicast` | SNB-2000, SNC-1300, SNP-3301/3370 | MPEG-4 | | `rtsp://IP:554/h264unicast` | SNP-3301/H, SNP-3370/TH | H.264 | | `rtsp://IP:554/mjpegunicast` | SNP-3301/H, SNP-3370/TH | MJPEG | | `rtsp://IP:554/H264/media.smp` | SNB-3000, SND-3080, SNV-3080/3081 | H.264 | | `rtsp://IP:554/MPEG4/media.smp` | SNV-3080/3081 | MPEG-4 | | `rtsp://IP:554/MJPEG/media.smp` | SNB-3000, SNV-3081, SNV-6084R | MJPEG | | `rtsp://IP:554/MediaInput/h264` | Misc. Samsung | H.264 | ### DVR/NVR URLs | Device | RTSP URL | Notes | | --- | --- | --- | | SRD-165 DVR | `rtsp://IP:558/` | Non-standard port 558 | | SME DVR | `rtsp://IP:554/mpeg4unicast` | MPEG-4 | | SMT DVR | `rtsp://IP:554/mpeg4unicast` | MPEG-4 | ## Connecting with VisioForge SDK Use your Samsung (Hanwha Wisenet) camera's RTSP URL with any of the three SDK approaches shown in the [Quick Start Guide](../#quick-start-code): ``` // Hanwha Wisenet X-series camera, main stream var uri = new Uri("rtsp://192.168.1.70:554/profile2/media.smp"); var username = "admin"; var password = "YourPassword"; ``` For sub-stream access, use `profile3/media.smp` instead of `profile2/media.smp`. For legacy Samsung S-series models, use the default password `4321` and URL path `/mpeg4unicast` or `/H264/media.smp`. ## Snapshot and MJPEG URLs | Type | URL Pattern | Notes | | --- | --- | --- | | JPEG Snapshot | `http://IP/cgi-bin/video.cgi?msubmenu=jpg` | Current models | | MJPEG Stream | `http://IP/cgi-bin/video.cgi?msubmenu=mjpg` | Current models | | Legacy Snapshot | `http://IP/video?submenu=jpg` | Pre-Wisenet models | | Legacy MJPEG | `http://IP/video?submenu=mjpg` | Pre-Wisenet models | | CGI Snapshot | `http://IP/cgi-bin/webra_fcgi.fcgi?api=get_jpeg_raw&chno=CHANNEL` | DVR models | | Snap (sized) | `http://IP/snap.jpg?JpegSize=XL` | Some Bosch-OEM firmware | ## Troubleshooting ### Default password differences - **Current Hanwha Vision models:** Password must be set during initial setup via web browser - **Legacy Samsung S-series:** Default password is `4321` - **Very old Samsung models:** Some used `admin` / `admin` ### profile2 vs profile1 in URL Samsung/Hanwha cameras use `profile2/media.smp` for the main stream (not `profile1`). This is a common source of confusion: - `profile2/media.smp` = Main stream (typically H.264 at full resolution) - `profile3/media.smp` = Sub stream - The profile numbers may differ based on camera configuration ### ONVIF double-slash issue The ONVIF URL format requires a double slash before `onvif`: - Correct: `rtsp://IP:554//onvif/profile1/media.smp` - Incorrect: `rtsp://IP:554/onvif/profile1/media.smp` ### Brand name confusion Samsung Techwin was acquired by Hanwha in 2015. The brand has been called: - **Samsung Techwin** (before 2015) - **Hanwha Techwin** (2015-2022) - **Hanwha Vision** (2022-present) - **Wisenet** (product brand name, used throughout) All use the same RTSP URL patterns within their respective generation. ## FAQ **What is the default RTSP URL for Samsung/Hanwha cameras?** For current Wisenet models, the URL is `rtsp://admin:password@CAMERA_IP:554/profile2/media.smp`. For legacy Samsung models, try `rtsp://admin:4321@CAMERA_IP:554/mpeg4unicast` or `rtsp://CAMERA_IP:554/H264/media.smp`. **Is Samsung the same as Hanwha Vision?** Yes. Samsung's security camera division was acquired by Hanwha Group in 2015. The product brand is **Wisenet**. Legacy Samsung cameras (SNB, SND, SNO series) and current Hanwha Vision cameras (XNO, XND, PNO series) use similar RTSP patterns. **Do Samsung/Hanwha cameras support H.265?** Yes. Current X-series and P-series cameras support H.265 (HEVC). Legacy S-series cameras typically support H.264 and MPEG-4 only. **What VMS works with Hanwha cameras?** Hanwha's own VMS is **Wisenet WAVE**. However, all Hanwha cameras support standard RTSP and ONVIF, making them compatible with any third-party software including VisioForge SDK applications. ## Related Resources - [All Camera Brands — RTSP URL Directory](../) - [Hanwha Vision Connection Guide](../hanwha/) — Current brand name, same URLs - [Wisenet Connection Guide](../wisenet/) — Hanwha Vision product family - [IP Camera Preview Tutorial](../../videocapture/video-tutorials/ip-camera-preview/) - [SDK Installation & Samples](../#get-started) ---END OF PAGE--- ## Sanyo IP Camera RTSP URL Patterns and C# .NET Integration **URL:** https://www.visioforge.com/help/docs/dotnet/camera-brands/sanyo/ **Description:** Connect Sanyo VCC, VDC, and VCC-HD series IP cameras in C# .NET using RTSP URL patterns, snapshot endpoints, and VisioForge SDK code examples. **Tags:** Video Capture SDK, Media Blocks SDK, .NET, Windows, macOS, Linux, Android, iOS, Capture, Streaming, IP Camera, RTSP, ONVIF, H.264, MJPEG, C# # How to Connect to Sanyo IP Camera in C# .NET [Video Capture SDK .Net](https://www.visioforge.com/video-capture-sdk-net) [Media Blocks SDK .Net](https://www.visioforge.com/media-blocks-sdk-net) ## Brand Overview **Sanyo** (Sanyo Electric Co., Ltd.) was a Japanese electronics manufacturer headquartered in Osaka, Japan. Sanyo's security camera division produced the well-regarded VCC and VDC camera lines for professional surveillance installations. In 2009-2011, Panasonic acquired Sanyo Electric, and the camera technology was integrated into Panasonic's i-PRO product line. While Sanyo cameras are no longer manufactured, many units remain deployed in legacy installations worldwide. **Key facts:** - **Product lines:** VCC (box cameras), VDC (dome cameras), VCC-HD (HD series) - **Status:** Discontinued (acquired by Panasonic 2009-2011) - **Protocol support:** RTSP, HTTP/CGI, limited ONVIF (newer firmware) - **Default RTSP port:** 554 - **Default credentials:** admin / admin - **ONVIF support:** Limited (older firmware only) - **Video codecs:** H.264, MJPEG - **Successor:** Panasonic i-PRO Sanyo Cameras Are Discontinued Sanyo security cameras are discontinued. Sanyo Electric was acquired by Panasonic, and the camera technology was integrated into Panasonic's i-PRO product line. See our [Panasonic/i-PRO connection guide](../panasonic/) for current products. ## RTSP URL Patterns ### Standard URL Format Sanyo cameras use the `VideoInput` RTSP path: ``` rtsp://[USERNAME]:[PASSWORD]@[IP]:554/VideoInput/1/h264/1 ``` | Parameter | Value | Description | | --- | --- | --- | | `VideoInput` | 1, 2, 3... | Camera channel (1 for standalone cameras) | | `h264` | h264 | H.264 video codec | | Trailing `1` | 1 | Stream index | ### Camera Models | Model | Type | Main Stream URL | Notes | | --- | --- | --- | --- | | VCC-HD2300P | HD box camera | `rtsp://IP:554/VideoInput/1/h264/1` | H.264 main stream | | VCC-HD series | HD cameras | `rtsp://IP:554/VideoInput/1/h264/1` | H.264 main stream | | VCC-9574N | Box camera | `rtsp://IP:554/VideoInput/1/h264/1` | H.264 main stream | | VCC-P9574N | PTZ camera | `rtsp://IP:554/VideoInput/1/h264/1` | H.264 main stream | | VDC series | Dome cameras | `rtsp://IP:554/VideoInput/1/h264/1` | H.264 main stream | ### DVR Channel URLs For Sanyo DVR systems with multiple channels: | Channel | Main Stream URL | | --- | --- | | Camera 1 | `rtsp://IP:554/VideoInput/1/h264/1` | | Camera 2 | `rtsp://IP:554/VideoInput/2/h264/1` | | Camera N | `rtsp://IP:554/VideoInput/N/h264/1` | ### Alternative URL Formats | URL Pattern | Notes | | --- | --- | | `rtsp://IP:554/VideoInput/1/h264/1` | Standard H.264 stream (recommended) | | `rtsp://IP:554/VideoInput/CHANNEL/h264/1` | Multi-channel DVR access | ## Connecting with VisioForge SDK Use your Sanyo camera's RTSP URL with any of the three SDK approaches shown in the [Quick Start Guide](../#quick-start-code): ``` // Sanyo VCC-HD2300P, main stream var uri = new Uri("rtsp://192.168.1.90:554/VideoInput/1/h264/1"); var username = "admin"; var password = "YourPassword"; ``` For multi-channel DVR access, replace `VideoInput/1` with the appropriate channel number. ## Snapshot and MJPEG URLs Sanyo's liveimg.cgi Endpoint Sanyo cameras use a distinctive `/liveimg.cgi` endpoint for HTTP snapshots and MJPEG streams. The `serverpush=1` parameter enables continuous MJPEG streaming. | Type | URL Pattern | Notes | | --- | --- | --- | | Live Snapshot | `http://IP/liveimg.cgi` | Single JPEG frame | | MJPEG Stream | `http://IP/liveimg.cgi?serverpush=1` | Continuous server-push MJPEG | | MJPEG with Channel | `http://IP/liveimg.cgi?serverpush=1&jpeg=1&stream=CHANNEL` | Channel-specific MJPEG stream | | Channel Snapshot (DVR) | `http://IP/liveimg.cgi?ch=CHANNEL` | Channel-specific snapshot for DVR | ## Troubleshooting ### "401 Unauthorized" error Sanyo cameras use basic authentication by default. Ensure you are providing correct credentials: 1. Access the camera at `http://CAMERA_IP` in a browser 2. Log in with your credentials (default: admin / admin) 3. Verify the RTSP service is enabled in network settings 4. Use those credentials in your RTSP URL ### H.264 stream not available Older Sanyo models may only support MJPEG. If the H.264 URL does not work, try using the MJPEG HTTP stream instead: ``` http://CAMERA_IP/liveimg.cgi?serverpush=1 ``` ### Firmware and compatibility Since Sanyo cameras are discontinued, firmware updates are no longer available. If you encounter compatibility issues: - Ensure the camera firmware is the latest available version - Try using ONVIF discovery if direct URL connection fails - Consider migrating to Panasonic i-PRO cameras, which inherit Sanyo's technology ### MJPEG server-push not working The `serverpush=1` parameter requires the camera's HTTP server to support chunked transfer encoding. Some older firmware versions may not support this reliably. Try the single snapshot endpoint (`/liveimg.cgi` without parameters) and poll at your desired frame rate instead. ## FAQ **Are Sanyo cameras still supported?** Sanyo security cameras are discontinued. Sanyo Electric was fully acquired by Panasonic, and the surveillance camera technology was merged into Panasonic's i-PRO product line. No new firmware updates or support are available for Sanyo-branded cameras. **What is the default RTSP URL for Sanyo cameras?** The URL is `rtsp://admin:password@CAMERA_IP:554/VideoInput/1/h264/1` for the main H.264 stream. For DVR setups, replace `VideoInput/1` with the appropriate channel number (e.g., `VideoInput/2` for channel 2). **Do Sanyo cameras support ONVIF?** Only some Sanyo cameras with newer firmware versions have limited ONVIF support. Most older models do not support ONVIF and require direct RTSP URL configuration. **What should I use instead of Sanyo cameras?** Panasonic's i-PRO product line is the direct successor to Sanyo's security camera division. The i-PRO cameras use similar VideoInput RTSP paths and offer modern features like H.265, advanced analytics, and full ONVIF support. See our [Panasonic/i-PRO connection guide](../panasonic/). **How do I get snapshots from a Sanyo camera?** Use the `/liveimg.cgi` HTTP endpoint: `http://CAMERA_IP/liveimg.cgi` returns a single JPEG frame. Add `?serverpush=1` for a continuous MJPEG stream, or `?ch=CHANNEL` for a specific DVR channel. ## Related Resources - [All Camera Brands — RTSP URL Directory](../) - [Panasonic/i-PRO Connection Guide](../panasonic/) — Successor product line - [IP Camera Preview Tutorial](../../videocapture/video-tutorials/ip-camera-preview/) - [SDK Installation & Samples](../#get-started) ---END OF PAGE--- ## Sony SNC IP Camera RTSP URL Patterns and C# .NET Setup **URL:** https://www.visioforge.com/help/docs/dotnet/camera-brands/sony/ **Description:** Sony SNC CH, DH, EB, CX, and IPELA camera RTSP URL patterns for C# .NET. Stream and record with VisioForge Video Capture SDK integration code. **Tags:** Video Capture SDK, Media Blocks SDK, .NET, Windows, macOS, Linux, Android, iOS, Capture, Streaming, Encoding, IP Camera, RTSP, ONVIF, H.264, MJPEG, C# # How to Connect to Sony IP Camera in C# .NET [Video Capture SDK .Net](https://www.visioforge.com/video-capture-sdk-net) [Media Blocks SDK .Net](https://www.visioforge.com/media-blocks-sdk-net) ## Brand Overview **Sony** (Sony Corporation, Security Systems Division) was a major manufacturer of professional IP surveillance cameras under the **IPELA** brand and later the **SNC** (Sony Network Camera) product line. Sony exited the security camera market in 2020, selling its security business to **Bosch**. However, a large installed base of Sony cameras remains in use worldwide, particularly in enterprise and government installations. **Key facts:** - **Product lines:** SNC-CH (box, H.264), SNC-DH (dome, H.264), SNC-EB/ER (E-series), SNC-CX (compact), SNC-VB/VM/WR/XM (current-gen before exit), SNC-DF/RX/RZ/CS (legacy IPELA), SNT (video encoders) - **Protocol support:** RTSP, ONVIF, HTTP/CGI, Sony proprietary (DEPA) - **Default RTSP port:** 554 - **Default credentials:** admin / admin (must be changed on setup) - **ONVIF support:** Yes (SNC-CH/DH and newer models) - **Video codecs:** H.264, H.265 (late models), MPEG-4 (legacy), MJPEG - **Status:** Sony exited security camera market in 2020 End of life Sony exited the security camera market in 2020. While existing cameras continue to work, no new firmware updates or models are being released. The RTSP URLs documented here remain valid for existing installations. ## RTSP URL Patterns ### Current-Gen Models (SNC-CH/DH/EB/ER/CX/VB/VM/WR/XM) | Stream | RTSP URL | Codec | Notes | | --- | --- | --- | --- | | Video 1 (main) | `rtsp://IP:554/media/video1` | H.264 | Main stream | | Video 2 (sub) | `rtsp://IP:554/media/video2` | H.264 | Sub stream | | ONVIF profile | `rtsp://IP//profile` | H.264 | ONVIF-based (note double slash) | | Direct | `rtsp://IP//media/video1` | H.264 | Alternative (double slash) | ### Model-Specific URLs | Model Series | RTSP URL | Resolution | Notes | | --- | --- | --- | --- | | SNC-CH110 | `rtsp://IP/media/video1` | 1280x1024 | Box camera | | SNC-CH120/CH140 | `rtsp://IP/media/video1` | 1280x1024 / 1920x1080 | Box camera | | SNC-CH160/CH180 | `rtsp://IP/media/video1` | 1920x1080 | Box camera | | SNC-CH210/CH260/CH280 | `rtsp://IP/media/video1` | 1920x1080 / 2MP | Box camera | | SNC-DH110/DH120/DH140 | `rtsp://IP/media/video1` | Up to 1080p | Fixed dome | | SNC-DH160/DH180 | `rtsp://IP/media/video1` | 1920x1080 | Fixed dome | | SNC-DH210/DH260 | `rtsp://IP/media/video1` | 1920x1080 | Fixed dome | | SNC-EB600B | `rtsp://IP/media/video1` | 1080p | E-series | | SNC-CX600W | `rtsp://IP:554//media/video1` | 1080p | Compact | | SNC-VB630/WR630/XM632 | `rtsp://IP//profile` | 1080p+ | Latest gen | | SNC-DM110 | `rtsp://IP:554//media/video1` | 720p | Mini dome | ### Legacy IPELA Models (SNC-RX/RZ/DF/CS/EP) Older Sony IPELA cameras typically don't support RTSP and use HTTP-based streaming: | Model Series | URL | Notes | | --- | --- | --- | | SNC-RX530/RX550 | `http://IP/jpeg/vga.jpg` | JPEG snapshot | | SNC-RZ25/RZ30/RZ50 | `http://IP/oneshotimage.jpg` | JPEG snapshot | | SNC-DF40/DF50/DF70/DF80 | `http://IP/image` | JPEG snapshot | | SNC-CS11/CS3P/CS50P | `http://IP/oneshotimage.jpg` | JPEG snapshot | | SNC-EP520/EP580 | `http://IP/jpeg/vga.jpg` | JPEG snapshot | | SNC-M1/M3 | `http://IP/image` | Very old MPEG-4 | ### Video Encoder URLs | Encoder | URL | Notes | | --- | --- | --- | | SNT-EX101/EX104 | `http://IP/oneshotimage.jpg` | Snapshot per channel | | SNT-EX104 (channel) | `http://IP/CH1/oneshotimage.jpg` | Channel-specific | | SNT-V704 | `http://IP/CH1/oneshotimage.jpg` | 4-channel encoder | ## Connecting with VisioForge SDK Use your Sony camera's RTSP URL with any of the three SDK approaches shown in the [Quick Start Guide](../#quick-start-code): ``` // Sony SNC camera, main stream var uri = new Uri("rtsp://192.168.1.55:554/media/video1"); var username = "admin"; var password = "YourPassword"; ``` For sub-stream access, use `/media/video2` instead. ## Snapshot and MJPEG URLs | Type | URL Pattern | Notes | | --- | --- | --- | | JPEG Snapshot | `http://IP/oneshotimage.jpg` | Most SNC models | | JPEG (VGA) | `http://IP/jpeg/vga.jpg` | VGA resolution | | JPEG (QVGA) | `http://IP/jpeg/qvga.jpg` | QVGA resolution | | MJPEG Stream | `http://IP/img/mjpeg.cgi` | Continuous MJPEG | | MJPEG (alt) | `http://IP/mjpeg` | Alternative MJPEG path | | H.264 over HTTP | `http://IP/h264` | H.264 stream via HTTP | | Image | `http://IP/image` | Generic snapshot | | Channel snapshot | `http://IP/oneshotimage1` | Channel-specific | ## Troubleshooting ### Double slash in URLs Some Sony models use a double slash before the path in RTSP URLs: - `rtsp://IP//media/video1` (double slash) - `rtsp://IP:554/media/video1` (single slash with port) Both formats usually work, but try the double-slash variant if the standard URL fails. ### ONVIF vs direct RTSP Sony cameras support both direct RTSP and ONVIF-based connections: - Direct RTSP: `rtsp://IP:554/media/video1` (recommended) - ONVIF: `rtsp://IP//profile` (ONVIF-discovered URL) ### Legacy cameras without RTSP Older Sony IPELA cameras (SNC-RX, SNC-RZ, SNC-DF, SNC-CS, SNC-M series) often don't support RTSP and only offer HTTP JPEG/MJPEG. For these cameras, use HTTP snapshot integration. ### Sony exited the market Sony sold its security camera business in 2020. Existing cameras continue to function but receive no new firmware updates. Plan for eventual migration when deploying new integrations. ## FAQ **What is the default RTSP URL for Sony SNC cameras?** For current Sony SNC cameras, use `rtsp://admin:password@CAMERA_IP:554/media/video1` for the main stream and `media/video2` for the sub stream. **Does Sony still make IP cameras?** No. Sony exited the security camera market in 2020. Existing Sony SNC cameras remain in use and their RTSP streams continue to work, but no new models or firmware updates are being released. **Do Sony cameras support ONVIF?** Yes. Sony SNC-CH, SNC-DH, and newer series support ONVIF Profile S. Use `rtsp://IP//profile` for ONVIF-based connections. **What about Sony IPELA cameras?** IPELA was Sony's earlier camera brand. Many IPELA models (SNC-RX, SNC-RZ, SNC-DF series) only support HTTP JPEG/MJPEG, not RTSP. Later IPELA models (SNC-CH/DH series) do support RTSP via `media/video1`. ## Related Resources - [All Camera Brands — RTSP URL Directory](../) - [Canon Connection Guide](../canon/) — Japanese enterprise cameras - [Axis Connection Guide](../axis/) — Enterprise surveillance peer - [IP Camera Preview Tutorial](../../videocapture/video-tutorials/ip-camera-preview/) - [SDK Installation & Samples](../#get-started) ---END OF PAGE--- ## How to Connect to Speco Technologies IP Camera in C# .NET **URL:** https://www.visioforge.com/help/docs/dotnet/camera-brands/speco/ **Description:** Speco Technologies O Series, VIP, and DVR RTSP integration for C# .NET. URL patterns, channel selection, and VisioForge SDK code for IP and analog cameras. **Tags:** Video Capture SDK, Media Blocks SDK, .NET, Windows, macOS, Linux, Android, iOS, Capture, Streaming, Encoding, IP Camera, RTSP, ONVIF, H.264, MJPEG, C# # How to Connect to Speco Technologies IP Camera in C# .NET [Video Capture SDK .Net](https://www.visioforge.com/video-capture-sdk-net) [Media Blocks SDK .Net](https://www.visioforge.com/media-blocks-sdk-net) ## Brand Overview **Speco Technologies** is an American professional surveillance company based in Amityville, New York. Founded in 1969, Speco manufactures IP cameras, analog cameras, DVRs, NVRs, and access control equipment for the professional security integrator market. Speco products are sold through authorized distributors and security integrators rather than direct-to-consumer channels, making them a common choice in commercial installations. **Key facts:** - **Product lines:** O Series (IP cameras: O2B, O2D, OINT), VIP Series (IP cameras), ZIP Series, SIP Series, LS Series, DVR lines (TH/TL, RS, PCPRO) - **Protocol support:** RTSP, ONVIF, HTTP/CGI - **Default RTSP port:** 554 - **Default credentials:** admin / admin - **ONVIF support:** Yes (all current IP cameras) - **Video codecs:** H.264 (all current models), MPEG-4 (older models) Multiple Product Lines Speco Technologies has many distinct product lines, each with different RTSP URL formats. Identify your exact model series (O, VIP, LS, ZIP, SIP, or DVR type) before configuring the stream URL. The root stream `rtsp://IP:554/` works on many Speco devices as a quick test. ## RTSP URL Patterns ### O Series IP Cameras The O Series is Speco's current IP camera line, including bullet (O2B), dome (O2D), and intensifier (OINT) models: ``` rtsp://[USERNAME]:[PASSWORD]@[IP]:554/ ``` | Model | Resolution | Main Stream URL | Notes | | --- | --- | --- | --- | | O2B2 (bullet) | 1080p | `rtsp://IP:554/` | Root stream | | O2D4 (dome) | 1080p | `rtsp://IP:554/` | Root stream | | OINT56B1G (intensifier) | 1080p | `rtsp://IP:554/mpeg4` | MPEG-4 stream | | OINT56B1G (intensifier) | 1080p | `rtsp://IP:554/` | Root stream (H.264) | ### VIP Series IP Cameras The VIP Series uses a numbered stream path format: ``` rtsp://[USERNAME]:[PASSWORD]@[IP]:554/1/stream1 ``` | Model | Resolution | Main Stream URL | Notes | | --- | --- | --- | --- | | VIP2B1M (bullet) | 1080p | `rtsp://IP:554/1/stream1` | Stream 1 (main) | | VIP2C1N (cube) | 1080p | `rtsp://IP:554/1/stream1` | Stream 1 (main) | ### LS Series The LS Series uses a channel-based H.264 path and also supports a credential-in-URL format: | URL Pattern | Notes | | --- | --- | | `rtsp://IP:554/cam1/h264` | Channel 1 H.264 stream | | `rtsp://IP:554/cam2/h264` | Channel 2 H.264 stream | | `rtsp://IP:554/cam[N]/h264` | Channel N H.264 stream | | `rtsp://IP:554//user=admin_password=tlJwpbo6_channel=1_stream=0.sdp` | Credential-in-URL format | LS Series Credential Format The LS Series supports an unusual credential-in-URL format where the username and password are embedded directly in the path. The password in this format is device-specific and may differ from the web interface password. Check the device's RTSP settings page for the correct value. ### ZIP Series The ZIP Series uses a profile-based streaming format: ``` rtsp://[USERNAME]:[PASSWORD]@[IP]:554//stream0/Channel=0;Profile=0 ``` | Model | Main Stream URL | Notes | | --- | --- | --- | | ZIP2B (bullet) | `rtsp://IP:554//stream0/Channel=0;Profile=0` | Profile 0 (main) | ### DVR Models Speco DVRs use various URL formats depending on the DVR line: | DVR Series | URL Pattern | Notes | | --- | --- | --- | | DVR4WM | `rtsp://IP:554/` | Root stream | | RS Series | `rtsp://IP:554/Live/Channel=1` | Live channel format | | RS Series | `rtsp://IP:554/Live/Channel=2` | Channel 2 | | General DVRs | `rtsp://IP:554/` | Root stream (fallback) | ### DVR Channel URLs (RS Series) For Speco RS Series DVRs: | Channel | Main Stream URL | | --- | --- | | Camera 1 | `rtsp://IP:554/Live/Channel=1` | | Camera 2 | `rtsp://IP:554/Live/Channel=2` | | Camera N | `rtsp://IP:554/Live/Channel=N` | ### All URL Formats Summary | URL Pattern | Product Line | Notes | | --- | --- | --- | | `rtsp://IP:554/` | O Series, DVRs, general | Root stream (works on many devices) | | `rtsp://IP:554/mpeg4` | O Series (older) | MPEG-4 stream | | `rtsp://IP:554/1/stream1` | VIP Series | Numbered stream format | | `rtsp://IP:554/cam[N]/h264` | LS Series | Channel-based H.264 | | `rtsp://IP:554//stream0/Channel=0;Profile=0` | ZIP Series | Profile-based format | | `rtsp://IP:554/Live/Channel=N` | RS DVR | Live channel format | ## Connecting with VisioForge SDK Use your Speco camera's RTSP URL with any of the three SDK approaches shown in the [Quick Start Guide](../#quick-start-code): ``` // Speco O2D4 dome camera, root stream var uri = new Uri("rtsp://192.168.1.64:554/"); var username = "admin"; var password = "admin"; ``` For VIP Series cameras, use the `/1/stream1` path instead: ``` // Speco VIP2B1M bullet camera, main stream var uri = new Uri("rtsp://192.168.1.64:554/1/stream1"); var username = "admin"; var password = "admin"; ``` ## Snapshot and MJPEG URLs ### IP Camera Snapshots | Type | URL Pattern | Models | Notes | | --- | --- | --- | --- | | Still Image | `http://IP/stillimg.jpg` | O2B2, O2D4, OINT56B1G | Basic JPEG snapshot | | Still Image (port 554) | `http://IP:554/stillimg.jpg` | O2B2, O2D4, OINT56B1G | Alternate port | | Encoder Snapshot | `http://IP/cgi-bin/encoder?USER=user&PWD=pass&SNAPSHOT` | IP-SD10X, SIP Series | CGI-based with credentials | | System Stream | `http://IP/cgi-bin/cmd/system?GET_STREAM&USER=user&PWD=pass` | Various IP cameras | System command format | ### DVR Snapshots | Type | URL Pattern | DVR Series | Notes | | --- | --- | --- | --- | | Full Image | `http://IP/images1full` | Various DVRs | Replace `1` with channel number | | SIF Image | `http://IP/images1sif` | Various DVRs | Lower resolution, replace `1` with channel | | Get Image | `http://IP/getimage?camera=1&fmt=full` | Various DVRs | Replace `1` with channel number | | Mobile Snapshot | `http://IP/mobile/channel1.jpg` | PCPRO DVR | Mobile-optimized, replace `1` with channel | | TH/TL Stream | `http://IP/ivop.get?action=live&THREAD_ID=` | TH/TL DVR | Live stream via HTTP | ## Troubleshooting ### Inconsistent URL formats across product lines Speco Technologies has many different product lines, each with its own RTSP URL format. If one URL pattern does not work, try the root stream `rtsp://IP:554/` first as a baseline test. Then try the format specific to your product line as listed in the tables above. ### Root stream limitations The root stream (`rtsp://IP:554/`) works on many Speco devices for the main stream but is unreliable for accessing sub-streams or specific channels on multi-channel devices. Use the product-line-specific URL format for full control over stream selection. ### LS Series credential-in-URL format The LS Series uses an unusual URL format where credentials are embedded in the path (`/user=admin_password=VALUE_channel=1_stream=0.sdp`). The password in this format may be a device-generated value that differs from the web interface password. Check the device's **RTSP Settings** page in the web interface for the correct credential string. ### Network discovery Speco provides a DDNS tool and device discovery utility for finding cameras on the network. Download the Speco DDNS tool from the Speco Technologies website to locate devices that are not responding at expected IP addresses. ### Default credentials Speco devices typically ship with default credentials of `admin` / `admin`. If these do not work, the password may have been changed during installation by the security integrator. ## FAQ **What is the default RTSP URL for Speco cameras?** For most Speco IP cameras, try the root stream first: `rtsp://admin:admin@CAMERA_IP:554/`. For VIP Series cameras use `rtsp://IP:554/1/stream1`, and for LS Series cameras use `rtsp://IP:554/cam1/h264`. The correct URL depends on your specific product line. **Do Speco cameras support ONVIF?** Yes. All current Speco IP cameras support ONVIF. ONVIF discovery and streaming is the most reliable way to connect to Speco cameras if you are unsure of the exact RTSP URL format for your model. **Why are there so many different URL formats for Speco cameras?** Speco Technologies has been manufacturing surveillance equipment since 1969 and has acquired or developed multiple product lines over the decades. Each product line (O Series, VIP, LS, ZIP, SIP, DVR lines) may use different firmware and streaming architectures, resulting in different URL formats. Always identify your exact model series before configuring the connection. **How do I find my Speco camera on the network?** Use Speco's DDNS tool or device discovery utility, available from the Speco Technologies website. Alternatively, use ONVIF discovery through the VisioForge SDK or a network scanning tool to locate the camera's IP address on your local network. ## Related Resources - [All Camera Brands — RTSP URL Directory](../) - [EverFocus Connection Guide](../everfocus/) — Professional surveillance cameras - [Save Original RTSP Stream](../../mediablocks/Guides/rtsp-save-original-stream/) — Record Speco streams without re-encoding - [IP Camera Preview Tutorial](../../videocapture/video-tutorials/ip-camera-preview/) - [SDK Installation & Samples](../#get-started) ---END OF PAGE--- ## Swann IP Camera RTSP URL and C# .NET Connection Guide **URL:** https://www.visioforge.com/help/docs/dotnet/camera-brands/swann/ **Description:** Swann NHD, SWNHD, DVR/NVR, and ADS camera RTSP URL patterns for C# .NET. Stream and record using VisioForge Video Capture SDK integration code. **Tags:** Video Capture SDK, Media Blocks SDK, .NET, Windows, macOS, Linux, Android, iOS, Capture, Streaming, IP Camera, RTSP, ONVIF, MJPEG, C# # How to Connect to Swann IP Camera in C# .NET [Video Capture SDK .Net](https://www.visioforge.com/video-capture-sdk-net) [Media Blocks SDK .Net](https://www.visioforge.com/media-blocks-sdk-net) ## Brand Overview **Swann** (Swann Communications) is an Australian consumer security brand headquartered in Melbourne, Australia, now owned by **Infinova**. Swann is one of the best-known consumer and prosumer security brands, popular for their bundled DVR/NVR camera systems sold through major retailers. Swann offers a range of standalone IP cameras, analog-over-coax (BNC) camera systems, and network video recorders. **Key facts:** - **Product lines:** NHD (current network HD cameras), SWNHD (HD IP cameras), SWPRO (analog-over-coax), DVR/NVR systems, ADS (legacy IP cameras) - **Protocol support:** RTSP, ONVIF (current NHD models), HTTP/MJPEG (legacy) - **Default RTSP port:** 554 - **Default credentials:** admin / admin or admin / (empty) on older models - **ONVIF support:** Yes (current NHD-series cameras) - **Video codecs:** H.264, H.265 (current models), MPEG-4 (legacy DVRs) - **OEM base:** Many newer Swann NVRs are Hikvision OEM and use Hikvision RTSP URL patterns Swann NVRs and Hikvision Many current Swann NVRs are manufactured by Hikvision and use Hikvision firmware. If the standard Swann RTSP URL does not work on your NVR, try the Hikvision URL format (`/Streaming/Channels/`). See our [Hikvision connection guide](../hikvision/) for details. ## RTSP URL Patterns ### Current NHD-Series IP Cameras Standalone Swann NHD-series IP cameras (SWNHD-820CAM, SWNHD-830CAM, NHD-866, etc.) use the following URL: ``` rtsp://[USERNAME]:[PASSWORD]@[IP]:554/live/h264 ``` ### NVR Systems (Hikvision-Based) Most current Swann NVRs use Hikvision-style RTSP paths: ``` rtsp://[USERNAME]:[PASSWORD]@[IP]:554//Streaming/Channels/[CHANNEL_ID] ``` | Channel | Main Stream | Sub Stream | | --- | --- | --- | | Camera 1 | `rtsp://IP:554//Streaming/Channels/1` | `rtsp://IP:554//Streaming/Channels/102` | | Camera 2 | `rtsp://IP:554//Streaming/Channels/2` | `rtsp://IP:554//Streaming/Channels/202` | | Camera N | `rtsp://IP:554//Streaming/Channels/N` | `rtsp://IP:554//Streaming/Channels/N02` | Channel numbering For Hikvision-based NVRs, the main stream channel ID matches the camera number (1, 2, 3...). The sub stream uses the format `N02` where N is the camera number (102, 202, 302...). ### Legacy DVR Models Older Swann DVR systems (DVR4-PRO-NET, etc.) and standalone cameras use MPEG-4: ``` rtsp://[USERNAME]:[PASSWORD]@[IP]:554/mpeg4 ``` ### URL Summary Table | Model / Series | Main Stream URL | Notes | | --- | --- | --- | | NHD-series cameras (SWNHD-820/830) | `rtsp://IP:554/live/h264` | Standalone IP cameras | | IP-3G ConnectCam | `rtsp://IP:554/mpeg4` | Legacy standalone | | Max-IP-Cam | `rtsp://IP:554/mpeg4` | Legacy standalone | | Current NVR (channel 1) | `rtsp://IP:554//Streaming/Channels/1` | Hikvision OEM | | Current NVR (channel 1, sub) | `rtsp://IP:554//Streaming/Channels/102` | Hikvision OEM | | DVR4-PRO-NET | `rtsp://IP:554/mpeg4` | Legacy DVR | | Generic Swann IP cameras | `rtsp://IP:554/live/h264` | Try this first | ## Connecting with VisioForge SDK Use your Swann camera's RTSP URL with any of the three SDK approaches shown in the [Quick Start Guide](../#quick-start-code): ``` // Swann NHD-series camera, main stream var uri = new Uri("rtsp://192.168.1.90:554/live/h264"); var username = "admin"; var password = "YourPassword"; ``` For NVR sub-stream access, use `/Streaming/Channels/102` instead of `/Streaming/Channels/1`. ## Snapshot and MJPEG URLs | Type | URL Pattern | Notes | | --- | --- | --- | | HTTP stream (ADS-440 legacy) | `http://IP/videostream.asf?user=USER&pwd=PASS` | ASF format, no RTSP | | MJPEG stream (legacy) | `http://IP/videostream.cgi?user=USER&pwd=PASS` | Older models | | ONVIF snapshot | `http://IP/onvif-http/snapshot` | NHD-series with ONVIF | Legacy HTTP-only cameras The ADS-440 series and some other older Swann models only support HTTP streaming (ASF or MJPEG) and do not support RTSP at all. Use the HTTP URL directly for these cameras. ## Troubleshooting ### Identify your NVR firmware type Many Swann NVRs are Hikvision OEM. To determine which URL format to use: 1. Access the NVR web interface at `http://NVR_IP` 2. Check the login page — Hikvision-based NVRs often show a Hikvision-style interface 3. Try the Hikvision URL first (`/Streaming/Channels/1`), then fall back to Swann URLs (`/live/h264` or `/mpeg4`) ### "Connection refused" on legacy cameras Older Swann cameras (ADS-440 series, early DVR models) may not support RTSP at all. These cameras use HTTP-based streaming only. Try the HTTP ASF or MJPEG URL instead of RTSP. ### Default credentials not working - Current models typically ship with admin / admin but require password change on first setup - Some older models use admin with an empty password - Always complete initial setup via the Swann web interface or SwannView app before attempting RTSP access ### SwannView vs local RTSP access SwannView (Swann's cloud service) is separate from local RTSP access. You do not need a SwannView account to use RTSP streaming on your local network. RTSP works purely over the local network connection. ## FAQ **What is the default RTSP URL for Swann cameras?** For current NHD-series cameras, use `rtsp://admin:password@CAMERA_IP:554/live/h264`. For Swann NVRs (Hikvision-based), use `rtsp://admin:password@NVR_IP:554//Streaming/Channels/1` for channel 1 main stream. **Are Swann NVRs compatible with Hikvision RTSP URLs?** Yes. Many current Swann NVRs are manufactured by Hikvision and use identical firmware. The Hikvision RTSP URL format (`/Streaming/Channels/`) works on these systems. If the standard Swann URL fails, try the Hikvision format. **Do all Swann cameras support RTSP?** No. Some legacy Swann models (particularly the ADS-440 series) only support HTTP-based streaming in ASF or MJPEG format. All current NHD-series cameras and NVRs support RTSP. **Do Swann cameras support ONVIF?** Yes, current NHD-series cameras support ONVIF. Legacy models (SWPRO, ADS series) generally do not support ONVIF. ## Related Resources - [All Camera Brands — RTSP URL Directory](../) - [Lorex Connection Guide](../lorex/) — Consumer/prosumer segment peer - [Hikvision Connection Guide](../hikvision/) — Swann NVRs with Hikvision firmware - [IP Camera Preview Tutorial](../../videocapture/video-tutorials/ip-camera-preview/) - [SDK Installation & Samples](../#get-started) ---END OF PAGE--- ## Tenda IP Camera RTSP URL and C# .NET Connection Guide **URL:** https://www.visioforge.com/help/docs/dotnet/camera-brands/tenda/ **Description:** Tenda CP, CT, IT series and pan/tilt camera RTSP URL patterns for C# .NET. Stream and record using VisioForge Video Capture SDK integration code. **Tags:** Video Capture SDK, Media Blocks SDK, .NET, Windows, macOS, Linux, Android, iOS, Capture, Streaming, IP Camera, RTSP, ONVIF, C# # How to Connect to Tenda IP Camera in C# .NET [Video Capture SDK .Net](https://www.visioforge.com/video-capture-sdk-net) [Media Blocks SDK .Net](https://www.visioforge.com/media-blocks-sdk-net) ## Brand Overview **Tenda Technology** is a Chinese networking equipment manufacturer headquartered in Shenzhen, China. Founded in 1999, Tenda is primarily known for routers and networking gear but has expanded into the security camera market with a growing line of affordable IP cameras targeting the consumer and small business segments. Tenda cameras are gaining traction in emerging markets across Asia, South America, and Africa. **Key facts:** - **Product lines:** CP (pan/tilt), CT (outdoor bullet/turret), IT (indoor) - **Protocol support:** RTSP, ONVIF (select models), HTTP - **Default RTSP port:** 554 - **Default credentials:** admin / admin (varies by model) - **ONVIF support:** Yes (newer models) - **Video codecs:** H.264, H.265 (select models) - **Companion app:** Tenda Security app (for setup and remote viewing) ## RTSP URL Patterns ### Standard URL Format Tenda cameras use a stream-number-based RTSP URL: ``` rtsp://[USERNAME]:[PASSWORD]@[IP]:554/stream1 ``` | Stream | URL Pattern | Description | | --- | --- | --- | | Main stream | `rtsp://IP:554/stream1` | Full resolution | | Sub stream | `rtsp://IP:554/stream2` | Lower resolution | ### Camera Models | Model | Type | Resolution | Main Stream URL | Audio | | --- | --- | --- | --- | --- | | CP3 (pan/tilt indoor) | Indoor PTZ | 1920x1080 | `rtsp://IP:554/stream1` | Yes | | CP6 (2K pan/tilt) | Indoor PTZ | 2304x1296 | `rtsp://IP:554/stream1` | Yes | | CP7 (4MP pan/tilt) | Indoor PTZ | 2560x1440 | `rtsp://IP:554/stream1` | Yes | | CT3 (outdoor bullet) | Outdoor | 1920x1080 | `rtsp://IP:554/stream1` | Yes | | CT6 (2K outdoor) | Outdoor | 2304x1296 | `rtsp://IP:554/stream1` | Yes | | CT7 (4MP outdoor) | Outdoor | 2560x1440 | `rtsp://IP:554/stream1` | Yes | | IT6 (indoor) | Indoor | 1920x1080 | `rtsp://IP:554/stream1` | Yes | | IT7 (2K indoor) | Indoor | 2304x1296 | `rtsp://IP:554/stream1` | Yes | ### Alternative URL Formats | URL Pattern | Notes | | --- | --- | | `rtsp://IP:554/stream1` | Main stream (recommended) | | `rtsp://IP:554/stream2` | Sub stream | | `rtsp://IP:554/live/ch0` | Alternative format (some models) | | `rtsp://IP:554/cam/realmonitor?channel=1&subtype=0` | Dahua-compatible (some OEM firmware) | ## Connecting with VisioForge SDK Use your Tenda camera's RTSP URL with any of the three SDK approaches shown in the [Quick Start Guide](../#quick-start-code): ``` // Tenda CP7 (4MP pan/tilt), main stream var uri = new Uri("rtsp://192.168.1.90:554/stream1"); var username = "admin"; var password = "YourPassword"; ``` For sub-stream access, use `/stream2` instead of `/stream1`. ## Snapshot URLs | Type | URL Pattern | Notes | | --- | --- | --- | | JPEG Snapshot | `http://IP/cgi-bin/snapshot.cgi` | Requires basic auth | ## Troubleshooting ### Camera requires app setup first Tenda cameras must be initially configured through the Tenda Security app. The camera needs WiFi credentials and account setup before RTSP is accessible. After setup, you can connect directly via RTSP on the local network. ### Multiple URL formats Some Tenda cameras use different firmware bases. If `/stream1` does not work, try: 1. `rtsp://IP:554/live/ch0` (alternative format) 2. `rtsp://IP:554/cam/realmonitor?channel=1&subtype=0` (Dahua-compatible) 3. Use ONVIF discovery to retrieve the correct URL automatically ### Finding the camera IP Tenda WiFi cameras get their IP via DHCP. Find it in: 1. The Tenda Security app (Device Info) 2. Your router's DHCP client list 3. ONVIF discovery (if supported) ## FAQ **What is the default RTSP URL for Tenda cameras?** Most Tenda cameras use `rtsp://admin:password@CAMERA_IP:554/stream1` for the main stream and `/stream2` for the sub stream. Some models use alternative URL paths. **Do Tenda cameras support ONVIF?** Newer Tenda camera models support ONVIF for standardized discovery and streaming. Older or budget models may not. Check your camera's specifications in the Tenda Security app. **Are Tenda cameras good for development integration?** Tenda cameras offer competitive pricing and standard RTSP support, making them suitable for development and prototyping. For production deployments requiring guaranteed RTSP/ONVIF compatibility, consider established surveillance brands like [Hikvision](../hikvision/), [Dahua](../dahua/), or [Reolink](../reolink/). ## Related Resources - [All Camera Brands — RTSP URL Directory](../) - [TP-Link Connection Guide](../tp-link/) — Similar consumer segment - [Mercusys Connection Guide](../mercusys/) — Budget camera alternative - [IP Camera Preview Tutorial](../../videocapture/video-tutorials/ip-camera-preview/) - [SDK Installation & Samples](../#get-started) ---END OF PAGE--- ## Tiandy IP Camera in C# .NET — RTSP, ONVIF Setup Guide **URL:** https://www.visioforge.com/help/docs/dotnet/camera-brands/tiandy/ **Description:** Connect Tiandy IP cameras (TC-C, TC-NC, TC-A, TC-R NVR) to C# / .NET apps via RTSP and ONVIF. Default stream URLs, credentials, H.265 configs. Code sample. **Tags:** Video Capture SDK, Media Blocks SDK, .NET, Windows, macOS, Linux, Android, iOS, Capture, Streaming, Decoding, IP Camera, RTSP, ONVIF, H.265, MJPEG, C# # How to Connect to Tiandy IP Camera in C# .NET [Video Capture SDK .Net](https://www.visioforge.com/video-capture-sdk-net) [Media Blocks SDK .Net](https://www.visioforge.com/media-blocks-sdk-net) ## Brand Overview **Tiandy Technologies** (Tiandy Technologies Co., Ltd.) is a Chinese video surveillance manufacturer headquartered in Tianjin, China. Founded in 1994, Tiandy is one of China's largest security equipment manufacturers and has been expanding rapidly into international markets across Asia, the Middle East, Africa, and Latin America. Tiandy specializes in AI-powered IP cameras, NVRs, and integrated video management solutions. **Key facts:** - **Product lines:** TC-C (current IP cameras), TC-NC (legacy IP), TC-A (AI analytics), TC-R (NVRs), TC-NR (network recorders) - **Protocol support:** RTSP, ONVIF Profile S/T, HTTP/CGI - **Default RTSP port:** 554 - **Default credentials:** admin / 1111 (older models) or admin / admin123 (varies by region) - **ONVIF support:** Yes (current models) - **Video codecs:** H.264, H.265 (SuperH.265), MJPEG - **AI features:** Smart H.265+, face detection, perimeter protection, people counting ## RTSP URL Patterns ### Standard URL Format Tiandy cameras use a channel and stream-based RTSP URL structure: ``` rtsp://[USERNAME]:[PASSWORD]@[IP]:554/cam/realmonitor?channel=1&subtype=0 ``` | Parameter | Value | Description | | --- | --- | --- | | `channel` | 1, 2, 3... | Camera channel (1 for standalone cameras) | | `subtype` | 0 | Main stream (highest resolution) | | `subtype` | 1 | Sub stream (lower resolution) | Dahua-Compatible URL Format Many Tiandy cameras use the same `cam/realmonitor` RTSP URL format as Dahua cameras. If you are familiar with Dahua integration, the same URL patterns may work with Tiandy. See our [Dahua connection guide](../dahua/) for additional details. ### Alternative URL Formats | URL Pattern | Description | | --- | --- | | `rtsp://IP:554/cam/realmonitor?channel=1&subtype=0` | Dahua-compatible (many models) | | `rtsp://IP:554/live/ch0` | Main stream (legacy format) | | `rtsp://IP:554/live/ch1` | Sub stream (legacy format) | | `rtsp://IP:554/media/video1` | Uniview-compatible (some models) | | `rtsp://IP:554/Streaming/Channels/101` | Hikvision-compatible (some OEM models) | | `rtsp://IP:554/h264` | Simple H.264 stream path | ### Camera Models | Model Series | Resolution | Main Stream URL | Audio | | --- | --- | --- | --- | | TC-C32JN (2MP bullet) | 1920x1080 | `rtsp://IP:554/cam/realmonitor?channel=1&subtype=0` | No | | TC-C34JN (4MP bullet) | 2560x1440 | `rtsp://IP:554/cam/realmonitor?channel=1&subtype=0` | No | | TC-C35JN (5MP bullet) | 2592x1944 | `rtsp://IP:554/cam/realmonitor?channel=1&subtype=0` | No | | TC-C38JN (4K bullet) | 3840x2160 | `rtsp://IP:554/cam/realmonitor?channel=1&subtype=0` | Yes | | TC-C32DN (2MP dome) | 1920x1080 | `rtsp://IP:554/cam/realmonitor?channel=1&subtype=0` | No | | TC-C34DN (4MP dome) | 2560x1440 | `rtsp://IP:554/cam/realmonitor?channel=1&subtype=0` | Yes | | TC-C32EP (2MP turret) | 1920x1080 | `rtsp://IP:554/cam/realmonitor?channel=1&subtype=0` | Yes | | TC-C34EP (4MP turret) | 2560x1440 | `rtsp://IP:554/cam/realmonitor?channel=1&subtype=0` | Yes | | TC-A32E2T (2MP AI) | 1920x1080 | `rtsp://IP:554/cam/realmonitor?channel=1&subtype=0` | Yes | | TC-C32WP (2MP WiFi) | 1920x1080 | `rtsp://IP:554/cam/realmonitor?channel=1&subtype=0` | Yes | ### NVR Channel URLs For Tiandy NVRs (TC-R3100, TC-R3200, TC-NR series): | Channel | Main Stream | Sub Stream | | --- | --- | --- | | Camera 1 | `rtsp://IP:554/cam/realmonitor?channel=1&subtype=0` | `rtsp://IP:554/cam/realmonitor?channel=1&subtype=1` | | Camera 2 | `rtsp://IP:554/cam/realmonitor?channel=2&subtype=0` | `rtsp://IP:554/cam/realmonitor?channel=2&subtype=1` | | Camera N | `rtsp://IP:554/cam/realmonitor?channel=N&subtype=0` | `rtsp://IP:554/cam/realmonitor?channel=N&subtype=1` | ## Connecting with VisioForge SDK Use your Tiandy camera's RTSP URL with any of the three SDK approaches shown in the [Quick Start Guide](../#quick-start-code): ``` // Tiandy TC-C34JN (4MP bullet), main stream var uri = new Uri("rtsp://192.168.1.90:554/cam/realmonitor?channel=1&subtype=0"); var username = "admin"; var password = "YourPassword"; ``` For sub-stream access, use `subtype=1` instead of `subtype=0`. ## Snapshot and MJPEG URLs | Type | URL Pattern | Notes | | --- | --- | --- | | JPEG Snapshot | `http://IP/cgi-bin/snapshot.cgi?channel=1` | Requires digest authentication | | MJPEG Stream | `http://IP/cgi-bin/mjpg/video.cgi?channel=1&subtype=1` | Continuous MJPEG | ## Troubleshooting ### Multiple URL formats Tiandy cameras may use different RTSP URL formats depending on firmware version and model. If one format does not work, try alternatives in this order: 1. `rtsp://IP:554/cam/realmonitor?channel=1&subtype=0` (Dahua-compatible, most common) 2. `rtsp://IP:554/live/ch0` (legacy Tiandy format) 3. `rtsp://IP:554/h264` (simple path) ### Default credentials vary Tiandy default passwords differ by model and region. Common defaults include: - `admin` / `1111` - `admin` / `admin123` - `admin` / `123456` If none of these work, the camera may require initial activation via the web interface or Tiandy's EasyLive utility. ### SuperH.265 codec Tiandy's SuperH.265 is a proprietary optimization that produces standard H.265/HEVC streams. No special decoder is required. The VisioForge SDK handles H.265 streams natively. ## FAQ **What is the default RTSP URL for Tiandy cameras?** Most Tiandy cameras use `rtsp://admin:password@CAMERA_IP:554/cam/realmonitor?channel=1&subtype=0` for the main stream, which is the same format as Dahua cameras. Some older models use `rtsp://IP:554/live/ch0` instead. **Are Tiandy cameras Dahua OEMs?** No. Tiandy is an independent manufacturer with its own hardware and firmware. However, some Tiandy firmware uses the same RTSP URL format as Dahua (`cam/realmonitor`), which is common across several Chinese surveillance manufacturers. **Do Tiandy cameras support ONVIF?** Yes. Current Tiandy models support ONVIF Profile S and Profile T. ONVIF must be enabled in the camera's web interface under network settings. Some models require creating a separate ONVIF user account. **Which Tiandy camera series should I choose?** **TC-C** is the current mainstream series. The number after "TC-C3" indicates resolution: **2** = 2MP, **4** = 4MP, **5** = 5MP, **8** = 4K. The suffix letters indicate form factor: **JN** = bullet, **DN** = dome, **EP** = turret/eyeball, **WP** = WiFi. ## Related Resources - [All Camera Brands — RTSP URL Directory](../) - [Dahua Connection Guide](../dahua/) — Similar URL format - [Uniview Connection Guide](../uniview/) — Another major Chinese surveillance brand - [IP Camera Preview Tutorial](../../videocapture/video-tutorials/ip-camera-preview/) - [SDK Installation & Samples](../#get-started) ---END OF PAGE--- ## Toshiba IP Camera RTSP URL and Streaming in C# .NET **URL:** https://www.visioforge.com/help/docs/dotnet/camera-brands/toshiba/ **Description:** Toshiba IK-WB, IK-WD, IK-WR, and IK-WP camera RTSP URL patterns for C# .NET. Stream and record with VisioForge Video Capture SDK integration. **Tags:** Video Capture SDK, Media Blocks SDK, .NET, Windows, macOS, Linux, Android, iOS, Capture, Streaming, IP Camera, RTSP, ONVIF, H.264, MJPEG, C# # How to Connect to Toshiba IP Camera in C# .NET [Video Capture SDK .Net](https://www.visioforge.com/video-capture-sdk-net) [Media Blocks SDK .Net](https://www.visioforge.com/media-blocks-sdk-net) ## Brand Overview **Toshiba** (Toshiba Corporation) is a Japanese multinational conglomerate headquartered in Tokyo, Japan. Toshiba's security division produced the **IK-W series** of IP cameras, covering box, dome, bullet, and PTZ form factors. Toshiba has since exited the standalone security camera market and sold its surveillance business. Despite discontinuation, many IK-W series cameras remain deployed in commercial and industrial installations worldwide. **Key facts:** - **Product lines:** IK-WB (box cameras), IK-WD (dome cameras), IK-WR (bullet/rugged cameras), IK-WP (PTZ cameras) - **Protocol support:** RTSP, HTTP/CGI, ONVIF (limited, newer models only) - **Default RTSP port:** 554 - **Default credentials:** admin / 1234 - **ONVIF support:** Limited (newer IK-W14/16/30/70/80 models only) - **Video codecs:** H.264 (IK-W14/16/30/70/80 series), MJPEG (older models) Discontinued Product Line Toshiba has exited the IP camera market and sold its surveillance business. No new firmware updates or official support are available. Many early IK-WB models (01A, 02A, 11A) support HTTP snapshot only and do not provide RTSP streaming. ## RTSP URL Patterns ### Standard URL Format Toshiba IK-W series cameras use the `live.sdp` URL pattern: ``` rtsp://[USERNAME]:[PASSWORD]@[IP]:554/live.sdp ``` | Parameter | Value | Description | | --- | --- | --- | | `live.sdp` | Primary stream | Main H.264 stream (highest resolution) | | `live2.sdp` | Sub stream | Secondary stream (lower resolution) | | `live3.sdp` | Third stream | Third stream (mobile-optimized, select models) | ### Camera Models - RTSP Streams | Model | Type | Main Stream URL | Sub Stream URL | Notes | | --- | --- | --- | --- | --- | | IK-WB16A | Box | `rtsp://IP:554/live.sdp` | -- | H.264 | | IK-WB80A | Box | `rtsp://IP:554/live.sdp` | -- | H.264 | | IK-WD01A | Dome | `rtsp://IP:554/live.sdp` | -- | H.264 | | IK-WD12A | Dome | `rtsp://IP:554//live.sdp` | -- | Double-slash path | | IK-WD14A | Dome | `rtsp://IP:554/live.sdp` | `rtsp://IP:554/live2.sdp` | Also supports `live3.sdp` | | IK-WR04A | Bullet | `rtsp://IP:554/live.sdp` | -- | H.264 | | IK-WR12A | Bullet | `rtsp://IP:554/live.sdp` | -- | H.264 | | IK-WR14A | Bullet | `rtsp://IP:554/live.sdp` | -- | H.264 | | IK-WP41A | PTZ | `rtsp://IP:554/live.sdp` | -- | H.264 | ### Models by Series #### IK-WB Series (Box Cameras) | Model | Streaming | Protocol | | --- | --- | --- | | IK-WB01A | HTTP snapshot only | HTTP | | IK-WB02A | HTTP snapshot only | HTTP | | IK-WB11A | HTTP snapshot only | HTTP | | IK-WB15A | HTTP snapshot + CGI | HTTP | | IK-WB16A | RTSP `live.sdp` | RTSP + HTTP | | IK-WB16A-W | RTSP `live.sdp`, `live3.sdp` | RTSP + HTTP | | IK-WB21A | HTTP CGI only | HTTP | | IK-WB30A | RTSP `live.sdp` | RTSP + HTTP | | IK-WB70A | RTSP `live.sdp` | RTSP + HTTP + MJPEG | | IK-WB80A | RTSP `live.sdp` | RTSP + HTTP + MJPEG | #### IK-WD Series (Dome Cameras) | Model | Streaming | Protocol | | --- | --- | --- | | IK-WD01A | RTSP `live.sdp` | RTSP | | IK-WD12A | RTSP `//live.sdp` | RTSP (double-slash) | | IK-WD14A | RTSP `live.sdp`, `live2.sdp`, `live3.sdp` | RTSP (multi-stream) | #### IK-WR Series (Bullet/Rugged Cameras) | Model | Streaming | Protocol | | --- | --- | --- | | IK-WR01A | HTTP snapshot only | HTTP | | IK-WR02A | HTTP snapshot only | HTTP | | IK-WR04A | RTSP `live.sdp` | RTSP | | IK-WR12A | RTSP `live.sdp` | RTSP + MJPEG | | IK-WR14A | RTSP `live.sdp` | RTSP + HTTP | #### IK-WP Series (PTZ Cameras) | Model | Streaming | Protocol | | --- | --- | --- | | IK-WP41A | RTSP `live.sdp` | RTSP | ### Alternative URL Formats Some Toshiba models use a double-slash in the RTSP path: | URL Pattern | Notes | | --- | --- | | `rtsp://IP:554/live.sdp` | Standard (recommended) | | `rtsp://IP:554//live.sdp` | Double-slash variant (IK-WD12A, some IK-WD14A units) | | `rtsp://IP:554/live2.sdp` | Sub stream (IK-WD14A) | | `rtsp://IP:554/live3.sdp` | Third stream (IK-WB16A-W, IK-WD14A) | Double-Slash Path If `rtsp://IP:554/live.sdp` does not work on your Toshiba camera, try the double-slash variant `rtsp://IP:554//live.sdp`. Some IK-WD models require this format. ## Connecting with VisioForge SDK Use your Toshiba camera's RTSP URL with any of the three SDK approaches shown in the [Quick Start Guide](../#quick-start-code): ``` // Toshiba IK-WD14A, main stream var uri = new Uri("rtsp://192.168.1.90:554/live.sdp"); var username = "admin"; var password = "1234"; ``` For sub-stream access on supported models, use `live2.sdp` instead of `live.sdp`. ## Snapshot and MJPEG URLs | Type | URL Pattern | Compatible Models | Notes | | --- | --- | --- | --- | | JPEG Snapshot | `http://IP/__live.jpg?&&&` | IK-WB01A, WB11A, WB15A, WB16A-W, WB21A | Note underscore prefix | | CGI Snapshot | `http://IP/GetData.cgi` | IK-WB01A, WB11A, WB15A, WB21A, WR01A | Basic snapshot | | Configurable Snapshot | `http://IP/GetData.cgi?CH=CHANNEL&Codec=jpeg&Size=WIDTHxHEIGHT` | IK-WB series | Set resolution and channel | | Resolution Snapshot | `http://IP/cgi-bin/viewer/video.jpg?resolution=WIDTHxHEIGHT` | IK-WB15A, WB16A, WB30A, WB70A, WR12A, WR14A | Specify output resolution | | Simple Snapshot | `http://IP/Jpeg/CamImg.jpg` | IK-WB02A, WR01A | Basic JPEG capture | | MJPEG Stream | `http://IP/video.mjpg` | IK-WB70A, WB80A, WR12A | Continuous MJPEG stream | HTTP-Only Models Early Toshiba models (IK-WB01A, WB02A, WB11A, WR01A, WR02A) do not support RTSP. For these cameras, use HTTP snapshot URLs or MJPEG streams. You can capture these via the VisioForge SDK's HTTP source or MJPEG source modes. ## Troubleshooting ### Camera is HTTP-only (no RTSP) Many early IK-WB models (01A, 02A, 11A) and IK-WR models (01A, 02A) do not support RTSP streaming at all. These cameras only provide HTTP snapshot and CGI endpoints. If your camera does not respond on port 554, check whether it is an HTTP-only model from the tables above. ### Underscore prefix in snapshot URL The `__live.jpg` snapshot URL uses a **double underscore prefix**, which is unusual. Make sure to include both underscores: ``` http://192.168.1.90/__live.jpg?&&& ``` The trailing `&&&` characters are also required on some firmware versions. ### Double-slash in RTSP path Some IK-WD series cameras (WD12A, certain WD14A units) require a double forward slash in the RTSP path: ``` rtsp://admin:1234@192.168.1.90:554//live.sdp ``` If the standard single-slash URL does not connect, try this variant. ### No firmware updates available Toshiba has exited the security camera market. No new firmware, patches, or official support channels are available. If you encounter bugs or security vulnerabilities, consider replacing the camera with a currently supported model. ### Default credentials not working The factory default credentials are **admin / 1234**. If these do not work, the password may have been changed by a previous administrator. A hardware factory reset (usually a pinhole reset button) will restore defaults on most models. ## FAQ **What is the default RTSP URL for Toshiba IP cameras?** The primary RTSP URL is `rtsp://admin:1234@CAMERA_IP:554/live.sdp` for models that support RTSP streaming. Use `live2.sdp` for the sub stream on models like the IK-WD14A. Note that older IK-WB01A/02A/11A and IK-WR01A/02A models do not support RTSP at all. **Are Toshiba IP cameras still supported?** No. Toshiba sold its surveillance business and exited the IP camera market. No firmware updates, new models, or official technical support are available. Existing cameras continue to function but will not receive security patches or feature updates. **Do Toshiba cameras support ONVIF?** Only newer models in the IK-W14/16/30/70/80 range have limited ONVIF support. Older models (IK-WB01A through WB11A, IK-WR01A/02A) do not support ONVIF. For ONVIF discovery and configuration, use only the supported models. **Why does my Toshiba camera only provide snapshots, not video streams?** Early Toshiba IK-W models were designed as network snapshot cameras and do not include an RTSP server. These models (IK-WB01A, WB02A, WB11A, WR01A, WR02A) only support HTTP-based JPEG snapshots and CGI endpoints. To get continuous video, you need a newer model from the IK-W14/16/30/70/80 series. ## Related Resources - [All Camera Brands — RTSP URL Directory](../) - [Sony Connection Guide](../sony/) — Japanese enterprise cameras - [JVC Connection Guide](../jvc/) — Japanese legacy surveillance brand - [IP Camera Preview Tutorial](../../videocapture/video-tutorials/ip-camera-preview/) - [SDK Installation & Samples](../#get-started) ---END OF PAGE--- ## TP-Link and Tapo IP Camera RTSP URL Guide for C# .NET **URL:** https://www.visioforge.com/help/docs/dotnet/camera-brands/tp-link/ **Description:** TP-Link and Tapo C series camera RTSP URL patterns for C# .NET. Integrate TL-SC, NC, and Tapo models with VisioForge Video Capture SDK. **Tags:** Video Capture SDK, Media Blocks SDK, .NET, Windows, macOS, Linux, Android, iOS, Capture, Streaming, IP Camera, RTSP, ONVIF, MP4, H.264, H.265, MJPEG, C# # How to Connect to TP-Link IP Camera in C# .NET [Video Capture SDK .Net](https://www.visioforge.com/video-capture-sdk-net) [Media Blocks SDK .Net](https://www.visioforge.com/media-blocks-sdk-net) ## Brand Overview **TP-Link** is a global networking equipment manufacturer headquartered in Shenzhen, China. While primarily known for routers and networking gear, TP-Link produces IP cameras under both the **TP-Link** brand (TL-SC series, now discontinued) and the **Tapo** smart home brand (Tapo C series, currently active). The Tapo line has become one of the best-selling consumer camera brands globally due to aggressive pricing and app-based setup. **Key facts:** - **Product lines:** TL-SC series (legacy, discontinued), NC series (cloud cameras, discontinued), Tapo C series (current smart home cameras) - **Protocol support:** RTSP, HTTP/MJPEG, ONVIF (Tapo models with firmware update), proprietary cloud protocol - **Default RTSP port:** 554 - **Default credentials:** Varies by generation (see below) - **ONVIF support:** Tapo C series (requires enabling in Tapo app); TL-SC series has no ONVIF - **Video codecs:** H.264 (all models), H.265 (Tapo C320WS and newer) ### Credentials by Product Line | Product Line | Default Username | Default Password | Notes | | --- | --- | --- | --- | | TL-SC series | admin | admin | Legacy, fixed | | NC series | admin | admin | Cloud-managed | | Tapo C series | (set in app) | (set in app) | Must create RTSP credentials in Tapo app | Tapo camera credentials Tapo cameras require you to create a separate **camera account** in the Tapo app (Advanced Settings > Camera Account) before RTSP access works. This username/password is different from your TP-Link cloud account. ## RTSP URL Patterns ### Tapo C Series (Current Models) The Tapo camera line uses a straightforward RTSP URL format: | Model | RTSP URL | Stream | Audio | | --- | --- | --- | --- | | Tapo C100 (indoor) | `rtsp://IP:554/stream1` | Main (1080p) | Yes | | Tapo C100 (indoor) | `rtsp://IP:554/stream2` | Sub (360p) | Yes | | Tapo C110 (indoor 3MP) | `rtsp://IP:554/stream1` | Main (2304x1296) | Yes | | Tapo C110 (indoor 3MP) | `rtsp://IP:554/stream2` | Sub | Yes | | Tapo C200 (pan/tilt) | `rtsp://IP:554/stream1` | Main (1080p) | Yes | | Tapo C200 (pan/tilt) | `rtsp://IP:554/stream2` | Sub (360p) | Yes | | Tapo C210 (pan/tilt 3MP) | `rtsp://IP:554/stream1` | Main (2304x1296) | Yes | | Tapo C310 (outdoor) | `rtsp://IP:554/stream1` | Main (2048x1296) | Yes | | Tapo C320WS (outdoor 2K) | `rtsp://IP:554/stream1` | Main (2560x1440) | Yes | | Tapo C500 (outdoor PTZ) | `rtsp://IP:554/stream1` | Main (1080p) | Yes | | Tapo C520WS (outdoor 2K PTZ) | `rtsp://IP:554/stream1` | Main (2560x1440) | Yes | ### TL-SC Series (Legacy Models) The discontinued TL-SC series used different URL formats depending on the model: | Model | RTSP URL | Codec | Audio | | --- | --- | --- | --- | | TL-SC3130 | `rtsp://IP:554/video.mp4` | MPEG-4 | Yes | | TL-SC3130G | `rtsp://IP:554/video.mp4` | MPEG-4 | Yes | | TL-SC3171 | `rtsp://IP:554/video.mp4` | MPEG-4 | Yes | | TL-SC3171G | `rtsp://IP:554/video.mp4` | MPEG-4 | Yes | | TL-SC3230 | `rtsp://IP:554/video.h264` | H.264 | Yes | | TL-SC3230N | `rtsp://IP:554/video.h264` | H.264 | Yes | | TL-SC3430 | `rtsp://IP:554/video.h264` | H.264 | Yes | | TL-SC3430N | `rtsp://IP:554/video.h264` | H.264 | Yes | | TL-SC4171G | `rtsp://IP:554/video.mp4` | MPEG-4 | Yes | ### TL-SC Alternative URL Formats | URL Pattern | Codec | Notes | | --- | --- | --- | | `rtsp://IP:554/video.mp4` | MPEG-4 | Primary for SC3xxx models | | `rtsp://IP:554/video.h264` | H.264 | Primary for newer SC models | | `rtsp://IP:554/video.mjpg` | MJPEG | Lower quality, wider compatibility | | `rtsp://IP:554/video.pro2` | MPEG-4 | Alternative profile | | `rtsp://IP:554/live.sdp` | H.264 | SDP-based stream | | `rtsp://IP:554/cam1/h264` | H.264 | Channel-based format | | `rtsp://IP:554/media.amp` | Auto | Axis-compatible firmware | ## Connecting with VisioForge SDK Use your TP-Link camera's RTSP URL with any of the three SDK approaches shown in the [Quick Start Guide](../#quick-start-code): ``` // TP-Link Tapo C200, main stream var uri = new Uri("rtsp://192.168.1.100:554/stream1"); var username = "admin"; var password = "YourPassword"; ``` For sub-stream access, use `/stream2` instead. ## Snapshot and MJPEG URLs ### Tapo C Series | Type | URL Pattern | Notes | | --- | --- | --- | | Snapshot | `http://IP/snapshot.jpg` | May require authentication | ### TL-SC Series | Type | URL Pattern | Notes | | --- | --- | --- | | JPEG Snapshot | `http://IP/jpg/image.jpg` | Basic snapshot | | Sized Snapshot | `http://IP/jpg/image.jpg?size=3` | Predefined size | | CGI Snapshot | `http://IP/cgi-bin/jpg/image` | CGI-based | | MJPEG Stream | `http://IP/video.mjpg` | Continuous MJPEG | | MJPEG (quality) | `http://IP/video.mjpg?q=30&fps=33&id=0.5` | Quality/FPS control | | Video CGI | `http://IP/video.cgi?resolution=VGA` | Resolution-specific | | Net Video CGI | `http://IP/cgi-bin/net_video.cgi?channel=1` | Channel-based | | Axis-compatible | `http://IP/axis-cgi/mjpg/video.cgi` | Emulated Axis API | ## Troubleshooting ### Tapo camera: "Connection refused" or "Unauthorized" The most common issue with Tapo cameras is not setting up RTSP credentials: 1. Open the **Tapo app** on your phone 2. Go to your camera's settings 3. Navigate to **Advanced Settings > Camera Account** 4. Create a username and password 5. Use these credentials (not your TP-Link account) in RTSP URLs ### Tapo camera: ONVIF not working ONVIF is disabled by default on Tapo cameras. To enable it: 1. Open the Tapo app 2. Go to camera settings > Advanced Settings 3. Enable **ONVIF** toggle 4. Camera will reboot ### TL-SC models: wrong codec URL TL-SC cameras are codec-specific in their URLs: - **SC3130/3171 series:** Use `/video.mp4` (MPEG-4) - **SC3230/3430 series:** Use `/video.h264` (H.264) - Using the wrong codec in the URL path will result in no stream ### Stream2 on Tapo cameras shows low resolution This is by design. `stream2` is the sub stream intended for lower bandwidth. Use `stream1` for full resolution. You can adjust the sub stream resolution in the Tapo app under camera settings. ### TL-SC models: videostream.asf not working The `videostream.asf` URL format requires URL-embedded credentials: `http://IP/videostream.asf?user=admin&pwd=admin&resolution=64&rate=0` The `resolution` parameter values: 32 = 320x240, 64 = 640x480. ## FAQ **What is the default RTSP URL for Tapo cameras?** The URL is `rtsp://username:password@CAMERA_IP:554/stream1` for the main stream and `stream2` for the sub stream. You must first create RTSP credentials in the Tapo app under Advanced Settings > Camera Account. **Can I use Tapo cameras without the Tapo cloud service?** Yes. Once you set up RTSP credentials via the Tapo app, you can access the camera's RTSP stream directly over your local network without any cloud dependency. The Tapo app is only needed for initial setup and credential configuration. **What's the difference between TL-SC and Tapo cameras?** The TL-SC series was TP-Link's older IP camera line (discontinued) with traditional web-based management. Tapo is the current smart home camera brand with app-based setup. Both support RTSP but use different URL patterns and authentication methods. **Do Tapo cameras support H.265?** Select models like the Tapo C320WS and C520WS support H.265 encoding. Most Tapo cameras use H.264. Check your specific model's specifications for H.265 support. ## Related Resources - [All Camera Brands — RTSP URL Directory](../) - [Reolink Connection Guide](../reolink/) — Consumer alternative with RTSP - [Mercusys Connection Guide](../mercusys/) — TP-Link sub-brand, same firmware - [IP Camera Preview Tutorial](../../videocapture/video-tutorials/ip-camera-preview/) - [SDK Installation & Samples](../#get-started) ---END OF PAGE--- ## How to Connect to Ubiquiti (UniFi) IP Camera in C# .NET **URL:** https://www.visioforge.com/help/docs/dotnet/camera-brands/ubiquiti/ **Description:** Ubiquiti UniFi Protect G3, G4, G5, and AI series RTSP URL patterns for C# .NET. Enable RTSP in UniFi and integrate with VisioForge SDK code. **Tags:** Video Capture SDK, Media Blocks SDK, .NET, VideoCaptureCoreX, Windows, macOS, Linux, Android, iOS, Capture, Streaming, IP Camera, RTSP, ONVIF, C# # How to Connect to Ubiquiti (UniFi) IP Camera in C# .NET [Video Capture SDK .Net](https://www.visioforge.com/video-capture-sdk-net) [Media Blocks SDK .Net](https://www.visioforge.com/media-blocks-sdk-net) ## Brand Overview **Ubiquiti Inc.** is an American technology company headquartered in New York City, known for networking equipment under the **UniFi** brand. Ubiquiti's camera line is part of the **UniFi Protect** ecosystem, which includes cameras, NVRs (Network Video Recorders), doorbells, and sensors. UniFi Protect cameras are managed through a central console (Dream Machine, Cloud Key, or NVR) and are popular in prosumer and SMB environments. **Key facts:** - **Product lines:** UniFi Protect G3 (1080p), G4 (2K/4MP), G5 (2K/4MP updated), AI series (with onboard AI), UVC (legacy AirCam) - **Protocol support:** RTSP (must be enabled per camera), ONVIF (limited), proprietary UniFi Protect protocol - **Default RTSP port:** 7447 (UniFi Protect) or 554 (legacy AirCam) - **Default credentials:** Set during UniFi Protect setup (RTSP uses separate per-camera credentials) - **ONVIF support:** Not natively supported; RTSP is the third-party integration method - **Video codecs:** H.264 (all models) RTSP must be enabled UniFi Protect cameras do **not** have RTSP enabled by default. You must enable RTSP for each camera individually through the UniFi Protect web interface or app. Without enabling it, the camera will not respond to RTSP connections. ### Enabling RTSP on UniFi Protect Cameras 1. Open the **UniFi Protect** web interface (via your Dream Machine, Cloud Key, or NVR) 2. Go to **Devices** and select the camera 3. Open **Settings** tab 4. Scroll to **Advanced** section 5. Enable **RTSP** toggle 6. Note the RTSP URL displayed (includes unique token) ## RTSP URL Patterns ### UniFi Protect Cameras (Current) UniFi Protect cameras expose RTSP on **port 7447** with stream quality selection: | Stream | RTSP URL | Resolution | Notes | | --- | --- | --- | --- | | High quality | `rtsp://IP:7447/STREAM_TOKEN` | Full (up to 2688x1512) | Main stream | | Medium quality | `rtsp://IP:7447/STREAM_TOKEN` | Reduced | Medium stream | | Low quality | `rtsp://IP:7447/STREAM_TOKEN` | Low (640x360) | Bandwidth-optimized | Stream tokens UniFi Protect generates unique RTSP URLs per camera when you enable RTSP. The URL contains a unique token. You can find the exact URL in the UniFi Protect interface under each camera's Advanced settings. The RTSP URL format is typically: ``` rtsp://CAMERA_IP:7447/UNIQUE_TOKEN_STRING ``` Where the token is auto-generated and displayed in the UniFi Protect UI. ### UniFi Protect Camera Models | Model | Resolution | Streams | Form Factor | | --- | --- | --- | --- | | G3 Instant | 1920x1080 | High/Low | Indoor mini | | G3 Flex | 1920x1080 | High/Medium/Low | Indoor/outdoor flex | | G3 Bullet | 1920x1080 | High/Medium/Low | Outdoor bullet | | G3 Dome | 1920x1080 | High/Medium/Low | Outdoor dome | | G4 Instant | 2688x1512 | High/Medium/Low | Indoor mini | | G4 Bullet | 2688x1512 | High/Medium/Low | Outdoor bullet | | G4 Dome | 2688x1512 | High/Medium/Low | Outdoor dome | | G4 Pro | 3840x2160 | High/Medium/Low | Outdoor pro | | G4 PTZ | 3840x2160 | High/Medium/Low | PTZ | | G5 Bullet | 2688x1512 | High/Medium/Low | Outdoor bullet | | G5 Dome | 2688x1512 | High/Medium/Low | Outdoor dome | | G5 Turret Ultra | 3840x2160 | High/Medium/Low | Outdoor turret | | AI 360 | 3840x2160 | High/Medium/Low | Fisheye | | AI Bullet | 3840x2160 | High/Medium/Low | Outdoor bullet | | AI Pro | 3840x2160 | High/Medium/Low | Outdoor pro | ### Legacy AirCam/AirVision URLs Older Ubiquiti cameras (AirCam series, before UniFi Protect) used standard port 554: | Model | RTSP URL | Notes | | --- | --- | --- | | AirCam | `rtsp://IP:554/live/ch00_0` | Main stream | | AirCam Dome | `rtsp://IP:554/live/ch00_0` | Dome variant | | AirCam Mini | `rtsp://IP:554/live/ch00_0` | Mini variant | | AirCam (channel) | `rtsp://IP:554/ch0N_0` | N = channel number | ## Connecting with VisioForge SDK Use your UniFi Protect camera's RTSP URL with any of the three SDK approaches shown in the [Quick Start Guide](../#quick-start-code): ``` // UniFi Protect camera, token-based auth (no username/password needed) var uri = new Uri("rtsp://192.168.1.40:7447/YOUR_STREAM_TOKEN"); ``` UniFi Protect cameras use token-based authentication -- the unique stream token is provided in the UniFi Protect UI when you enable RTSP. No separate username or password is required. For different quality streams (high/medium/low), select the corresponding stream in the Protect interface to get its token. For legacy AirCam models, use port 554 with credentials `ubnt`/`ubnt` and path `/live/ch00_0`. ## Snapshot URLs ### Legacy AirCam | Type | URL Pattern | Notes | | --- | --- | --- | | Snapshot | `http://IP/snapshot.cgi` | Basic snapshot | | Snapshot (auth) | `http://IP/snapshot.cgi?user=USER&pwd=PASS` | With credentials | | Snapshot (alt) | `http://IP:554/snapshot.cgi?user=USER&pwd=PASS&count=0` | Via RTSP port | ### UniFi Protect UniFi Protect cameras do not expose HTTP snapshot endpoints directly. Snapshots are accessed through the UniFi Protect API or by capturing frames from the RTSP stream in your application. ## Troubleshooting ### "Connection refused" on port 554 UniFi Protect cameras use **port 7447** for RTSP, not the standard port 554. Port 554 only applies to legacy AirCam models. Make sure you're using the correct port: - **UniFi Protect cameras:** Port 7447 - **Legacy AirCam:** Port 554 ### RTSP not enabled RTSP is disabled by default on UniFi Protect cameras. You must enable it in the UniFi Protect interface: 1. UniFi Protect > Devices > Select Camera > Settings > Advanced > Enable RTSP ### Stream token changed The RTSP stream token can change if you: - Disable and re-enable RTSP on the camera - Reset the camera - Update firmware Always verify the current RTSP URL in the UniFi Protect interface if your connection stops working. ### High latency UniFi Protect cameras can exhibit 2-5 second latency by default. To reduce latency: - Set `LowLatencyMode = true` on the `RTSPSourceSettings` passed to VideoCaptureCoreX - Select the low-quality stream (lower resolution = less buffering) - Use TCP transport for more reliable delivery ### No ONVIF support UniFi Protect cameras do not support ONVIF. Use RTSP for third-party integration. If you need ONVIF discovery, it won't work with these cameras. ## FAQ **What is the default RTSP URL for UniFi Protect cameras?** The RTSP URL format is `rtsp://CAMERA_IP:7447/UNIQUE_TOKEN`. RTSP must be enabled per-camera in the UniFi Protect interface, which will display the unique URL. There is no universal default URL -- each camera gets a unique stream token. **Can I use UniFi cameras without UniFi Protect?** Current UniFi cameras require a UniFi Protect controller (Dream Machine, Cloud Key, or NVR) for initial setup and management. Once RTSP is enabled, you can stream to third-party software. Legacy AirCam models work standalone. **Do UniFi cameras support H.265?** As of current firmware, UniFi Protect cameras stream H.264 over RTSP. H.265 support may be available for internal recording but is not typically exposed via RTSP. **What are the default credentials for AirCam?** Legacy AirCam cameras use `ubnt` / `ubnt` as default credentials. Current UniFi Protect cameras use token-based RTSP authentication. ## Related Resources - [All Camera Brands — RTSP URL Directory](../) - [Reolink Connection Guide](../reolink/) — Prosumer alternative with RTSP - [IP Camera Preview Tutorial](../../videocapture/video-tutorials/ip-camera-preview/) - [SDK Installation & Samples](../#get-started) ---END OF PAGE--- ## How to Connect to Uniview (UNV) IP Camera in C# .NET **URL:** https://www.visioforge.com/help/docs/dotnet/camera-brands/uniview/ **Description:** Uniview IPC-B, IPC-T, IPC-D, IPC-E, and NVR RTSP URL patterns for C# .NET. ONVIF-compatible integration with VisioForge SDK code samples. **Tags:** Video Capture SDK, Media Blocks SDK, .NET, Windows, macOS, Linux, Android, iOS, Capture, Streaming, Decoding, IP Camera, RTSP, ONVIF, H.265, MJPEG, C# # How to Connect to Uniview (UNV) IP Camera in C# .NET [Video Capture SDK .Net](https://www.visioforge.com/video-capture-sdk-net) [Media Blocks SDK .Net](https://www.visioforge.com/media-blocks-sdk-net) ## Brand Overview **Uniview** (Zhejiang Uniview Technologies Co., Ltd.), also known as **UNV**, is the world's third-largest video surveillance manufacturer by market share, behind Hikvision and Dahua. Founded in 2005 and headquartered in Hangzhou, China, Uniview pioneered IP video surveillance in China and offers a full range of IP cameras, NVRs, VMS software, and access control products for enterprise and government markets. **Key facts:** - **Product lines:** IPC-B (bullet), IPC-T (turret), IPC-D (dome), IPC-E (eyeball), IPC-P (PTZ), NVR30x/50x (NVRs) - **Protocol support:** RTSP, ONVIF Profile S/G/T, HTTP/CGI, SDK (EZStation) - **Default RTSP port:** 554 - **Default credentials:** admin / 123456 (must be changed on first login with newer firmware) - **ONVIF support:** Yes (all current models) - **Video codecs:** H.264, H.265 (U-Code Smart Codec), MJPEG - **Market position:** #3 globally in video surveillance Uniview vs UNV Branding Uniview markets under both the **Uniview** and **UNV** brand names depending on the region. The RTSP URL patterns and firmware are identical regardless of branding. Some OEM partners rebrand Uniview hardware under their own labels. ## RTSP URL Patterns ### Standard URL Format Uniview cameras use a media profile-based URL structure: ``` rtsp://[USERNAME]:[PASSWORD]@[IP]:554/media/video[STREAM] ``` | Parameter | Value | Description | | --- | --- | --- | | `video1` | Main stream | Highest resolution (4K/5MP/4MP/2MP) | | `video2` | Sub stream | Lower resolution, reduced bandwidth | | `video3` | Third stream | Mobile-optimized (if supported) | ### Alternative URL Formats Uniview cameras support multiple RTSP URL patterns: | URL Pattern | Description | | --- | --- | | `rtsp://IP:554/media/video1` | Main stream (recommended) | | `rtsp://IP:554/media/video2` | Sub stream | | `rtsp://IP:554/media/video3` | Third stream | | `rtsp://IP:554/unicast/c1/s0/live` | Unicast main stream (alternative) | | `rtsp://IP:554/unicast/c1/s1/live` | Unicast sub stream (alternative) | | `rtsp://IP:554/live/ch00_0` | Legacy format (older firmware) | | `rtsp://IP:554/live/ch00_1` | Legacy sub stream | ### IP Camera Models | Model Series | Resolution | Main Stream URL | Audio | | --- | --- | --- | --- | | IPC-B112-PF28 (2MP bullet) | 1920x1080 | `rtsp://IP:554/media/video1` | No | | IPC-B314-APKZ (4MP bullet) | 2688x1520 | `rtsp://IP:554/media/video1` | Yes | | IPC-B315-APKZ (5MP bullet) | 2880x1620 | `rtsp://IP:554/media/video1` | Yes | | IPC-T112-PF28 (2MP turret) | 1920x1080 | `rtsp://IP:554/media/video1` | No | | IPC-T314-APKZ (4MP turret) | 2688x1520 | `rtsp://IP:554/media/video1` | Yes | | IPC-D312-APKZ (4MP dome) | 2688x1520 | `rtsp://IP:554/media/video1` | Yes | | IPC-D314-APKZ (4MP dome) | 2688x1520 | `rtsp://IP:554/media/video1` | Yes | | IPC-E312-APKZ (4MP eyeball) | 2688x1520 | `rtsp://IP:554/media/video1` | Yes | | IPC-P1E2-I (2MP PTZ) | 1920x1080 | `rtsp://IP:554/media/video1` | Yes | | IPC-B182-PF28 (4K bullet) | 3840x2160 | `rtsp://IP:554/media/video1` | Yes | ### NVR Channel URLs For Uniview NVRs (NVR301, NVR302, NVR304, NVR501, NVR516): | Channel | Main Stream | Sub Stream | | --- | --- | --- | | Camera 1 | `rtsp://IP:554/media/video1` | `rtsp://IP:554/media/video2` | | Camera 2 | `rtsp://IP:554/media/video3` | `rtsp://IP:554/media/video4` | | Camera 3 | `rtsp://IP:554/media/video5` | `rtsp://IP:554/media/video6` | | Camera N | `rtsp://IP:554/media/video[2N-1]` | `rtsp://IP:554/media/video[2N]` | NVR Channel Numbering On Uniview NVRs, the video stream number encodes both the channel and stream type. Each channel uses two consecutive numbers: odd for main stream, even for sub stream. Camera 1 = video1/video2, Camera 2 = video3/video4, and so on. ## Connecting with VisioForge SDK Use your Uniview camera's RTSP URL with any of the three SDK approaches shown in the [Quick Start Guide](../#quick-start-code): ``` // Uniview IPC-B314-APKZ, main stream var uri = new Uri("rtsp://192.168.1.90:554/media/video1"); var username = "admin"; var password = "YourPassword"; ``` For sub-stream access, use `/media/video2` instead of `/media/video1`. ## Snapshot and MJPEG URLs | Type | URL Pattern | Notes | | --- | --- | --- | | JPEG Snapshot | `http://IP/cgi-bin/snapshot.cgi` | Requires digest authentication | | ONVIF Snapshot | `http://IP/onvif-http/snapshot?channel=1` | ONVIF HTTP snapshot | ## Troubleshooting ### Default password must be changed Uniview cameras with current firmware require the default password (`123456`) to be changed during initial setup. If you haven't configured the camera yet: 1. Access the camera at `http://CAMERA_IP` in a browser 2. Complete the activation wizard 3. Set a strong password 4. Use those credentials in your RTSP URL ### "unicast" vs "media" URL format If `/media/video1` does not work on your camera, try the unicast format: `rtsp://IP:554/unicast/c1/s0/live`. Older Uniview firmware versions may only support the unicast path. Newer firmware supports both formats. ### H.265 stream not playing Uniview's U-Code smart codec produces standard H.265/HEVC streams. If H.265 playback fails: 1. Install the HEVC decoder redistributable 2. Or switch the camera to H.264 encoding in the web interface: **Setup > Video > Video** 3. Use `rtspSettings.UseGPUDecoder = true` for hardware-accelerated H.265 decoding ### ONVIF discovery issues ONVIF is enabled by default on Uniview cameras but may require a separate ONVIF password. Check **Setup > Network > ONVIF** in the web interface and ensure the ONVIF user account is configured. ## FAQ **What is the default RTSP URL for Uniview cameras?** The standard URL is `rtsp://admin:password@CAMERA_IP:554/media/video1` for the main stream. Use `/media/video2` for the sub stream. Some older models use `rtsp://IP:554/unicast/c1/s0/live` instead. **Is Uniview the same as UNV?** Yes. Uniview and UNV are the same company (Zhejiang Uniview Technologies). The branding varies by region. All cameras use identical firmware, RTSP URL formats, and web interfaces regardless of whether they carry the Uniview or UNV label. **Do Uniview cameras support ONVIF?** Yes. All current Uniview cameras support ONVIF Profile S and Profile T. ONVIF allows automatic camera discovery and standardized stream access without using brand-specific RTSP URLs. **How do I access multiple channels on a Uniview NVR?** Uniview NVRs use sequential video stream numbers: Camera 1 = video1 (main) / video2 (sub), Camera 2 = video3 (main) / video4 (sub), and so on. The formula is: main stream = video[2N-1], sub stream = video[2N] where N is the camera channel number. ## Related Resources - [All Camera Brands — RTSP URL Directory](../) - [Hikvision Connection Guide](../hikvision/) — Global market leader, different URL format - [Dahua Connection Guide](../dahua/) — Another major Chinese surveillance brand - [IP Camera Preview Tutorial](../../videocapture/video-tutorials/ip-camera-preview/) - [SDK Installation & Samples](../#get-started) ---END OF PAGE--- ## Verkada Camera RTSP and C# .NET Integration Options **URL:** https://www.visioforge.com/help/docs/dotnet/camera-brands/verkada/ **Description:** Verkada camera integration options in C# .NET. Understand cloud-managed architecture, RTSP limitations, and alternative approaches for Verkada cameras. **Tags:** Video Capture SDK, Media Blocks SDK, .NET, MediaBlocksPipeline, Windows, macOS, Linux, Android, iOS, Capture, Streaming, Webcam, IP Camera, RTSP, ONVIF, C# **API:** MediaBlocksPipeline, SystemVideoSourceBlock, VideoRendererBlock # How to Connect to Verkada Camera in C# .NET [Video Capture SDK .Net](https://www.visioforge.com/video-capture-sdk-net) [Media Blocks SDK .Net](https://www.visioforge.com/media-blocks-sdk-net) ## Brand Overview **Verkada** is an American cloud-managed security camera company headquartered in San Mateo, California. Founded in 2016, Verkada offers enterprise-grade cameras with a fully cloud-managed architecture. Unlike traditional IP cameras, Verkada cameras are managed exclusively through Verkada's cloud platform — there are no local RTSP streams, ONVIF support, or direct network access to the cameras. **Key facts:** - **Product lines:** CD (mini dome), CB (bullet), CE (outdoor dome), CF (fisheye), CM (multi-sensor), CP (PTZ) - **Architecture:** Cloud-managed — all video processing and access goes through Verkada Command platform - **RTSP support:** No - **ONVIF support:** No - **Local network access:** No direct access — cameras communicate only with Verkada cloud - **Video codecs:** H.264, H.265 (managed by cloud platform) - **API access:** Verkada API (cloud-based, requires enterprise subscription) No RTSP or Local Streaming Verkada cameras do **not** support RTSP, ONVIF, or any standard local streaming protocol. They are cloud-managed devices that can only be accessed through Verkada's Command platform or API. Direct integration using VisioForge SDK's RTSP source is not possible with Verkada cameras. ## Why Verkada Has No RTSP Verkada's architecture is fundamentally different from traditional IP cameras: 1. **Cloud-first design:** Video is processed on-camera and streamed to Verkada's cloud 2. **No local network ports:** Cameras do not expose port 554 or any RTSP endpoint 3. **Managed access:** All video access goes through Verkada Command (web/mobile) 4. **Zero-trust security:** No direct camera-to-client connections on the LAN This architecture provides simplified deployment and centralized management but eliminates direct SDK integration. ## Integration Options ### Option 1: Verkada API (Cloud-Based) Verkada offers a REST API for enterprise customers that provides: - Camera listing and status - Video export/download (clips) - Thumbnail/snapshot retrieval - Event and alert data The API does **not** provide live RTSP or real-time video streams. It is designed for clip retrieval and metadata access. ### Option 2: HDMI Output (Select Models) Some Verkada models include an HDMI output port for local display. You can capture this output using an HDMI capture card: ``` // Capture HDMI output from Verkada camera via USB capture card var pipeline = new MediaBlocksPipeline(); // Use system video source (HDMI capture card appears as webcam) var captureDevice = new SystemVideoSourceBlock(captureDeviceSettings); var videoRenderer = new VideoRendererBlock(pipeline, VideoView1); pipeline.Connect(captureDevice.Output, videoRenderer.Input); await pipeline.StartAsync(); ``` This approach provides real-time local video but requires physical HDMI connectivity and a capture card. ### Option 3: Alternative Cameras with RTSP If you need direct RTSP integration with enterprise-grade cameras, consider these alternatives: | Alternative | Market Segment | RTSP | ONVIF | Guide | | --- | --- | --- | --- | --- | | Axis | Enterprise | Yes | Yes | [Connection Guide](../axis/) | | Bosch | Enterprise | Yes | Yes | [Connection Guide](../bosch/) | | Hanwha Vision | Enterprise | Yes | Yes | [Connection Guide](../hanwha/) | | Avigilon | Enterprise | Yes | Yes | [Connection Guide](../avigilon/) | | Hikvision | Enterprise | Yes | Yes | [Connection Guide](../hikvision/) | ## FAQ **Can I connect to Verkada cameras with RTSP?** No. Verkada cameras do not support RTSP, ONVIF, or any local streaming protocol. They are cloud-managed devices accessible only through Verkada's Command platform or API. **Does Verkada have an API for video access?** Yes, but the Verkada API provides clip export and snapshot retrieval, not live video streaming. Real-time video is only available through the Verkada Command web interface or mobile app. Enterprise API access requires a Verkada subscription. **Can I use VisioForge SDK with Verkada cameras?** Not directly via RTSP. The only local integration option is capturing the HDMI output of select Verkada models using a capture card with VisioForge SDK's system video source. For cloud-based integration, you would need to use Verkada's API separately. **What enterprise cameras support RTSP?** For enterprise cameras with full RTSP and ONVIF support, see our guides for [Axis](../axis/), [Bosch](../bosch/), [Hanwha Vision](../hanwha/), [Avigilon](../avigilon/), and [Hikvision](../hikvision/). ## Related Resources - [All Camera Brands — RTSP URL Directory](../) - [Axis Connection Guide](../axis/) — Enterprise alternative with RTSP - [Bosch Connection Guide](../bosch/) — Enterprise alternative with RTSP - [Rhombus Connection Guide](../rhombus/) — Another cloud-managed platform - [SDK Installation & Samples](../#get-started) ---END OF PAGE--- ## Vivotek IP Camera RTSP URL and C# .NET Connection Guide **URL:** https://www.visioforge.com/help/docs/dotnet/camera-brands/vivotek/ **Description:** Vivotek FD, IP, SD, and FE fisheye camera RTSP URL patterns for C# .NET. Stream and record using VisioForge Video Capture SDK with ONVIF support. **Tags:** Video Capture SDK, Media Blocks SDK, .NET, Windows, macOS, Linux, Android, iOS, Capture, Streaming, Encoding, IP Camera, RTSP, ONVIF, H.265, MJPEG, C# # How to Connect to Vivotek IP Camera in C# .NET [Video Capture SDK .Net](https://www.visioforge.com/video-capture-sdk-net) [Media Blocks SDK .Net](https://www.visioforge.com/media-blocks-sdk-net) ## Brand Overview **Vivotek Inc.** is a Taiwanese manufacturer of network surveillance solutions headquartered in New Taipei City. Founded in 2000, Vivotek is one of the world's leading IP camera brands, widely deployed in enterprise, retail, transportation, and city surveillance. Vivotek is known for its wide range of form factors including fisheye, panoramic, speed dome, and specialty cameras. **Key facts:** - **Product lines:** FD (fixed dome), IP (box/bullet), IB (bullet), SD (speed dome), FE (fisheye), MD (mobile dome), CC (compact), VS (video servers/encoders) - **Protocol support:** RTSP, ONVIF (Profile S/G/T), HTTP/CGI, MJPEG - **Default RTSP port:** 554 - **Default credentials:** root / (empty or set during setup); legacy models: root / root - **ONVIF support:** Yes (all current models) - **Video codecs:** H.264, H.265, MJPEG ## RTSP URL Patterns ### Current Models All current Vivotek cameras use the `live.sdp` URL pattern for RTSP streaming: | Stream | RTSP URL | Notes | | --- | --- | --- | | Stream 1 (main) | `rtsp://IP:554/live.sdp` | Main stream, H.264/H.265 | | Stream 2 (sub) | `rtsp://IP:554/live2.sdp` | Sub stream | | Stream 3 | `rtsp://IP:554/live3.sdp` | Third stream (if supported) | | Stream 4 | `rtsp://IP:554/live4.sdp` | Fourth stream (some models) | ### Model-Specific URLs | Model Series | RTSP URL | Form Factor | | --- | --- | --- | | FD81xx (fixed dome) | `rtsp://IP:554/live.sdp` | Fixed dome | | FD83xx (fixed dome) | `rtsp://IP:554/live.sdp` | Fixed dome | | FD8134/FD8136 | `rtsp://IP:554/live.sdp` | Mini dome | | FD8161/FD8162/FD8166 | `rtsp://IP:554/live.sdp` | Fixed dome | | FD8335H | `rtsp://IP:554/live.sdp` | Fixed dome | | FD8361/FD8362E/FD8372 | `rtsp://IP:554/live.sdp` | Fixed dome | | FE8171V/FE8172V/FE8174 | `rtsp://IP:554/live.sdp` | Fisheye | | IP7130/IP7131/IP7132 | `rtsp://IP:554/live.sdp` | Box camera | | IP7160/IP7161 | `rtsp://IP:554/live.sdp` | Box camera | | IP7330/IP7361 | `rtsp://IP:554/live.sdp` | Bullet | | IP8130/IP8133/IP8152 | `rtsp://IP:554/live.sdp` | Box camera | | IP8331/IP8332/IP8335H | `rtsp://IP:554/live.sdp` | Box camera | | IP8362/IP8364 | `rtsp://IP:554/live.sdp` | Box camera | | SD8362E | `rtsp://IP:554/live.sdp` | Speed dome | | CC8130 | `rtsp://IP:554/live.sdp` | Compact | | MD7560/MD8562 | `rtsp://IP:554/live.sdp` | Mobile dome | ### Legacy Models Older Vivotek models (IP3xxx, IP6xxx, PT3xxx, PZ6xxx series) used HTTP-only streaming: | Model Series | URL | Notes | | --- | --- | --- | | IP3121/IP3122/IP3133/IP3135 | `http://IP/cgi-bin/video.jpg?size=2` | JPEG only | | IP6127 | `http://IP/cgi-bin/video.jpg?size=2` | JPEG only | | PT3112/PT3122 | `http://IP/cgi-bin/video.jpg?size=2` | Pan/tilt, JPEG | | PZ6114/PZ6122 | `http://IP/cgi-bin/video.jpg?size=2` | Pan/zoom, JPEG | ### Video Server URLs Vivotek video servers encode analog camera feeds for IP streaming: | Model | RTSP URL | Notes | | --- | --- | --- | | VS2403 | `rtsp://IP:554/live.sdp` | Video server, multi-channel | | VS3100P | `http://IP/cgi-bin/video.jpg?size=2` | Legacy encoder | | VS7100 | `rtsp://IP:554/live.sdp` | Video server | | VS8102 | `rtsp://IP:554/live.sdp` | Video server | | VS8401 | `rtsp://IP:554/live.sdp` | 4-channel server | | VS8801 | `rtsp://IP:554/live.sdp` | 8-channel server | ### NVR URLs | Model | RTSP URL | Notes | | --- | --- | --- | | NR8x01 NVR | `rtsp://IP:554/live.sdp` | Via NVR | ## Connecting with VisioForge SDK Use your Vivotek camera's RTSP URL with any of the three SDK approaches shown in the [Quick Start Guide](../#quick-start-code): ``` // Vivotek camera, main stream var uri = new Uri("rtsp://192.168.1.50:554/live.sdp"); var username = "root"; var password = "YourPassword"; ``` For sub-stream access, use `/live2.sdp` instead. ## Snapshot and MJPEG URLs | Type | URL Pattern | Notes | | --- | --- | --- | | JPEG Snapshot | `http://IP/cgi-bin/viewer/video.jpg?resolution=640x480` | Current models | | JPEG Snapshot (channel) | `http://IP/cgi-bin/viewer/video.jpg?channel=1&resolution=640x480` | Multi-channel | | MJPEG Stream | `http://IP/video.mjpg` | Continuous MJPEG | | MJPEG Stream (alt) | `http://IP/video2.mjpg` | Second stream | | MJPEG (params) | `http://IP/video.mjpg?q=30&fps=33&id=0.5` | With quality/fps params | | Legacy Snapshot | `http://IP/cgi-bin/video.jpg` | Older models | | Legacy Snapshot (sized) | `http://IP/cgi-bin/video.jpg?size=2` | Older models, VGA | | Snapshot CGI | `http://IP/snapshot.cgi` | Some models | ## Troubleshooting ### Consistent URL pattern Unlike many brands, Vivotek uses the same `live.sdp` RTSP URL pattern across virtually all their RTSP-capable models. If `rtsp://IP:554/live.sdp` doesn't work, try: - `rtsp://IP:554/live2.sdp` (sub stream) - `rtsp://IP:554/live3.sdp` (third stream) ### Default credentials - **Current models:** `root` with password set during initial setup - **Legacy models:** `root` / (empty password) or `root` / `root` - Some models require setup via the web interface before RTSP is accessible ### Non-standard ports on some models Some Vivotek cameras may use non-standard RTSP ports (e.g., 1025, 1032) if configured. Check the camera's web interface under Network > RTSP settings if port 554 doesn't respond. ### Legacy HTTP-only cameras Very old Vivotek cameras (IP31xx, IP61xx, PT31xx, PZ61xx series) only support HTTP JPEG and MJPEG streams, not RTSP. These cameras cannot use the RTSP source -- use HTTP snapshot or MJPEG integration instead. ## FAQ **What is the default RTSP URL for Vivotek cameras?** The standard URL is `rtsp://root:password@CAMERA_IP:554/live.sdp` for the main stream. Use `live2.sdp` for the sub stream and `live3.sdp` for the third stream. This pattern works across virtually all RTSP-capable Vivotek models. **Do Vivotek cameras support H.265?** Yes. Current Vivotek cameras support H.265 (HEVC). Use the same `live.sdp` URL -- the codec is configured in the camera's web interface, not in the URL. **What is the difference between live.sdp and live2.sdp?** `live.sdp` is the main (highest quality) stream, `live2.sdp` is typically a lower-resolution sub stream for bandwidth-constrained viewing, and `live3.sdp` is a third stream often used for mobile viewing. **Do Vivotek video servers support RTSP?** Yes. Current Vivotek video servers (VS2403, VS7100, VS8102, VS8401, VS8801) support RTSP using the same `live.sdp` URL pattern as cameras. Legacy servers (VS3100P) only support HTTP JPEG. ## Related Resources - [All Camera Brands — RTSP URL Directory](../) - [GeoVision Connection Guide](../geovision/) — Taiwanese enterprise cameras - [ACTi Connection Guide](../acti/) — Taiwanese professional cameras - [IP Camera Capture to MP4](../../videocapture/video-tutorials/ip-camera-capture-mp4/) — Record Vivotek streams to file - [IP Camera Preview Tutorial](../../videocapture/video-tutorials/ip-camera-preview/) - [SDK Installation & Samples](../#get-started) ---END OF PAGE--- ## Wisenet RTSP URL — Connect IP Camera with C# .NET SDK **URL:** https://www.visioforge.com/help/docs/dotnet/camera-brands/wisenet/ **Description:** Wisenet X, P, Q, L series RTSP URL patterns for C# .NET apps. Hanwha Vision camera and NVR integration with ONVIF support and VisioForge SDK code. **Tags:** Video Capture SDK, Media Blocks SDK, .NET, Windows, macOS, Linux, Android, iOS, Capture, Streaming, Decoding, IP Camera, RTSP, ONVIF, MJPEG, C# # How to Connect to Wisenet IP Camera in C# .NET [Video Capture SDK .Net](https://www.visioforge.com/video-capture-sdk-net) [Media Blocks SDK .Net](https://www.visioforge.com/media-blocks-sdk-net) ## Brand Overview **Wisenet** is the product brand name used by **Hanwha Vision** (formerly Hanwha Techwin / Samsung Techwin) for all IP cameras, NVRs, and video management systems. Wisenet is not a separate company but rather the product family name used across Hanwha Vision's full surveillance lineup. **Key facts:** - **Manufacturer:** Hanwha Vision (South Korea) - **Product tiers:** X (premium), P (AI), Q (mainstream), Q mini (compact), L (value), T (thermal) - **Protocol support:** RTSP, ONVIF Profile S/G/T, SUNAPI (proprietary) - **Default RTSP port:** 554 - **Default credentials:** admin / (set during activation) - **ONVIF support:** Yes (all current models) - **Video codecs:** H.264, H.265, WiseStream III, MJPEG Wisenet = Hanwha Vision Products Wisenet is the **product brand**, Hanwha Vision is the **company**. All Wisenet cameras use the same RTSP URL patterns. For detailed connection instructions including NVR channel access and troubleshooting, see our [Hanwha Vision connection guide](../hanwha/). For legacy Samsung-branded cameras, see the [Samsung/Hanwha guide](../samsung/). ## RTSP URL Patterns ### Standard URL Format All Wisenet cameras share the same profile-based URL structure: ``` rtsp://[USERNAME]:[PASSWORD]@[IP]:554/profile[N]/media.smp ``` ### By Product Tier | Wisenet Tier | Example Models | Main Stream URL | Key Feature | | --- | --- | --- | --- | | **X series** (premium) | XNO-6080R, XND-8080RV, XNP-6120H | `rtsp://IP:554/profile2/media.smp` | Best WDR, low-light | | **P series** (AI) | PNO-A9081R, PND-A9081RV | `rtsp://IP:554/profile2/media.smp` | Deep learning analytics | | **Q series** (mainstream) | QNO-8080R, QND-8080R, QNE-8021R | `rtsp://IP:554/profile2/media.smp` | Balanced features/price | | **Q mini** (compact) | QND-8021 | `rtsp://IP:554/profile2/media.smp` | Discreet form factor | | **L series** (value) | LNO-6032R, LND-6032R | `rtsp://IP:554/profile2/media.smp` | Entry-level | | **T series** (thermal) | TNO-4030T, TNO-4050T | `rtsp://IP:554/profile2/media.smp` | Thermal + visible | ### Multi-Sensor and Multi-Directional Models | Model Type | Stream URL | Notes | | --- | --- | --- | | Single sensor | `rtsp://IP:554/profile2/media.smp` | Standard | | Multi-sensor channel 1 | `rtsp://IP:554/profile2/media.smp/trackID=channel1` | First sensor | | Multi-sensor channel 2 | `rtsp://IP:554/profile2/media.smp/trackID=channel2` | Second sensor | | Stitched panoramic | `rtsp://IP:554/profile2/media.smp/trackID=channel5` | Combined view | ### NVR / WAVE VMS Access For Wisenet NVRs (XRN, QRN, LRN series): | Channel | Main Stream | Sub Stream | | --- | --- | --- | | Camera 1 | `rtsp://IP:554/profile2/media.smp/trackID=channel1` | `rtsp://IP:554/profile3/media.smp/trackID=channel1` | | Camera 2 | `rtsp://IP:554/profile2/media.smp/trackID=channel2` | `rtsp://IP:554/profile3/media.smp/trackID=channel2` | | Camera N | `rtsp://IP:554/profile2/media.smp/trackID=channelN` | `rtsp://IP:554/profile3/media.smp/trackID=channelN` | ## Connecting with VisioForge SDK Use your Wisenet camera's RTSP URL with any of the three SDK approaches shown in the [Quick Start Guide](../#quick-start-code): ``` // Wisenet QNO-8080R (Q series 5MP), main stream var uri = new Uri("rtsp://192.168.1.90:554/profile2/media.smp"); var username = "admin"; var password = "YourPassword"; ``` For sub-stream access, use `/profile3/media.smp` instead of `/profile2/media.smp`. ## Snapshot and MJPEG URLs | Type | URL Pattern | Notes | | --- | --- | --- | | JPEG Snapshot | `http://IP/cgi-bin/video.cgi?msubmenu=jpg&action=view&Resolution=1920x1080&Quality=5&Channel=0` | Requires digest auth | | MJPEG Stream | `http://IP/cgi-bin/video.cgi?msubmenu=mjpeg&action=view&Channel=0&Stream=0` | Continuous MJPEG | ## Troubleshooting ### Which profile number is the main stream? Wisenet cameras typically use `profile2` as the main (highest quality) stream. This is different from most other brands. If you get unexpected results, check the profile configuration in the camera's web interface (**Setup > Video/Audio > Video Profile**). ### WiseStream III bandwidth savings WiseStream III dynamically adjusts encoding per region in the frame. The output is standard H.265 or H.264 -- no special decoder is needed. WiseStream settings can be configured in the camera's web interface. ### Camera activation New Wisenet cameras require activation (setting a password) before use. Use the Wisenet Installation Wizard utility, web browser, or Wisenet mobile app for initial setup. ## FAQ **What is the default RTSP URL for Wisenet cameras?** All Wisenet cameras use `rtsp://admin:password@CAMERA_IP:554/profile2/media.smp` for the main stream. Use `profile3` for the sub stream. **What is the difference between Wisenet X, P, Q, and L?** **X** = premium enterprise. **P** = AI-powered analytics. **Q** = mainstream business. **L** = value/entry-level. **T** = thermal. All tiers use the same RTSP URL format. **Is Wisenet the same as Samsung security cameras?** Wisenet is the current product brand from Hanwha Vision, which acquired Samsung's security division in 2015. Legacy Samsung Techwin cameras may use different URL formats. See our [Samsung/Hanwha guide](../samsung/) for older models. ## Related Resources - [All Camera Brands — RTSP URL Directory](../) - [Hanwha Vision Connection Guide](../hanwha/) — Detailed Hanwha Vision integration - [Samsung/Hanwha Legacy Guide](../samsung/) — Older Samsung Techwin models - [IP Camera Preview Tutorial](../../videocapture/video-tutorials/ip-camera-preview/) - [SDK Installation & Samples](../#get-started) ---END OF PAGE--- ## How to Connect to Wyze Camera in C# .NET - RTSP Workarounds **URL:** https://www.visioforge.com/help/docs/dotnet/camera-brands/wyze/ **Description:** Connect to Wyze cameras in C# .NET using RTSP firmware or Docker RTSP bridge. RTSP limitations, workarounds, and alternative approaches explained. **Tags:** Video Capture SDK, Media Blocks SDK, .NET, Windows, macOS, Linux, Android, iOS, Capture, Streaming, IP Camera, RTSP, ONVIF, C# # How to Connect to Wyze Camera in C# .NET [Video Capture SDK .Net](https://www.visioforge.com/video-capture-sdk-net) [Media Blocks SDK .Net](https://www.visioforge.com/media-blocks-sdk-net) ## Brand Overview **Wyze Labs** is an American consumer electronics company based in Kirkland, Washington. Known for extremely affordable smart home cameras, Wyze became one of the best-selling camera brands in North America. However, Wyze cameras are **cloud-first devices** with very limited RTSP support, making direct integration challenging. **Key facts:** - **Product lines:** Cam v3/v4 (indoor/outdoor), Cam Pan v3 (PTZ), Cam OG (compact), Doorbell, Floodlight - **Protocol support:** Wyze Cloud (primary), RTSP (limited — requires special firmware on select models) - **Default RTSP port:** 8554 (when using RTSP firmware) - **ONVIF support:** No - **Video codecs:** H.264 - **Cloud dependency:** High — most features require Wyze app and cloud Very Limited RTSP Support Wyze cameras do **not** natively support RTSP. Official RTSP firmware was released only for the **Wyze Cam v2** and original **Wyze Cam Pan**, and these firmware builds are no longer actively maintained. For newer models (v3, v4, OG, Pan v3), RTSP requires third-party solutions like custom firmware. ## RTSP Support by Model | Model | Native RTSP | RTSP Firmware | Third-Party RTSP | Notes | | --- | --- | --- | --- | --- | | Wyze Cam v2 | No | Yes (beta) | Yes | Official RTSP firmware available | | Wyze Cam Pan v1 | No | Yes (beta) | Yes | Official RTSP firmware available | | Wyze Cam v3 | No | No | Yes (docker-wyze-bridge) | Community workaround | | Wyze Cam v4 | No | No | Yes (docker-wyze-bridge) | Community workaround | | Wyze Cam Pan v3 | No | No | Yes (docker-wyze-bridge) | Community workaround | | Wyze Cam OG | No | No | Yes (docker-wyze-bridge) | Community workaround | | Wyze Doorbell v2 | No | No | Limited | May work with bridge | | Wyze Cam Floodlight v2 | No | No | Yes (docker-wyze-bridge) | Community workaround | ## Option 1: Official RTSP Firmware (Cam v2 / Pan v1 Only) Wyze released beta RTSP firmware for the Cam v2 and original Cam Pan. When flashed: ### RTSP URL Format ``` rtsp://[IP]:8554/live ``` Non-Standard Port Wyze RTSP firmware uses port **8554**, not the standard 554. ### Setup Steps 1. Download the RTSP firmware from Wyze support (search "Wyze RTSP firmware") 2. Flash the firmware to the camera via microSD card 3. In the Wyze app, go to camera settings and enable RTSP 4. Note the RTSP URL shown in the app (usually `rtsp://CAMERA_IP:8554/live`) ### Connecting with VisioForge SDK ``` // Wyze Cam v2 with RTSP firmware var uri = new Uri("rtsp://192.168.1.90:8554/live"); var username = ""; // no authentication on Wyze RTSP firmware var password = ""; ``` Use your Wyze camera's RTSP URL with any of the three SDK approaches shown in the [Quick Start Guide](../#quick-start-code). ## Option 2: Docker Wyze Bridge (All Models) For Wyze Cam v3, v4, Pan v3, OG, and other newer models, the community-developed **docker-wyze-bridge** project creates an RTSP proxy that converts Wyze cloud streams to local RTSP: ### How It Works 1. Docker Wyze Bridge authenticates with your Wyze account 2. It connects to the camera through the Wyze cloud API 3. It re-streams the video as a local RTSP stream 4. Your application connects to the bridge, not directly to the camera ### RTSP URL Format (via Bridge) ``` rtsp://[BRIDGE_IP]:8554/[CAMERA_NAME] ``` Where `CAMERA_NAME` is the name you assigned in the Wyze app (spaces replaced with dashes, lowercased). ### Connecting via Bridge with VisioForge SDK ``` // Wyze Cam v3 via docker-wyze-bridge var uri = new Uri("rtsp://192.168.1.50:8554/front-door"); var username = ""; // bridge handles auth var password = ""; ``` Bridge Limitations Docker Wyze Bridge introduces additional latency (typically 3-10 seconds) since the video passes through the Wyze cloud before reaching your local RTSP stream. It also requires your Wyze account credentials and an active internet connection. ## Troubleshooting ### No RTSP option in Wyze app The RTSP toggle only appears on Wyze Cam v2 and Pan v1 when flashed with the RTSP firmware. It is not available on newer models. For v3/v4/OG/Pan v3, use the Docker Wyze Bridge approach. ### RTSP firmware not connecting After flashing RTSP firmware on the Cam v2: 1. Wait 2-3 minutes for the camera to fully boot 2. Verify the camera is on the same network as your application 3. Try `rtsp://CAMERA_IP:8554/live` in VLC first to confirm the stream works 4. The stream has no authentication -- leave username/password empty ### High latency with Docker Wyze Bridge The bridge routes video through Wyze's cloud servers, adding latency. For low-latency requirements, Wyze cameras may not be suitable. Consider cameras with native RTSP support like [Reolink](../reolink/), [Amcrest](../amcrest/), or [TP-Link Tapo](../tp-link/). ### Stream quality Wyze cameras typically output 1080p H.264 streams. The RTSP firmware does not support changing resolution or codec. What the camera captures is what the RTSP stream provides. ## FAQ **Do Wyze cameras support RTSP natively?** No. Wyze cameras are cloud-first devices. The Wyze Cam v2 and original Cam Pan have official beta RTSP firmware, but it is no longer actively maintained. Newer models (v3, v4, OG, Pan v3) do not have RTSP firmware and require third-party bridges. **Can I use Wyze cameras without the cloud?** Very limited. Even with RTSP firmware, the initial setup requires the Wyze app and cloud account. The RTSP firmware for Cam v2/Pan v1 disables some cloud features. For newer models, the Docker Wyze Bridge still routes through the cloud. **What cameras should I use instead of Wyze for RTSP?** For affordable cameras with native RTSP support, consider [Reolink](../reolink/) (consumer), [Amcrest](../amcrest/) (consumer/SMB), [TP-Link Tapo](../tp-link/) (consumer), or [EZVIZ](../ezviz/) (smart home). All of these provide direct RTSP access without workarounds. **Do Wyze cameras support ONVIF?** No. Wyze cameras do not support ONVIF in any firmware version. ## Related Resources - [All Camera Brands — RTSP URL Directory](../) - [Reolink Connection Guide](../reolink/) — Affordable alternative with native RTSP - [Amcrest Connection Guide](../amcrest/) — Consumer cameras with full RTSP - [TP-Link Connection Guide](../tp-link/) — Budget cameras with RTSP support - [SDK Installation & Samples](../#get-started) ---END OF PAGE--- ## Zavio IP Camera RTSP URL Guide for C# .NET Integration **URL:** https://www.visioforge.com/help/docs/dotnet/camera-brands/zavio/ **Description:** Zavio bullet, dome, and PTZ camera RTSP URL patterns for C# .NET. ONVIF-compatible integration with VisioForge SDK code for all Zavio models. **Tags:** Video Capture SDK, Media Blocks SDK, .NET, Windows, macOS, Linux, Android, iOS, Capture, Streaming, IP Camera, RTSP, ONVIF, MP4, H.264, MJPEG, C# # How to Connect to Zavio IP Camera in C# .NET [Video Capture SDK .Net](https://www.visioforge.com/video-capture-sdk-net) [Media Blocks SDK .Net](https://www.visioforge.com/media-blocks-sdk-net) ## Brand Overview **Zavio** (Zavio Inc.) is a Taiwanese IP camera manufacturer headquartered in Hsinchu, Taiwan. Zavio is known for professional-grade network cameras with distinctive URL patterns that include both direct stream paths and profile-based paths. The company targets SMB and professional security markets with a range of bullet, dome, fixed, mini, and PTZ camera models. **Key facts:** - **Product lines:** B (bullet), D (dome), F (fixed/box), M (mini), P (PTZ/pan-tilt), V (vandal-proof) - **Protocol support:** RTSP, ONVIF, HTTP/CGI, MJPEG - **Default RTSP port:** 554 - **Default credentials:** admin / admin - **ONVIF support:** Yes (most models) - **Video codecs:** H.264, MPEG-4, MJPEG - **Dual URL patterns:** Some models use `/video.mp4`, others use `/video.proN` (profile-based) Profile-Based URLs Zavio cameras support profile-based URLs. Use `/video.pro1` for the primary profile and `/video.pro2` for the secondary profile. The available profiles depend on your camera's configuration. ## RTSP URL Patterns ### Standard URL Format Zavio cameras support two primary RTSP URL patterns: ``` rtsp://[USERNAME]:[PASSWORD]@[IP]:554/video.mp4 ``` ``` rtsp://[USERNAME]:[PASSWORD]@[IP]:554//video.pro1 ``` | URL Path | Description | | --- | --- | | `/video.mp4` | MP4 main stream (most common format) | | `//video.pro1` | Profile 1 / primary stream (double-slash prefix) | | `//video.pro2` | Profile 2 / sub stream (double-slash prefix) | | `//video.h264` | Direct H.264 stream (some models) | ### Camera Models | Model | Type | Main Stream URL | Notes | | --- | --- | --- | --- | | B5110 (bullet) | Bullet | `rtsp://IP//video.pro1` | Profile-based, also supports `//video.h264` | | B5210 (bullet) | Bullet | `rtsp://IP//video.pro1` | Profile-based | | B7110 (bullet) | Bullet | `rtsp://IP:554/video.mp4` | MP4 main stream | | B7210 (bullet) | Bullet | `rtsp://IP:554/video.mp4` | MP4 main stream | | D3100 (dome) | Dome | `rtsp://IP//video.pro1` | Profile-based | | D3200 (dome) | Dome | `rtsp://IP:554/video.mp4` | MP4 main stream | | D4210 (dome) | Dome | `rtsp://IP:554/video.mp4` | MP4 main stream | | D50E (dome) | Dome | `rtsp://IP:554/video.mp4` | MP4 main stream | | D510E (dome) | Dome | `rtsp://IP:554/video.mp4` | MP4 main stream | | D520E (dome) | Dome | `rtsp://IP:554/video.mp4` | MP4 main stream | | D7111 (dome) | Dome | `rtsp://IP:554//video.pro2` | Profile 2 sub stream | | D7210 (dome) | Dome | `rtsp://IP:554//video.pro2` | Profile 2 sub stream | | F1100 (fixed) | Fixed | `rtsp://IP:554/video.mp4` | MP4 main stream | | F1105 (fixed) | Fixed | `rtsp://IP:554/video.mp4` | MP4 main stream | | F1150 (fixed) | Fixed | `rtsp://IP:554/video.mp4` | MP4 main stream | | F210A (fixed) | Fixed | `rtsp://IP:554/video.mp4` | MP4 main stream | | F3100 (fixed) | Fixed | `rtsp://IP:554/video.mp4` | MP4 main stream | | F3102 (fixed) | Fixed | `rtsp://IP:554/video.mp4` | MP4 main stream | | F3110 (fixed) | Fixed | `rtsp://IP:554//video.pro2` | Profile 2 sub stream | | F3115 (fixed) | Fixed | `rtsp://IP:554/video.mp4` | MP4 main stream | | F312A (fixed) | Fixed | `rtsp://IP:554/video.mp4` | MP4 main stream | | F3201 (fixed) | Fixed | `rtsp://IP:554/video.mp4` | MP4 main stream | | F3206 (fixed) | Fixed | `rtsp://IP:554/video.mp4` | MP4 main stream | | F3210 (fixed) | Fixed | `rtsp://IP:554/video.mp4` | MP4 main stream | | F3215 (fixed) | Fixed | `rtsp://IP:554/video.mp4` | MP4 main stream | | F511E (fixed) | Fixed | `rtsp://IP:554/video.mp4` | MP4 main stream | | F520IE (fixed) | Fixed | `rtsp://IP:554/video.mp4` | MP4 main stream | | F521E (fixed) | Fixed | `rtsp://IP:554/video.mp4` | MP4 main stream | | F731E (fixed) | Fixed | `rtsp://IP:554/video.mp4` | MP4 main stream | | M510W (mini) | Mini | `rtsp://IP:554/video.mp4` | Wireless mini camera | | M511E (mini) | Mini | `rtsp://IP:554/video.mp4` | Mini camera | | P5110 (PTZ) | PTZ | `rtsp://IP:554/video.mp4` | Pan-tilt-zoom | | P5115 (PTZ) | PTZ | `rtsp://IP:554/video.mp4` | Pan-tilt-zoom | | P5210 (PTZ) | PTZ | `rtsp://IP:554/video.mp4` | Pan-tilt-zoom | ### Alternative URL Formats Some Zavio models support these alternative URLs: | URL Pattern | Notes | | --- | --- | | `rtsp://IP:554/video.mp4` | MP4 stream (recommended for most models) | | `rtsp://IP//video.pro1` | Profile 1, primary stream | | `rtsp://IP:554//video.pro2` | Profile 2, sub stream | | `rtsp://IP//video.h264` | Direct H.264 stream (B5110 and similar) | ## Connecting with VisioForge SDK Use your Zavio camera's RTSP URL with any of the three SDK approaches shown in the [Quick Start Guide](../#quick-start-code): ``` // Zavio B7110, MP4 main stream var uri = new Uri("rtsp://192.168.1.90:554/video.mp4"); var username = "admin"; var password = "admin"; ``` For profile-based cameras, use `//video.pro1` for the primary stream or `//video.pro2` for the sub stream. ## Snapshot and MJPEG URLs | Type | URL Pattern | Notes | | --- | --- | --- | | Profile Snapshot | `http://IP/cgi-bin/view/image?pro_CHANNEL` | Snapshot by profile number | | JPEG Snapshot | `http://IP/jpg/image.jpg` | Standard JPEG snapshot | | Sized JPEG | `http://IP/jpg/image.jpg?size=3` | JPEG with size parameter | | CGI JPEG | `http://IP/cgi-bin/jpg/image` | CGI-based JPEG snapshot | | MJPEG Stream | `http://IP/video.mjpg` | Continuous MJPEG stream | | MJPEG (quality/FPS) | `http://IP/video.mjpg?q=30&fps=33&id=0.5` | MJPEG with quality and FPS control | | Profile HTTP Stream | `http://IP/stream?uri=video.proN` | Profile-based HTTP stream | ## Troubleshooting ### "401 Unauthorized" error Zavio cameras ship with default credentials of `admin` / `admin`. If the camera has been configured with different credentials: 1. Access the camera at `http://CAMERA_IP` in a browser 2. Log in and check **Network > RTSP** settings 3. Verify that RTSP authentication is enabled and your credentials are correct ### Choosing between /video.mp4 and /video.proN Zavio cameras have two URL families. The correct choice depends on your model: - **Most models** (B7110, F210A, F312A, F520IE, F521E, F731E, etc.): Use `/video.mp4` - **Older or profile-based models** (B5110, B5210, D3100): Use `//video.pro1` - If one format fails, try the other ### Double-slash in profile URLs Profile-based Zavio URLs require a double-slash (`//`) before `video.proN`. This is intentional: - Correct: `rtsp://IP//video.pro1` - Incorrect: `rtsp://IP/video.pro1` If you omit the double-slash on a profile-based model, the connection may fail. ### No video with MPEG-4 codec Some older Zavio models default to MPEG-4 encoding. If you experience codec issues: - Log in to the camera web interface - Change the video codec to **H.264** under the stream configuration - Use the `/video.mp4` or `//video.pro1` URL after changing the setting ### Port 554 connection refused Verify that RTSP is enabled on the camera: - Web interface: Check **Network > RTSP** settings - Confirm port 554 is not blocked by a firewall - Default RTSP port is 554 ## FAQ **What is the default RTSP URL for Zavio cameras?** The most common URL is `rtsp://admin:admin@CAMERA_IP:554/video.mp4` for the MP4 main stream. For profile-based models, use `rtsp://admin:admin@CAMERA_IP//video.pro1` instead. **Do Zavio cameras support ONVIF?** Yes. Most Zavio models support ONVIF, which provides a standardized method for camera discovery and streaming without needing brand-specific URL patterns. **What is the difference between /video.mp4 and /video.pro1?** `/video.mp4` is a direct stream path used by most newer Zavio models. `//video.pro1` and `//video.pro2` are profile-based paths that reference stream profiles configured in the camera's web interface. Profile 1 is typically the main (high-resolution) stream, and Profile 2 is typically the sub (lower-resolution) stream. **What are the default login credentials for Zavio cameras?** The default username is `admin` and the default password is `admin`. It is strongly recommended to change these credentials after initial setup. **Can I control MJPEG quality and frame rate?** Yes. Zavio cameras support MJPEG parameters in the URL. Use `http://IP/video.mjpg?q=30&fps=33&id=0.5` to specify quality (`q`), frames per second (`fps`), and stream identifier (`id`). ## Related Resources - [All Camera Brands — RTSP URL Directory](../) - [Edimax Connection Guide](../edimax/) — Taiwanese SMB cameras - [ONVIF Capture with Postprocessing](../../mediablocks/Guides/onvif-capture-with-postprocessing/) — Zavio ONVIF capture pipeline - [IP Camera Preview Tutorial](../../videocapture/video-tutorials/ip-camera-preview/) - [SDK Installation & Samples](../#get-started) ---END OF PAGE--- ## Zmodo RTSP URL Guide — Connect IP Cameras in C# .NET **URL:** https://www.visioforge.com/help/docs/dotnet/camera-brands/zmodo/ **Description:** Zmodo ZH Wi-Fi, ZP PoE, and DVR/NVR RTSP URL patterns for C# .NET. Stream and record Zmodo cameras with VisioForge Video Capture SDK integration. **Tags:** Video Capture SDK, Media Blocks SDK, .NET, Windows, macOS, Linux, Android, iOS, Capture, Streaming, IP Camera, RTSP, ONVIF, H.264, MJPEG, C# # How to Connect to Zmodo IP Camera in C# .NET [Video Capture SDK .Net](https://www.visioforge.com/video-capture-sdk-net) [Media Blocks SDK .Net](https://www.visioforge.com/media-blocks-sdk-net) ## Brand Overview **Zmodo Technology** is a consumer security camera brand headquartered in Shenzhen, China. Zmodo is known for affordable Wi-Fi and wired IP cameras, DVR/NVR systems, and smart home security products. The brand targets the budget consumer market and is widely available through online retailers. **Key facts:** - **Product lines:** ZH-IXx (Wi-Fi cameras), ZP-IBH/IBI (PoE cameras), CM-I (legacy IP cameras), ZMD-ISV (DVR systems), Greet (smart doorbell) - **Protocol support:** RTSP, HTTP/MJPEG (legacy), Zmodo Zink (proprietary), ONVIF (limited, some ZP models) - **Default RTSP port:** 10554 (Wi-Fi cameras), 554 (standard/DVR models) - **Default credentials:** admin / admin or admin / (empty password) - **ONVIF support:** Limited (some newer ZP-series PoE models only) - **Video codecs:** H.264, MPEG-4 (legacy DVR) Zmodo Zink cameras Zmodo cameras that use the proprietary **Zink** protocol do **not** support RTSP at all. These cameras can only be accessed through the Zmodo app. Check your camera's specifications before attempting RTSP connections. ## RTSP URL Patterns Zmodo cameras use different RTSP ports and URL formats depending on the product line. ### Wi-Fi Cameras (ZH-Series) -- Port 10554 ``` rtsp://[USERNAME]:[PASSWORD]@[IP]:10554//tcp/av0_0 ``` Non-standard port 10554 Zmodo Wi-Fi cameras (ZH-series) use **port 10554**, not the standard 554. This is the most common connection issue with Zmodo cameras. | Stream | RTSP URL | Notes | | --- | --- | --- | | Main stream | `rtsp://IP:10554//tcp/av0_0` | Full resolution | | Sub stream | `rtsp://IP:10554//tcp/av0_1` | Lower resolution | ### Model-Specific URLs (Wi-Fi / PoE) | Model | RTSP URL | Type | | --- | --- | --- | | ZH-IXA15-WC | `rtsp://IP:10554//tcp/av0_0` | Wi-Fi indoor | | ZH-IXB15-WC | `rtsp://IP:10554//tcp/av0_0` | Wi-Fi indoor | | ZH-IXC15-WC | `rtsp://IP:10554//tcp/av0_0` | Wi-Fi indoor | | ZH-IXD15-WC | `rtsp://IP:10554//tcp/av0_0` | Wi-Fi indoor | | ZH-IBH13-W | `rtsp://IP:10554//tcp/av0_0` | Wi-Fi bullet | | ZP-IBH13-P | `rtsp://IP:10554//tcp/av0_0` | PoE bullet | | ZP-IBI13-W | `rtsp://IP:10554//tcp/av0_0` | PoE indoor | ### Standard H.264 Cameras -- Port 554 Some Zmodo cameras use the standard RTSP port: | Stream | RTSP URL | Notes | | --- | --- | --- | | H.264 direct | `rtsp://IP:554/h264` | Standard port | | Channel stream | `rtsp://IP:554/VideoInput/1/h264/1` | Channel-based | | Channel number | `rtsp://IP:554/[CHANNEL]` | Direct channel | ### Legacy CM-I Series | Model | RTSP URL | Alt URL | Notes | | --- | --- | --- | --- | | CM-I11123BK | `rtsp://IP:554/VideoInput/1/h264/1` | `http://IP/videostream.asf` | HTTP fallback | | CM-I12316GY | `rtsp://IP:554/VideoInput/1/h264/1` | `http://IP/videostream.asf` | HTTP fallback | ### DVR/NVR Systems | Model | RTSP URL | Notes | | --- | --- | --- | | ZMD-ISV-BFS23NM | `rtsp://IP:554/VideoInput/1/h264/1` | Channel 1 | | DVR (MPEG-4) | `rtsp://IP:554/mpeg4` | Legacy format | | DVR (auth in URL) | `rtsp://IP:554/0/USERNAME:PASSWORD/main` | Auth in path | ## Connecting with VisioForge SDK Use your Zmodo camera's RTSP URL with any of the three SDK approaches shown in the [Quick Start Guide](../#quick-start-code): ``` // Zmodo ZH-series Wi-Fi camera, main stream -- note port 10554! var uri = new Uri("rtsp://192.168.1.60:10554//tcp/av0_0"); var username = "admin"; var password = "admin"; ``` For sub-stream access, use `//tcp/av0_1` instead of `//tcp/av0_0`. ## Snapshot and MJPEG URLs | Type | URL Pattern | Notes | | --- | --- | --- | | Snapshot | `http://IP/snapshot.cgi?user=USER&pwd=PASS` | Standard models | | Snapshot (camera) | `http://IP/snapshot.cgi?camera=1` | Camera selection | | DVR Snapshot | `http://IP/cgi-bin/snapshot.cgi?loginuse=USER&loginpas=PASS` | DVR systems | | ASF Stream | `http://IP/videostream.asf?user=USER&pwd=PASS&resolution=64&rate=0` | Legacy CM-I | | MJPEG Stream | `http://IP/videostream.cgi?rate=11` | Legacy models | ## Troubleshooting ### Must use port 10554 for Wi-Fi cameras The most common Zmodo connection issue is using port 554 when the camera requires **port 10554**. All ZH-series Wi-Fi cameras and many ZP-series PoE cameras use port 10554. If your connection times out on port 554, switch to 10554. ### TCP transport in URL path The `//tcp/av0_0` path explicitly specifies TCP transport. This is built into the Zmodo URL format and is not optional. Do not remove the `//tcp/` prefix from the path. ### Zmodo app required for initial setup Some Zmodo cameras require the Zmodo mobile app for initial Wi-Fi setup and activation. RTSP access may not be available until the camera has been set up through the app at least once. Complete the initial setup before attempting RTSP connections. ### Zink protocol cameras do not support RTSP Zmodo cameras that use the proprietary **Zink** protocol are designed exclusively for the Zmodo ecosystem and do not support RTSP, ONVIF, or any third-party streaming protocol. Check the camera specifications or packaging for "Zink" branding. If your camera uses Zink, it cannot be accessed via RTSP. ### Legacy CM-I cameras use HTTP streaming Older CM-I series cameras may have limited or unreliable RTSP support. If RTSP fails on a CM-I model, fall back to the HTTP ASF or MJPEG streaming URLs: `http://IP/videostream.asf?user=USER&pwd=PASS`. ### DVR authentication format Some Zmodo DVRs embed credentials in the RTSP path rather than using standard RTSP authentication: `rtsp://IP:554/0/USERNAME:PASSWORD/main`. If standard authentication fails, try this URL format. ## FAQ **What is the default RTSP URL for Zmodo Wi-Fi cameras?** For ZH-series Wi-Fi cameras, the URL is `rtsp://admin:admin@CAMERA_IP:10554//tcp/av0_0`. Note the non-standard port 10554 and the `//tcp/` prefix in the path. **Why does my Zmodo camera use port 10554 instead of 554?** Zmodo chose port 10554 for their Wi-Fi camera line. This is a fixed port in the camera firmware. Some standard (non-Wi-Fi) Zmodo cameras and DVR systems use the standard port 554. **Do all Zmodo cameras support RTSP?** No. Zmodo cameras that use the proprietary Zink protocol do not support RTSP. These cameras are limited to the Zmodo app and cloud service. Most ZH-series, ZP-series, and CM-I series cameras do support RTSP. **Does Zmodo support ONVIF?** ONVIF support on Zmodo cameras is limited. Some newer ZP-series PoE models include ONVIF support, but most consumer Wi-Fi models (ZH-series) do not. Check your specific model's specifications for ONVIF compatibility. **What is the difference between av0\_0 and av0\_1?** In the Zmodo RTSP URL, `av0_0` is the main (highest quality) stream and `av0_1` is the sub (lower resolution) stream. Use `av0_1` when you need lower bandwidth consumption for remote viewing. ## Related Resources - [All Camera Brands — RTSP URL Directory](../) - [Foscam Connection Guide](../foscam/) — Budget consumer IP cameras - [IP Camera Preview Tutorial](../../videocapture/video-tutorials/ip-camera-preview/) - [SDK Installation & Samples](../#get-started) ---END OF PAGE--- ## VisioForge .NET SDKs — Changelog and Release Notes **URL:** https://www.visioforge.com/help/docs/dotnet/changelog/ **Description:** Version history for Video Capture, Media Player, Video Edit, and Media Blocks SDKs. New features, bug fixes, API changes, and platform updates. **Tags:** Video Capture SDK, Media Player SDK, Media Blocks SDK, Video Edit SDK, .NET, DirectShow, Windows, Capture, Playback, Streaming, Editing **API:** VideoCaptureCore, VideoCaptureCoreX, VideoView, MediaPlayerCoreX, DeviceEnumerator # Changelog Changes and updates for all .Net SDKs. ## 2026.9.1 - [Video Capture SDK .Net] **Removed: the RTSP X network streaming output.** `NetworkStreamingFormat.RTSP_X` and the `RTSPXOutput` settings class are gone from `VideoCaptureCore`, and the `VisioForge.DotNet.Core.Redist.RTSPX.x64` package is no longer published - it carried its own GStreamer runtime that had not been refreshed since 2024 and loaded alongside the current one. Use `VideoCaptureCoreX` with `RTSPServerOutput`/`RTSPServerSettings`, which serves RTSP from the maintained runtime and needs no extra package. `NetworkStreamingFormat.RTSP_H264_AAC_SW` remains available on `VideoCaptureCore` (#1262). - [Media Blocks SDK .Net] **Fixed: on Windows, stopping an SRT pipeline never returned when the receiving peer had gone away.** `StopAsync` blocked indefinitely on `SRTSinkBlock` and `SRTMPEGTSSinkBlock`, and the pipeline could never be disposed - the bundled SRT plugin kept closing and reopening the connection, and End-Of-Stream could not be delivered while the sink's streaming thread was inside that loop. The Windows redistributable now carries the corrected SRT plugin macOS has shipped since 2026.8.5, so a stop against an unreachable or flapping peer completes in about a second (#1190). - [Core] **The RAV1E AV1 encoder now encodes across CPU cores.** `rav1enc` splits work by tiles and the SDK never set that property, so it ran the whole frame as a single tile and encoded at the same speed on 4 cores as on 32. The new `RAV1EEncoderSettings.Tiles` defaults to 16: measured on 720p30, 8 seconds of content now takes about 29 seconds instead of 84, for roughly 1% more bitrate at the same `Quantizer`. Set `Tiles = 0` for the previous single-tile output (#1345). - [Media Blocks SDK .Net] **Fixed: a Basler camera was opened by its position in the device list, not by the camera you named.** `BaslerCameraInfo` read only `DeviceIndex`, so an instance built with `new BaslerCameraInfo(name)` - which leaves that index at 0 - read its sensor size from, and streamed, the first Basler device on the machine whatever the name said. The camera is now found by its serial number, full name, user-defined name or name, and `pylonsrc` is pointed at it by identity rather than by index; a named camera that is not present is now reported and the capture fails to start, instead of quietly streaming another one (#1344). ## 2026.8.31 - [Media Blocks SDK .Net] **Fixed: a video mixer could save a source that would not load back, and a restored Basler source could report zero frame rate.** A mixer source whose camera name had been cleared was written into the document without it, the snapshot reported success, and loading that document failed - it is refused at save time now, naming the block. And a Basler camera whose frame rate could not be read when the document was saved kept a zero frame rate on every later load, which reached the recording's frame info; it is re-read now, as the sensor size already was. - [Media Blocks SDK .Net] **Fixed: a Spinnaker source could open a different camera than the one it was told to, without saying so.** The camera was addressed by its position in the enumerated list rather than by its own index, so one camera failing to initialize - held by another process, for instance - shifted every camera after it, and the source silently opened its neighbour. A name matching no camera at all, or matching two identical bodies (the name is the model name, which they share), was equally silent. The index is now the camera's own, `SpinnakerCameraInfo` carries the serial number, and all three cases are reported. two handles leaked during enumeration are released; one camera failing to answer no longer hides every other camera on the rig, and no longer leaves a truncated list cached; a camera whose model name cannot be read is listed under its serial number instead of under a name every unreadable camera shares; and a camera index the element cannot address fails the source instead of quietly opening a different camera - the element accepts 0-7, so on a rig with nine or more cameras the ninth and beyond now report an error at build time rather than streaming a neighbour. - [X-engines] **Fixed: an SDK error killed the process when the application had not subscribed `OnError`.** `VideoEditCoreX` reported such an error by logging it, and the log is what raises the error event, so every error re-entered the reporting path and recursed until the stack overflowed - the process died with no exception and no message. A render that could not build its encoder was the common way in. The error is now reported once, and shown on the video view exactly as the other engines do. `MediaBlocksPipeline` had the same loop on its two "VisioForge\_MFP.dll not found" messages, which recursed whenever a debugger was attached (#1173). - [Media Blocks SDK .Net] **Fixed: a virtual camera sink with an input that was created but never connected wedged the pipeline.** `VirtualCameraSinkBlock` built the chain for a pad that exists rather than for one that is connected, so an unconnected input left a branch with nothing feeding it - a branch that can neither preroll nor reach End-Of-Stream, leaving either `StartAsync` or `StopAsync` never returning. Two connected inputs of the same type are now reported as an error too - only one of them was ever linked (#1288). - [Media Blocks SDK .Net] **`NDISinkBlock.IsAvailable()` now reports `false` when the NDI runtime is missing.** It answered from the GStreamer element alone, so on a machine carrying the plugin but no NDI runtime it reported the sink as available and the pipeline then failed to start (#1288). - [Media Blocks SDK .Net] **Fixed: stopping a pipeline whose `NDISinkBlock` had only a video input never returned.** `StopAsync` blocked forever and the pipeline could never be disposed; adding an audio input was the only workaround. The sink built its audio chain even when no audio was connected, and the unfed combiner pad stalled the End-Of-Stream a graceful stop sends. A video-only NDI sink now stops normally. An NDI sink with no video input, which cannot produce an NDI stream at all, is now reported as a build error instead of hanging the same way (#1288). - [Media Blocks SDK .Net] **Fixed: nothing decoded when a decoder was connected to `UniversalDemuxBlock`.** The demuxer hands out encoded data, so a decoder behind it is the normal way to use it - and that graph delivered no frames at all, while the pipeline reported a successful start and put nothing on the bus. A stream the demuxer was told not to render was sent to a plain null sink, which stalled the demuxer until the pipeline reached playing, and the pipeline could not reach playing because the decoder branch was starved of the frames it needed. This affects `UniversalDemuxBlock` and `UniversalAutoDemuxerBlock` with `renderVideo` or `renderAudio` turned off, and every decoder behind them, `UniversalDecoderBlock`, `DecodeBinBlock` and the codec-specific decoder blocks alike. A demuxer also no longer throws when the file turns out to hold more streams of a type than its media info reported, and `UniversalDemuxBlock` can now output a metadata stream (#836). - [Media Blocks SDK .Net] **`UniversalDemuxSettings.Type` can now be set.** It was declared without a setter, so that settings class always meant automatic container detection whatever was assigned to it; the per-format settings classes were the only way to pick a specific demuxer. The default is unchanged (#836). - [Media Blocks SDK .Net] **Pipeline documents now write enum settings by name instead of by number.** Many of the SDK's enums declare their members per platform, so the same ordinal meant a different member elsewhere - `1` was `WASAPI` on Windows and `Decklink` on macOS - and a document moved between platforms silently restored the wrong device API, encoder or format. A saved pipeline now reads `"api": "WASAPI"`. Documents written before this still load; a document written by this build cannot be opened by an earlier one (#1322). - [Media Blocks SDK .Net] **A pipeline document now restores the audio device a block was using.** `AudioRendererBlock`, `SystemAudioSourceBlock` and the WASAPI, WASAPI2, DirectSound, loopback and PulseAudio audio sources hold an `AudioOutputDeviceInfo` or `AudioCaptureDeviceInfo`, and neither could be written to a document and read back - so a saved pipeline came back either refusing to load or holding no device at all. A document now stores what identifies the device (its name, path, API and, on macOS, the stable CoreAudio `unique-id`), and materialization matches that against the devices the machine actually has, handing the block a live device again. This also fixes a saved configuration opening the wrong speaker or microphone: the numeric CoreAudio id and the WASAPI path are both reassigned between runs, and the match now re-reads the current ones. When the named device is gone, the pipeline still builds on a system device of the same API and materialization reports it as the new `MBS063` warning naming both devices. `AlliedVisionSourceSettings` restores from the camera's identity the same way, without opening the camera (#1322). - [Media Blocks SDK .Net] **Fixed: a pipeline document silently lost mandatory block settings and restored a block wired to the wrong thing.** A setting exposed as a read-only property - the bridge `Channel` above all, but also `CustomMediaBlockSettings.ElementName`, `GLOverlaySettings.Filename`, `GLEquirectangularViewSettings.VideoWidth`/`VideoHeight`, `AlliedVisionSourceSettings.Camera` and the GenICam region, frame rate and pixel format - was never written into a saved document, and came back as `null` or `0` with validation, deserialization and materialization all reporting success. Two app bridges saved on different channels reloaded onto the same one. Those settings now round-trip, a document missing one is reported as `MBS043` naming the property instead of restoring a mis-wired block, and `MediaBlockDescriptor.Properties` lists them (with the new `IsRequired` and `IsReadOnly` flags) so an editor can author them. Eight settings types could not be restored at all, because a constructor parameter matched no property and the serializer refuses to bind such a constructor - every document holding a `BridgeAudioSource`, `HTTPSource`, `AudioRenderer`, `OpenCVTemplateMatch`, `LiveSourceSwitch`, `LiveSourceSwitchDynamic`, `AlliedVisionSource` or `VideoAspectRatioCrop` block failed to load. All of them now restore. The parameters are renamed to match their properties: `BridgeAudioSourceSettings(channel, info)`, `HTTPSourceSettings(location, isLive)`, `AudioRendererSettings(info)`, `CVTemplateMatchSettings(templateImage)` and `LiveSourceSwitchSettings(videoWidth, videoHeight, videoFrameRate)`. Positional calls are unaffected; code passing these by name must be updated (#1322). - [Media Blocks SDK .Net] **Fixed: a pipeline document holding a `SpinnakerSource` block could not be loaded, and a mixer holding a Spinnaker source could not be saved.** The constructor's first parameter matched no property, which the serializer refuses outright, and the region, frame rate and pixel format were never written into the document. All four settings now round-trip. The parameter is renamed to match its property: `SpinnakerSourceSettings(name, region, frameRate, pixelFormat)`. Positional calls are unaffected; code passing the first argument by name must be updated (#1338). - [Media Blocks SDK .Net] **Fixed: a pipeline document holding a `GenICamSource` or `BaslerSource` block came back without its camera.** `GenICamSourceSettings` declares two constructors and no parameterless one, which the serializer refuses outright, so no document holding the block loaded at all - while its region, frame rate and pixel format were written into the document regardless. `BaslerSourceSettings.Camera` was never written, so the block restored with no camera while saving, validation and loading all reported success. Both now round-trip from the identity the document carries, and a Basler document that carries the sensor size no longer opens the camera to re-read it. The first parameter of both `GenICamSourceSettings` constructors is renamed `deviceName` -> `name` to match its property; positional calls are unaffected. A `SpinnakerSource` or `GenICamSource` document carrying no camera name, or an empty one, is now reported as `MBS043` instead of silently opening the first camera on the machine (#1338). - [Media Blocks SDK .Net] **Fixed: a video mixer holding an Allied Vision or GenICam camera could not be saved.** The mixer wrote a source only when it could read it back, and that check looked at public constructors alone - so it refused a settings class whose deserialization constructor is private, with an `MBS060`, even though loading a document restores it correctly. Both cameras now save and reload as mixer sources. A mixer source missing a mandatory setting - the region above all - is reported now too, where it used to load as a camera with no region and then fail when the pipeline started (#1338). - [Core] **Fixed: a capture device whose sample rate range lies outside 22050-96000 Hz disappeared from the device's format list.** A narrow-band device publishing, say, `rate=(int)[ 8000, 16000 ]` matched none of the rates the enumeration samples a range at, so it produced no entries at all. Its own bounds are published instead (#1317). - [Core] **Fixed: a capture device publishing its sample rate or channel count as a list disappeared from the device's format list entirely.** `AudioCaptureDeviceInfo.Formats` read only the single-value and range forms, so a caps structure written as `rate=(int){ 44100, 48000 }` produced no entries at all rather than one per combination (#1317). - [Core] **Fixed: audio frames delivered as 24-bit-in-32 or as 20-/18-bit reported the wrong bytes per sample.** `AudioFrame.Info.BPS` carried the number of significant bits rather than the container width, so a consumer of `BufferSinkBlock` or `AudioSampleGrabberBlock` read 3 bytes per sample where the buffer holds 4 (`S24_32*`) - a 25% undercount that garbles the audio - and 2 bytes where 20- and 18-bit formats hold 3. `S24BE` reported 0. Unchanged for 8-, 16-, 32- and 64-bit formats, which is everything the SDK produces by default (#1317). - [Core] **Fixed: 24-bit-in-32 audio formats were dropped from capture-device format lists and could not be requested.** GStreamer writes these as `S24_32LE`/`S24_32BE`/`U24_32LE`/`U24_32BE` while the `AudioFormatX` enum spells them without the underscore, and the SDK converted between the two by name. A device offering one of them lost it from `AudioCaptureDeviceInfo.Formats`, and asking for it anywhere a format is applied - audio capture, the audio mixer, WAV output, a push source, the iOS/Mac audio renderer - produced a format name no element accepts. Both directions are now translated (#1317). - [Core] **On macOS and Mac Catalyst the default audio capture format now follows the device's own sample rate.** `AudioCaptureDeviceInfo.GetDefaultFormat()` preferred 44100 Hz and, when a device published no 16-bit stereo combination at all, fell back to whichever entry sorted first alphabetically. Since the capture format is applied to the capture device itself, that could ask CoreAudio to run an input at a rate it does not use - CoreAudio cannot resample an input, so the hardware's nominal rate was changed instead. The rate now comes from the format the device reports as its own; 16-bit stereo is still preferred for the sample format and channel count, which CoreAudio does convert. Devices publishing 16-bit stereo at 44100 or 48000 Hz - the common case - keep the format they had (#1317). - [Media Blocks SDK .Net] **`IsAvailable()` on the video and audio encoders and decoders no longer reports a codec that cannot actually be created.** It answered from the GStreamer registry alone, and the registry caches a plugin's element list while the elements a plugin registers are decided when it loads — the Media Foundation plugin names its encoders by hardware-MFT enumeration index, and the NVIDIA, Intel and Direct3D plugins register their elements only for the hardware present at scan time. After a driver, GPU or Windows-codec change the registry could still list an element the plugin no longer provides; `IsAvailable()` returned `true` and the pipeline then failed to build with an unrelated-looking error. The check now also loads the element's plugin and asks it again, which refreshes the registry's list for that plugin. The first `IsAvailable()` call for a given backend is correspondingly slower, since it now loads that backend's plugin — around 0.3 s for NVIDIA and 0.7 s for Media Foundation on the measured host, once per plugin per process — and that plugin's vendor libraries are loaded into the process even if the pipeline ends up encoding in software (#1175). - [Media Blocks SDK .Net] **`MFH264EncoderSettings.GetDeviceIDs()` and `MFHEVCEncoderSettings.GetDeviceIDs()` no longer list a Media Foundation device that cannot be created**, and they identify each device from the loaded MFT rather than from the cached registry metadata, which could name a different encoder. Two consequences on a host where such a stale entry existed: a device that used to appear and then fail is now absent, and `DeviceID` — a position in this list — can shift, so an application that persisted a `DeviceID` should re-resolve it against `GetDeviceIDs()` rather than assume last run's number (#1175). - [Media Blocks SDK .Net] **Windows: using a Media Foundation encoder no longer permanently breaks every later NVIDIA NVENC encode in the process.** GStreamer eagerly activated NVIDIA's Media Foundation H.264 and HEVC MFTs while registering the plugin, even when the pipeline only requested the Microsoft AAC encoder. If the public NVENC API had already been initialized, the next `nvh264enc`/`nvh265enc` session failed with `NV_ENC_ERR_INVALID_VERSION` (`0xf`) and no later session could recover. The bundled Media Foundation plugin now excludes NVIDIA's video MFTs before `IMFActivate::ActivateObject`. Microsoft, Intel, AMD, software Media Foundation video encoders, all Media Foundation audio codecs, video capture (`mfvideosrc`) and device enumeration remain available. **What changes on an NVIDIA machine:** NVIDIA's Media Foundation *video* encoders are no longer registered by the plugin. `MFH264EncoderSettings` and `MFHEVCEncoderSettings` keep selecting the same encoder and the same `DeviceID` numbering as before — they already excluded NVIDIA entries when enumerating — **with one exception: a host whose only Media Foundation HEVC encoder was NVIDIA's.** There the settings class enumerated nothing and fell back to the bare `mfh265enc` element, which used to be the NVIDIA one; nothing registers that name now, so `HEVCEncoderBlock.IsAvailable(new MFHEVCEncoderSettings())` returns `false` and `HEVCEncoderType.MF_HEVC` is unavailable. Install the Microsoft HEVC Video Extensions, or encode HEVC through `NVENCHEVCEncoderSettings`. H.264 is not affected in the same way: Windows always registers the Microsoft software H.264 MFT. What changes is the plain GStreamer element: `mfh264enc` and `mfh265enc` are now backed by the next non-NVIDIA MFT on the host — Intel or AMD hardware where present, otherwise the Microsoft software H.264 MFT and the HEVC Video Extension — so a hand-written pipeline string naming them gets a different encoder. Use `NVENCH264EncoderSettings`, `NVENCHEVCEncoderSettings` or `NVENCAV1EncoderSettings` for NVIDIA hardware encoding; they are unaffected and are the faster path in any case (#842). - [Media Blocks SDK .Net] **`MFAACEncoderSettings` is no longer deprecated.** It was marked obsolete because using it broke NVENC later in the same process; that was never the AAC encoder's doing — requesting it loads the Media Foundation plugin, whose video-MFT registration was the real cause, and that is fixed above. Code using it no longer produces a compiler warning. `AVENCAACEncoderSettings` stays the Windows default for `MP4Output`; prefer `MFAACEncoderSettings` for `VideoEditCoreX` render paths, where libav AAC does not round-trip the GstPreset (#842). - [Media Blocks SDK .Net] **Fixed: `AudioRendererBlock.Mute` could not turn audio back on on iOS and Mac Catalyst.** Setting it to `false` wrote volume 0 again, leaving the renderer silent and reporting itself muted. Muting now preserves the configured volume, and unmuting restores audible output (#1318). - [Core] **Fixed: HTTPS and RTSPS connections on Mac Catalyst could not initialize TLS.** The GStreamer runtime was searched for in a `lib` subfolder that Mac Catalyst app bundles do not contain, so its OpenSSL TLS backend and certificate database were never loaded. The SDK now finds the bundled runtime and verifies TLS peers as on macOS (#1327). - [Core] **On macOS and Mac Catalyst an application no longer re-scans the whole GStreamer plugin set on every launch.** The scan is now cached in the application's own Caches directory (`Library/Caches/VisioForge//gstreamer/`, inside the sandbox container for a sandboxed app) and paid once - on the first start after installing or updating the application, and after that only for plugins whose files changed. Nothing needs to be deployed or configured; deleting the cache folder costs one more scan (#1299). - [Core] **On macOS and Mac Catalyst `GST_PLUGIN_PATH` is no longer set in the .NET environment.** It is published to the process environment GStreamer itself reads, which the .NET one on Unix never was - so `Environment.GetEnvironmentVariable("GST_PLUGIN_PATH")` now returns nothing on these platforms, and a child process started by the application no longer inherits the application's own plugin directory. Pass it explicitly to a child that needs it (#1299). ## 2026.8.30 - [Media Blocks SDK .Net] **Fixed: a chroma key saved into a pipeline document lost its source video resolution, and restored as a block that never worked.** `ChromaKeySettingsX.SourceVideoResolution` is the one setting the keying filter cannot do without - it builds its video format from it - and it was read-only, so it was never written into a saved document and every restored chroma key came back with no resolution at all. Materialization reported success, and the failure showed up only when the pipeline was started: the block could not be built, and a block that cannot be built stops the whole pipeline from starting, with nothing in the diagnostics to say why. The property is now settable and round-trips, and `ChromaKeyBlock` refuses settings whose resolution is missing or has a zero extent, so such a document is reported as failing with `MBS040` naming the property instead of restoring a dead block (#1319). - [Media Blocks SDK .Net] **The OpenCV blocks now work on macOS.** All sixteen blocks in the `VisioForge.Core.MediaBlocks.OpenCV` namespace, `VideoStabilizationBlock` among them, were documented as cross-platform but their GStreamer plugin shipped for Windows only, so on macOS every one of them reported `IsAvailable()` as `false`. Add the new [VisioForge.CrossPlatform.OpenCV.macOS](https://www.nuget.org/packages/VisioForge.CrossPlatform.OpenCV.macOS) redistributable alongside `VisioForge.CrossPlatform.Core.macOS` and they work as they do on Windows. The package is one universal (x64 + ARM64) plugin with OpenCV 4.14.0 linked into it, so there are no separate OpenCV libraries to deploy. Linux, iOS, Mac Catalyst, Android and Windows arm64 still have no OpenCV redistributable and the blocks stay unavailable there (#1283). - [Media Blocks SDK .Net] **Fixed: on macOS `CVFaceDetectBlock`, `CVFaceBlurBlock` and `CVHandDetectBlock` never found their default Haar cascade files.** The default cascade names were resolved against an `x64` or `x86` subfolder of the application directory and nowhere else - a layout only the Windows redistributables create. Detection silently produced no results, with the cause visible only in the GStreamer log. The cascades are now looked up in the redistributable's own layout on every platform. Setting a cascade property to a full path is unaffected (#1283). - [Core] **Fixed: reading or writing a GStreamer property whose type is `glong` or `gulong` threw `EntryPointNotFoundException` on Windows.** Those two value types were read and written through four native functions that no shipped GStreamer build has ever exported, so every access to such a property failed on x86, x64 and ARM64 alike. They now go through the standard GLib accessors, and a value too large for the 32-bit Windows `glong` is reported as an overflow rather than stored as a different number (#1160). - [Demos] **Fixed: restarting the Bridge Demo no longer leaves an MP4 recorder running in the background.** Starting another recording now finalizes and releases the preceding recorder first, whether Start is pressed again directly or after Stop. The output file is no longer held open by an abandoned muxer, and completed recordings retain their MP4 index. - [Demos] **Fixed: several demos started an operation and moved on without waiting for it.** The Bridge, Bridge Source Switch, Audio Extractor and all three PreEventRecording demos (WPF and both Avalonia heads) destroyed the SDK, or let the process go, while engine teardown was still running - a recording being closed with the window could be left unfinalized, and the Media Blocks Avalonia one disposed its pipeline without stopping it first. Those window-close handlers now cancel the close, finish stopping and disposing, and then close for real; a second close request during teardown no longer slips past. The RTSP MultiViewSync demo's Stop button returned before the three pipelines had stopped, and the Video Edit Main Demo's Join button reported completion immediately; both now wait. The macOS Simple Media Player closed its window without blocking the main thread on player teardown, and the two Avalonia PreEventRecording motion handlers no longer block an SDK callback thread on the UI thread. - [Media Blocks SDK .Net] **`OSXAudioSourceBlock` has been removed - use `SystemAudioSourceBlock` with `OSXAudioSourceSettings`.** It was a leftover second macOS audio capture block: it built the same `osxaudiosrc`, but ignored the requested audio format and offered no volume or mute control, and nothing in the SDK, the demos or the documentation samples that actually ran ever created it - `OSXAudioSourceSettings.CreateBlock()`, `DeviceEnumerator` and every macOS demo have built a `SystemAudioSourceBlock` for years. Replace `new OSXAudioSourceBlock(settings)` with `new SystemAudioSourceBlock(settings)`; the settings class, the device selection and the captured audio are unchanged. A pipeline JSON document saved with that block in it names a block type the SDK no longer has, so it is reported as unknown at validation and restores without its audio source - rebuild and re-save such a document (#1290). - [Media Blocks SDK .Net] **Fixed: on macOS and Mac Catalyst the audio format requested through `OSXAudioSourceSettings.Format` was silently ignored.** The capture device negotiated whatever it preferred - typically 32-bit float - so an application asking for 16-bit stereo got something else without any warning. The requested sample format, sample rate and channel count now reach `osxaudiosrc`. `Format` no longer defaults to a hardcoded 16-bit 44100 Hz stereo, because that value is now enforced and no longer a placeholder: leave it null to let the device choose, or take a real one from the enumeration with `AudioCaptureDeviceInfo.GetDefaultFormat()`, which is what `CreateSourceSettings()` already does (#1290). - [Media Blocks SDK .Net] **The Metal video processing blocks now work on an iOS device.** `MetalVideoCompositorBlock`, `MetalConvertScaleBlock`, `MetalTransformBlock`, `MetalDeinterlaceBlock`, `MetalOverlayBlock` and `MetalVideoFilterBlock` were documented as available on iOS and compiled there, but the Metal plugin behind them was never loaded, so every one of them reported `IsAvailable()` as `false` and could not be built into a pipeline. The plugin is now part of the iOS runtime, and it is the same current build the macOS and Mac Catalyst packages carry - so `MetalVideoCompositorBlock` also composes onto an output of any size, rather than failing negotiation whenever something downstream asked for a size other than the size of its inputs. Two limits remain, both unchanged: the Metal renderer (`MetalVideoRendererSettings`) is macOS only, and the blocks are unavailable in the iOS Simulator, where `IsAvailable()` still returns `false` (#1296). - [Media Blocks SDK .Net] **Fixed: a pipeline document naming `VideoMixerSource` passed validation and then failed to build, and the mixer's sources were never saved in the first place.** `MediaBlocksPipelineValidator` reported the block as constructible while `MediaBlocksPipelineMaterializer` threw `MBS040: ... The method or operation is not implemented` and discarded the whole pipeline, because `VideoMixerSourceSettings.CreateBlock()` was not implemented. It now builds the block, so a document restores it. The settings also **persist their inputs**: the sources, their rectangles and their chroma keys were held in a private list that was silently left out of every saved document and every `ToDocument()` snapshot, so a two-camera mixer came back as an empty canvas. They are now the public `VideoMixerSourceSettings.Sources` list of `VideoMixerSourceStream`, written and read with the source's own settings class named in the JSON; a source class this build does not contain - several are platform-specific - is reported rather than restored as an empty input. Capturing a live pipeline now also warns (`MBS060`) about any block the document cannot rebuild, instead of reporting the snapshot complete. **API change:** `VideoMixerSourceBlock` now derives from `SuperMediaBlock` rather than `SourceMediaBlock`, which is what lets a block built from `VideoMixerSourceSettings.CreateBlock()` wire itself up when you connect only its output - previously that produced a pipeline that stalled at start with no error. It keeps behaving as a source; the only members it no longer inherits are `Stop()`, which did nothing, and `IsSubtitlesAvailable()`, which it still provides. **Renamed arguments:** `VideoMixerSourceSettings.Add(source, left, top, width, height)` never took a width and a height - the last two arguments went straight into `Rect(left, top, right, bottom)`, so `Add(src, 960, 0, 960, 1080)` produced a zero-width input, not a 960-wide one. The parameters are now named `right` and `bottom`. Behaviour is unchanged, so positional calls keep working; a call that passed the arguments **by name** (`width:` / `height:`) no longer compiles, and it was producing the rectangle the new names describe all along (#1230). - [Core] **The Windows GStreamer plugin cache is now kept per SDK version, and a rebuilt plugin of the same size is no longer ignored.** On Windows the SDK mirrors an application's `x64` / `x86` native folder into a shared folder under `%PUBLIC%\.gstreamer` and loads from there, so that every VisioForge application on the machine shares one warm GStreamer plugin registry instead of each paying a full cold scan. That folder was shared by every SDK version ever run on the machine and was only ever added to, so a native library a newer release no longer ships stayed on the load path indefinitely - an application could keep working on a machine that had run an older release and fail on a clean one. It is now `%PUBLIC%\.gstreamer\-\`, keyed to the SDK version together with a stamp of the core and Libav redistributables the application actually deployed, so deployments on different natives no longer overwrite each other's files on every start; a cache the SDK created and nothing has started for 30 days is removed, while a folder left by an older SDK that still uses the previous shared layout is left alone. Whether a cached file is up to date is decided by its size **and** its timestamp, rather than by size alone - a rebuilt library of the same size used to be kept forever. The first start after an SDK upgrade repopulates the cache and rebuilds the registry once. `VisioForgeX.CacheFolder` still overrides the location: point it at the application's own native folder before `InitSDK` to skip the shared cache entirely and load exactly what the application deployed (#1289). - [Core] **Fixed: an ARM64 Windows application could not find the SDK's native libraries.** The runtime looked for them in an `x64` subfolder whatever the process architecture, while the ARM64 redistributable packages deploy to `arm64`, so initialization failed with "GStreamer libraries not found. Check the deployment and add required NuGet packages." x86, x64 and ARM64 processes now each use their own folder (#1289). - [Media Blocks SDK .Net] **Fixed: `AOMAV1EncoderSettings` can now create and configure the AOM AV1 encoder on macOS, Mac Catalyst, and Linux.** The settings are applied for both Media Blocks pipelines and Video Capture / Video Edit output; the required AOM runtime is bundled for the Apple packages. Two defaults changed so that rate control actually works: **`MaxQuantizer` now defaults to 63** - at its previous 0 the quantizer was pinned, the encoder ignored `TargetBitrate`, the buffer sizes and the overshoot/undershoot values, and a 720p clip asked for 1500 kbits/sec was written at about 66 Mbits/sec - and **`TargetBitrate` now defaults to 0**, meaning the encoder scales its own default to the frame size (256 kbits/sec at 320x240, about 6900 kbits/sec at 1920x1080) instead of applying 256 kbits/sec at every resolution. Any value the encoder would refuse - `CPUUsed` outside 0-9, `DropFrame`, `OvershootPCT` or `UndershootPCT` above 100, `TileColumns` or `TileRows` above 6, a resize or super-resolution denominator outside 8-16, a super-resolution threshold outside 1-63, a `TargetBitrate` above 2000000 kbits/sec, a quantizer above 63 or a minimum above the maximum - is now **left unapplied and reported as a warning** rather than dropped in silence or failing the whole pipeline inside the encoder; a refused quantizer pair encodes at 0-63 rather than at the element's own 0, which would have disabled rate control. **`Threads` is now always resolved by the SDK**: 0 and any value above the 64 threads the encoder accepts both become this machine's processor count, clamped to 1-64, because the encoder's own automatic count is not clamped and fails to initialize on a host wider than that. `TileColumns` and `TileRows` are log2 counts (0 = one, 1 = two, 2 = four), as the encoder takes them. AOM is intended for quality-focused offline encoding; prefer SVT-AV1 for general software encoding because it is substantially faster. On Windows, iOS and Android the `av1enc` element is still not part of the runtime, so `AOMAV1EncoderSettings.IsAvailable()` stays `false` there (#1286). - [Core] **The OpenCV redistributable packages are rebuilt on OpenCV 4.14.0 and are much smaller.** `VisioForge.CrossPlatform.OpenCV.Windows.x64` and `.x86` shipped OpenCV 4.7.0 from February 2023 together with 42 OpenCV libraries the GStreamer OpenCV elements never load. They now carry OpenCV 4.14.0 and only the libraries those elements need, so the x86 package drops from 94 MB to 44 MB and the x64 package from 113 MB to 64 MB. Part of what the x86 package shed is a 26 MB 64-bit `opencv_videoio_ffmpeg470_64.dll` that no 32-bit application could ever load. All 23 OpenCV elements are unchanged. **The plugin now requires GStreamer 1.28 or newer** - the version it is built against, and the version the matching `VisioForge.CrossPlatform.Core.Windows.*` packages ship; it previously declared 1.22. An application that puts an older GStreamer ahead of the SDK's own on `PATH` will find the plugin refused, and GStreamer reports that as a single warning, so the OpenCV elements would simply be missing (#1276). - [Media Blocks SDK .Net] **Fixed: `AV1EncoderBlock` ignored every SVT-AV1 setting, and several of them did nothing on the other engines too.** In Media Blocks the encoder was built and then never configured, so `Preset`, `TargetBitrate`, `MaxBitrate`, `CQP`, `CRF` and `IntraPeriodLength` were all dropped and the encoder ran at its own defaults (preset 10, CRF 35). On every engine, `Threads`, `Tier`, `TileColumns` and `TileRows` were written to element properties `svtav1enc` does not have, which GStreamer answers with a warning and no effect; they now reach the encoder the way SVT-AV1 takes them, and **`TileColumns` and `TileRows` are log2 counts** (0 = one, 1 = two, 2 = four) - up to 4 for columns, up to 6 for rows, and at most 128 tiles between them. Values above that are clamped rather than passed through: SVT-AV1 rejects such a configuration outright ("MaxTiles is 128 and MaxTileCols is 16") and the encoder can take the process down with it. Every other setting the encoder would refuse - a `Preset` outside 0-13, a bitrate outside 1-100000 kbits/sec, a `CQP` or `CRF` outside 1-63, an `IntraPeriodLength` below -2 - is now **left unapplied and reported as a warning** instead of being dropped in silence, and so is any setting a different rate-control mode makes irrelevant. The encoder keeps its own working default in each case rather than being handed a value it cannot use. `CQP` never took effect either, on any engine: the encoder picks its rate-control mode in the order bitrate, CRF, CQP, and CRF has a non-zero default, so a CQP-only configuration encoded in CRF mode - setting `CQP` now disables CRF as it always claimed to. **Behavior change:** an application that set SVT-AV1 properties through Media Blocks and tuned around them being ignored will now get the encoder it asked for. (#835) - [Media Blocks SDK .Net] **Fixed: the default SVT-AV1 configuration produced a stream with no keyframes after the first.** `IntraPeriodLength` defaulted to `-1`, which this encoder reads as *insert no further intra frames* rather than *automatic* - so a recording was hard to seek, and a client joining an SRT or RIST stream mid-flight never received a keyframe and never rendered. The default is now `-2`, the encoder's own automatic setting; pass `-1` explicitly if a single-keyframe stream is what you want. This affected the VideoCaptureCoreX / VideoEditCoreX render path, where the value was applied; Media Blocks left the encoder at its own `-2` default because it applied nothing at all (#835). - [Media Blocks SDK .Net] **The SVT-AV1 encoder (`SVTAV1EncoderSettings`) is now available on macOS and Mac Catalyst.** The `svtav1enc` element and its library ship in the additional runtime package - `VisioForge.CrossPlatform.Core.macOS.Adds` and `VisioForge.CrossPlatform.Core.macCatalyst.Adds` - the same way `gstsvtav1.dll` has always shipped in the Windows `.Adds` packages. Reference the `.Adds` package for your platform beside the core one - `VisioForge.CrossPlatform.Core.macOS.Adds` 2026.8.25 or newer, `VisioForge.CrossPlatform.Core.macCatalyst.Adds` 2026.8.26 or newer; without it `AV1EncoderBlock.IsAvailable(new SVTAV1EncoderSettings())` returns `false` and the rav1e encoder (`RAV1EEncoderSettings`) remains the software AV1 option. On iOS no AV1 encoder is available at all (#835). - [Core] **Fixed: AV1 files did not play on iOS.** No AV1 decoder was registered at all, and GStreamer's FFmpeg wrapper deliberately does not provide one, so playback worked only on the chips whose VideoToolbox decodes AV1 (A17 Pro and later) and produced nothing anywhere else. The `dav1d` software decoder is now registered on iOS, so AV1 plays on every supported device; VideoToolbox is still preferred where the hardware has it. AV1 *encoding* remains unavailable on iOS - Apple ships no AV1 hardware encoder, and the software AV1 encoders are not part of the iOS redistributable, so `SVTAV1EncoderSettings` and `RAV1EEncoderSettings` report unavailable there (#1287). - [Core] **Fixed: several Apple VideoToolbox encoder settings did nothing on iOS.** `ForceHWUsage` was ignored, `PreserveAlpha` was not offered at all, `AppleMediaHEVCProfile.Main10` warned that it could not negotiate, and `RateControl` / `DataRateLimitBitrate` / `DataRateLimitDuration` were dropped with a warning - all because the SDK still assumed the iOS runtime was the old GStreamer 1.24.9 build. iOS has shipped 1.28.6 for some time, so the HEVC alpha encoder (`vtenc_h265a`), 10-bit HEVC and the CBR/capped-ABR rate control now work there exactly as they do on macOS and Mac Catalyst. `AppleMediaH264EncoderSettings.ForceHWUsage`, `AppleMediaHEVCEncoderSettings.ForceHWUsage` and `AppleMediaHEVCEncoderSettings.PreserveAlpha` are now present in the iOS build; `ForceHWUsage` has no effect there, because every VideoToolbox encoder on iOS is hardware and GStreamer registers no separate hardware-only element (#1287). - [Core] **Fixed: VP8 and VP9 were unavailable in the iOS Simulator.** The `vpx` plugin was registered only on a physical device, although the simulator framework contains it (#1287). - [Core] **Fixed: on Mac Catalyst no GStreamer log message ever reached the SDK.** Every GStreamer debug line was routed to a static shim meant for iOS devices instead of to the SDK's own handler, so nothing appeared in the log context or in `Trace`, and the DeckLink "Signal lost" notification - which is raised from that handler - never fired on this platform. `Gst.GstDebug.RemoveLogFunction` also always reported that it had removed nothing, so a host's own log handler installed through `Gst.GstDebug.AddLogFunction` could not be taken down again. Mac Catalyst now behaves exactly as macOS does: log messages are delivered to managed handlers and removing a handler works. Real iOS is unchanged (#1259). - [Media Blocks SDK .Net] **Fixed: an RTSP RAW or NDI source restored from a pipeline document validated clean, built clean and then refused to start.** `StartAsync` returned `false` with "Media info is not available" or "Unable to get NDISource info.", because a document carries a source's endpoint but never its media information, and those two sources pick their elements from it - the depayloader and parser for RTSP RAW, the converters for NDI on desktop. `MediaBlocksPipeline.StartAsync` now probes such a source once, before it builds the graph, so a restored pipeline starts the way a hand-built one does - as does one whose settings you construct with the public constructor and configure by hand. `VideoCaptureCoreX` and `MediaPlayerCoreX` build their graph through the synchronous `Start`, so an NDI or RTSP RAW source there still needs `NDISourceSettings.CreateAsync` / `RTSPRAWSourceSettings.CreateAsync`, as before. The endpoint has to be reachable at that moment, and a source that cannot be read is reported by name. The synchronous `Start` has nowhere to await a probe and is unchanged - use `RTSPRAWSourceSettings.CreateAsync` / `NDISourceSettings.CreateAsync` there. `NDISourceSettings` gains a `ReadInfoAsync` method for probing an existing instance. **Behavior change:** `MediaBlocksPipeline.Connect` now returns `false` when a block it would have to add is refused - it reported success and left the block out of the pipeline before, so the graph was built without it and nothing said so. That happens when the pipeline is not stopped: use `AddBlockLive` / `ConnectLive` to change a running graph (#1229). ## 2026.8.29 - [Core] **Fixed: Mac Catalyst reported one placeholder audio device and never asked for camera or microphone permission.** `AudioSources`/`AudioSourcesAsync` and `AudioOutputs`/`AudioOutputsAsync` answered every Catalyst caller with a single "Default" entry carrying no CoreAudio identity, the audio device monitors refused to start (so `OnDeviceEnumerationCompleted` never fired for them), and the permission request was skipped outright. All three are lifted: Catalyst now enumerates the real CoreAudio inputs and outputs, its audio monitors run, and camera and microphone access is requested the same way as on macOS. The behaviour was introduced against a deadlock that turned out to belong to a test host launched as a bare executable rather than to Mac Catalyst itself. **Action required for Mac Catalyst apps:** the bundle's `Info.plist` must now declare `NSCameraUsageDescription` and `NSMicrophoneUsageDescription` - the system terminates a process that requests access without them, rather than denying it - and prefer `AudioSourcesAsync`/`AudioOutputsAsync` over the synchronous overloads there, since starting the CoreAudio device provider waits behind the permission prompt (#1242). - [Media Blocks SDK .Net] **Fixed: a pipeline that was stopped and disposed still held every block it contained, so memory grew with each pipeline an application built.** Each block's input and output pads carry an end-of-stream probe whose callback is pinned for the life of the underlying GStreamer pad, and nothing released it - the pad, the block, its settings and its encoder or renderer element all stayed alive for the rest of the process. Disposing a pipeline now releases the pads of every block it owns, and a block disposed on its own releases its own; restarting a stopped pipeline is unaffected (#827). - [Core] **New: `Gst.Context` is now part of the SDK, and `Element.GetContexts()` hands back real contexts instead of unusable list wrappers.** The generated type had been left out of the build and, as generated, was unusable - a structure with no fields at all, so every one of its members was commented out because it would have handed GStreamer a one-byte buffer where a context pointer belongs. It now carries the native context handle and its members work: constructing a context from its type, reading the context type, the payload structure (read-only and writable) and the persistent and writable flags, testing the type, taking a writable copy with `MakeWritable()`, and `Ref`/`Unref`. `Gst.Element.SetContext` is new, and the `Gst.Element.Contexts` property is replaced by a `Gst.Element.GetContexts()` method returning `Gst.Context[]` - a breaking change against the previous release, where it was `GLib.List[]`. It is a method because every call takes a reference on every context that is yours to give back: call it once into a local, release each context with its own `Unref()`, and do not touch the array afterwards. That replaces the previously documented release step, `Gst.Global.ContextReplace(ref handle)`. A struct has no finalizer, so release a long-lived context once, on the owning instance, since `Context` copies share the handle; after that release, and on the empty value `Gst.Context.Zero`, its members throw `ObjectDisposedException` and `InvalidOperationException` rather than handing `NULL` to GStreamer, and `IsEmpty` is the empty-state discriminator. In the same spirit, three calls that GStreamer would have answered with a log line and a plausible-looking result now say what is wrong: `WritableStructure()` throws `InvalidOperationException` on a context something else already holds a reference to (only an unshared context is writable, so write before setting it on an element, not after), `Element.SetContext` throws `ArgumentException` on an empty or released context instead of silently doing nothing, and a null context type is refused rather than turned into an empty context or a false type match. The struct also carries an internal released flag next to the handle, so pass `Gst.Context` values to native code by their `handle` field, not by marshaling the struct itself. `Gst.Uri.Zero` and the new `Gst.Context.Zero` are `static readonly` rather than plain static fields: now that both structs carry a handle, assigning to the shared empty value would have poisoned it process-wide, so code that wrote to `Gst.Uri.Zero` no longer compiles. `Gst.Toc` and `Gst.TocEntry` had the same field-less defect and are covered by their own entry below (#1257). - [Core] **New: `Gst.Toc` and `Gst.TocEntry` are now part of the SDK, so chapters can be read from a file and written into one.** Both generated types had been left out of the build and, as generated, were unusable - structures with no fields at all, so every member handed GStreamer a one-byte buffer where a table-of-contents pointer belongs. They now carry the native handle and their members work: building a table of contents and nesting entries under it, reading and writing entry tags (the chapter title lives there), start/stop times and loops, finding an entry by UID at any depth, and `Ref`/`Unref`/`Copy`. `Toc.GetEntries()` and `TocEntry.GetSubEntries()` return `Gst.TocEntry[]` and replace the `Toc.Entries` / `TocEntry.SubEntries` properties, which handed back raw handles. Everything a table of contents is actually reached through came back with them: `Message.ParseToc` / `Message.NewToc`, `Event.ParseToc` / `Event.NewToc`, `DiscovererInfo.Toc`, `DiscovererStreamInfo.Toc`, and `TocSetterAdapter.GetToc()` / `SetToc()` - so a TOC can be pulled off the pipeline bus or the discoverer and set on a muxer such as `matroskamux` - chapters written into a Matroska file this way read back out of it with their titles and start/stop times, nested under the edition Matroska wraps them in. The table of contents on a `Gst.ITocSetter` is a `GetToc()`/`SetToc()` pair rather than a `Toc` property, because the two halves have opposite ownership: reading takes a reference that is yours to release, writing leaves the reference with you. `Toc.AppendEntry` and `TocEntry.AppendSubEntry` take their argument by `ref`: the call takes the entry's reference over, and passing by reference is what lets the binding mark the caller's value released so a later `Unref()` cannot corrupt GStreamer's reference count. Values that come from a getter GStreamer does not transfer - the entries of a TOC, an entry's parent or sub-entries, a discoverer's TOC - are borrowed: they are readable and editable but refuse `Unref()`, and `IsBorrowed` reports which is which; take `Ref()` or `Copy()` to keep one past its owner. Calls GStreamer would have answered with a log line and a plausible-looking result now say what is wrong: writing tags to or appending an entry to something else already holds a reference to, appending an entry that already belongs to a table of contents, parsing a TOC out of a message or event that is not a TOC one, and null or out-of-range arguments are all refused with an exception. A struct has no finalizer, so release a long-lived value once, on the owning instance; after that release, and on the empty values `Gst.Toc.Zero` / `Gst.TocEntry.Zero`, members throw rather than handing `NULL` to GStreamer, and `IsEmpty` is the empty-state discriminator - it is also how a missed `FindEntry` and a top-level entry's absent parent report themselves. As with `Gst.Context`, pass these values to native code by their `handle` field, not by marshaling the struct itself (#1257). - [Core] **Fixed: `GES.Global.ListAssets()` could hand out freed assets and leaked a native list on every call.** GES lends out the assets its cache owns and asks the caller to free only the list holding them, but the binding did the opposite - it kept the list and released every asset, spending the reference the cache still relies on. An asset could then be finalized while still registered, so a later request for the same asset returned freed memory. The assets are now left alone and the list is released (#1231). - [Core] **Fixed: overriding a gio or GES virtual method that returns a list could corrupt memory or crash.** `FileEnumerator.OnNextFilesFinish`, the four `Resolver` lookups, the three `VolumeMonitor` collections, `GES.Container.OnUngroup` and the GES track-element creation callback each built two native lists over the same result and released neither, referencing every element twice and then walking the already-freed list from the finalizer, which crashes the process. Every callback that returns a list now hands the caller exactly one, with the ownership its documented transfer mode calls for, and gives up its own claim on it - so a list an override built and still holds is no longer freed twice (`Resolver.OnLookupRecords`, `OnLookupRecordsFinish`, `TlsDatabase.OnLookupCertificatesIssuedBy`, `OnLookupCertificatesIssuedByFinish`). `Resolver.OnLookupService` and `OnLookupServiceFinish` additionally threw on every call and could not be overridden at all; they now work (#1248, #1247). - [Media Blocks SDK .Net] **Windows: the bundled GStreamer runtime moves from 1.28.2 to 1.28.6, on x64, x86 and ARM64.** 1.28.3 through 1.28.6 are bug-fix and security-fix releases - nvcodec, RTP/RTCP, `h264parse`/`h265parse` duration handling, a compositor regression and HLS live seekable ranges among them - and Windows now matches the runtime macOS, Mac Catalyst and iOS already ship. The WASAPI capture buffer size restored in 2026.8.1 is unaffected: the patched `wasapi2src`/`wasapi2sink` were rebuilt against 1.28.6 and re-measured, since the upstream defect is still present in this release. **New elements, on x64 and x86:** `objectdetectionoverlay` and `segmentationoverlay` for drawing detection and segmentation results, `onvifmeta2relationmeta`/`relationmeta2onvifmeta` for moving analytics metadata to and from ONVIF, `burn-yoloxinference` for YOLOX inference, `demucs` for audio source separation, `msesrc`, the curl sinks and source (`curlhttpsink`, `curlfilesink`, `curlftpsink`, `curlsmtpsink`, `curlhttpsrc`), and `originalbuffersave`/`originalbufferrestore`. `rsvgdec` and `rsvgoverlay` reach x86, which did not have them; x64 already did. **ARM64 gains no elements** in this release and **loses `dvdreadsrc` and `rsndvdbin`** - upstream no longer builds the DVD plugins for that architecture. No bundled library changes file name on x64 or x86, so an incremental rebuild needs nothing special there. - [Media Blocks SDK .Net] **Windows ARM64: `VisioForge.CrossPlatform.Core.Windows.Adds.arm64` is an add-on package now, not a second copy of the runtime.** It used to mirror the whole GStreamer install, so installing it next to `VisioForge.CrossPlatform.Core.Windows.arm64` downloaded 55 MB twice and wrote every file into the output folder twice, with no way to tell which copy won. It now carries only the additional plugins and their private dependencies, exactly as the x64 and x86 Adds packages do, and declares a dependency on the ARM64 Core package - referencing the Adds package alone is enough, NuGet brings the Core package with it. Nothing is lost: the two packages together still ship every element ARM64 had before. `rsvgdec` and `rsvgoverlay` also move from the x86 Adds package into the x86 Core package, so the SVG elements come from the same package on all three architectures (#1261). - [Media Blocks SDK .Net] **Windows ARM64: three x64 DLLs that could never load are no longer shipped in the ARM64 runtime.** `libgcc_s_seh-1.dll`, `libstdc++-6.dll` and `libwinpthread-1.dll` came straight from the upstream ARM64 GStreamer installer, which ships the x64 MinGW runtime under its ARM64 tree; nothing in the ARM64 packages referenced them. Removing them makes the package about 8 MB smaller to download (27 MB on disk) with no element lost (#1261). - [Media Blocks SDK .Net] **Windows x64 and x86: the unused MinGW C++ runtime is no longer shipped.** The GStreamer build drops `libstdc++-6.dll` and friends into an otherwise MSVC runtime, and on x64 nothing referenced any of them - `libgcc_s_seh-1.dll`, `libstdc++-6.dll` and `libwinpthread-1.dll` are all gone, about 8 MB less to download (27.9 MB on disk). On x86 only `libstdc++-6.dll` goes, about 7.5 MB less (23.9 MB on disk): the rest of that runtime is really used there, by the mp3 decoder. Every plugin still loads on both architectures - verified with `gst-inspect-1.0` against the package files alone, 192 plugins and none blacklisted (#1277). - [Core] **Fixed: `GLib.List` and `GLib.SList` leaked the string copies they allocate.** Building a list from managed strings with `elementsOwned: false` duplicated every string into glib memory and freed nothing on dispose, leaking each copy for the life of the process. The wrapper now releases the storage it allocated itself on `Dispose()` / `Empty()`, while elements a native list lent it stay untouched - a list mixing borrowed and managed elements frees exactly what it allocated. A borrowed wrapper that released element storage refuses further use: reads and appends throw `ObjectDisposedException` instead of touching freed memory, while an owned list survives `Empty()` as an empty list whose later string appends are released on the next `Empty()`. `Clone()` of a string list frees its copies on the clone instead of the source (#1232). - [Core] **Fixed: six more list-returning GStreamer properties handed back unreadable elements and leaked.** `VideoDecoder.Frames`, `VideoEncoder.Frames`, `Toc.Entries`, `TocEntry.SubEntries`, `Adapter.GetList` and `Adapter.TakeList` all typed their elements as the list container itself, so every element was a wrapper over a pointer that is not a list node and read as garbage. Where GStreamer transfers ownership of the elements, disposing that array also released each of them as if it were a GObject - which GStreamer silently ignores, leaking a reference per element on every call. Each property now returns its real element type with the ownership GStreamer documents: `Gst.Buffer[]` for the two `Adapter` methods, which release themselves, and raw handles for `VideoDecoder.Frames` / `VideoEncoder.Frames`, whose element type cannot carry a native pointer. Note where GStreamer transfers ownership, the reference is now **yours to release**: each handle from those two with the new `Gst.Video.VideoCodecFrame.Unref(IntPtr)`. The two table-of-contents properties are covered by the `Gst.Toc` entry above. The old `GLib.List[]` signatures are removed. The element contexts carried the same defect and are covered by the `Gst.Element.GetContexts()` entry above (#1240). - [Core] **Fixed: native text in GStreamer binding structures was decoded with the system ANSI codepage instead of UTF-8.** Names, descriptions, hosts, credentials and addresses read through `ElementFactory.StaticPadTemplates`, `Gst.Video.VideoFormatInfo`, `Gst.Audio.AudioFormatInfo`, `Gst.FormatDefinition`, `Gst.PluginDesc`, `Gst.Rtp.RTPPayloadInfo`, the RTSP (`RTSPUrl`, `RTSPTransport`, `RTSPAuthParam`, `RTSPAuthCredential`, `RTSPAddress`), SDP, WebRTC, gio and Pango structures all came back as mojibake on any Windows codepage that is not UTF-8. They now decode as UTF-8. `ElementFactory.StaticPadTemplates` additionally leaked a string copy on every access to a template's `Get()` or `Caps` and handed GStreamer a re-encoded copy of its own text in place of the original; that leak is gone. Two consequences there, both breaking: `Gst.StaticPadTemplate.NameTemplate` and `Gst.StaticCaps.String` are now read-only properties rather than settable fields (they carry the native pointer, and code that assigned one, took it by `ref`/`out`, or reflected over it as a field will not compile), and comparing two `StaticPadTemplate` or `StaticCaps` values now compares the native text identity rather than the decoded characters (#1240). ## 2026.8.28 - [Core] **Fixed: GStreamer wrapper members silently did nothing after `Dispose()`.** Calling any member of a disposed `Gst.Caps`, `Buffer`, `BufferList`, `TagList`, `Structure`, `Message`, `Event`, `Query`, `Sample`, `Memory`, `MiniObject`, `DateTime`, `Iterator`, `Promise` or `DebugMessage` handed a NULL handle to GStreamer, which logged a silent critical and carried on — or returned a quiet default that looked like real data; the struct-field accessors (`Buffer.Pts`, `Caps`/`Structure` field reads) read through a NULL pointer outright. Those members now throw `ObjectDisposedException` naming the type, so the misuse surfaces at the call site. `Dispose()` stays idempotent, and `Handle`, `Owned`, `Equals` and `GetHashCode` keep working on a disposed wrapper, so release-once code and comparisons are unaffected. Also fixed here, the same defect in three places: `new Gst.Sample(buffer, caps, segment, null)`, `Message.AddRedirectEntry(location)` — which threw on every call — and `Buffer.ReplaceMemory`/`ReplaceAllMemory`/`ReplaceMemoryRange` with a null memory (the way to drop memory blocks without inserting a replacement) all threw `NullReferenceException`, because the optional argument was dereferenced before its own null check (#1241). - [Core] **Fixed: `Gst.GstDebug.GetAllCategories()` returned unusable data.** Its elements were typed as `GLib.SList` while GStreamer actually hands back debug categories, so reading an element produced garbage values or a crash, and a category's name and description were unreachable. The method now returns `Gst.DebugCategory[]` - a value-copy struct exposing the category name, description, color and current threshold, decoded as UTF-8. Two members that silently did nothing now throw `NotSupportedException` and are marked `[Obsolete]`: `DebugCategory.Free()` (deprecated upstream no-op) and `DebugCategory.ResetThreshold()` (wrote into a temporary copy, never into the live category). `DebugCategory` equality now compares the category's native identity plus the copy's threshold and color, instead of comparing decoded strings. The old `GLib.SList[]` signature is removed (#1233). - [Core] **Fixed: starting or stopping audio on iOS could hang the app.** The bundled iOS GStreamer held the audio ring-buffer lock across the CoreAudio start/stop calls that wait for the render callback to finish; the render callback takes the same lock. The start path was already fixed upstream for iOS 17+, and the same fix now covers the stop path and the pre-1.28 render-callback teardown (#1131). - [Core] **The iOS bundled GStreamer runtime moved from 1.24.9 to 1.28.6**, matching macOS and macCatalyst. Brings the 1.26/1.28 plugin set to iOS (the reworked direct-rendering decode path, `io_proc_dropping` audio teardown, the VideoToolbox rate-control properties and the alpha encoder variant) and ends the divergence where iOS alone shipped a runtime without the deadlock fixes above. The Metal compositor plugin (`vfmetalcompositor`) is now part of the iOS framework. The official 1.28.6 iOS package no longer carries `frei0r`, and it replaces `y4mdec`/`y4menc` with the single `y4m` plugin. - [Media Blocks SDK .Net] **Fixed: stopping a capture session after a source error could crash the process.** A microphone or other live source that failed during the session no longer access-violates on `StopAsync`; a recording that was still producing video is still finalized (#825). - [Media Player SDK .Net] **Fixed: switching audio on a multi-track file jumped the picture back to the first video track, and switching video silenced the playing audio.** `Audio_Stream_Select` / `Video_Stream_Select` on `MediaPlayerCoreX` and `SimplePlayerCoreX` now keep the streams they are not switching. `SimplePlayerCoreX.Audio_Streams_Current` reports the active audio index instead of a hardcoded `1` (#1216). - [Core] **`Gst.Uri` members now throw on a released or empty instance instead of failing silently.** Reading a property, converting to a string or mutating a `Gst.Uri` after its `Unref()` — or on the empty value `Gst.Uri.Zero` — used to hand `NULL` to GStreamer, which logged a silent critical or quietly returned an empty result indistinguishable from a real one. These members now throw `ObjectDisposedException` after release and `InvalidOperationException` on the empty handle; managed comparison (`Equals`/`GetHashCode`), a repeated `Unref()` and `ToString()` on the empty value (it renders as an empty string) keep working. The new `IsEmpty` property is the parse-failure discriminator. Struct copies taken before the release still share the handle and stay unreusable after it — release once, on the owning instance. The struct also carries an internal released flag next to the handle, so pass `Gst.Uri` values by their `handle` field to native code, not by marshaling the struct itself (16 bytes on 64-bit) (#1236). - [Core] **New: `Gst.Uri` is now part of the SDK.** The generated type had been left out of the build and, as generated, was unusable. It now carries the native URI handle and its members work: constructing from parts or parsing a string, reading scheme, host, path, fragment, the query table and the query keys, joining a reference against a base. The handles the constructors return own a reference and a struct has no finalizer, so release a long-lived one with its `Unref()` method - once, on the owning instance, since `Uri` copies share the handle. Also, `GLib.PtrArray.Clone()` on an elements-owned array whose element type is not a GObject now throws `ArgumentException` instead of silently sharing element storage that dies with the source (#1205). - [Core] **Fixed: `GES.TrackElement.AllControlBindings` returned garbage on every read.** GStreamer hands back a hash table there, not a list, and the binding read the hash table's memory as a list. The property now returns the control-binding property names through `g_hash_table_get_keys` and frees the temporary list it builds; the list marshaller refuses any non-list native return with a clear exception, and a `NULL` return still reads as an empty array (#1205). - [Core] **Fixed: `Gst.GstDebug.GetAllCategories()` leaked the native category list on every call.** GStreamer hands back a copy of the process-static debug categories that the caller must free, but the `GLib.SList` wrapper discarded its ownership flags, so disposing the wrapper freed neither that list nor - on any other `SList`-based API - the elements it claimed to own. The flags are now honoured: an owned SList frees its container and takes a reference per GObject element, a borrowed one releases nothing; ownership of element storage it cannot release (boxed handles, raw ints, value-type copies) is refused with `ArgumentException`, `Clone()` on both list wrappers now owns and frees its copy instead of leaking it and enumerating through a lost element type - and copies the elements themselves, so a clone survives its source's disposal - and every read of a disposed wrapper throws `ObjectDisposedException` instead of reading freed memory (#1205). ## 2026.8.27 - [Core] **Fixed: device enumeration could hang forever on Mac Catalyst.** `AudioOutputsAsync`, `AudioSourcesAsync` and camera/microphone permission requests relied on CoreAudio/AVFoundation calls that never return in some macabi processes; the permission ask is now bounded — skipped with a warning only where the query is measured to never answer — and audio enumeration falls back to a safe single default device, so Catalyst apps no longer wedge on startup-time enumeration (#1150). - [Core] **Fixed: macOS startup logged hundreds of GIO module-load failures and a duplicate OpenSSL TLS backend registration.** SSL initialization now loads only the intended GIO TLS module, once, instead of treating every dylib in the app bundle as a GIO module (#1200). - [Core] **Fixed: reading `Video_Streams`, `Audio_Streams` or `Subtitle_Streams` while a stream switch was in progress could throw `InvalidOperationException`.** The bus thread used to empty and refill those lists in place; a property read that landed in the middle of that update now sees a complete snapshot (#1219). - [Video Edit SDK .Net] **Fixed: audio settings changed between two renders on one `VideoEditCoreX` were silently ignored by the second render.** `Output_AudioChannels` and `Output_AudioSampleRate` written after a render had finished never reached the rebuilt timeline's audio track, so the next output kept the previous render's channel count and sample rate. The output settings are now applied to the tracks of the pipeline being started (#850). - [Video Edit SDK .Net] **Fixed: `Input_AddVideoLayer` and `Input_AddTestClip` threw `NullReferenceException` when used after a render had finished.** Both now rebuild the timeline first, as `Input_Clear_List` and the file inputs already did, so a second editing session on one instance works (#850). - [Video Edit SDK .Net] **Fixed: `Debug_Mode` did not enable the SDK's debug-level diagnostics.** The engine configured a debug logger but left its context in non-debug mode, so debug entries were dropped before reaching the log file (#850). - [Video Edit SDK .Net] **Fixed: memory grew across renders that use fade transitions.** Each `FadeIn` / `FadeOut` on a clip leaked a GStreamer control source per render, so a long editing session or a batch of renders accumulated them (#850). - [Core] **`GLib.List` now refuses to build an element-owning list it cannot honour instead of corrupting reference counts.** Passing `elementsOwned: true` while appending wrapped objects used to store their borrowed handles and release them on `Dispose()`, spending references the list never took; it now takes a reference of its own for a GObject element, and throws `ArgumentException` for an element it cannot reference at all - an `Opaque`, an element that does not match the declared element type, or a disposed wrapper (#839). - [Core] **Fixed: switching audio or video streams leaked a small amount of native memory on every switch.** `Audio_Stream_Select` / `Video_Stream_Select` on `MediaPlayerCoreX` and `SimplePlayerCoreX` built the SELECT\_STREAMS stream-id list without ownership flags, so its disposal freed neither the list nodes nor the copied stream-ID strings; the list is now built owned and freed after the event is sent. A stream with no ID is now rejected with a log entry and `false`, where `SimplePlayerCoreX` used to throw on a null stream and both engines silently sent an event that changed nothing (#1208). - [Core] **Fixed: `Gst.Event.ParseSelectStreams` leaked the returned list.** The C builds a fresh list of copied stream IDs and hands the ownership over, but the binding wrapped it without ownership flags, so disposing the wrapper freed neither the list nodes nor the strings (#1208). - [Core] **New: `DeviceEnumerator.OnDeviceEnumerationCompleted`** reports when the first enumeration of a device list has finished, so an application can start a device monitor without waiting for it and show its own "enumerating..." state while the list fills through `OnVideoSourceAdded` / `OnAudioSourceAdded` / `OnAudioSinkAdded`. `DeviceEnumerationCompletedEventArgs` names the list: `VideoSources`, `AudioSources` or `AudioOutputs` (#1108). - [Core] **Starting a device monitor no longer reads the device list while holding a lock shared by every `DeviceEnumerator` in the process.** The monitor now waits for GStreamer to report that its device providers are up - they start on their own thread from GStreamer 1.28 on - and reads the list afterwards, when that read no longer blocks. On macOS the wait covers the camera or microphone permission dialog, so a dialog left on screen no longer holds up unrelated enumerations for as long as it is up (#1108). - [Media Blocks SDK .Net] **Fixed: a recording or streaming branch could stop reporting end-of-stream, and a source could hand out a video or audio pad that was already dead.** Across the output blocks (MP4, MKV, AVI, WebM, FLV, WMV, MP3, M4A, FLAC, Ogg, YouTube, Facebook Live), the RTMP/RTSP/NDI/UDP sources, the demuxers, the audio and video effects blocks and the overlay managers, a GStreamer pad was released while the block that owned it was still using it. Nothing failed visibly at the time - the next call on that pad simply did nothing - so the symptoms were downstream: end-of-stream never firing, a recording left unfinalized, or a pad handed to an `OnVideoPadAdded` / `OnAudioPadAdded` subscriber going inert as soon as the handler returned (#850). - [Media Blocks SDK .Net] **Fixed: `InterPipeSinkBlock.IsAvailable()` and `InterPipeSourceBlock.IsAvailable()` could report that InterPipe was installed when only the unrelated proxy elements were present.** The probes now check the actual `interpipesink` and `interpipesrc` elements, so platform and deployment availability is reported accurately (#1193). - [Core] **Reading a queue's fill level no longer enumerates the element's whole property list.** `QueueBlock.CurrentLevelBuffers`, `CurrentLevelBytes` and `CurrentLevelTime` are meant to be polled per frame, and each read used to build a managed descriptor for every property the element declares; a poll of all three now allocates about a fifth of what it did. The same applies to any element property probed through `PipelineHelper.ElementHasProperty`, which additionally reports `false` for an element that has already been released instead of answering from the base element type. - [Media Blocks SDK .Net] **A live pipeline can now be saved as a JSON document.** `MediaBlocksPipeline.ToDocument()` captures the running graph - blocks, their identities and their connections - and `ToJson()` / `SaveJsonAsync(path)` write it out; the capture is safe while the pipeline is playing, which makes it the save-during-Run path. A block that does not expose its settings contributes its position but not its configuration, and says so through a diagnostic rather than producing a document that would rebuild it on defaults - check `MediaBlocksPipelineSnapshotResult.Complete` before treating a capture as a faithful copy. - [Media Blocks SDK .Net] **A relative file path named by a `*Location` setting now resolves against the document base directory**, which is what the HLS sink calls its segments, its playlist and its init segment. - [Core] **Fixed: reading or animating a video mixer input that has no sink pad crashed instead of reporting no such input.** A stream added to the mixer settings after the block was built never gets a pad of its own, and reading it back or starting a fade or move on it walked off the end of the pad list. Such a call now returns `null` / does nothing and reports it through the log, on `VideoMixerBlock` and `GLVideoMixerBlock` on every platform and on the D3D11 compositor on Windows; the Metal compositor on macOS and iOS already behaved this way and now logs it too. A fade or move whose input pad is released while it is running also stops cleanly instead of leaving the input part-way through the animation (#1191). - [Core] **Fixed: constructing a `GLib.PtrArray` threw `EntryPointNotFoundException` on Windows.** The type declared its `g_ptr_array_*` entry points against libgobject and its `g_object_unref` against libglib - exactly backwards - so the first call into the type failed on Windows, while Linux and macOS resolved the symbols through library dependencies by accident. Each import now names the library that actually owns its symbol (#1207). - [Core] **Fixed: cloning a `GLib.PtrArray` crashed the process, and every clone leaked the native container.** `Clone()` called `g_ptr_array_copy` through a one-argument declaration, while the native function takes three (`array`, copy function, user data) - the missing arguments arrived as garbage and were called as a function pointer. It now declares the real signature and passes NULL for a shallow copy, as the C API allows, the clone owns its copied container so `Dispose()` actually frees it, and cloning a disposed array throws `ObjectDisposedException` instead of crashing later (#1207). - [Media Blocks SDK .Net] **New: `VideoMixerBlock.RemoveInputPadLive` removes an input that was added with `AddInputPadLive` and hands the mixer's input back to it.** A live-added input used to occupy a mixer input permanently - the only way to reclaim it was to tear the pipeline down. Removal is safe against a running graph: the input is stopped and unlinked first, then the mixer reclaims its pad. Only live-added inputs can be removed; the inputs configured at build stay index-aligned with the mixer's stream settings. Also fixed: the tee helper and the muxer sinks' `ConnectVideo` (MP4, MKV, AVI, MOV, WebM, OGG, FLV, MPEG-TS) kept a requested pad when a connection failed instead of handing it back (#1210). - [Media Blocks SDK .Net] **Fixed: the video and audio effect blocks could not be restored from a pipeline JSON document.** `VideoBalance`, `VideoResize`, `VideoCrop`, `VideoBox`, the OpenGL effects, the audio effects and thirty-odd of their siblings all failed with "no construction path", because their settings class is named after the effect - `ResizeVideoEffect`, `CropVideoEffect` - rather than ending in `Settings`. The block catalog now also reads a block's own `Settings` property. Across its 387 blocks, and counting the correction below, the number a document can restore went from 314 to 329 and the number a caller holding only a descriptor can create from 216 to 288 - `TextOverlay`, `ImageOverlay`, `VideoMixer`, `HLSSink` and the OpenCV filters among them. - [Media Blocks SDK .Net] **Fixed: a crop or a video box restored from a document came back cropping nothing.** `CropVideoEffect` and `BoxVideoEffect` kept their four edges behind a private setter, so the margins were dropped in both directions of the serializer and the stage became a passthrough while reporting success. The edges are now settable. - [Media Blocks SDK .Net] **Three blocks that took their whole configuration as a bare value gained a settings class**: `FlipRotateSettings`, `WAVSinkSettings` and `BarcodeDetectorSettings`. A rotation, a WAV recording destination and a barcode detector mode can now be stored in a pipeline document and edited through the block catalog's property metadata. The existing constructors are unchanged. - [Media Blocks SDK .Net] **`ResizeVideoEffect`, `CropVideoEffect`, `BoxVideoEffect`, `GLResizeVideoEffect`, `ImageOverlaySettings` and `TextOverlaySettings` gained a public parameterless constructor**, which is what JSON deserialization needs; the crop and the box default to a passthrough and the two resizes to 1920x1080. - [Media Blocks SDK .Net] **Fixed: seven network sources could not be restored from a pipeline JSON document.** `HTTPMJPEGSource`, `NDISource`, `NDISourceX`, `RTMPSource`, `RTSPRAWSource`, `SRTSource` and `SRTRAWSource` passed preflight validation and then failed halfway through materialization, because the only constructor on their settings class was private - an async `CreateAsync` probes the endpoint before handing one back. Each of those settings classes now has a public parameterless constructor for the persistence path; `CreateAsync` is unchanged and remains the way to probe a reachable endpoint up front. A source built from a document does not contact its endpoint until the pipeline opens it. - [Media Blocks SDK .Net] **Fixed: a document naming `SRTSource` or `NDISourceX` built the wrong block.** `SRTSourceSettings` is shared by the decoding and the raw SRT source and `NDISourceSettings` by the NDI and the Windows-only NDI X source, while `CreateBlock()` on each names only one of the pair - so the other came up as its sibling, with different pads, and the document's own connections then failed to resolve. A settings class shared by two blocks now reaches its block through the block's own constructor. - [Media Blocks SDK .Net] **`RTSPRAWSourceSettings.Uri` and `.AudioEnabled` are now settable.** Both were read-only outside `CreateAsync`, so a document's endpoint and audio flag were dropped in both directions of the serializer and the source came up pointing nowhere while reporting success. - [Media Blocks SDK .Net] **Fixed: nineteen block types built a different block than the one you asked for.** `MediaBlockCatalog.Get(MediaBlockType.MP4Output).CreateBlock()` returned an `MP4SinkBlock` - a bare muxer instead of the whole encode-and-mux stage - and so did a document naming one. `PlayBinSource` came back as a `UniversalSourceBlock`, `SeparateOutput` as a `BridgeVideoSourceBlock`, `UniversalSourceMini` as a `UniversalSourceBlock`, `SRTSink` as an `SRTMPEGTSSinkBlock`. The cause: several blocks share one settings class, whose `CreateBlock()` names only one of them, and the catalog called it for all of them. A shared settings class now reaches its block through the block's own constructor. - [Media Blocks SDK .Net] **A block whose settings alone cannot build it is now refused up front instead of failing halfway through loading a document.** Twenty-four block types name a settings class but also require a second one the document cannot carry - the `*Output` blocks want encoder settings, `DecklinkVideoAudioSink` a second sink settings, `SeparateOutput` a live pipeline. They reported themselves constructible, passed preflight validation, and then failed during materialization, which discards the whole pipeline over one entry. Preflight now reports `MBS032` naming the block, and `MediaBlockDescriptor.CanConstruct` answers what the loader can actually do. - [Media Blocks SDK .Net] **Fixed: `RTSPSource`, `RTSPRAWSource` and `RTMPSource` threw `NullReferenceException` instead of reporting an empty URL.** The "URL is empty" check dereferenced the URI it was testing, so a source built without one crashed rather than logging and refusing to build. - [Media Blocks SDK .Net] **Fixed: `AudioMixer` was configured through the wrong settings class.** The block catalog bound it to `AudioMixerSourceSettings`, which needs a live pipeline and cannot be created at all, instead of `AudioMixerSettings` - so the mixer offered the wrong properties to edit, a pipeline document could not carry its output format, and `IgnoreInactivePads` was unreachable from a document. The catalog now prefers a constructor that can actually be called when a block has several. - [Demos] **Media Blocks Studio: the Player and picture-in-picture scenarios now carry the effect stages they describe** - colour balance, a mirror and an upscale on the player, a crop and a resize on the picture-in-picture camera branch. ## 2026.8.26 - [Demos] **Media Blocks Studio: nine bundled scenarios that run offline.** The startup screen shows nine curated pipelines - player and live effects, camera capture, screen+camera picture-in-picture, live mixer, transcoding, multi-output streaming, AI vision, audio lab and RTSP - each with a still captured from its own output, an outcome line, media tags and platform/requirement chips. Every scenario is an ordinary JSON document under `Assets/Scenarios` that the app reads at runtime, so the file you open, edit and save is the file the gallery runs. The baseline needs no camera, network or media file: five scenarios generate their own video and audio and three read a bundled clip. "Run Demo" opens the graph and starts it; two scenarios first ask for what the bundle cannot carry - an RTSP endpoint and a path to an ONNX detection model. - [Demos] **Fixed: the Media Blocks Studio editor came up empty.** Opening a pipeline showed the toolbar over a blank area with no canvas, block catalog, inspector or panels, and the block catalog reported no blocks at all. The application did not include the Dock and Nodify control themes, presented its panels with the wrong data, and never initialized the SDK. Connections between blocks are now drawn as well: a node was previously built with one input and one output regardless of the block, so anything wired to an indexed pad - a mixer input, a source's audio output - was dropped silently. - [Media Blocks SDK .Net] **Fixed: several blocks could not be restored from a pipeline JSON document.** `RTSPSource`, `VideoMixer` and `Tee` entries failed to materialize, and `Volume` and `Equalizer10` could not carry their gain, mute or band values at all, because those settings types had no constructor the persistence layer could call and, for the two audio blocks, no settings type at all. `VolumeSettings` and `Equalizer10Settings` are new; `RTSPSourceSettings` and `VideoMixerBaseSettings` gained a public parameterless constructor; `TeeBlock` gained constructor defaults. Settings whose only constructor takes all-optional parameters - `VirtualAudioSource` among them - are now accepted too. - [Media Blocks SDK .Net] **A relative file path in a pipeline document now resolves against the document base directory even when the setting is a URI**, which is the shape `UniversalSourceSettings` uses, so a document can reference an asset shipped beside it. - [Media Blocks SDK .Net] **Preflight validation now reports an input asset that does not exist** - a detection or OCR model path, or a local file URI - as an error instead of letting the pipeline materialize into a stage that silently does nothing. A sink filename is an output and is still not required to exist. - [Core] **Fixed: `ElementX.ReadProperties()` returned structure-typed element properties (for example `rtspsrc` `sdes`) whose native memory was already freed**, so reading such an entry afterwards could crash or return garbage. Boxed values are now kept as a deep copy (#1184). - [Core] **Fixed: `ElementX.ReadProperties()` aborted with an exception on elements holding properties without a managed representation (for example `gltransformation`)** instead of skipping them; unreadable properties are now skipped, and calling the method again refreshes existing entries instead of failing (#1184). - [Core] **Fixed: `ElementX.ReadProperties()` raised a GLib critical for every write-only element property (for example `playbin` `subtitle-font-desc`)** by trying to read a value such a property cannot have. Those properties are still listed, with a `null` value, and are no longer read (#1184). - [Demos] **Media Blocks Studio: generated Inspector, Help, runtime controls and crash recovery.** The editor now generates the Inspector form from each block's descriptor property metadata (typed parsing with min/max clamping; live-safe properties apply to the running pipeline without a rebuild) and a Help card from the block descriptor. The workspace gained Run/Pause/Resume/Stop over `MediaBlocksPipelineMaterializer` with error/stop event logging, position polling, structured diagnostics navigation and a single-slot live video preview. Pipelines autosave to %AppData% on a 10 s debounce with a restore prompt on the next start, and unsaved changes are confirmed before New/Open/close. - [Media Blocks SDK .Net] **Local file sources are now JSON-serializable.** `UniversalSourceSettings` and `DemuxerSourceSettings` had only a private constructor and private setters for their file/URI properties, so a pipeline document carrying a local file could not be loaded or materialized. Both now expose a public constructor and settable URI/Filename/render flags, so file-based pipelines round-trip through the versioned JSON document format. - [Core] **Fixed: the LUT (color lookup table) video effect silently did nothing on Intel Macs.** The native processor library shipped in the macOS and Mac Catalyst packages was built for Apple Silicon only, so on an x86\_64 Mac it could not be loaded at all and every LUT-based effect was a no-op. The library is now a universal x86\_64+arm64 binary (#1101). - [Core] **Fixed: calling `VProcessor.UpdateFilterParameters` threw `EntryPointNotFoundException` on macOS/macCatalyst.** The shipped native library predated the managed wrapper and did not export the entry point; it now does (#1157). - [Core] **The GStreamer log callback no longer claims ownership of logged objects.** The SDK's log handler built a managed wrapper around the subject object of every log line GStreamer emitted, including plugin-internal GObjects the SDK never created; for an object that logs while still floating (any `GstObject` logging before its owner sinks it) the wrapper adopted the floating reference, so the owner's later unref finalized the object while the binding still held a toggle reference on it — surfacing as `[VisioForge-Lifetime] toggle ref outlived its object` and, in Release, as a use-after-free risk whenever debug logging was enabled (#1165). Handlers registered through `Gst.LogFunction` now receive `_object = null` unless a managed wrapper for the logged object already exists. - [Core] **Fixed: custom GStreamer log handlers could never be detached on desktop platforms.** `Gst.GstDebug.RemoveLogFunction` compared against a freshly built native function pointer instead of the one recorded at registration time and therefore matched nothing; every handler stayed installed for the life of the process. Removal now unregisters by the handle captured when the handler was added — the same scheme already used on Unity. As a consequence, removing without an argument detaches only the handlers this assembly registered rather than every log function in the process, so third-party and default GStreamer logging survives SDK teardown (#1165). - [Core] **Fixed: native memory grew steadily while reading GStreamer element properties.** Long-running pipelines leaked a small native allocation on every property read: `QueueBlock` level properties (`CurrentLevelBuffers`/`CurrentLevelBytes`/`CurrentLevelTime`, typically polled per frame), video mixer and compositor input reads, OpenGL shader and 360-view settings updates (a whole structure copy per update, so dragging a slider accumulated allocations for the process lifetime), file sink filename reads, and the volume/mute getters of the system and PulseAudio audio sources and of the audio renderer (#1185). - [Core] **Fixed: `InterPipeSinkBlock.GetNumListeners()` always returned 0**, whatever the number of connected InterPipe sources (#1185). - [Core] Fixed a slow native memory leak in device enumeration: every probed device property leaked one boxed GValue per enumeration pass (#1174). - [Core] Fixed: one audio device losing a property-probe race (device removed mid-enumeration) aborted the whole output-enumeration pass, hiding every device enumerated after it; the pass now continues, with the failure contained to that single entry. ## 2026.8.25 - [Demos] **New: Media Blocks Studio, the cross-platform Avalonia showcase and pipeline editor for Media Blocks SDK.** The first stage ships the application shell under `_DEMOS/Media Blocks SDK/Avalonia/Media Blocks Studio` (Windows `net10.0-windows`, macOS `net10.0-macos`, Linux `net10.0`): a dark broadcast-style startup gallery with New/Open/Recent projects, an IDE-style workspace built on Nodify.Avalonia 2.0.0 (infinite node canvas with pan, zoom, selection and connection dragging) and Dock.Avalonia 12.0.0.2 (catalog on the left, Inspector/Help tabs on the right, Preview/Metrics/Diagnostics/Logs docked at the bottom). The searchable block list reads the SDK's read-only block catalog directly; pipelines are created, edited, validated against `MediaBlocksPipelineValidator`, saved to and loaded from the versioned JSON document format with undo/redo. - [Media Blocks SDK .Net] **New: document-to-live materialization and preflight validation.** A pipeline JSON document can now be turned into a running-ready `MediaBlocksPipeline`: `MediaBlocksPipelineMaterializer.Materialize` builds every block through the block catalog, binds settings from their JSON payloads (including all-optional-parameter constructors), resolves host resources through `IMediaBlockResourceResolver`, restores connections using the documented `input`/`output`/`input:N`/`output:N` pad id convention, and returns a document-block-id to live-block mapping with full diagnostics. Blocks that cannot be created - unknown type, missing factory, unavailable on this platform - stay in the document as placeholders with an error diagnostic; they never discard the rest of the pipeline. `MediaBlocksPipelineValidator.Validate` performs the complete preflight check: structure, known blocks, construction paths, availability probes, pad reference shape, resource resolver presence and unsupported feedback cycles; errors block materialization and run, warnings do not. Relative file paths inside settings resolve against the document directory when one is given (`baseDirectory`). New convenience: `MediaBlocksPipeline.LoadJsonAsync` replaces the contents of a stopped pipeline from JSON in one call. - [Media Blocks SDK .Net] **Metal-accelerated video elements are now available on Intel Macs.** The `vfmetal*` plugin shipped in the macOS and Mac Catalyst runtime packages was built for Apple Silicon only, so on an Intel Mac it could not be loaded at all and every element it provides - the Metal compositor, video sink, filter, converter/scaler, transform, deinterlacer and overlay - was simply absent from the GStreamer registry. It is now a universal x86\_64+arm64 binary (#1101). - [Video Capture SDK .Net] **Fixed: video frames could silently stop flowing after live video effects were removed or cleared during capture (`Video_Effects_Remove` by instance or name, and `Video_Effects_Clear`).** The pause issued before the filters are unplugged and the resume after are asynchronous GStreamer state changes, but the resume was not waited out - a PAUSED to PLAYING transition that never completes stops frames with no error raised anywhere. Both operations now wait (bounded) for the resume to settle and report through `OnError` if the pipeline fails to return to the playing state (#1152). Behavior change: removing or clearing effects while capture is paused no longer resumes playback - a deliberate pause is preserved, matching what live effect addition has always done. - [Media Blocks SDK .Net] **Fixed: stopping an SRT pipeline could hang `StopAsync` forever on macOS when the peer was unreachable or kept dropping the connection, and a test or app that gave up mid-stream could then die with a SIGSEGV at process exit.** The native SRT sink captures the auto-reconnect setting once per write/read call, so turning reconnect off while the streaming thread was already inside its reconnect loop did not end the loop - EOS could never reach the sink and teardown blocked indefinitely. Both SRT sink blocks now receive an early stop signal (`RequestStop`) that disables auto-reconnect before EOS, and the macOS native package's `libgstsrt.dylib` honors a mid-flight reconnect switch-off instead of reopening forever (#879). - [Media Blocks SDK .Net] **Fixed: the raw `MPEGTSSinkBlock` → `SRTSinkBlock` path published streams that carried bytes but no playable video.** The muxer emitted one buffer per 188-byte TS packet and the SRT sink sent each as its own SRT message - seven times the message rate for the same payload, which starved video on the transport. The muxer output is now aligned to 7 TS packets (1316 bytes) per buffer, matching what the combined SRT MPEG-TS sink has always done. The alignment applies to every raw `MPEGTSSinkBlock` output, including default `.ts` file recordings; the multiplexed stream itself is unchanged and stays spec-legal (#879). - [Media Blocks SDK .Net] **Fixed: MPEG-1 video produced no video output through `UniversalDemuxDecoderBlock` (and could not decode through `UniversalSourceBlockV2` in the rare no-parser path).** The by-name decoder selectors asked for an element gst-libav never registers - it builds decoder names at runtime and explicitly skips `mpeg1video`, so `avdec_mpeg1video` does not exist and element creation failed silently, dropping the video stream. MPEG-1 is now handed to `avdec_mpeg2video`, which decodes both generations. MPEG audio Layer 1 and Layer 2 hit the same defect family: `UniversalSourceBlockV2` routed them to `avdec_mp2` and `UniversalDecoderBlock`'s Layer 1/2 ladders listed only names gst-libav does not register (`mp1`/`mp2` are in its audio skip list), so that audio silently got no decoder; both now decode through `avdec_mp3`, which handles every MPEG audio layer (#1132). - [Media Blocks SDK .Net] **Fixed: a live element could be stopped while a buffer was still passing through it, which could freeze the pipeline.** Updating `GLShaderBlock` settings on a running pipeline, and removing an `AudioMixerBlock` input from one, both blocked the surrounding pads and then took the element to the NULL state - but installing a pad block does not wait for a streaming thread already inside it to leave, and stopping an element under that thread deadlocks against it. Both paths now wait for the element to be out of the data flow first, and report a failure instead of stopping it if that wait does not complete (#1143). **Breaking: `GLShaderBlock.Update()` returns `bool` instead of `void`**, so a caller can see when the new shader did not go live - which is what a paused pipeline gives back, since a sink holding a buffer in preroll keeps a streaming thread inside the chain. Push the settings again after resuming. - [Core] **macOS: audio capture/render devices are selected by their stable CoreAudio unique ID, not by the numeric device ID.** The numeric AudioDeviceID CoreAudio assigns is reassigned on replug, on other devices being added, and across reboots, so a saved configuration could silently open a different device. `AudioCaptureDeviceInfo` and `AudioOutputDeviceInfo` now publish the provider's stable `UniqueID` (plus `IsDefault`), and `OSXAudioSourceSettings` / `OSXAudioSinkSettings` accept it; the pipeline prefers the unique ID and falls back to the recorded numeric ID for configurations saved before this change. A saved unique ID that no longer exists now fails the pipeline start with a diagnostic instead of opening whatever sits at the old numeric ID (#1106). - [Core] **Fixed: selecting a specific macOS audio input device through `DeviceEnumerator` never worked** - the enumerated `AudioCaptureDeviceInfo.DeviceID` was never populated and stayed 0, so every capture built from a picked device opened the default input instead (#1106). - [Media Blocks SDK .Net] **New: a public block catalog.** `MediaBlockCatalog` enumerates every built-in Media Block the loaded SDK assemblies carry - over 400 blocks across VisioForge.Core and the AI/OpenGL satellites - with one descriptor per block: stable type, concrete and settings CLR types, human-readable name, visual category, keywords for search, an availability probe (wired to each block's own `IsAvailable()`), factory support, and property metadata generated from the settings type (display name, default value, editor kind, enum values). Blocks whose settings are built by factories rather than edited as POCOs - device sources, demuxers created through async `Create` methods - are classified as runtime-configured instead of pretending to have an editable surface. New types: `MediaBlockCatalog`, `MediaBlockDescriptor`, `MediaBlockPropertyDescriptor`, `MediaBlockAvailabilityResult`, `IMediaBlockResourceResolver`. - [Media Blocks SDK .Net] **Settings JSON now survives round trips for media value objects.** `VideoFrameRate` is persisted as its num/den pair, `Size` as width/height, and colors (`SKColor`) as RGBA bytes; previously these either could not be deserialized at all or came back zeroed. Read-only computed members of settings objects no longer enter the payload at all - they cannot be read back and silently corrupted document round trips. The DVB source's native tuning handle is excluded from serialization like every other native pointer. - [Media Blocks SDK .Net] **MAUI: `VideoViewX` gains `SetIPhotography` and `SetCamera2Controls` on Android**, matching the Uno and Avalonia video views. They forward to the native view, so camera photography controls can be configured on the MAUI control itself; outside Android the methods do not exist (#311). - [Media Blocks SDK .Net] **Fixed: the built-in RTSP server could fail to start with a Media Foundation H264 or HEVC encoder selected.** The pipeline string for the RTSP media factory carried every MF encoder property unconditionally, but GStreamer installs those properties only when the Media Foundation transform advertises them - on a host where the MFT exposes less, `gst_parse_launch` rejected the whole string (`no property "qp" in element "mfh264enc"`) and the server never came up. The launch string now carries the element name and bitrate only, and the remaining settings are applied to the real element after the factory builds the pipeline, skipping any property the MFT does not advertise (#858). - [Media Blocks SDK .Net] **Breaking: the unused `MPEG2VideoEncoderSettings.Profile` property and the `MPEG2VideoEncoderProfile` enum have been removed.** The FFmpeg MPEG-2 encoder these settings drive (`avenc_mpeg2video`) cannot apply an MPEG-2 profile or level at all - gst-libav deliberately skips the codec's profile/level options when exposing element properties and never maps them from caps either - so the property silently did nothing and every stream was written with the libav defaults (Main profile). Verified against GStreamer 1.28.2; a regression test now pins the stream profile the encoder actually produces (#259). - [Media Blocks SDK .Net] **Breaking: four more dead `MPEG2VideoEncoderSettings` properties removed - `ForceDuplicatedMatrix`, `IntraQuantBias`, `InterQuantBias` and `MPEGQuant`.** None of them exists as a property on `avenc_mpeg2video`, so every pipeline logged a GLib critical per property and silently ignored the value; no caller could have observed any effect. Also fixed `FrameSkipCompare` being rejected at runtime with a type-mismatch critical - the value is boxed as an integer now, like every other enum setting on this encoder. - [Core] **Mac Catalyst builds no longer silently lose macOS behaviour behind `#if !__IOS__` guards.** The `__IOS__` define is set for `net10.0-maccatalyst` too, so code guarded only against iOS was compiled out of every Catalyst build with no warning: the video overlay sink never had `force-aspect-ratio` set, opening or playing media could switch audio off while additional audio streams or audio processing blocks were queued, a `file://` URI passed to `Audio_AdditionalStreams_AddAsync` failed where a plain path worked, and the Video FingerPrinting log context stayed unwired so its diagnostics fell back to raw trace output instead of the SDK logger. All twenty-two affected sites now use the guard shape the rest of the SDK already used, which lets Mac Catalyst through wherever macOS is let through (#1141). - [Core] **Blu-ray and DVB source types are declared on Mac Catalyst, matching the macOS API surface.** Blu-ray playback needs only playbin, tsdemux and h264parse, all of which ship in the macCatalyst GStreamer runtime, so `BluRaySourceSettings` and `BluRaySourceBlock` work there exactly as they do on macOS. `dvbsrc` ships in neither Apple desktop runtime, so the DVB types now exist for API parity alone and their availability check reports false at runtime - the same answer macOS gives (#1141). - [Core] **`Pango.CoreTextFont` is now declared on Mac Catalyst**, matching the macOS API surface. The file was hidden behind a bare `#if !__IOS__`, which compiles out of Catalyst as well because `__IOS__` is defined for it too (#1142); its DllImport now names the library that actually exports the symbol on the Apple builds (`libpangocairo`, not `libpango`). - [Media Blocks SDK .Net] **The unused public type `RemoveSilenceSettings` has been removed.** No API in the SDK ever accepted it, so code holding an instance could not pass it anywhere; silence removal is configured through `RemoveSilenceAudioEffect` (for `AudioEffectsBlock` / `MediaPlayerCoreX`) or directly on `RemoveSilenceBlock`, which expose the same `Threshold` and `Squash` properties (#1117). - [Media Blocks SDK .Net] **New: versioned JSON persistence for pipelines and blocks.** A pipeline can now be saved to and restored from a human-readable `.json` document that carries the pipeline settings, every block with its settings, the connections between blocks, and an optional opaque editor section. The integer `MediaBlockType` value is the authoritative discriminator, so a document restores to exactly the blocks it was written with; unknown properties, unknown sections and blocks this SDK does not know about are preserved without loss, so newer files still load on older SDKs. New public API: `MediaBlocksPipelineDocument`, `MediaBlockDocument`, `MediaBlocksPipelineJsonSerializer`, `MediaBlockJsonSerializer`, `MediaBlocksDiagnostic`, and a schema-migration registry (`IMediaBlocksPipelineDocumentMigration`) for future format versions. Materializing a document into a live pipeline arrives in the next stage. - [Media Blocks SDK .Net] **Every `MediaBlockType` member now carries an explicit integer value, identical on every platform and build flavor.** The values were previously implicit except for a few anchors, which made them differ between Windows and non-Windows builds around the platform-gated members - any integer-serialized block type crossing a flavor boundary was ambiguous. The numbering follows the existing Windows order, so existing explicit pins (251, 277, 400+) are unchanged. Two members that silently carried duplicate numbers move to fresh unique ones: `UDPRAWMPEGTSSource` from 400 (collided with `ONNXInference`) to 443, and `WebView2Source` from 401 on Windows (collided with `YOLOObjectDetector`) to 444 - the old numbers were ambiguous by construction, so no working code can have relied on them. - [Media Blocks SDK .Net] **Blocks that shared a `MediaBlockType` value now have their own: `UniversalAutoDemux`, `UniversalSourceMini`, `FallbackSwitchSource`, `ImageOverlayCairo`, `FrameDoubler`, `CustomColorspaceX`, `SqueezebackBlockV2`, `PreEventSeparateOutput`, `TextOverlaySource`, `ImageVideoSourceCairo`, `UniversalTransform`, `UniversalDecoder`, `UniversalDemuxDecoder`, `AppBridgeAudioSink`/`Source`/`VideoSink`/`VideoSource`, `StreamSourceWithDecoder` and `LiveSourceSwitchDynamic` (424-442).** The primary class of each pair keeps the historical value; the variants listed here are new members appended at the end, so nothing is renumbered. Affected classes: `UniversalAutoDemuxerBlock`, `UniversalSourceBlockMini`, `FallbackSwitchSourceBlock`, `ImageOverlayCairoBlock`, `FrameDoublerBlock`, `CustomColorspaceXBlock`, `SqueezebackBlockV2`, `PreEventSeparateOutputBlock`, `TextOverlaySourceBlock`, `ImageVideoSourceCairoBlock`, the `AppBridge*Block` quartet, `StreamSourceBlockWithDecoder`, `LiveSourceSwitchBlockDynamic`, and `IOSVideoSourceBlock`, which now correctly reports the existing `IOSVideoSource` instead of `SystemVideoSource`. Code that switched on these types may need the new members added to its cases. - [Media Blocks SDK .Net] **Breaking: the unfinished YAML persistence API is removed.** `YAMLBlock`, the commented-out `YAMLConfig`, `IMediaBlock.ToYAMLBlock()` and `MediaBlock.ToYAMLBlock()` are gone; none of them ever produced output (`ToYAMLBlock` threw `NotImplementedException`). JSON is the only supported Media Blocks persistence format. - [Media Blocks SDK .Net] **macOS and Mac Catalyst: the Metal video renderer no longer hangs a process that has no window, and the Metal elements are no longer picked automatically.** Two defects in the bundled `vfmetal` plugin, both of which a customer could reach without ever naming a Metal element. `vfmetalvideosink` created its own window through a blocking call onto the main thread; in a process whose main thread is not running a Cocoa event loop - a console tool, a service, a test host - that call never returned and the pipeline sat in preroll forever, with nothing on the bus to say why. Worse, the same call could deadlock an ordinary windowed application: an app that starts a pipeline and then waits for it on its UI thread was blocking the very thread the sink needed. The sink no longer waits at all - it asks for the window and drops frames until it appears, which lets the pipeline preroll and frees the UI thread to create it. The first frame is kept rather than discarded, so a pipeline that is only paused - a preview, a scrub, a thumbnail - still shows its picture the moment the window appears. If fifteen seconds pass with no window the pipeline reports an error saying whether a window handle was missing or simply never acted on, and a pipeline that finishes without ever displaying anything says so on the bus when it stops. `vfmetalcompositor` and `vfmetalvideosink` also registered at ranks high enough to be auto-selected, so the Metal compositor silently became the mixer inside every `VideoEditCoreX` timeline and the Metal sink was what `autovideosink` chose; both now register at rank none, like the other five Metal elements, and are used only when you ask for them by name. Separately, `MetalVideoCompositorBlock` failed negotiation whenever anything downstream asked for an output size other than the size of its inputs; it now accepts the requested size and composes onto a canvas of that size, as the software compositor does - each input still sits where its pad properties put it rather than being stretched to fill. The plugin is also rebuilt against the 1.28.6 runtime the rest of the package ships (#878). - [Media Blocks SDK .Net] **macOS: three further fixes in the Metal video renderer, found while fixing the above.** Resizing the video window could briefly show the picture offset or stretched: the frame's position was computed against the new window size while the picture itself was still being drawn at the old one. A second defect could crash the process during teardown - the thread delivering frames read the render view at the moment the window was being closed, and could be left holding memory that had just been released. And `IVideoView`-style re-parenting now works: handing the renderer a second, different window used to be ignored silently, so it kept drawing into the first one; it now detaches and attaches to the new one (#878). - [Media Blocks SDK .Net] **GStreamer pipelines and reported codecs are built identically on every system locale.** Six places wrote or compared locale-sensitive text where GStreamer only ever accepts invariant text. The Apple H.264 encoder writes its `quality` parameter into the pipeline string - fractional **0.5 by default**, so with no property ever set - and on every comma-decimal locale (German, Russian, French and most of continental Europe) it produced `quality=0,5`, which the parser rejects: an RTSP server built on those settings handed every connecting client an error instead of a stream. The MP3 encoder had the same defect in its VBR quality parameter, reachable by selecting the Quality rate control with a fractional quality such as 2.5; the NVIDIA H.264 and HEVC encoders in their `const-quality` parameter, reachable with any fractional quality value; and the VP8/VP9 encoders in their three buffer-size parameters - the element takes whole milliseconds there, so on those locales the comma form broke every duration, and a sub-millisecond duration is now truncated to the whole millisecond instead of being written as an unparsable fraction. And under the Turkish and Azerbaijani casing rules a codec name reported by stream discovery came back as `VİDEO/H264` instead of `H264` - silently, with no error anywhere. gst-launch strings and codec identifiers are invariant by construction and are now written as such, on every platform (#1133). - [Media Blocks SDK .Net] **macOS and Mac Catalyst: a new AAC encoder, `AppleAACEncoderSettings`, backed by the AudioToolbox encoder built into the operating system.** It is the same encoder the rest of macOS produces AAC with, it handles up to **8 channels** where the existing AAC backends stop at six, and it offers four rate control modes including true VBR - set `RateControl` to `Variable` and drive the rate with `VBRQuality` instead of `Bitrate`, which the two variable modes ignore. It appears in every output's `GetAudioEncoders()` list as "Apple AAC". **It is not the default**, and that was a measurement rather than a preference: against a lossless source on Apple Silicon the two encoders trade places with the bitrate - behind `avenc_aac` at 96 kbps, level at 128 kbps, ahead at 192 kbps - while their CPU cost is indistinguishable, since AAC encoding runs well over a hundred times faster than realtime either way. `AVENCAACEncoderSettings` therefore stays the default and nothing changes unless you select the new one. Not available on iOS: the GStreamer runtime shipped for iOS does not carry the element yet, so check `AppleAACEncoderSettings.IsAvailable()` rather than the platform (#1110). - [Media Blocks SDK .Net] **DV and DVCPRO files no longer fail to open at random with "Cannot access memory for read and write operation".** Roughly one attempt in twenty - measured 1 in 30 on macOS - the file never reached PLAYING and the pipeline reported that error from `avdec_dvvideo`. The libav decoder in GStreamer 1.28 can decode straight into the video renderer's own buffer pool, but it describes the frame with its own, more strongly aligned layout - for 720x480 DV that puts the second colour plane 768 bytes past what the renderer allocated - and reading the frame back then fails. **This is not macOS-specific and the change is not platform-gated:** the defect is in the runtime both platforms now ship (1.28.6 on macOS, 1.28.2 on Windows); macOS is simply where it was measured. The libav video decoders that take that path now decode into their own memory and copy the finished frame out. That is every libav decoder except H.264, H.265 and H.266, so **expect one extra frame copy per frame wherever an `avdec_` decoder handles DV, DVCPRO, MPEG-1/2, MPEG-4, DivX/Xvid, WMV, MS-MPEG4 or ProRes** - formats that are software-decoded anyway. Hardware decoders and every non-libav element are unchanged. The fix reaches both the blocks that pick a decoder by name - `UniversalSourceBlockV2`, `UniversalDecoderBlock`, `UniversalDemuxDecoderBlock` - and the decoders `decodebin`, `uridecodebin`, `playbin` and GES build for themselves inside `MediaBlocksPipeline`, `VideoEditCoreX` and `SimplePlayerCoreX`. A pipeline you assemble yourself out of raw GStreamer elements is not covered, and neither is the internal media-info discovery graph, which cannot hit this (#1121). - [Media Blocks SDK .Net] **New: `AppleMediaHEVCEncoderSettings` - HEVC encoding through Apple VideoToolbox, including 10-bit and an alpha channel.** There was no VideoToolbox HEVC encoder in the SDK at all, so on a Mac `HEVCEncoderBlock.GetDefaultSettings()` found no hardware encoder and HEVC output was unavailable. It now returns this one. `Profile` selects Main or Main 10 (10-bit), and `PreserveAlpha` switches to the alpha-capable encoder; both need the GStreamer 1.28.6 runtime, which ships in the macOS and Mac Catalyst packages - the iOS package still bundles 1.24.9, where neither is available. - [Media Blocks SDK .Net] **New: constant-bitrate rate control on the VideoToolbox encoders.** `AppleMediaH264EncoderSettings` and `AppleMediaHEVCEncoderSettings` gain `RateControl` (`ABR`, the default, or `CBR`) plus `DataRateLimitBitrate` / `DataRateLimitDuration`, a bitrate ceiling averaged over a sliding window - what a fixed-bandwidth endpoint needs on top of a target bitrate. The two are alternatives, not complements: with `CBR` selected VideoToolbox ignores the data rate limits outright, because constant bitrate is already a ceiling; the limits apply in `ABR` mode. Two caveats worth planning around: truly constant bitrate requires macOS 13+ or iOS 16+ on Apple Silicon - elsewhere VideoToolbox emulates it through limits of its own and says so in its log, and the output is near-constant rather than constant; and on iOS the properties do not exist in the bundled runtime at all, so the setting is discarded with a warning (#1109). - [Media Blocks SDK .Net] **macOS and Mac Catalyst: the bundled GStreamer runtime moves from 1.24.12 to 1.28.6, and the audio output no longer hangs on shutdown.** Stopping a pipeline whose audio went to the system output could wedge the process: pausing tore the CoreAudio render callback down from inside the audio device's own IO thread, and that inverted two locks against each other. Measured on this machine before the upgrade, one run in five of the audio processing suite hung and had to be killed after 15 minutes; after it, none. Three things come with the new runtime that are worth knowing about. **VideoToolbox gains hardware decoding of VP9 and AV1 and 10-bit HEVC encoding**, and the H.264/HEVC encoders gain real rate control (constant-bitrate, and a hard data-rate cap) - availability depends on the Mac, so ask the SDK rather than assuming. **Vulkan-based elements work on Apple Silicon for the first time**: the library we shipped was built for Intel only, so on an M-series Mac none of them loaded at all. And the **iSAC speech codec is gone** - GStreamer dropped it upstream, and there is no replacement in the runtime; pipelines that asked for it by name will report a missing element. Everything else the SDK creates was checked element by element against the old runtime and is unchanged. **Delete `bin` and `obj` once after taking this update.** Several bundled libraries change file name in this release - OpenSSL, libsoup and the FFmpeg libraries all move to a new major version - and an incremental rebuild leaves the previous ones in the output directory beside the new ones. - [Media Blocks SDK .Net] [Video Edit SDK .Net] **DV output now pins the video format to PAL SD (720x576, 25 fps) instead of failing negotiation on any non-SD source.** The DV encoding profile carried no restriction caps, so the encoder was handed the source's native resolution and framerate and negotiation failed. Note that DV encoding is currently blocked by an upstream gst-libav defect (#1126); this fix makes the profile correct for when it is unblocked. - [Media Blocks SDK .Net] **macOS and Mac Catalyst: the bundled CoreAudio plugin carries one fix on top of upstream 1.28.6.** Stopping a CoreAudio device holds a lock that the device's own audio callback needs, and the thread doing the stopping sits inside CoreAudio holding it for milliseconds - measured on an Apple Silicon Mac at a median of 1.6 ms and as long as 240 ms. Upstream removed that inversion where the device is *started* and never where it is stopped. In practice 1.28.6 is very hard to hang this way, because the callback now stands down before it touches that lock whenever the pipeline is paused first - which every shutdown does; the case it leaves open is an audio capture source renegotiating its format, which stops the device with no pause in front of it. The bundled `libgstosxaudio.dylib` is therefore built from upstream 1.28.6 sources with the stop side removed too. Everything else in the runtime is unchanged upstream bytes. - [Media Blocks SDK .Net] **macOS and Mac Catalyst: barcode detection through `BarcodeDetectorBlock` (the GStreamer `zbar` element) no longer crashes the whole process on the first frame.** The bundled `libzbar` was built by a compiler that exploits undefined behaviour in zbar's backward image scan: the scan's row-step arithmetic wraps to an invalid pointer value, and the compiled code materializes that wrapped pointer literally instead of decrementing the pointer, so scanning any image wider than two pixels dereferences address 0xffffffffffffffff and dies with SIGSEGV - deterministically, in every host process, on both Apple Silicon and Intel. The two instructions are corrected in place; QR detection verified working after the fix (#1168). - [Media Blocks SDK .Net] **A branch of a running pipeline could stop delivering data for good after a dynamic add or remove.** Blocking a pad that was already blocked installed a second block the SDK had no handle on - it remembered only the first - so unblocking the pad left the second one in place for the life of the process, and the branch went silent or froze with nothing in the log. Reachable wherever two block scopes could overlap on one pad: the live audio and video mixers, `LiveVideoCompositorV2`, and element removal or replacement in a running pipeline. The same bookkeeping was a shared static table with no locking, and it never released the pads of removed inputs - one pad object pinned in memory per removed mixer or compositor input, permanently. It is gone: each block now carries its own handle. `MediaBlockPad.BlockPadLive()` changes with it in two visible ways: blocking an already-blocked pad is now a no-op that reports success rather than a second block nobody can lift, and a block that could not be installed reports `false` instead of reporting success (#1115). - [Media Blocks SDK .Net] **Updating an OpenGL shader's settings on a running pipeline no longer leaves the block half-connected.** `GLShaderBlock.Update()` swaps the `glshader` element for a freshly configured one, and the block kept holding the pads of the element that was removed - every later connection, pad block or end-of-stream notification through that block then went to an element nothing feeds. The block now re-reads both pads after the swap. The element replacement underneath it was also reporting success over a pipeline it had cut in half: a replacement element that has only one of the two pads the position needs threw or silently linked against nothing, and a link the SDK could not make was logged and then reported as a completed replacement. Both are refused now, with the old element left running (#1136). - [Core] **Media analysis no longer fails on a rotated video when the system locale writes its negative sign with a non-ASCII character.** ffprobe reports a portrait phone recording as `rotate=-90`, and the rotation was read through the machine's current locale. On the 57 cultures whose negative sign is not a plain hyphen - every Arabic locale, which prefixes it with U+061C, and the Persian ones, which use U+200E U+2212 - that parse threw and the file could not be analysed at all. ffprobe output is invariant by construction and is now parsed as such, along with the container bitrate and every duration (#1104). - [Core] **ONVIF: authenticated requests carry a valid timestamp on any system locale.** The `Created` value of the WS-Security UsernameToken was rendered through the machine's calendar, so a Thai machine sent the year 2569, a Persian one 1405 and a Saudi one 1447 and the camera rejected the request. In the legacy ONVIF client the same string is also what the password digest is computed over, so both were wrong. `xs:duration` values had the matching defect in both directions: written with a comma on any comma-decimal locale, and read back either failing outright (Russian, French) or silently taken as five seconds instead of half a second (German) (#1104). - [Core] **ONVIF: a device's log timestamps are read in the right era.** The log reader picked out date fields using the machine's locale, so under the Umm al-Qura calendar (`ar-SA`) a plain ISO timestamp was not recognised at all, and under the Persian and Thai Buddhist calendars it was read into the wrong era - 2026-05-12 became 2647 or 1483. The invariant form is now tried first, with the machine's locale kept only as a fallback for a device that formats its log the same way (#1104). ## 2026.8.24 - [Core] **macOS: enumerating video sources no longer logs a warning for capture devices that are not AVFoundation cameras.** `VideoCaptureDeviceInfo` read the AVFoundation-only `device-index` property from every device it was given, and any other device class - a Decklink card, an ATEM surfaced through the Decklink provider - has no such property, so building its entry failed part-way and logged a warning. The property is now read only for AVFoundation devices (#1091). - [Core] **Breaking: `Gst.Rtsp.RTSPConnection.Receive`, `ReceiveUsec`, `ConnectWithResponse` and `ConnectWithResponseUsec` take their message by `ref`, and now actually hand it back.** All four marshalled the message into a temporary block, let GStreamer write the parsed message into that block, and then threw the block away - so every successful receive returned `Ok` with the caller's message unchanged - a fresh one still `RTSPMsgType.Invalid`, carrying no headers and no body, and everything C had allocated into it leaked. Worse on the failure path: GStreamer releases the message's contents before returning an error, so the caller was left holding freed pointers and a later `Unset()` released them a second time. The message is read back on every path now, so a read that reached the socket and then failed leaves it empty rather than dangling. A call rejected by GStreamer's own argument checks - a closed connection, which answers `Einval` - still returns the message untouched and owned by the caller (#1096). - [Media Blocks SDK .Net] **Stopping or disposing a pipeline no longer waits without a time limit for it to reach the NULL state.** A pipeline that reported the change as asynchronous and then never completed it left `StopAsync()` and `Dispose()` blocked for good. The wait is bounded now, matching the rest of the stop path: it logs a warning and the teardown carries on (#849). - [Media Blocks SDK .Net] **`AudioMixerBlock.CreateNewInputLive()` returns `null` when the input could not be added,** instead of a pad that was never wired to anything. Check the result before linking: the previous pad produced a GLib critical out of `gst_pad_link` and a link result that looked like an ordinary refusal. - [Media Blocks SDK .Net] **`RemoveSilenceBlock` and the `RemoveSilence` audio effect now actually remove silence.** The underlying element's `remove` property defaults to off and was never set, so the filter detected silence and then passed every buffer through unchanged - the block was a no-op whatever it was configured with. It is enabled now. **Check your `Threshold` before upgrading:** it is a linear amplitude, and the documentation used to have its direction backwards - it claimed 1.0 meant "no silence detection", where 1.0 is in fact full scale and classifies every sample as silence. That was harmless while nothing was ever dropped; now a threshold near 1.0 removes the whole stream. Two defaults move with it, both onto the element's own: `Threshold` from 0.05 (-26 dB, which would have cut ordinary quiet speech) to 0.001 (-60 dB), and `Squash` from `true` to `false`. Neither default breaks existing code - nothing was ever dropped, so neither had any effect to change; they are what the block does now that it works. One thing does: `Threshold` is validated against its documented 0.0-1.0 range now, the way the compressor's already was, so a value outside it throws `ArgumentOutOfRangeException` where it used to be accepted and ignored. With the block actually removing audio, an out-of-range threshold empties the track instead. `Squash = true` pulls every buffer after a removed passage back by its duration, so the audio track ends up shorter than the video of the same recording - set it yourself when you want the gapless, shortened output and nothing has to stay in sync with it. The `Squash` documentation was describing the missing `remove` property rather than what `Squash` does: silence is always dropped, and `Squash` decides whether the surviving buffers are pulled back to close the gap or keep their original timestamps (the default). - [Media Blocks SDK .Net] **`RemoveSilenceBlock.Threshold` and `RemoveSilenceAudioEffect.Threshold` now reach the silence detector.** The linear value was passed straight to an element property that is measured in decibels, and the conversion GLib applied silently turned the default 0.05 into 0 dB - full scale, where practically every sample counts as silence. The linear value is converted properly now; the public API is unchanged. - [Core] **`Gst.Sdp.SDPMessage`'s property setters now actually set what they say.** All seven wrote directly into the native struct at a computed field offset instead of calling GStreamer's own setter. For `Version`, `SessionName`, `Information` and `Uri` that stored a fresh copy over the old string without releasing it, leaking on every assignment. For `Origin`, `Connection` and `Key` it was worse: those fields are C structs embedded **by value** - `GstSDPOrigin` is six strings in a row - and the setter wrote a *pointer* to a temporary block into the first eight bytes of one, so `msg.Origin = o;` corrupted the username field, left the other five untouched, and leaked the block, while `msg.Connection = c;` never wrote `Ttl` or `AddrNumber` at all. All seven now go through `gst_sdp_message_set_*`, which replaces every field properly (#1086). - [Core] **Breaking: several `Gst.Sdp` members change shape, and the GStreamer binding's `Free()`, `Unset()` and `Clear()` methods no longer corrupt the heap.** `SDPMedia.Media`/`Proto`/`Information`/`Key` and `SDPTime.Start`/`Stop` become read-only properties; `SDPMessage.AddMedia`, `InsertTime` and `ReplaceTime` take their value by `ref` because C moves it into the message and the caller must not release it again; and the setters on `SDPMedia.Fmts`/`Connections`/`Bandwidths`/`Attributes` and `SDPTime.Repeat` are removed - they stored a plain pointer array in a field C keeps a `GArray*` in, so any call to one guaranteed a crash on the next release (use `AddFormat`, `AddConnection`, `AddBandwidth`, `AddAttribute` and `SDPTime.Set`). Those methods marshalled a copy of the value into a temporary native block and released *that*, which went wrong three ways at once: the marshaller allocates every `string` field with `CoTaskMemAlloc` and C frees it with `g_free`, the block itself was allocated with `AllocHGlobal` and freed with `g_free`, and the wrapper then freed the same pointer a second time - so `Gst.Rtsp.RTSPTransport.Free()`, `Gst.Rtsp.RTSPRange.Free()`, `Gst.Rtsp.Global.RtspRangeFree()`, `Gst.Sdp.SDPMedia.Free()`/`Uninit()` and the `Gst.Sdp.SDPAttribute`/`SDPBandwidth`/`SDPConnection`/`SDPTime`/`SDPZone` `Clear()` methods aborted the process instead of releasing anything. Values whose fields the binding copies - `RTSPTransport`, `RTSPTimeRange`, `SDPAttribute`, `SDPBandwidth`, `SDPConnection`, `SDPZone` - own no native memory at all, their factory already released it, so releasing one now clears the value and makes no native call. `SDPMedia` and `SDPTime` are the exceptions: they wrap live native memory, so their string fields become raw pointers behind **read-only properties** (`SDPMedia.Media`/`Proto`/`Information`/`Key`, `SDPTime.Start`/`Stop`), which is what makes `SetMedia`, `SetProto`, `SetInformation`, `SetKey`, `SDPTime.Set`, `Uninit()`, `Free()` and `SDPTime.Clear()` work; write through those methods rather than the properties, and only on a value you own - on one borrowed from `SDPMessage.GetMedia` the setter frees a string the message still points at. One thing to know about that: those properties now read native memory on every access, so a value obtained from `SDPMessage.GetMedia`/`GetTime` must not be read after the message is disposed - copy what you need out while it is alive. `Equals` and `GetHashCode` on those two structs consequently compare by pointer rather than by string content, the way they already did for the array fields - two medias with the same text are no longer equal, and a value's hash changes after a `SetMedia`. And the release methods on those two now really do release: call `Free()`/`Uninit()`/`Clear()` **only on a value you created** (`New`, `Init`, `Copy`, `SetMediaFromCaps`, `SDPTime.Set`), never on one borrowed from `SDPMessage.GetMedia`/`GetTime` - that one is a window onto memory the message owns, and releasing it leaves the message dangling until its own teardown trips over it. A borrowed value is also only valid until the message is next modified: `RemoveMedia`, `ReplaceTime` and their siblings release the element they drop, so read what you need out of a `GetMedia`/`GetTime` result before changing the message, not after. The same allocator mismatch is gone from the `Insert`/`Replace` overloads that take an `SDPAttribute`, `SDPBandwidth`, `SDPConnection` or `SDPZone`: C copies the struct into the message or media by shallow `memcpy` and frees its strings with `g_free`, and the binding was handing it CLR-allocated ones - no signature changed, the strings are now GLib-allocated at the boundary. `SDPMessage.AddMedia` takes `ref` because C moves the media into the message and empties the source. The matching leaks are gone with them: `Gst.Rtsp.Global.RtspMessageNew`/`NewData`/`NewRequest`/`NewResponse` leaked an 88-byte message plus its header array on every call, and `SDPMedia.New`/`Init`/`Copy`/`SetMediaFromCaps` leaked a media plus four arrays, because the only documented release path was one of the broken methods (#1086). - [Core] **Breaking: `Gst.Sdp.SDPMedia.Fmts`, `Connections`, `Bandwidths`, `Attributes` and `Gst.Sdp.SDPTime.Repeat` return typed arrays and finally read what they describe.** All five threw `ArgumentException` on any value that held something: they walked their field as a NULL-terminated array of pointers, and the helper doing the walking called `Marshal.PtrToStructure` in a form that refuses a value type - which is the only reason it did not hang instead, because its loop compared the walking address against zero while incrementing that same address and so had no exit at all. In C these fields are `GArray *`, not pointer arrays, so repairing the walk would still have taken the array's length field for an element pointer. `Fmts` and `Repeat` are `string[]` now, `Connections` is `SDPConnection[]`, `Bandwidths` is `SDPBandwidth[]` and `Attributes` is `SDPAttribute[]`, read through GStreamer's own indexed accessors - all but `Repeat`, for which C exports none, so that one reads the array directly; they were `IntPtr[]`. Reading one on an empty or already-released value returns an empty array rather than crashing. Unlike `Media`, `Proto`, `Information`, `Key`, `Start` and `Stop`, which read native memory on every access, the values these five hand back are copies taken at read time and stay valid after the media or time is released (#1087). - [Media Blocks SDK .Net] **One stalled pipeline no longer freezes bus message delivery for every other pipeline in the process.** Latency recalculation ran directly on the GLib main loop, which is shared process-wide and dispatches one source at a time. A pipeline whose latency query could not complete - a stalled mixer, a wedged source - therefore held that loop and stopped the EOS, error and state-change messages of all other pipelines, including the ones their `StopAsync`/`Dispose` were waiting on, so unrelated pipelines appeared to hang (#1065). The recalculation now runs off the bus loop, with bursts of latency notifications coalesced so a graph is never recalculated twice at once. - [Core] **Breaking: `Gst.Object.Replace` and `Gst.Rtsp.Global.RtspAuthCredentialsFree` change signature, and the GStreamer binding's `T **` out-parameters now return real data instead of uninitialised heap.** Eighteen P/Invoke declarations passed a C out-parameter by value, so native wrote its eight-byte pointer into the front of a caller-allocated struct-sized block and everything past that was read back as garbage - `Gst.Rtsp.RTSPUrl.Parse` returned a url whose host, path and credentials were undefined, `Gst.Rtsp.RTSPRange.Parse` returned a range whose unit was a random integer, and the same held for `RTSPTransport.New`, `SDPMedia.New`/`Copy`, the `RTSPMessage` constructors and `RTSPAddressPool.ReserveAddress`. `Gst.Object.Replace(oldobj, newobj)` was worse: it handed native the object pointer where C wants the address of a variable, so every call unreffed the object's class pointer and overwrote it - it becomes `Replace(ref Gst.Object oldobj, Gst.Object newobj)`, and the parameterless overload becomes `Replace(ref Gst.Object oldobj)`. `RtspAuthCredentialsFree` now takes the credential array pointer (`IntPtr`) rather than a single `RTSPAuthCredential`, which native was reading as a pointer and freeing. Two more of the same family are fixed with it: `Gst.Sdp.SDPMessage.Init` becomes an instance method (`msg.Init()`) and `Gst.Sdp.Global.SdpMessageInit` now takes the message, because C's `gst_sdp_message_init` re-initialises a message you already own - declared as an out-parameter it wrote a whole SDP message through an eight-byte stack slot and aborted the process inside malloc; and `WebRTCICE.OnGetLocalCandidates`/`OnGetRemoteCandidates` now return `WebRTCICECandidateStats[]`, since C returns a NULL-terminated array of pointers that was being read as a single struct. **`Gst.Video.VideoInfo.Init` and `Gst.Audio.AudioInfo.Init` become instance methods** for the same reason - C's `gst_video_info_init`/`gst_audio_info_init` initialise an info you already own, and as out-parameters they wrote a whole GstVideoInfo over the caller's stack frame and returned null every time; use `new VideoInfo()` / `new AudioInfo()` to get one, then `Init()` to reset it. `Gst.Rtsp.Global.RtspTransportInit`, `RTSPTransport.Init`, `Gst.Sdp.Global.SdpMediaInit` and `SDPMedia.Init` no longer hand those C functions an uninitialised heap block, which they began by calling `g_free` on. The `Gst.Rtsp.RTSPMessage` struct also gains the `type_data` union it was missing, so its layout matches the native one (#1062). - [Core] **macOS: video capture no longer opens a different camera than the one selected.** The device index passed to `avfvideosrc` was recorded once at enumeration time, but macOS may reorder cameras between enumeration and pipeline start (USB re-enumeration), so after such a reorder every new capture opened whatever device had taken the selected camera's position - typically failing with "Internal data stream error" or capturing from the wrong webcam. The position is now resolved from AVFoundation's live device list by stable unique ID right before each start; the enumerated index remains as a fallback. If the selected camera is no longer connected, capture now fails with an explicit error instead of silently opening a different camera. `VideoCaptureDeviceInfo` gains `AvfUniqueID` on macOS (#843). - [Core] **iOS: the selected camera is now opened by its AVFoundation unique ID rather than by its localized name.** Video capture looked the camera up by display name across every AVFoundation device, microphones included, so a name that was not unique - or that changed with the device language - could open a different camera or none at all. The unique ID recorded at enumeration is now authoritative: a camera that no longer resolves by it fails outright rather than falling back to a name match that could open a different camera. The name search remains only for a settings object built by hand, which carries no unique ID at all. A camera that cannot be found now fails with an error naming both the device and its unique ID (#1089). - [Core] **Video capture blocks no longer throw `NullReferenceException` when no camera was found.** `CreateWithDefaultDeviceAsync()` returns a block with no settings when device enumeration comes back empty - camera permission denied, a simulator, a machine with no webcam - and only the Android path checked for it. Every other platform dereferenced the missing settings and threw out of the public `Build()`; both `SystemVideoSourceBlock` and `IOSVideoSourceBlock` now return `false` and log what is missing. The same applies to settings that exist but name no device, and on iOS to settings with no video format. - [Core] **SDK log events now carry the exception object, not just its text.** Every logging call that takes an exception passed it to Serilog as a message-template value rather than as the exception, and a template with no placeholders discards it - so a sink whose output template renders `{Exception}` printed nothing there, and exception types and stack traces never reached the log at all. They are attached properly now, across the whole SDK. - [Core] `KLVDecoder` and `KLVRemux` are now `static` classes. Both only ever exposed static members, so documented usage (`KLVDecoder.DecodeFromFile(...)`) is unaffected; code that instantiated them with `new` will no longer compile. - [Core] `VideoFrameRate` gained the `<=` and `>=` operators, completing the comparison set alongside the existing `==`, `!=`, `<` and `>`. They use the same 0.0001 tolerance as `==`. ## 2026.8.23 - [Core] **WPF skin controls are now available on every Windows target framework.** `VisioForge.Core` previously compiled the WPF skins (`SkinPlaylist`, `SkinCaptureControls`, `SkinPlayerControls`, …) only for `net*-windows10.0` and .NET Framework targets, so projects targeting a plain `-windows` TFM such as `net10.0-windows` — including the Skinned Player and Skinned Capture demos under the nano build flavour — failed with "The tag 'SkinPlaylist' does not exist in XML namespace" (#859). Note that `SkiaSharp.Views.WPF` ships no asset for plain `-windows` targets, so restore falls back to its .NET Framework asset (NU1701); the controls compile and work. - [Media Blocks SDK .Net] **Fixed a process crash when a subtitle auto-hide timer fired after the overlay block had been torn down.** `OverlayManagerBlock.Video_Overlay_Update` dereferenced its internal element without a null check on the re-add path, so a late subtitle hide tick raised an unhandled `NullReferenceException` on a timer thread and aborted the whole process (#823). - [Media Blocks SDK .Net] **Media Foundation H.264/HEVC encoders no longer log a GLib critical and silently drop the reference-frames setting on every run where it is left at the default.** The default of 0 ("encoder default") lies below the encoder element's own property range, which starts at 1; the value is now skipped instead of being written out of range (#857). ## 2026.8.22 - [Core] **Breaking: `new Gst.Buffer(size)`, `new Gst.BufferX(size)` and `new Gst.BufferList(size)` are replaced by `Gst.Buffer.NewAllocate(size)`, `Gst.BufferX.NewAllocate(size)` and `Gst.BufferList.NewSized(size)`.** The size constructor sat one implicit conversion away from the pointer constructor `Buffer(IntPtr)`, and since .NET 7 an `int` literal converts implicitly to a native integer - so `new Gst.Buffer(1024)` silently bound to the pointer overload and produced a buffer wrapper over address 1024. Nothing failed at the call site; it crashed later inside GStreamer with no hint of where it came from. The allocating form is now a named factory that cannot be confused with wrapping a pointer, and both old spellings fail to compile with a message naming the replacement. Wrapping an existing native pointer is unchanged. - [Core] **Long GStreamer sessions no longer grow their native memory footprint on every negotiation, frame push and dropped frame.** The managed wrappers for `GstCaps`, `GstBuffer`, `GstEvent`, `GstMessage`, `GstMemory`, `GstSample`, `GstQuery` and `GstTagList` never released the native object: `Dispose()` and `using` on them did nothing at all, so every capability negotiation, every pad-caps query and every self-allocated buffer that was created and released left its native allocation behind for the life of the process. The effect grew with running time and with the number of pipelines built and torn down; it was largest on paths that touch caps or buffers per frame - pad probes, overlays, VU metering, and the custom mixer's queue-overflow frame drops. Reference counting is restored, so disposing these objects - or letting the garbage collector do it - now actually frees them. - [Video Edit SDK .Net] **Encoder settings on the render/output path are no longer silently lost on hosts where the encoder element exposes fewer properties.** Video Edit renders configured the encoder through the GStreamer `encodebin` profile, which writes every property with an unchecked `g_object_set`: a property the concrete element class does not expose - Media Foundation encoder classes are generated per device, so their property set differs from machine to machine - raised a GLib critical and was dropped without any error. The profile now pins only the encoder factory; the settings are applied to the encoder element after encodebin creates it, with each property probed first and a warning logged when one is not available. - [Media Blocks SDK .Net] **`SimpleVideoMarkDetectBlock.VideoMarkDetected` now actually fires.** The block installed its bus handler with `Bus.AddWatch`, but a GStreamer bus supports a single watch and the pipeline already owns it, so the install silently failed and watermark detection never reported anything; the handler is now delivered through the pipeline's own bus signal dispatch. Two defects found behind the same dead event are fixed with it: the detection pattern was read from a message field that does not exist (the element posts it as `data`), and the handler could be handed an already-released message by the pipeline's own bus handler running before it. - [Core] **Disposing `DeviceEnumerator` while another thread was starting device monitoring or enumerating NDI/Decklink devices no longer risks disposing the same GStreamer device monitor twice** - which surfaced as GLib object-lifetime criticals in the log, or as a device monitor left running after dispose. Monitor teardown now serializes with monitor creation through one lock (so device-monitor work is queued across enumerator instances), and concurrent `Dispose()` calls are safe. NDI enumeration still never blocks other instances: its potentially slow mDNS discovery runs outside the shared lock on an exclusively claimed monitor. - [Core] **Disposing any `DeviceEnumerator` instance no longer breaks NDI device-provider toggling for every other enumerator in the process.** Dispose released the shared registry-feature wrapper all instances use to load/unload the NDI provider, so after one enumerator was disposed its siblings passed a dead pointer into the GStreamer registry on every later enumeration (`gst_registry_remove_feature: assertion 'GST_IS_PLUGIN_FEATURE' failed` in the log). The reference is now dropped instead of disposed. - [Core] **Dropping an engine object without disposing it no longer risks killing GStreamer for the rest of the process.** `VideoCaptureCoreX`, `MediaPlayerCoreX`, `SimplePlayerCoreX`, `MediaBlocksPipeline`, the Live Video Compositor and its outputs, the overlay managers and several other classes ran their full GStreamer teardown from the garbage collector's finalizer thread when an instance was never disposed - which could take the process-global GStreamer registry with it, so every pipeline created afterwards failed to build with nothing in the log connecting the failure to the object collected minutes earlier. Finalizers now leave the native objects to the binding's deferred release path; `Dispose` remains the way to stop pipelines deterministically. One trade to know about: a recording whose engine was never disposed ends without a muxer trailer and stays unplayable - dispose explicitly to finalize files. - [Core] **An undisposed GigE (Aravis) camera now releases its stream and camera handles at collection** instead of taking locks, tearing down timers and raising events from the finalizer thread. Stopping acquisition still requires an explicit `Disconnect()`. - [Media Player SDK .Net] **A faulted dispose of `MediaPlayerCoreX` no longer leaves the player permanently half-torn-down with no way to finish it.** If stopping or closing the pipeline threw during `Dispose`/`DisposeAsync`, the player marked itself as disposed while the GStreamer pipeline had never reached NULL and internal resources were never released - and every later dispose call only re-observed the stored failure instead of retrying. A faulted teardown now leaves the player usable, flushes and re-arms the debug log for the next attempt, and a subsequent `Dispose()` or `DisposeAsync()` completes the teardown. - [Video Capture SDK .Net] **DirectShow Picture-in-Picture recording no longer fails with "Unable to set PIP layer settings" in Horizontal and Vertical layouts, and `PIP_CustomOutputSize_Set` now produces output of exactly the requested size.** The struct passed by value to the video mixer filter declared its frame-duration field as 32-bit while the native filter reads it as 64-bit, so every output-settings call was rejected and the mixer silently kept its previous canvas: in Horizontal/Vertical layouts the later layer-position calls then failed with an error at start, and with a custom output size smaller than the main video the recording came out at the wrong size. Output size is now applied before layer positions, the main video fills a custom canvas, and a failed PiP configuration call logs the failing parameters with the native result code. ## 2026.8.21 - [Demos] **The Avalonia demos and the console RTSP servers build again on macOS regardless of which macOS workload patch is installed.** They pinned `net10.0-macos26.2`, a target platform version that only machines whose workload manifests declare 26.2 accept - everywhere else the build failed before compilation with `NETSDK1140: 26.2 is not a valid TargetPlatformVersion for macOS`. The demos now use `net10.0-macos` with no version suffix, like the rest of the sample tree, so the platform version follows whatever the machine has installed. - [Demos] **The remaining Media Blocks console demos and the Blazor RTSP servers build again on Apple-silicon Macs.** An unconditional `PlatformTarget x64` conflicted with the `osx-arm64` runtime identifier inferred for `net10.0-macos` (`NETSDK1032`) in VideoResizer, FrameRateAdjuster, RTSPViewCV and both Blazor RTSP servers; the pin is now Windows-only. The ones used as `.app` bundles on macOS also lacked a bundle identifier and now declare one. - [Demos] **The Live Subtitles console sample no longer declares a macOS target.** Whisper.net requires static whisper.cpp archives on Apple platforms and `Whisper.net.Runtime` ships none for macOS, so the sample's speech-to-text pipeline could not link there; it stays available on Windows and Linux. - [Media Blocks SDK .Net] **Stopping a pipeline with `ObjectAnalyticsBlock` no longer logs analytics or overlay errors and no longer loses the frame that was in flight.** Teardown freed the block's renderer, tracker, zones and lines while the streaming thread could still be using them, so a frame arriving during the stop was dropped with a logged `ObjectDisposedException` or null-reference message; teardown now waits for the frame in flight before freeing anything. - [Media Blocks SDK .Net] **`FallbackSwitch` enabled on source settings passed directly to a source block is no longer silently ignored.** `RTSPSourceSettings.FallbackSwitch` (and the same property on the SRT, NDI, RTMP and HTTP source settings) is applied by `VideoCaptureCoreX` and by an explicit `FallbackSwitchSourceBlock`; a bare `RTSPSourceBlock`, `SRTSourceBlock`, `SRTRAWSourceBlock`, `NDISourceBlock` (or the Windows-only `NDISourceXBlock`), `RTMPSourceBlock` or `HTTPSourceBlock` does not use it, and enabling it there now logs a warning at build time explaining how to get automatic failover instead of proceeding without any message. - [Core] **`MediaInfoReaderX` no longer spins up a full-throughput decoder just to read file metadata.** The discovery pipeline let GStreamer auto-plug `dav1ddec` with its defaults - threading and frame delay sized to the CPU core count - so reading the metadata of one 8K AV1 file pre-allocated a reference-frame pool costing ~700 MB of working set on a 14-core machine and growing with every core. Discovery now pins that decoder to low-latency single-thread mode before it starts, bounding the same read by the stream's reference structure instead of the machine's core count (~310 MB for 8K AV1 on any machine). - [Core] **The built-in HLS/DASH HTTP server on macOS and Linux no longer dies if a player connects while it is starting.** - [Core] **The built-in HLS/DASH HTTP server on macOS and Linux now accepts IPv6 clients, including `http://localhost/` when that name resolves to `::1`.** - [Media Blocks SDK .Net] **Adding an audio or video effect to a running pipeline no longer leaves it paused.** Under concurrent effect changes, the pipeline could still be resuming when the add returned, leaving later effect operations or stopping playback waiting indefinitely. - [Media Blocks SDK .Net] **A video or audio effect added while the pipeline has just left Playing now reaches the running graph.** A pause that landed during the add used to leave a video filter in NULL, and to skip the audio filter until the next build. - [Media Blocks SDK .Net] **A pipeline that was preloaded and then resumed no longer flickers back to paused, and no longer seeks `StartPosition`, after playback was already started.** Resume (or the next `StartAsync`) had already published `Play`, but a late confirmation of the preload's pause could overwrite it and re-seek. `MediaPlayerCoreX.State`, which reports the pipeline's state, is covered by the same fix. - [Media Blocks SDK .Net] **A live-added proxy, buffer or subtitle bridge source now brings its whole graph up with the pipeline.** Those three sources published no core wrapper, so a live add synced only the one GStreamer element the block exposed and left the rest of the bridge in NULL. - [Media Blocks SDK .Net] **`MediaBlocksPipeline.SyncBlockStateLive` no longer throws on a block that was never built, and no longer races the block's own teardown.** Calling it out of order - before `AddBlockLive` built the block, or after it had been cleaned up - raised a `NullReferenceException` out of the SDK instead of returning `false` with a logged reason like every other refusal in that method. It also read the block's element and then synchronised it after releasing the lock that guarded it, so a teardown landing in that window left the live add reported as "failed to set block to Playing" with the real reason only in a GStreamer log line. The same "has not been built" refusal now also applies to `MediaBlockHelper.SetState` and `MediaBlockHelper.SendEvent`. - [Media Blocks SDK .Net] **RTSP playback no longer fails with "Failed to link RTSP pad: WasLinked" when the source re-announces a pad.** On a reconnect, or when an RTSP server re-announces a stream, `UniversalSourceBlockV2` could report a pad it had already linked as a link error and end the session - intermittently, since two of rtspsrc's streaming threads can pass the "is this pad linked" checks together. A duplicate announcement is now recognised from the link result itself - a second attempt reports `WasLinked`, which is logged at debug level instead of failing the session - and the handler's check-and-link section is serialised. - [Core] **A handler connected with `Connect(...)` or with `+=` on a generated GStreamer event no longer keeps that object alive for the life of the process.** Every `Connect(...)` on an element - the mechanism behind source, demuxer and decoder auto-plugging - and every `+=` on a generated event was recorded in a process-wide table that only an explicit unsubscribe ever cleared, and the entry held the element, the handler, and everything the handler had captured. An application that builds and tears down sources or decoders in a loop, a playlist or a transcode over a directory, grew without bound with nothing disposable to blame. A connection is now owned by the object it was made on and is released with it. Two defects of the same family go with it: a handler silently stopped being delivered once its wrapper had been disposed, and the callback's handle was released while an emission could still be inside it - a rare crash on a streaming thread when a recording was stopped on a file split. ## 2026.8.20 - [Video Capture SDK .Net] **`VideoCaptureCoreX.WaitForStartAsync` no longer waits forever, and no longer returns before the capture starts.** It polled for `PLAYING` and nothing else, so a source that never gets there - an RTSP or HTTP address that black-holes, a capture device with no signal, a Decklink with no input - parked a thread on a `Task` that never completed, and an asynchronous failure (which takes the pipeline back to `READY` without tearing it down) did the same. The wait now ends when the start settles somewhere it will not leave, and has a 30-second deadline; the new `WaitForStartAsync(TimeSpan timeout, CancellationToken cancellationToken = default)` overload chooses that deadline, cancels the wait, and returns whether `PLAYING` was actually reached. The documented fire-and-forget pairing `_ = StartAsync(); await WaitForStartAsync();` also no longer completes instantly against a capture whose pipeline does not exist yet. - [X-engines] **A second `Start()` landing while the first is still building is now rejected instead of building over it.** `VideoCaptureCoreX.Start()` and `MediaBlocksPipeline.Start()` had the guard only on their async twins, so a concurrent call cleared the first start's state and re-entered the build over the pipeline that call was still assembling. Relatedly, a start that fails now finishes its own rollback before it releases the start, so processing blocks registered by another thread are no longer disposed under it, and a throw out of a restart's teardown no longer leaves the instance permanently unable to start. - [Media Blocks SDK .Net] **A `ChromaKeyBlock` added to a running pipeline now brings its whole graph up with the pipeline, not just the compositor.** The block builds six elements, and a live add synchronised the state of only one of them, so the other five - the background scaler and capsfilter, the alpha key, and both converters - stayed in whatever state they had been created in. They now live in one bin, which is the one thing the pipeline brings up. - [Media Blocks SDK .Net] **A start the pipeline refuses is now reported as stopped instead of as playing.** When an element refused the transition to playing - a capture device that cannot be opened, a renderer that cannot create its window - `Start()` returned `false` but left `State` reporting `Play`, and left every element that had already opened a device, handle or socket holding it. The pipeline is now torn down and reports `State = Free`, so a retry rebuilds it. With `PauseOnStop` enabled that retry previously returned `true` without rebuilding anything, on a graph that never started. A start that never started no longer raises `OnStop` when it is stopped afterwards. `MediaPlayerCoreX.State`, which reports the pipeline's state, is covered by the same fix, and `VideoCaptureCoreX.Start` now returns as soon as the pipeline fails instead of going on to start the auto-start outputs against it. - [Media Blocks SDK .Net] **A preload that fails while prerolling is now reported.** `StartAsync(onlyPreload: true)` and `Start(onlyPreload: true)` returned `true` whenever the source failed asynchronously - a camera already in use, an unplayable file, a stream that never connects - and left the pipeline holding whatever its elements had opened, with nothing telling the caller. Only a transition the pipeline refused outright was reported. Both now return `false` and tear the partial graph down; `Pause()` on a running pipeline reports the same failure the same way. - [Media Blocks SDK .Net] **The processing block passed to an `LVCVideoInput` constructor is now applied.** On LiveVideoCompositor V2, the optional `processingBlock` argument of both `LVCVideoInput` constructors was stored and never linked into the graph: the input composited unprocessed, with no error and no log line, while the identically shaped argument of `LVCVideoAudioInput` worked. It is now an alias for `LVCVideoInput.ProcessingVideoBlocks`, so the block runs between the source and the mixer as the argument always implied. Code that already uses `ProcessingVideoBlocks` is unaffected. - [Media Blocks SDK .Net] **The `channel` parameter of `LiveVideoCompositorV2.Video_Effects_*` is deprecated.** V2 has a single effects block on the composed output, after the mixer, so the index never selected anything - `Video_Effects_Clear(channel: 1)` cleared the whole composition's effects, where the identically named V1 call validates the index and ignores a channel that does not exist. Every `Video_Effects_*` method now has a channel-free form; the overloads that take a `channel` still work, forward to it and warn. To process a single input rather than the composition, add a `VideoEffectsBlock` to that input's `LVCVideoInput.ProcessingVideoBlocks` - those blocks run between the source and the mixer, which is where V1's per-channel effects were. V1 is unchanged. - [Media Blocks SDK .Net] **An effect added to a running pipeline while that pipeline is being stopped is no longer left in the graph unreachable.** `VideoEffectsBlock.AddOrUpdateAsync` and `AudioEffectsBlock.AddOrUpdate` splice the new effect into the live graph, and that work can take seconds - it runs your `OnUpdate` handler twice and pauses the pipeline to relink it. A stop that gave up waiting for it went ahead and released the block anyway, and the insertion then carried on and spliced its element in regardless: the block no longer knew about it, so `Remove()` reported success without removing anything and the next `Build()` created a second element under the same name, for the rest of the run. Both blocks now stop an insertion the moment a teardown has been through, and leave the element to the pipeline's own disposal - on an ordinary stop that is what releases it. The effect stays registered, so the next build puts it in the graph. - [Media Blocks SDK .Net] `MediaBlocksPipeline.State` now reports `Pause` as soon as `StartAsync(onlyPreload: true)` / `Start(onlyPreload: true)` returns, instead of briefly reporting `Free` while the pipeline was already preloading. Inside that window a preloaded pipeline looked stopped to every "is anything running?" check: `StopAsync` and `Stop` returned without tearing it down and without raising `OnStop`, `Dispose` skipped the stop it does first, `ClearBlocks` disposed the blocks of a live pipeline instead of refusing, a `StartPosition` set on the preloaded pipeline was dropped instead of seeked, and starting playback right after a preload could be rejected with "Already starting or start in progress". `MediaPlayerCoreX.State`, which reports the pipeline's state, is covered by the same fix. ## 2026.8.19 - [Media Blocks SDK .Net] `RTSPSourceSettings.BufferMode` and `DropOnLatency` now reach the RTSP source. Setting them previously had no effect, so jitter-buffer tuning was silently ignored. The default jitter buffer is **500 ms**; `LowLatencyMode` uses **150 ms**, or the explicit `Latency` if you set it to 150 ms or less. - [Media Blocks SDK .Net] **Changing video mixer settings while the pipeline is being stopped no longer crashes or silently does nothing.** `SetSettings`, `Input_Update`, `Input_Move`, `StartFadeIn`, `StartFadeOut`, `Input_UpdateChromaKeySettings` and `Input_SetChromaKeyEnabled` ran with nothing serialising them against the block's own teardown, so a call that landed during a stop reached GStreamer through an element the teardown had already released - a `NullReferenceException`, or a change that was accepted and quietly not applied. Building a mixer while it was being stopped had the same problem and could throw out of `Build()`. Affects `VideoMixerBlock`, `VideoMixerSourceBlock`, `GLVideoMixerBlock`, `D3D11VideoCompositorBlock` and `MetalVideoCompositorBlock`. `AddInputPadLive` on a mixer that is not built now returns `null` and logs, instead of throwing. - [Media Blocks SDK .Net] **A video mixer fade or move animation no longer outlives the block that started it.** `StartFadeIn`, `StartFadeOut` and `Input_Move` animate on a background thread for the duration requested; stopping or disposing the mixer while one was running left that thread writing to a released element, which took the whole application process down with an unhandled `NullReferenceException`. Teardown now stops the animations and waits for them first. They also no longer keep the process alive after everything else has finished. - [Video Fingerprinting SDK .Net] **Disposing a `FrameSource` while `PlayAsync` was still starting no longer leaves a playing pipeline behind.** The teardown and the start shared no synchronization, so a `Dispose()` - or a `StopAsync()` - landing mid-start tore down the session the start was still building, and the start went on to leave a fully wired pipeline that nothing owned: `OnVideoFrame` kept firing for the rest of the process. Overlapping `PlayAsync`/`StopAsync` calls, which a UI can produce with two quick clicks, could also tear the same pipeline down twice. `FrameSource` now also implements `IAsyncDisposable`; `await frameSource.DisposeAsync()` is the deterministic teardown, because a synchronous `Dispose()` cannot wait for a start already in flight. - [Media Blocks SDK .Net] **Disposing a pipeline that was only preloaded (`StartAsync(onlyPreload: true)`) no longer hangs.** The teardown skipped the stop for a preloaded pipeline and set its elements to the null state under a live streaming thread, which wedged the disposing thread and the streaming thread against each other indefinitely. - [Media Blocks SDK .Net] **Disposing a pipeline while it was reporting a state change no longer hangs.** The teardown and the pipeline's own message thread could block on each other for good. - [Media Blocks SDK .Net] `VP8EncoderSettings.GetCaps()` now reports `video/x-vp8` instead of `video/x-vp9`. - [Media Blocks SDK .Net] An IPv6 URL such as `udp://[ff05::1]:5004` now reaches a UDP source, a universal source and an RTSP server without the brackets, so the element binds and joins multicast instead of failing silently. A Windows link-local zone id (`%12`) is left intact instead of being decoded as a byte. - [Media Blocks SDK .Net] `LiveSourceSwitchBlock.Switch(i)` no longer **pairs one source's video with another's audio** on a switcher that holds a mix of input types. A video-only input and a video+audio input take their switch pads from two independent counters, so the same index meant a different source in each of the two switches: with a video-only input added first, `Switch(1)` played the second input's picture with **silence**, because no input feeds audio pad 1. `Switch` now resolves the input at the given index and moves each switch to that input's own pad. An input that carries only one of the two streams leaves the other switch where it was, so switching to a video-only input keeps the audio that was playing. New `CurrentVideoIndex` / `CurrentAudioIndex` properties report the pads actually selected. Two smaller changes come with it: an index past the last added input is now refused and logged instead of pointing the switch at a reserved pad that carries nothing, and `SourceSwitchBlock.Switch` returns `bool` - `false` when the block is not built yet, the index is out of range, the pad at that index was never obtained, or a concurrent stop tore the element down - where it used to return `void`. Every one of those is logged; a switch that could not be applied no longer passes silently. - [Media Blocks SDK .Net] `LiveSourceSwitchBlockDynamic.Switch(slot)` no longer **silences the audio when the slot holds a video-only input**. Nothing feeds that slot's audio pad, so moving the audio switch there played silence; it now stays where it was, matching `LiveSourceSwitchBlock.Switch`. An **empty** slot is not that case - switching to a slot with no input in it still takes the audio with it, rather than leaving the previous source's sound playing under a black picture; one limit is structural, in that a switcher whose `MaxAudioInputsCount` is smaller than its `MaxVideoInputsCount` has no audio pad above the audio limit for the audio to move to. A slot index past the last slot is now refused and logged; on a switcher whose audio switch has more pads than its video one it used to move the audio switch while the video switch declined, so the sound went silent under a picture that kept running. Its `CurrentVideoIndex` / `CurrentAudioIndex` also **start at `-1` instead of `0`** - they used to report slot 0 before any switch had been applied, which was not true, and they now record only a switch the block actually applied. Code that reads either property before the first switch and indexes its own array with the result has to handle `-1`. - [Media Blocks SDK .Net] Disposing a `LiveSourceSwitchBlock` now **releases its inputs and internal resources**. The teardown freed nothing at all, so an application that created and disposed switchers - or added file inputs to one - leaked a whole graph, including a pipeline per input, on every instance. - [Media Blocks SDK .Net] A `LiveSourceSwitchBlock` configured for **one stream only** (`VideoStream` or `AudioStream` turned off) now starts. It threw a `NullReferenceException` on the first `StartAsync`, so the setting could not be used at all. `Input_AddAsync` now also **refuses an input for a stream the switch does not carry** and returns `false` instead of throwing, or - for an audio input on a video-only switch - accepting it and playing nothing. The same applies to `LiveSourceSwitchBlockDynamic.Input_AddToSlotAsync`, where a video/audio input on a switch without audio is now refused rather than half-connected. - [Media Blocks SDK .Net] Building a `BridgeBufferSourceBlock` whose paired sink was never created, or has already been disposed, no longer throws `ArgumentNullException` — `Build()` returns `false` instead. - [Media Blocks SDK .Net] **Retargeting a UDP sink at runtime no longer sends to a mixed destination.** `UDPSinkBlock.SetFilenameOrURL` and the UDP MPEG-TS sinks pushed the new host and the new port as two separate steps, so two calls landing at once could leave the sink streaming to one URL's host and the other's port. An **IPv6 URL now reaches the sink correctly** - `udp://[ff05::1]:5004` used to arrive with the brackets still on the address, which it cannot resolve, the URL reported back by `GetFilenameOrURL` could not be parsed again, and a link-local zone id (`udp://[fe80::1%25eth0]:5004`) kept its percent escape. This covers the UDP **sink**; the UDP source, universal source and RTSP server are the matching follow-up. New public overload `UDPSinkSettings.TryParseUrl(string url, out string host, out int port)` returns the parsed pair, for callers that must not read it back off shared settings. - [Core] Fixed a **memory leak on every GStreamer property or caps field set to a string, or to a caps, structure, buffer or tag reference**. The value handed to the element was copied but the caller's copy was never released, so each set leaked the string's allocation - or, for caps and elements, held a reference that kept a live GStreamer object alive for the rest of the process. Worst on properties pushed repeatedly: text and image overlay contents, bridge channel names, device paths, file names and URLs, and every caps renegotiation. Numeric and boolean properties were never affected. - [Media Blocks SDK .Net] A media block that is **garbage-collected without being disposed** no longer tears its GStreamer elements down from the finalizer thread. An application that forgot a `Dispose()`, or dropped a block after an exception, could see a crash or a stall inside the .NET finalizer during collection; abandoned blocks now leave their elements to the pipeline that owns them. - [Core] The WPF `VideoView` no longer shows a **black preview in a remote-desktop session** when the D3D11 composable renderer is requested. Such a session composes WPF in software and its Direct3D9 device sits on a different adapter, so the GPU surface can never be presented; the view now detects that and falls back to its software rendering path automatically, logging a warning, instead of displaying nothing. - [Core] Fixed the WPF `VideoView` **silently dropping back to software rendering on the second playback**. After a `Stop()` the next start rebuilt the view from the engine's renderer mode alone — and both the `D3D11Composable` and `Direct2DManaged` paths rewrite that mode to `FrameCallback` — so GPU-resident composition degraded to a per-frame CPU upload, with no error and `GetSurfaceProvider()` returning `null`. The view now remembers the renderer it was asked for and restores it on the next start; setting a different renderer mode on the engine between two starts still switches away from it, as before. - [Media Blocks SDK .Net] **Audio effects added during playback are now inserted at their position in the effect list**, so the applied order no longer depends on whether an effect was added before or during playback - and a second effect added straight after the first is no longer silently left out of the pipeline. The block's output also correctly follows the last effect after live additions and removals; removing the last effect used to leave the block pointing at the removed one. - [Media Blocks SDK .Net] An audio or video effect **added while the pipeline was being stopped or disposed** is no longer silently lost. Stopping the pipeline from the effect's own `OnUpdate` handler let the block build the effect's element against a pipeline that no longer existed: nothing failed, nothing was reported, and the effect was simply absent from the graph. The block now reports it and keeps the effect registered, so the next start puts it in. - [Core] Calling `Dispose()` on a GStreamer wrapper object no longer prints a GLib critical such as `gst_iterator_free: assertion 'it != NULL' failed` or `gst_structure_free: assertion 'structure != NULL' failed`. The object was always freed correctly; a second, redundant free with a null handle produced the log line. This affected `Gst.Iterator`, `Gst.Structure`, `Gst.Video.VideoInfo`, `Gst.Audio.AudioInfo`, `Gst.Video.VideoConverter`, `Gst.ParseContext` and the other non-reference-counted opaque wrapper types, all of which are now safe to dispose. ## 2026.8.18 - [Core] Fixed a **crash when playback was stopped while the WPF `VideoView` was rendering through `Direct2DManaged`**. The view freed the RGBA staging buffer on the UI thread while a frame was still being converted into it on the streaming thread, which corrupted the heap or took the process down outright. The same buffer was also sized from the very first frame and never grown, so a source that **switched to a higher resolution mid-stream** overflowed it. - [Core] Fixed the WPF `VideoView` **silently replacing a classic engine's `WPF_WinUI_Callback` / `FrameCallback`, `None`, `Direct2DManaged` or `D3D11Composable` renderer mode with EVR**. The view built a native HWND renderer instead of the requested one, so WPF controls placed over the video stopped composing (airspace), and for `WPF_WinUI_Callback` and `None` the engine's `Video_Renderer.VideoRenderer` read back `EVR` — a mode the application never set. (`Direct2DManaged` and `D3D11Composable` still read back as `FrameCallback`: the view draws those itself and the engine feeds it frames.) Calling `VideoView1.SetNativeRendering(false)` is no longer required for the software rendering path. - [Media Blocks SDK .Net] Stopping a pipeline that has **already reached the end of its stream** no longer waits ten seconds for an end-of-stream that has already happened. The output file was already complete; the stop just took that long to return. - [Media Blocks SDK .Net] Fixed **stopping a pipeline reporting a spurious error** — `Resume for EOS did not reach PLAYING ... Muxer may not finalize` — when the pipeline had not finished starting up yet. The stop also stalled two seconds before reporting it, and applications that treat an SDK error as a failure saw a clean stop as a failed one. - [Media Blocks SDK .Net] Fixed a **crash when chroma-key settings were changed while the pipeline was being stopped**. Updating the key color, alpha or sensitivity from one thread used to be able to land on the filter while another thread was tearing it down. - [Media Blocks SDK .Net] Fixed **audio effect settings being silently discarded when changed while the pipeline was being stopped**. Every audio effect — volume, balance, amplify, echo, compressor/expander, both equalizers, pitch, loudness normalization, RNNoise, HRTF, Csound, the Chebyshev filters, karaoke, wide stereo, reverberation and the rest — used to be able to push a change onto an element another thread had already released, in which case nothing happened and nothing was reported. - [Media Blocks SDK .Net] Fixed **removing an audio effect while the pipeline is being stopped leaving that effect in the graph**. The removal reported success while the effect was still spliced into the chain, and could also throw `IndexOutOfRangeException` out of `AudioEffectsBlock.Clear`. - [Media Blocks SDK .Net] Fixed **`AudioEffectsBlock.Remove` not removing an effect that had been updated since it was added**. The live element was unplugged but the effect stayed in the list, so the next time playback started it came back. - [Media Blocks SDK .Net] Fixed **`AudioEffectsBlock.AddOrUpdate` called twice with the same effect object stopping that effect's later property changes from reaching the graph**. - [Media Blocks SDK .Net] Audio effect names are now matched the same way everywhere — **case-insensitively**. Adding `Volume` and then `volume` used to create two effects that both drove the first one. - [Media Blocks SDK .Net] Fixed a **`NullReferenceException` when an audio effect property was changed after the pipeline had been stopped**. - [Media Blocks SDK .Net] Pipelines containing an `AudioEffectsBlock` no longer carry **one unused audio converter element** each. - [Media Blocks SDK .Net] Fixed **the whole video or audio effect chain silently disappearing for the rest of the run** after a stop that had to give up waiting for an effect operation to finish. The block was left claiming it was built while owning nothing, so every later start produced no effects at all and reported no error. - [Media Blocks SDK .Net] Fixed **`VideoEffectsBlock` keeping every effect object it was given alive after it was disposed**. The effects stayed subscribed to the disposed block, so neither they nor the pipeline's elements could be collected, and changing one of their properties afterwards reached a block whose pipeline was gone. ## 2026.8.17 - [Media Blocks SDK .Net] Fixed **playback freezing for the rest of the run when a video or audio effect added to a running pipeline is refused by the graph**. The effect is simply not applied now, instead of leaving the chain cut at the point it was being inserted. - [Media Blocks SDK .Net] Fixed the same freeze on the removal side: **removing a video or audio effect from a running pipeline no longer cuts the chain when the surrounding elements cannot be linked to each other**. The effect stays in place and the removal reports failure, instead of reporting success over a chain nothing flows through. - [Media Blocks SDK .Net] **Removing an effect that is built from several elements — box, crop, aspect-ratio crop, resize, pan/zoom, fisheye, LUT, text overlay, image overlay, QR overlay, mouse highlight, overlay manager, pitch, compressor/expander, loudness normalization — now takes them out of a running graph as one unit.** A removal that succeeded for some of an effect's elements and failed for the rest used to leave the effect half in the graph: the next effect added live could end up in the wrong position, or the block could stop producing output altogether. The removal now either takes the whole effect out or leaves it running untouched and reports failure. - [Media Blocks SDK .Net] **Removing a LUT or QR-code overlay effect live no longer leaves the chain pinned to that effect's pixel format.** Both build an internal format filter, and it used to stay in the graph after the effect was gone, forcing RGB on everything downstream of it for the rest of the run. - [Media Blocks SDK .Net] **Repeatedly adding and removing a LUT effect during playback no longer leaves an unused element in the pipeline for every add.** That internal format filter is now taken out with the rest of the effect instead of accumulating one per add; the QR-code overlay releases its own the same way. - [Media Blocks SDK .Net] **Changing an effect's settings from one thread while the pipeline is being stopped on another no longer silently does nothing.** The push used to be able to land on an element the teardown had already released, in which case it was discarded without any error being reported. Most visible on Android, where the renderer's resize is updated from the view thread whenever the view is resized or the device is rotated. - [Media Blocks SDK .Net] Fixed a **`NullReferenceException` when the Android renderer's view was resized while the pipeline was stopping**. ## 2026.8.16 - [Core] Fixed video fingerprinting **`FrameSource.PlayAsync` throwing `NullReferenceException` unless the optional `Crop` and `CustomResolution` properties were set**. - [Core] Video fingerprinting: **new `FrameSource.StopAsync()`** stops the current session and releases its pipeline so the instance can be reused — previously the only way to stop was disposing the whole object. - [Core] Video fingerprinting: **the `VFPAnalyzer` error callback now fires exactly once per failed analysis, on the caller's thread**, with the underlying cause — previously mid-run errors could be swallowed entirely or delivered from the pipeline's internal thread. - [Core] Video fingerprinting: **a repeated `FrameSource.PlayAsync` now stops and disposes the previous session** instead of leaving its pipeline playing for the life of the process, **a failed `PlayAsync` cleans up the half-built pipeline and is reported through the `VFPAnalyzer` error callback** instead of hanging the analysis, and `Dispose` tears the session down in a safe order. - [Core] Fixed **event handlers subscribed after start never being called** in `VideoCaptureCoreX` (`OnError`, `OnStart`, including separate outputs), `MediaPlayerCoreX` (`OnError`, `OnStart`, `OnPause`, `OnResume`) and the video fingerprinting `FrameSource` (`OnError`, `OnStop`) — the engines captured a snapshot of the handler list at start, so late subscribers were silently ignored and unsubscribing mid-session did not detach. - [Media Blocks SDK .Net] Fixed LiveVideoCompositor **`Video_Effects_Clear` removing every channel's effects instead of only the requested channel's** — clearing channel 0 no longer wipes the effects of all other channels for the rest of the run. - [Media Blocks SDK .Net] LiveVideoCompositor **video-effect calls that target a channel which does not exist, or that run after the compositor was disposed, no longer throw** `ArgumentOutOfRangeException` — the call is ignored and reported through the log and `OnError`. Applies to `Video_Effects_AddOrUpdateAsync`, `Video_Effects_Get`, both `Video_Effects_RemoveAsync` overloads and `Video_Effects_Clear`. - [Media Blocks SDK .Net] Fixed LiveVideoCompositor **`OnError` handlers never being called** — pipeline errors were dropped instead of reaching subscribers. - [Media Blocks SDK .Net] **Video effects added during playback are now inserted at their position in the effect list**, so the applied order no longer depends on whether an effect was added before or during playback, and the block's output correctly follows the last effect after live additions and removals. - [Media Blocks SDK .Net] **Video effect names are now matched without regard to case.** Adding `"Blur"` and then `"blur"` updates one effect instead of creating a second one that could never be updated or removed, and `Video_Effects_Get` keeps finding an effect whatever case it is asked for. - [Media Blocks SDK .Net] **Updating a video effect with one of a different type under the same name now replaces it in the pipeline.** The graph used to keep applying the old effect and only report the mismatch. - [Media Blocks SDK .Net] Fixed **a video effect added while the pipeline was starting never reaching the pipeline** for the rest of the run. It is now applied as soon as playback begins. - [Media Blocks SDK .Net] Fixed **adding, removing and updating video effects from several threads at once** leaving a filter in the pipeline that no public call could reach, or applying settings to an effect that was being removed. - [Media Blocks SDK .Net] Adding a video effect to a running pipeline now **returns only once playback has resumed**, so stopping right after it no longer reports that the pipeline could not be resumed. ## 2026.8.15 - [Media Player SDK .Net] / [Media Blocks SDK .Net] Fixed **`Video_Effects_RemoveAsync` never returning when the pipeline has nothing to pause** — a player that was never opened, or one already being stopped. It polled for the paused state with no way out, and in one overload it blocked the calling thread outright, so the call could not be interrupted from outside either. It now checks the pause once and returns: a pause that did not land is reported through the log and the effect is left in place. `LiveVideoCompositor.Video_Effects_RemoveAsync` is fixed the same way. - [Media Blocks SDK .Net] Fixed **adding a video effect never returning when the pipeline is shutting down**, and **adding one to a paused pipeline waiting forever**. The wait for playback to resume is now capped at thirty seconds; past it the effect is left for the next start and the wait is reported. - [Media Blocks SDK .Net] Fixed a **crash when changing a property of a video effect that is not applied to the running pipeline** — one added while playback was paused or stopped, with at least one other effect already active. The property setter threw an exception instead of doing nothing. - [Media Blocks SDK .Net] Fixed **an effect being applied twice to a running pipeline**, leaving a duplicate filter that could no longer be updated or removed, and **an effect coming back after being removed** when it had been re-added under the same name. ## 2026.8.14 - [Video Capture SDK .Net] / [Media Player SDK .Net] Fixed a **GStreamer error when removing a video effect** (grayscale, balance, and the other live filters) from a paused capture or player pipeline. - [Video Capture SDK .Net] / [Media Player SDK .Net] Fixed **video stopping after removing an image overlay, overlay manager, pan/zoom, or LUT effect** at runtime. - [Media Player SDK .Net] Fixed **audio going silent after removing an audio effect** during file playback. - [Media Player SDK .Net] / [Media Blocks SDK .Net] Fixed a **hang when removing pitch, compressor, loudnorm, or similar multi-element audio effects** from a live pipeline. - [Media Blocks SDK .Net] Fixed a **crash when disposing an `AudioEffectsBlock`** that still had effects in the public list. - [Video Capture SDK .Net] / [Media Blocks SDK .Net] Fixed **MP4 recordings that could not be played back after stopping a paused capture** (`VideoCaptureCoreX` / `MediaBlocksPipeline`). Start → Pause → Stop (without Resume) left a non-zero file with no `moov` index. Stopping a paused capture now finalizes the file. - [Media Blocks SDK .Net] **RTSP sources can send their own GET\_PARAMETER keep-alive.** Set `RTSPSourceSettings.ForceCustomKeepAlive` (or the same flag on `RTSPRAWSourceSettings`) to replace the default RTSP keep-alive with a GET\_PARAMETER every 30 seconds. Off by default — use it if a camera drops the session under the built-in keep-alive. - [Demos] The RTSP Preview demos now have a **transport selector (Auto / TCP / UDP)** and a **Force custom keep-alive** checkbox, so a camera that works in VLC but dies after a minute can be tried the same way without rebuilding. - [Media Blocks SDK .Net] Fixed **the first line of an `OverlayManagerText` (and `OverlayManagerDateTime`) disappearing when `Y` was 0 or close to the top of the frame.** `X` and `Y` are the top-left corner of the text in pixels; `(0, 0)` is a valid position and the first line of a multiline string is fully visible there. Previously the coordinates were treated as the Cairo baseline, so a block placed at the origin had its first line clipped off the top of the picture. - [Media Player SDK .Net] **`MediaPlayerCoreX` now has the same overlay manager as capture.** Set `Video_Overlay_Enabled` before `OpenAsync`/`PlayAsync` and use `Video_Overlay_Add` with `OverlayManagerText` (including `TextProvider`). The overlay is drawn on the preview only — after the sample grabber and after any custom video outputs — so the file on disk, snapshots and exports are not modified. Overlays added once stay across `Stop` and opening another file. ## 2026.8.13 - [Media Blocks SDK .Net] **`OverlayManagerText` can now build its text for every frame through the new `TextProvider` callback.** Set `TextProvider` to a `Func` and it is asked for the text once per frame, receiving the frame timestamp counted from the pipeline start; returning `null` falls back to `Text`. This is the supported way to overlay a live readout — sensor values, a clock, a frame counter, or a template mixing all three — without removing and re-adding the overlay or touching the pipeline. Assigning `Text` directly still works and is equally cheap: the text layout is cached on the element and re-measured only when the string, font or geometry actually changes, so an unchanged value costs nothing. The callback runs on the streaming thread while the overlay list is locked, so it must be short and must not block — calling back into a UI dispatcher from it can deadlock rather than merely drop a frame. A callback that throws is reported once through `OnError` and is then **not called again**: the element falls back to `Text` for the rest of the run, because retrying it would unwind an exception at the frame rate under that lock. Assign `TextProvider` again to re-enable it — worth knowing if your callback can throw on its first frame, while the values it reads are still being initialised. `OverlayManagerDateTime` inherits the property and substitutes its `[DATETIME]` token into whatever the callback returned. - [Media Blocks SDK .Net] **Overlay elements are now up to twice as fast on multi-core machines.** Cairo-based overlays render through `cairooverlay`, which only accepts BGRx/BGRA/RGB16, so a YUV source pays for two full-frame colour conversions per frame — and those conversions were running single-threaded, which was not enough to sustain 1080p50 on many machines. The recording branch was the first to suffer, because a preview renderer silently drops late frames while an encoder writes whatever reaches it, so the preview looked fine and the recorded file did not. Measured on a 14-core machine at 1920x1080 NV12: 361 to 815 frames per second through `OverlayManagerBlock`. Affects `OverlayManagerBlock`, `ImageOverlayCairoBlock`, `PanZoomBlock`, the mouse-highlight overlay and the Android text overlay. - [Media Blocks SDK .Net] Fixed **`StartTime` and `EndTime` on overlay elements being ignored unless both were set.** The visibility window was only applied when neither value was `TimeSpan.Zero`, so the common case of "show this for the first ten seconds" — a zero `StartTime` with a real `EndTime` — left the element on screen for the whole session. Either bound now defines a window on its own, and an `EndTime` of `TimeSpan.Zero` means the element has no end. The break is symmetric, so check both directions: an element with only `EndTime` set used to stay visible for the whole session and now disappears at that moment, and an element with only `StartTime` set used to be drawn from the first frame and is now hidden until that moment. If you set either value and relied on it being ignored, clear it. Frames that carry no timestamp at all — an `appsrc` feeding unstamped buffers, for instance — are outside any window that can be judged, and every element is drawn on them. - [Media Blocks SDK .Net] **RTCP is now on by default for RTSP sources.** `RTSPSourceSettings.DoRTCP` and `RTSPRAWSourceSettings.DoRTCP` defaulted to `false`, and the value is always written to the underlying RTSP source — so no VisioForge application ever sent RTCP receiver reports unless it set the property itself. Many cameras and RTSP servers use those reports to tell that the client is still watching and tear the session down without them: the picture freezes on the last decoded frame and the stream ends a session timeout later, with nothing in between to explain it. The same omission also made `NTPSync` ineffective, because the NTP mapping arrives in RTCP sender reports. Both properties now default to `true`, which is also the default of the underlying GStreamer element. Set `DoRTCP = false` explicitly if you talk to an old server that cannot handle RTCP. - [Demos] Fixed **the RTSP Preview demos building a second pipeline when Start was clicked twice.** Connecting to a camera takes a few seconds, and nothing appears on screen while it happens, so a second click was easy to make — it created a second pipeline over the same `VideoView` and opened a second session to the same camera. The two fought over the preview window, one of them failed with "Failed to open window", and on a camera that serves a single session its teardown stopped the stream for the surviving pipeline too, leaving a frozen picture. The Start button is now disabled while a start is in progress, a pipeline abandoned by a failed start is released instead of leaking, and the demos now report the stream ending — including a camera dropping the session — in their log instead of leaving a still frame with no explanation. - [Media Blocks SDK .Net] **A user-defined overlay element can now be drawn through the new `IOverlayManagerDrawable` interface.** `Video_Overlay_Add` accepts any `IOverlayManagerElement`, but only the built-in element types were rendered, so a custom type was silently never drawn. An element that implements `IOverlayManagerDrawable.Draw` now receives the live Cairo context of the frame exactly like `OverlayManagerCallback` does. A custom type that implements neither the interface nor a built-in type is still not drawn, but is now reported once through `OnError` naming the type instead of failing silently. ## 2026.8.7 - [Core] **The BCL cryptography packages now match the framework you target instead of always being the .NET 10 line.** `System.Security.Cryptography.Pkcs`, `System.Security.Cryptography.Xml` and `System.Formats.Asn1` were pinned at 10.0.10 for every target framework, so a .NET 6, 7, 8 or 9 application referencing a VisioForge package was pulled onto the 10.0.x line whether or not it wanted to be there — and an application holding the 8.0.x servicing line got a version conflict it could not resolve, because our own assemblies were compiled against `System.Security.Cryptography.Pkcs, Version=10.0.0.0`. A .NET 6, 7 or 8 application now resolves the 8.0.x line and .NET 9 the 9.0.x line; .NET 10, .NET Framework 4.7.2/4.8 and .NET Standard are unchanged at 10.0.10. **.NET Framework 4.6.1, .NET Core 3.1 and .NET 5 move down to the 6.0.x line** — that is the only line these three are supported on, and it is what gives them a real `net461` / `netcoreapp3.1` build instead of a `netstandard` fallback, but 6.0.x is out of support and did not receive the 2026 `System.Security.Cryptography.Xml` fixes. If you target one of those three frameworks and that matters to you, add an explicit `PackageReference` to `System.Security.Cryptography.Xml 10.0.10` in your own project — expect a build warning with it, because 10.0.x states it does not support those frameworks and falls back to its `netstandard2.0` build. That warning is exactly the reason the SDK itself does not take 10.0.x there. Every other rung sits at a patched version (8.0.4, 9.0.19, 10.0.10), because those advisories are fixed in each branch separately. On .NET 6 and .NET 7 this also replaces a `netstandard2.0` fallback with the real framework build. - [Core] **`System.Text.Encoding.CodePages` now matches the framework you target as well** — 6.0.1 on .NET Framework 4.6.1, .NET Core 3.1 and .NET 5, 8.0.0 on .NET 6 and .NET 7, and 10.0.6 unchanged on .NET 8 and newer, on .NET Framework 4.7.2/4.8 and on .NET Standard. Those older frameworks were previously handed the 10.0.6 package, which states it does not support them and gave them a `netstandard2.0` build; they now get one made for the framework they run on. This package carries no security advisory at any version. - [Core] Fixed **`VisioForge.DotNet.Core` not declaring its dependency on `System.Security.Cryptography.Pkcs`**. The package has needed it since 2026.2.19 — the licensing code verifies Authenticode signatures — but it was declared only from 2026.4.21 onwards, and only as a side effect of how the dependency graph happened to be built. If you are on a version between 2026.2.19 and 2026.4.18, the shipped assembly requires `System.Security.Cryptography.Pkcs 10.0.0.0` with nothing in the package asking for it; add the package reference yourself or move to a current release. - [Demos] Fixed **the Unity package's sample scenes logging three "The referenced script (Unknown) on this Behaviour is missing!" errors each** in any project that does not use the Universal Render Pipeline and the Input System. The scenes were authored from a URP 2D template and carried a `Light2D`, a `UniversalAdditionalCameraData` and an `InputSystemUIInputModule` that none of the samples use — the video is rendered into a uGUI `RawImage`, which needs no render pipeline and no input module. They now open cleanly on Built-in, URP and HDRP alike. - [Demos] Fixed **the Unity RTSP and IP-camera samples printing a "Frame stall" warning the moment a stream starts**, on the first connect and on every reconnect after it. The watchdog compared its timeout against the time since the last decoded frame, which is infinite before the first frame ever arrives and, after a drop, still points at the last frame of the previous session — so it fired seconds before the camera could deliver anything. The reported stall is now capped at the age of the current stream, and a camera that genuinely never delivers is still reported after the same timeout. - [Core] Fixed **the Avalonia `VideoView` reporting a black background even when one was set**. `GetBackgroundColor()` only read immutable solid-color brushes, so the mutable `SolidColorBrush` the control installs itself — and any colour a user assigns — always fell back to black, and that wrong colour fed the renderer as its clear colour. It now reads any solid-color brush, mutable or immutable. ## 2026.8.6 - [Core] Fixed **video editing and video preview breaking on macOS**. `VideoEditCoreX` failed every render that had a video track — any container, any codec — with `Internal data stream error`, while audio-only output still worked; and `VideoRendererBlock` froze the pipeline on the first frame in any application without a Cocoa UI running on its main thread, such as a console tool, a background service or a test host. GStreamer picks several elements automatically by rank rather than by name, and the Metal elements' ranks put them ahead of the software ones, so they were selected in places they were never meant for — including as the mixer inside every video-editing timeline. They are now registered for explicit use only, and the Metal video renderer is used only when you give it a view to draw into. `MetalVideoCompositor`, `MetalConvertScale`, `MetalVideoRendererSettings` and the other Metal wrappers are unaffected and still give you GPU rendering when you ask for it. - [Core] Fixed **`VideoRendererBlock(pipeline, windowHandle)` ignoring the window handle** on Windows and macOS — only the Android and iOS paths read it, so elsewhere the renderer behaved as though no target window had been given and opened one of its own. On macOS this constructor now also defaults to the Metal renderer, which is the only one there that can draw into a handle you supply. Two consequences, both documented on the constructor: the handle must be an `NSView*` (not an `NSWindow*`), and your main thread must keep running a Cocoa run loop while the pipeline plays, because the Metal renderer attaches to the view on the main queue. ## 2026.8.5 - [Core] **The SDK no longer brings a pre-release package into your dependency graph.** SkiaSharp moves from `3.119.4-preview.1.1` to the stable `3.119.4`, and Avalonia from 12.0.3 to 12.0.5 — the two had to move together, because Avalonia itself switched to the stable SkiaSharp in 12.0.4 and holding it back would have kept a preview build of the WebAssembly native assets in the graph. Restoring a VisioForge package used to pull those preview builds transitively, with no opt-in on your side and no warning: they simply appeared in your lock file and in `dotnet list package --include-transitive`. That matters if you mirror packages into an internal feed that rejects pre-release versions, or if a policy scan flags them. Everything the SDK resolves is now a stable release. The SkiaSharp difference itself is confined to bundled native libraries (libexpat 2.7.5, libpng 1.6.58) — no API changed. - [Core] **The Avalonia package no longer brings a nightly build of DialogHost.Avalonia with it.** `VisioForge.DotNet.Core.UI.Avalonia` uses MessageBox.Avalonia for `ShowMessageEx`, and MessageBox.Avalonia 12.0.0 — still its newest release — depends on `DialogHost.Avalonia 0.12.1-nightly.0.1`, so that nightly landed in the dependency graph of every application referencing our Avalonia package. DialogHost is now pinned to the stable 0.12.3. No API or behaviour change on our side. - [Core] **`VisioForge.DotNet.Core.AI.Whisper` now requires .NET 8 or newer.** Seven builds are gone from the package — `net5.0`, `net5.0-windows`, `net6.0`, `net6.0-windows`, `net7.0`, `net7.0-windows` and `net7.0-windows10.0.19041.0` — so a WinUI or WPF head on one of those is affected as much as a plain console project. `net8.0`, `net9.0`, `net10.0` and their Windows, Android, iOS, macOS and Mac Catalyst variants are unchanged. Speech-to-text runs on Whisper.net, which now depends on `Microsoft.Extensions.AI.Abstractions` and through it on `System.Text.Json` 10, and `System.Text.Json` 10 states that it does not support and has not been tested on anything below .NET 8 — so those seven builds could only have shipped in a configuration Microsoft declares untested. .NET 5, 6 and 7 are themselves all out of support. If you reference this package from any .NET 5, 6 or 7 project, retarget it to `net8.0` or later — keeping the same platform suffix if it has one; no code changes are needed. Only this package is affected — every other VisioForge package keeps its full framework list, down to .NET Framework 4.6.1. - [Core] **The macOS native package now ships the SRT and WebRTC GStreamer plugins.** Six plugins — `libgstsrt.dylib`, `libgstsrtp.dylib`, `libgstwebrtc.dylib`, `libgstrswebrtc.dylib`, `libgstwebrtcdsp.dylib` and `libgstwebrtchttp.dylib` — and the three libraries they load against (`libgstwebrtc-1.0.0.dylib`, `libgstwebrtcnice-1.0.0.dylib`, `libsrt.1.5.3.dylib`) were built and kept current but never packaged, so on macOS any pipeline using SRT or WebRTC failed to find its element, while identical code worked on Mac Catalyst, whose package has carried them all along. `VisioForge.CrossPlatform.Core.macOS.Adds` now ships the same 58 files as its Mac Catalyst counterpart. ## 2026.8.1 - [Demos] Fixed **several shipped samples referencing outdated packages**. The macOS and Mac Catalyst native packages in the demo projects were six months behind the published versions, a `net472` demo pinned a `System.Resources.Extensions` build meant for .NET 8 and newer, and the Virtual Camera and WebM redistributables were pinned to 2023-era releases. If you copied a demo project as a starting point, its package references were older than the SDK you installed. - [Core] **Security:** updated `System.Security.Cryptography.Xml` to 10.0.10, closing five advisories that affected the version shipped before it — CVE-2026-47304, a bypass of XML encryption protections rated 8.1, and four denial-of-service issues rated 7.5. `System.Security.Cryptography.Pkcs` and `System.Formats.Asn1` moved to 10.0.10 with it. The SDK does not call these APIs itself; they are reached through WCF, which ONVIF device communication uses. No action is needed on your side beyond taking the new package — but a security scan run against the previous release will have flagged it. - [Core] Fixed **a random process crash while GStreamer objects were being released**. On any platform, an application could die with an access violation (`0xC0000005` on Windows, `SIGSEGV` on macOS) on a background thread, with no error, no exception and nothing in the log to connect it to what the application had been doing — the crash landed long after the code that caused it. The SDK now checks that a native object is still alive before releasing it, and when it is not, writes one line naming the type instead of taking the process down. - [Core] **API change:** `VisioForge.GStreamer.API.CustomAPI.g_signal_connect`, `g_signal_connect_data` and `g_signal_handler_disconnect` now use `UIntPtr` for the GLib signal handler id instead of `uint`. The id is a `gulong`, which is 64-bit on macOS, Linux, iOS and Android, so the previous declaration truncated it. These are low-level interop helpers; if you call them directly, change the variable holding the handler id to `UIntPtr`. - [Media Blocks SDK .Net] **The SDK no longer takes ownership of the elements a decoder builds while playing a file.** Playing any file made the SDK hold a native reference to every element inside `uridecodebin` — parsers, demuxers, queues, several hundred per playback — and those references were given back only later, on a background thread, so the elements stayed alive past the pipeline that owned them. This is the same ownership mistake behind the render-time crash fixed below, on the playback path; measured on a four-class test run, the number of such references dropped by 78%. Affects every engine that plays or captures through a file or URL source. - [Core] Fixed **an error or warning on the pipeline bus tearing down the bus handler**. In `VideoEditCoreX` and `SimplePlayerCoreX`, an error message that carried no source element raised a `NullReferenceException` inside the handler, so that message and every message after it was lost — including the error you needed to see. A state-change message with no source could also be mistaken for one from the pipeline itself while the pipeline was being torn down. - [Video Edit SDK .Net] Fixed **a process crash after rendering with `VideoEditCoreX`**. An application that rendered several timelines in one session could die with an access violation on a background thread, typically long after the render had finished and the objects involved had been released. Rendering to WMV made it most likely, but the underlying cause affected any render. Applications that create and destroy `VideoEditCoreX` repeatedly — batch converters, render services — were the most exposed. - [Core] Fixed **`Debug_Mode` writing an empty log file**. With debug logging enabled, the log was buffered and never flushed when the engine was disposed, so a short session produced an empty file and a longer one lost everything after the last automatic flush — exactly the log you are asked for when reporting a problem. The file also stayed locked for the life of the process, so it could not be read or deleted. Affects `VideoCaptureCoreX`, `MediaPlayerCoreX`, `SimplePlayerCoreX`, `VideoEditCoreX` and `MediaBlocksPipeline`. - [Core] Fixed **the same empty log file when the engine was disposed with `await using`**. The fix above covered the synchronous `Dispose()` only, so `MediaPlayerCoreX` and `SimplePlayerCoreX` released asynchronously — the form most applications use — still produced an empty or truncated log and still held the file open. `SimplePlayerCoreX.DisposeAsync` is also safe to call twice now, and on all three engines a failure during teardown no longer swallows the log, which is precisely the case you need it for. - [Media Blocks SDK .Net] Fixed **open-vocabulary detection exhausting memory on Apple hardware**. `OpenVocabularyDetectorBlock` and `ObjectAnalyticsBlock` with an open-vocabulary detector could consume every gigabyte the machine had and bring it down rather than produce a detection. ONNX Runtime cannot map OWLv2 or Grounding DINO onto CoreML in one piece — it splits them into 126 and 255 separately compiled models — so `Provider = Auto` now selects the CPU for these two model families on Apple hardware and leaves every other AI block unchanged. Setting `Provider` to `CoreML` by name still does what you ask; it is not recommended for these models. On the CPU provider the memory retained after a detector is disposed also drops by about 2.4 GB on the same models, with no change to inference time. - [Media Blocks SDK .Net] Fixed **a crash while tearing down `ObjectAnalyticsBlock` with an open-vocabulary detector**. Disposing the block while a frame was still being analysed could free the inference session underneath the analysis and abort the process. - [Core] Fixed **Media Foundation H.264 and H.265 encoder settings being silently ignored**. On a machine whose Media Foundation encoder does not advertise a given control - the property set differs by GPU, driver and machine - the SDK wrote the value anyway. Nothing threw, the call reported success, and the encoder quietly kept its default, so the same code produced different output on different machines with no way to tell. Settings the encoder cannot accept are now skipped, and each one is named in a warning. This covers encoders you build yourself (`HEVCEncoderBlock`, `H264EncoderBlock`, `CreateBlock()`) and the AMD MA35D encoders and decoders. Encoding profiles - `MP4Output` and the other render outputs - are not covered yet, so the original symptom can still occur there. - [Core] Fixed **an instability while enumerating Decklink capture cards and outputs**. Plugging a card in or out, or listing devices from more than one place at once, could leave the SDK using a device object it had already released — harmless in the log on a good day, a crash on a bad one. - [Core] Fixed **WASAPI2 audio capture breaking up under load and never recovering**. From 2026.3.7, audio captured through a WASAPI2 device could develop artifacts that got worse over time and only cleared when the pipeline was restarted; the log filled with `Found N frames gap` warnings. The bundled GStreamer runtime was requesting a capture buffer of roughly 20 ms instead of the 200 ms it used to, so any brief stall lost audio at the driver. The buffer is back to its previous size on capture and playback alike, and the `LowLatency` setting again means what it says. Affects Windows x86, x64 and ARM64. - [Core] Added `BufferTime` and `LatencyTime` to `WASAPI2AudioCaptureDeviceSourceSettings`, `WASAPIAudioCaptureDeviceSourceSettings`, `LoopbackAudioCaptureDeviceSourceSettings`, `WASAPIRendererSettings` and `WASAPI2RendererSettings`. They control how much audio the device buffers — raise `BufferTime` on machines that see brief CPU spikes, lower it when you need latency. Defaults are 200 ms and 10 ms, matching previous behaviour; set either to `TimeSpan.Zero` to leave the underlying element untouched. - [Core] An audio renderer whose output plugin is missing from the deployment now reports a clear error instead of throwing a `NullReferenceException` out of `StartAsync`. - [Core] Fixed **the built-in HLS/DASH HTTP server never starting on Windows unless the application ran as administrator**. With `Custom_HTTP_Server_Enabled` set, the sink reported no error and the pipeline ran, but nothing was ever served — the server binds `http://*:/`, which Windows refuses to a process without an elevated token unless a URL reservation exists, and the failure went no further than one line in the log. The server now falls back to the loopback prefixes — both `http://localhost:/` and `http://127.0.0.1:/`, so a player on the same machine works whichever of the two it is given — and the log names the `netsh http add urlacl` command to run once as administrator to reach the server from other devices. Elevated applications and machines that already have the reservation are unaffected, as are macOS and Linux. - [Core] Fixed **an application that never exits after `DestroySDK()`**. The SDK runs the GStreamer main loop on a foreground thread, and `DestroySDK()` could return having failed to stop it: the request to stop was dropped whenever it arrived in the moment between that thread being created and it reaching the loop, and nothing checked afterwards. The process then stayed alive with no window, no error and nothing running — visible as an application that closes but keeps a process in the task list, or a console tool that never returns to the prompt. `DestroySDK()` now waits for the loop thread to actually finish before returning, and reports it in the log if it does not. - [Core] Fixed **the WASAPI2 audio renderer going silent whenever `Volume` was below 1.0**. The value was passed to the renderer as a whole number, so anything between 0.0 and 1.0 was rounded down to zero — setting `Volume = 0.5` produced silence rather than half volume. Only `Volume = 1.0` behaved as expected. ## 2026.7.27 - [Media Blocks SDK .Net] Fixed **a stopped pipeline not resuming when it was started again** — after `StopAsync()`, a `StartAsync()` on the same `MediaBlocksPipeline` with the same blocks returned `true` and then did nothing: a recorder wrote no bytes, a preview stayed black, and no error was reported. Stopping now keeps the blocks and the connections you made, and starting rebuilds the pipeline from them, so the same pipeline instance can be recorded, stopped and recorded again. You no longer have to recreate the pipeline and every block between runs (doing so still works). A sink filename changed between runs — `SetFilenameOrURL` — is picked up by the next run. - [Media Blocks SDK .Net] Fixed **a group of blocks that stayed silent after a pipeline was restarted**, each in the same way: the block reported a successful start and then produced nothing. OCR (`OcrBlock`) and Data Matrix (`DataMatrixDecoderBlock`) stopped raising their detection events; `UniversalDemuxBlock`, `UniversalAutoDemuxerBlock` and `UniversalDecoderBlock` delivered no data on the second run (the demuxer could also throw from a streaming thread); `StreamSourceBlock` came up over a closed stream, and now also rewinds a seekable one so a restarted source plays from the beginning; `PreEventRecordingBlock` dropped every frame and then threw from `TriggerRecording()`; both squeezeback blocks failed to rebuild. The bridge blocks silently lost the `OnEOS` handler you had attached at the first stop. - [Media Blocks SDK .Net] `MediaBlocksPipeline.ClearBlocks()` now **disposes the blocks it removes**. Removing a block hands it back to nobody, and the stop path no longer disposes it, so keeping it alive leaked whatever it held — an inference session, an encoder, a device handle. Do not call `ClearBlocks()` for blocks you mean to reuse; a stopped pipeline can simply be started again with the same blocks. - [Media Blocks SDK .Net] A stop no longer closes a file opened by `StreamSourceBlock(filename)` for good: the file is released on every stop, as before, and reopened when the pipeline is started again. Stopping and then deleting, overwriting or re-recording to the same path keeps working. A stream you passed in yourself is still never closed by the block — it is yours. - [Media Blocks SDK .Net] Fixed **a crash on Android when the video surface was recreated after the pipeline was stopped** — rotating the device or returning from the background after `StopAsync()` dereferenced the pipeline the stop had already released. - [Media Blocks SDK .Net] Fixed **an intermittent crash while a pipeline was being stopped or restarted**. Under a restart-heavy load the process aborted outright about one run in three, with no exception to catch — a bus message could still be in the middle of being handled when the stop released the pipeline underneath it. Stopping now waits for an in-flight bus message to finish before releasing anything, and gives up after two seconds rather than hanging. - [Media Blocks SDK .Net] Fixed a family of **latent memory-corruption defects around teardown and restart**, in sample grabbers, renderers, sources, decoders, bridge blocks, effects and device enumeration. Nothing failed visibly: GStreamer's own type checks turned the affected calls into no-ops, so the symptom was warnings in the log rather than a crash — but the same code was one timing change away from a hard `AccessViolationException`. Restarting a pipeline produces far fewer `GST_IS_ELEMENT` / `GST_IS_PAD` warnings; the remaining ones are being worked through. - [Media Blocks SDK .Net] Fixed **removing a video or audio effect at runtime leaving the pipeline holding a released element**. Every effect filter — 51 of the video ones and 15 of the audio ones — released its GStreamer element while still pointing its own input and output at it, so removing an effect, or clearing them all, worked on the surface while the next teardown reached through a dangling reference. As with the teardown defects above, GStreamer's type checks kept it to log warnings instead of a crash, but the memory was already gone. - [Media Blocks SDK .Net] Fixed **`UniversalTransformBlock` releasing its own pads on the first frame**. The transform callback released the pads the block had published, so every later probe, unlink and teardown on that block used a dead reference. `CustomMediaBlock` did the same to the pads its wrapped element owns, including the pad handed to it when a demuxer creates one. - [Core] Fixed **a reference-counting error that corrupted GStreamer's encoder registry on Windows**. Enumerating the available hardware encoders released a reference the SDK never held, on every encoder registered on the machine — audio ones included. GStreamer detected it, logged a warning per encoder and recovered, so nothing failed visibly, but the accounting was left inconsistent and a concurrent registry change could have turned that into a crash. - [Media Blocks SDK .Net] Fixed **Vorbis audio bitrate settings being ignored**. `VorbisEncoderSettings.Bitrate`, `MaxBitrate` and `MinBitrate` are documented as "-1 to disable", which is also their default, and that default was passed to the encoder as an out-of-range value. The encoder rejected the whole assignment and fell back to its own defaults, so a bitrate you set took effect only if you had also set the other two. Encoding profiles built from these settings carried the same invalid value. - [Media Blocks SDK .Net] Fixed **the pipeline-graph debug helpers misbehaving once playback had finished**. `Debug_GetPipeline()` and `Debug_SavePipeline()` called after a stop — including the stop that happens on its own when a file reaches the end — wrote no graph and logged a GStreamer warning instead. `Debug_GetPipeline()` now returns an empty string, as documented, and `Debug_SavePipeline()` does nothing. The same applies to `VideoCaptureCoreX.Debug_SavePipeline()`. - [Video Capture SDK .Net] Fixed **`Video_Source_GetResolutionAndFrameRate` and `Audio_Source_GetInfo` damaging a running capture**. Both released the source block's own pad, so calling either of these read-only queries while capturing left the source unusable. - [Video Capture SDK .Net] Fixed **the second recording of a separate-capture output silently producing no file**. With an output registered and the engine running, `StartCaptureAsync(index, filename)` worked the first time and every later call returned `true` while writing nothing — the record button worked exactly once per application run. All subsequent recordings now write to the file passed to `StartCaptureAsync`, with the preview left untouched, which is what the API is for. ## 2026.7.26 - [Media Blocks SDK .Net] Added **`AndroidUVCSourceBlock`** — capture from a **USB (UVC) camera connected to an Android device over OTG**, such as a webcam or a capture dongle. These cameras are invisible to the regular `SystemVideoSourceBlock`, because Android only exposes them through Camera2 on devices whose vendor ships the External Camera HAL (Samsung, among others, does not). Connected cameras are listed with `AndroidUVCDevices.FindCameras()`, access is requested with `AndroidUVCDevices.RequestPermissionAsync()`, and the requested resolution and frame rate are matched against the modes the camera advertises. Your app must declare **and be granted `android.permission.CAMERA`** — Android refuses to hand a USB video device to an app without it, even though the Android camera API is not used. Unplugging the camera ends the stream, so the pipeline reports end-of-stream rather than stalling silently. Requires **Android 9 (API 28) or later**. Note that a camera enumerating at USB 2.0 speed offers markedly lower frame rates than on a desktop: a Logitech BRIO, for example, tops out at 1080p30 (MJPEG) with no 4K modes available at all. - [Video Capture SDK .Net] **USB (UVC) cameras on Android can now be used with `VideoCaptureCoreX`** — assign an `AndroidUVCSourceSettings` to `Video_Source` and the camera works like any other source, so recording to MP4, network streaming, video effects and snapshots are all available. New `AndroidUVCDevices.GetModes()` lists the resolutions, frame rates and formats you can actually pick from — formats the SDK cannot stream are left out — so you can offer the real choices instead of requesting a mode and silently getting the nearest one, and `AndroidUVCSourceSettings.Format` asks for one of them. Two things to know: an unplugged camera is reported through `OnError`, not `OnStop` - and only once the stream has been silent for a few seconds, so handle Android's `ACTION_USB_DEVICE_DETACHED` broadcast as well if your app needs to react the moment the cable comes out; and a camera with a built-in microphone also registers as a USB audio input that Android prefers for recording but that cannot be captured while the camera is streaming, so such a recording is video-only. Live capture should also set the new `VideoCaptureCoreX.Video_Output_IsSync = false`, which stops the bridge feeding an output pipeline from waiting on the clock - left synced it can fill its queue and stall the preview along with it. `Audio_Output_IsSync` is the matching switch for the audio branch, so a capture with audio can hand both branches over on the same terms. - [Demos] Added a **USB Camera** Android sample showing live preview from a UVC camera attached over OTG, including the device and permission handling, in both a Media Blocks SDK and a Video Capture SDK version — the latter also records to MP4. ## 2026.7.24 - [Video Capture SDK .Net] Fixed **Picture-in-Picture crashing on .NET 9 and .NET 10** — `VideoCaptureCore` terminated with an unrecoverable `ExecutionEngineException` at `Start`/`StartAsync` as soon as a PiP source was added (the same code worked on .NET 8). Adding a PiP overlay now works on all supported .NET versions. - [Video Edit SDK .Net] Fixed the legacy FFMPEG output crashing at start on .NET 9 and .NET 10 with the same `ExecutionEngineException`; it now works as it did on .NET 8. - [Media Blocks SDK .Net] [Video Capture SDK .Net] Fixed **video missing or corrupted when streaming MPEG-TS over SRT** (`SRTMPEGTSSinkBlock`, `SRTOutput`). The MPEG-TS muxer now emits a full 1316-byte payload per buffer instead of one transport packet at a time, so SRT sends whole datagrams rather than seven times as many undersized ones. Receivers such as MediaMTX, ffmpeg or OBS no longer see an audio-only or truncated stream. The UDP, multi-UDP and RIST MPEG-TS outputs get the same alignment. - [Media Blocks SDK .Net] [Video Capture SDK .Net] Fixed **corrupted video from the Apple (iOS / macOS / Mac Catalyst) H.264 hardware encoder**. `AppleMediaH264EncoderSettings.AllowFrameReordering` was enabled by default; the resulting B-frames left a large share of the encoded frames with a presentation timestamp earlier than their own decode timestamp, so MPEG-TS outputs (SRT, UDP, RIST) and MP4/MOV recordings played back torn or undecodable in MediaMTX, ffmpeg and VLC. RTMP/FLV happened to tolerate it, which is why streaming from iOS looked broken over SRT but fine over RTMP. The property now defaults to `false`; set it back to `true` only for offline encoding where you can verify the resulting timestamps. - [Media Blocks SDK .Net] [Video Capture SDK .Net] Fixed **SRT and RIST output failing to start on macOS and Mac Catalyst** when the Apple hardware H.264 encoder was used: the stream parser those outputs need to feed the MPEG-TS muxer was omitted on those platforms. - [Media Blocks SDK .Net] [Video Capture SDK .Net] [Video Edit SDK .Net] Fixed **MPEG-TS output producing an empty file** when AAC audio was encoded with a software encoder (`voaacenc`, used on macOS, Linux and iOS). The MPEG-TS muxer only accepts framed AAC, which those encoders do not advertise, so the audio never linked and the muxer waited on it instead of writing - the recording ended as a 0-byte `.ts`. Affects `MPEGTSSinkBlock`/`MPEGTSOutput` and the SRT, UDP and RIST outputs built on them. - [Media Blocks SDK .Net] Fixed **RTSP playback failing with "Failed to link RTSP pad: WasLinked"** in `UniversalSourceBlockV2`. When the source announced a pad it had already handed over - on reconnect, or when a server re-announced a stream - the block tried to link it a second time and reported the result as an error, ending the session. - [Media Blocks SDK .Net] Fixed **DASH output never starting** (`DASHSinkBlock`): the sink requested its input pads without a name, which `dashsink` rejects because it takes the stream index from the pad name. No manifest or segments were written and the pipeline hung on start instead of reporting the failure. - [Media Blocks SDK .Net] Fixed **text overlays rendering as empty boxes (▯▯▯) on iOS, Android and macOS** — the SDK now sets up font resolution at startup, so `TextOverlayBlock`, subtitle overlays and the trial watermark draw real glyphs instead of tofu. Fonts your app bundles are picked up automatically, and on iOS the SDK carries a fallback font so text renders even in an app that bundles none. ## 2026.7.22 - [Video Capture SDK .Net] Fixed RTSP / IP camera **login and password being URL-encoded**, which broke authentication for credentials containing special characters such as `&`, `@`, `%`, `?` or spaces (e.g. a password `password&@%!?End` was sent to the camera as `password%26%40%25!%3fEnd`). Credentials are now used verbatim. Applies to both the `RTSPSourceSettings` (X engine) and `IPCameraSourceSettings` (VideoCaptureCore) sources. If you previously worked around this by storing the pre-encoded value on the device, revert it to the real password after upgrading. - [Core] MAUI apps now build cleanly for Android 16: the bundled HarfBuzzSharp native library is updated to a 16 KB page-size-aligned build, removing the `XA0141` ("Android 16 will require 16 KB page sizes") warning on Android app builds. ## 2026.7.21 - [Media Blocks SDK .Net] Added **AMD Alveo MA35D** hardware acceleration (via the AMD AMA Video SDK) on Linux: H.264, HEVC and AV1 encoders (`AMAH264EncoderSettings` / `AMAHEVCEncoderSettings` / `AMAAV1EncoderSettings`), matching decoders, and an `AMAScalerBlock`. A specific MA35D card is selected with the `Device` property (`-1` auto-selects), so you can pin encoding/decoding to the accelerator rather than the host GPU. Requires the AMD AMA Video SDK (kernel driver + GStreamer plugins) to be installed. ## 2026.7.10 - [Media Blocks SDK .Net] Added **`AudioEventDetectorBlock`** — on-device audio event detection that recognizes real-world sounds (siren, dog bark, glass break, alarm, music, speech, and hundreds more from the 521-class AudioSet ontology) in live or file audio using a YAMNet ONNX classifier. Audio passes through unchanged; detections are raised via `OnAudioEvent` with a label, confidence, and start/end time, using score smoothing and hysteresis so one continuous sound is a single event rather than a burst of duplicates. Optional class allowlist and a live top-K scores event. Works in `VideoCaptureCoreX`/`MediaPlayerCoreX` via `Audio_Processing_AddBlock`. - [Demos] Added an **Audio Event Detection** WPF sample (Media Blocks SDK): open a file or select a microphone, live event log with label/confidence/time, class-filter box, and threshold slider. ## 2026.7.9 - [Core] Video stream info now reports the pixel aspect ratio (`VideoStreamInfo.ParNumerator`/`ParDenominator`) when the negotiated caps carry it, so anamorphic sources can be displayed at the correct proportions. - [Media Blocks SDK .Net] Fixed pipeline restart after a failed start: blocks no longer report themselves as built when their Build fails, so a retried start rebuilds them instead of running a half-built pipeline. - [Media Blocks SDK .Net] File output blocks (M4A/MP4/MKV/AVI) now fail cleanly instead of throwing an unhandled exception when configured with an unsupported encoder, so the pipeline reports a normal start error you can handle. - [Core] Fixed stale frame dimensions after a mid-stream resolution change in video frame grabbing: frame callbacks and snapshots kept reporting the old width/height/stride, so the frame data could be mis-read at the new size. - [Media Blocks SDK .Net] Added AI auto-reframe (`AutoReframeBlock`): converts landscape footage into vertical 9:16 (or 1:1, 4:5) video that dynamically crops around the detected subject with smooth, jitter-free tracking — ideal for Shorts/Reels/TikTok. - [Demos] Added an **Auto Reframe** WPF sample (Media Blocks SDK): open a landscape file, follow the subject in a side-by-side original/reframed preview (9:16, 1:1, or 4:5), configure smoothing, dead zone, detection interval, and the followed class, and optionally export the reframed output to MP4. - [Media Blocks SDK .Net] Added on-device **speaker diarization** ("who spoke when"): the new `SpeakerDiarizationBlock` analyses the audio as it plays and, once the recording has finished, reports every speech turn with the speaker who made it. Diarization is inherently offline — a voice heard at minute 1 can only be matched to the same voice at minute 40 once the whole recording has been heard — so the turns are raised at end-of-stream (`OnSpeakerSegment`, or `GetTimeline()` in one piece); check `IsTimelineComplete` before reading them. Pair it with speech-to-text via `DiarizedTranscriptBuilder` for a speaker-labeled transcript. Works with `MediaPlayerCoreX`/`VideoCaptureCoreX` and manual Media Blocks pipelines. Set `NumSpeakers` when you know the count, or leave it at `-1` and tune `ClusterThreshold` (a cosine distance — smaller yields more speakers). - [Media Blocks SDK .Net] Speaker diarization is **multilingual**: alongside the default English WeSpeaker voiceprint model you can select the Apache-2.0 3D-Speaker ERes2NetV2 embedding (`SpeakerDiarizationSettings.EmbeddingModel = ERes2NetV2Multilingual`) for far better speaker separation on non-English or mixed-language audio. The feature front-end adapts to the chosen model automatically, so no other code changes are needed when you switch. - [Media Blocks SDK .Net] Fixed degraded **speech-to-text accuracy on any source that is not already 16 kHz mono** — that is, on essentially every camera, capture card, media file and RTSP stream. The audio front-end decimated to the 16 kHz the model needs without band-limiting first, so everything above 8 kHz folded back into the speech band and corrupted the features both Whisper and the voice-activity detector consume. The audio is now low-pass filtered before the rate conversion. - [Media Blocks SDK .Net][Video Capture SDK .Net] Added **PTZ auto-tracking** — an ONVIF PTZ camera can now automatically follow a detected object. `PTZAutoTrackingController` turns detections from `ObjectAnalyticsBlock` (or `YOLOObjectDetectorBlock`) into continuous pan/tilt/zoom commands with a configurable dead zone, sticky target tracking, a lost-target timeout (with optional return-to-preset), and command rate limiting. Target selection by largest object, first detected, tracker ID, or class label. Includes the new "PTZ Auto Tracking" WPF demo. - [Media Blocks SDK .Net][Video Capture SDK .Net] PTZ auto-tracking can now run an **idle preset patrol** — when no target reappears for a configurable delay, the camera cycles through a list of ONVIF presets (with a per-preset dwell time) until a new target is acquired, which immediately aborts the patrol and resumes tracking. - [Demos] Added a **PTZ Auto Tracking** WPF sample for the Media Blocks SDK — the same ONVIF auto-tracking built on a low-level `MediaBlocksPipeline` (RTSP source → `ObjectAnalyticsBlock` → video renderer, with `PTZAutoTrackingController` driving the camera). - [Media Blocks SDK .Net] Added **`VideoStabilizationBlock`** — real-time video stabilization that removes camera shake by estimating global inter-frame motion (translation and rotation) with OpenCV optical flow, smoothing the camera trajectory, and warping each frame back onto the smoothed path. Configurable smoothing radius, crop/zoom ratio, and per-frame correction limits; all tunable live. Requires the OpenCV redistributable (Windows). - [Media Blocks SDK .Net][Video Capture SDK .Net][Media Player SDK .Net] `VideoStabilizationBlock` can now be used with the X engines: pass it to `Video_Processing_AddBlock()` on `VideoCaptureCoreX` or `MediaPlayerCoreX` to stabilize a live camera or a playback stream, with live retuning through `ApplySettings()`. - [Demos] Added a **Video Stabilization** WPF sample (Media Blocks SDK): open a file, preview stabilized playback, record the stabilized result to MP4, and adjust the smoothing radius and crop ratio live. - [Demos] Added a **Video Stabilization Capture X** WPF sample (Video Capture SDK X): stabilize a live camera with `VideoCaptureCoreX` and tune the stabilizer while the capture runs. - [Demos] Added a **Video Stabilization Camera** WPF sample (Media Blocks SDK): stabilize a live camera with a hand-built `MediaBlocksPipeline` (camera source → stabilizer → renderer), with live tuning. ## 2026.7.8 - [Video Edit SDK .Net] Fixed a native process crash (fail-fast) when rendering FLAC output from a timeline with more than one clip (or a gap before the audio clip) in `VideoEditCoreX`. - [Video Capture SDK .Net] Fixed empty WMA audio-only recordings from the legacy `VideoCaptureCore` engine: the default WMA profile was variable-bitrate (VBR), which the WM ASF Writer cannot produce from a live capture source, so the file contained only an ASF header with no audio data. The default is now an equivalent constant-bitrate WMA profile. - [Core][Video Capture SDK .Net][Media Blocks SDK .Net] Fixed a **32-bit (x86)** ABI bug that mis-sized the native `GMutex` field (as a pointer) in the GStreamer object layout, shifting every element's field offsets by 8 bytes on x86. This made the element pad list read as empty and caused a NullReferenceException crash whenever the video/audio sample grabber, snapshots, or a frame-processing block was used on 32-bit. Frame grabbing, snapshots, and per-frame processing now work correctly on x86 (x64 unaffected). ## 2026.7.6 - [Media Blocks SDK .Net] Fixed an intermittent "Unable to create sample grabber element" failure that could occur when starting several camera pipelines (e.g. multiple RTSP cameras) at the same time. Managed element construction is now thread-safe. - [Media Blocks SDK .Net] Fixed a NullReferenceException crash in the video sample grabber (and related processing elements) that could occur on the streaming thread when a frame buffer was momentarily unavailable. ## 2026.7.3 - [Media Blocks SDK .Net] Added **`PIIRedactionBlock`** — automatic on-video redaction of personally identifiable information: faces (YuNet), vehicle license plates (FastALPR detector), and on-screen text (PP-OCRv5 detection + recognition — recognition filters out the detector's non-text false positives — with an optional regex filter that redacts only matching text such as e-mails or phone numbers). Redaction styles: Gaussian blur, pixelate, and solid fill. Each category can be toggled live; regions are padded and held between detection cycles so PII stays covered through motion and detector flicker. Works in `VideoCaptureCoreX`/`MediaPlayerCoreX` via `Video_Processing_AddBlock`. - [Demos] Added a **PII Redaction** WPF sample (Media Blocks SDK): webcam, file, or RTSP source with live category/style switching. - [Demos] Added **Player PII Redaction X** and **Capture PII Redaction X** samples (WPF and MAUI) — live face/plate/text redaction on `MediaPlayerCoreX` (file playback) and `VideoCaptureCoreX` (camera) via `Video_Processing_AddBlock`. ## 2026.7.2 - [Media Blocks SDK .Net] Added an **open-vocabulary object-detection** block (`OpenVocabularyDetectorBlock`) that detects objects from free-text prompts (OWLv2 / Grounding DINO) instead of a fixed class list, with prompts swappable at runtime. It can also drive `ObjectAnalyticsBlock` as a detector for tripwire / zone analytics. - [Media Blocks SDK .Net] Added a **Florence-2 vision-language** block (`VLMBlock`) for frame captioning, OCR, phrase grounding, and object detection. - [Media Blocks SDK .Net] Added a **CLIP video-embedding** block (`VideoEmbeddingBlock`) with a semantic frame-search index, for natural-language search over indexed video. - [Media Blocks SDK .Net] `VideoEmbeddingBlock` can index a file at full decode speed with no dropped samples via `VideoEmbeddingSettings.BackpressureNoDrop` (backpressures the pipeline instead of dropping frames when the encoder is busy). - [Media Blocks SDK .Net] `OpenVocabularyDetectorBlock` confidence and IoU thresholds can now be adjusted at runtime (`SetConfidenceThreshold` / `SetIoUThreshold`); the new value takes effect on the next frame without rebuilding the pipeline. - [Demos] Added three WPF samples: **Open Vocabulary Detection**, **VLM Captioning**, and **Semantic Video Search**. - [Media Player SDK .Net] Added `MediaPlayerCoreX.Video_Renderer_IsSync` — set it to `false` to run the video renderer without clock synchronization so a file is processed at full decode speed (for offline AI indexing / analysis) instead of in real time; `null` (default) keeps the automatic behavior. - [Demos] Added **X-engine** versions of the new AI samples (WPF and MAUI): **Open Vocabulary Detection** and **VLM Captioning** for both `VideoCaptureCoreX` (camera) and `MediaPlayerCoreX` (file), plus **Semantic Video Search** for `MediaPlayerCoreX`. Each inserts the AI block through the `Video_Processing_AddBlock` API. ## 2026.6.30 - [Demos] Added **Face Recognition** and **OCR** demos for the X engines, in both WPF and MAUI: **Player Face Recognition X** and **Player OCR X** (`MediaPlayerCoreX`), plus **Capture Face Recognition X** and **Capture OCR X** (`VideoCaptureCoreX`). Each inserts the AI block through the `Video_Processing_AddBlock` API — the face demos enroll people from photos and label them on the video; the OCR demos draw and log recognized text. - [Demos] Added a **Capture Live Subtitles X** WPF sample (`VideoCaptureCoreX` with on-device Whisper speech-to-text subtitles). ## 2026.6.29 - [Media Blocks SDK .Net] Speech-to-text (`SpeechToTextBlock`) now always transcribes the full input losslessly — the source is paced to Whisper so no audio is ever dropped. The previous live drop-buffer mode and the `SpeechToTextSettings.BackpressureWhenBusy` option were removed (the lossless behavior is now the only mode). ## 2026.6.27 - [Video Capture SDK .Net] `VideoCaptureCoreX` can now insert AI processing blocks — object detection, OCR, face recognition, license-plate recognition, object analytics, background removal, generic ONNX inference, and Whisper speech-to-text — directly into the capture pipeline through `Video_Processing_AddBlock` / `Audio_Processing_AddBlock`, with on-frame overlays and detection events. - [Media Player SDK .Net] `MediaPlayerCoreX` gains the same `Video_Processing_AddBlock` / `Audio_Processing_AddBlock` API to run AI processing (object detection, OCR, speech-to-text, and more) on played files and streams. - [Demos] Added a **Player AI Processing** demo (WPF): plays a file in `MediaPlayerCoreX` with a YOLO object detector or a Whisper speech-to-text block inserted through the new processing-block API. - [Demos] Added four **MAUI** AI demos (Android/iOS/Mac Catalyst/Windows) for the new X-engine processing-block API: **Player Object Detection X** and **Player Live Subtitles X** (`MediaPlayerCoreX`), plus **Capture Object Detection X** and **Capture Live Subtitles X** (`VideoCaptureCoreX`). - [Media Blocks SDK .Net] Fixed an `AccessViolationException` ("Attempted to read or write protected memory") that could crash the application when using text overlays (`OverlayManagerBlock` / `OverlayManagerText`) — most reliably reproduced by adding a text overlay right after `StartAsync` and then stopping. The font-enumeration path freed Pango-owned font objects it did not own, corrupting memory during a later garbage collection or pipeline shutdown. - [Media Blocks SDK .Net] Fixed a related intermittent fatal crash ("Attempt to execute managed code after the .NET runtime thread state has been destroyed") that could abort the process during text overlay or font enumeration when a background media thread was recycled, or at application exit. The available-fonts / monospace-detection path no longer attaches a managed callback to Pango's internal font map. ## 2026.6.24 - [Media Blocks SDK .Net] Fixed a rare crash during pipeline shutdown or garbage collection in applications with many active GStreamer objects, such as multi-camera RTSP capture with sample grabbers, bridges, and file outputs. - [Media Blocks SDK .Net] `FaceRecognitionBlock` — enrolling a face from a photo that carries an EXIF orientation tag (typical of phone camera shots) now works; the image is rotated upright before detection instead of reporting "no face found". - [Demos] Added a **Face Recognition Uno** demo (Uno Platform): live camera 1:N face recognition with on-frame name/box overlay, photo enrollment, and switchable SFace / AuraFace embedding models. Android-focused. - [Demos] The Face Recognition demos (WPF and CLI) now let you pick the embedding model: **SFace (128-D)** or **AuraFace (512-D, ArcFace family, Apache-2.0)** — a higher-accuracy, commercially licensed 512-D embedder downloaded on demand. The CLI adds an `--embedding sface|auraface` switch. - [Demos] Face Recognition WPF demo: switching the embedding model now automatically rebuilds the gallery from the enrolled photos, so changing models no longer makes every face read as **Unknown** (embeddings from different models are not comparable). - [Demos] Face Recognition MAUI demo: added the same SFace/AuraFace embedder selection and automatic gallery rebuild, plus a **video-file source** with a seek bar and a real-time / max-speed playback toggle (in addition to the live camera). ## 2026.6.23 - [Media Blocks SDK .Net] Unity samples now use Unity's default Enter Play Mode behavior (Domain + Scene Reload); disabling Domain Reload is no longer required. The SDK survives the Editor's Play/Stop and script-recompile domain reloads via a built-in reload guard. ## 2026.6.21 - [Video Capture SDK X .Net] Added **Android audio playback capture** support to `VideoCaptureCoreX` — assign `AndroidAudioPlaybackCaptureSourceSettings` to `Audio_Source` to record the audio played by **other apps** (system AudioPlaybackCapture API, Android 10 / API 29+, on top of a `MediaProjection` token) straight to a file. Includes a new native Android "Audio Playback Capture" demo built on `VideoCaptureCoreX` that records another app's audio to an `.m4a` file. Only apps that allow playback capture (usage MEDIA/GAME/UNKNOWN and not opted out) can be captured. ## 2026.6.20 - [Media Blocks SDK .Net] `VideoSampleGrabberBlock` now works as a terminal block: if you leave its output unconnected (e.g. you only poll `GetLastFrameAsSKBitmap()` or handle `OnVideoFrameBuffer`), the block self-terminates so frames keep flowing. Previously a grabber with an unconnected output stalled after the first frame, so every snapshot returned the same initial image. - [Media Blocks SDK .Net] `VideoSampleGrabberBlock.GetLastFrameAsSKBitmap()` and `GetLastFrameAsBitmap()` now return `null` when no frame has been captured yet, instead of throwing a `NullReferenceException`. - [Media Blocks SDK .Net] Setting `VideoSampleGrabberBlock.SaveLastFrame = false` now discards the cached frame, so toggling it back on later never hands back a stale frame captured during an earlier session. - [Media Blocks SDK .Net] `KLVParser` now reads MISB KLV packets larger than 127 bytes. Standard MISB ST 0601 metadata uses BER long-form lengths, and the parser previously threw on the common 1- and 2-byte long-form lengths — so real-world packets failed to parse. All BER length forms are now decoded correctly. ## 2026.6.19 - [Media Blocks SDK .Net] Added **Android audio playback capture** — the new `AndroidAudioPlaybackCaptureSourceBlock` records the audio played by **other apps** using the system AudioPlaybackCapture API (Android 10 / API 29+) on top of a `MediaProjection` token, with a configurable format and usage filter (`AndroidAudioPlaybackCaptureSourceSettings`). Includes a new native Android "Audio Playback Capture" demo that records another app's audio to an `.m4a` file. Only apps that allow playback capture (usage MEDIA/GAME/UNKNOWN and not opted out) can be captured. - [Media Blocks SDK .Net] Speech-to-text (`SpeechToTextBlock`) gains a lossless file-transcription mode: set `SpeechToTextSettings.BackpressureWhenBusy = true` to pace a file source to the transcription engine so no audio is dropped and the pipeline position tracks the transcription frontier — ideal for transcribing a file as fast as the engine allows without losing speech. The new `SpeechToTextBlock.RequestStop()` lets you stop promptly mid-file, and an `OnEndOfStream` event fires when transcription finishes. ## 2026.6.18 - [Media Blocks SDK .Net] Fixed WMV/ASF output where the video stream was written with a roughly 1000-hour timestamp offset while audio started at zero — players saw a broken duration and the video and audio never shared a timeline. WMV/ASF files now have correctly aligned, overlapping video and audio timestamps. - [Media Blocks SDK .Net] Fixed MP4 recordings produced from a still/image source (`ImageVideoSourceBlock`, live mode) ending up unreadable ("moov atom not found") — a live image source now finalizes its file correctly on stop. - [Media Blocks SDK .Net] VP9 WebM output now uses a real-time-capable speed/quality default: `VP9EncoderSettings.CPUUsed` defaults to `4` instead of `0`. The previous slowest/highest-quality default could not keep up with a live source, so the recorded video track could be truncated to about a second while audio ran the full length. Set `CPUUsed = 0` to restore maximum quality for offline encoding. - [Media Blocks SDK .Net] The rav1e AV1 encoder (`RAV1EEncoderSettings`) now defaults to the fastest speed preset (`SpeedPreset = 10`) instead of `6`. rav1e is a quality-oriented, very slow software encoder; the previous default could encode well under real time (~1 fps at 720p), stalling live and short captures. Lower `SpeedPreset` for higher quality in offline encoding where throughput does not matter. ## 2026.6.14 - [Media Blocks SDK .Net] The AI blocks — `YOLOObjectDetectorBlock`, `OcrBlock`, object analytics, ANPR, `BackgroundRemovalBlock` (`VisioForge.DotNet.Core.AI`) and `SpeechToTextBlock` (`VisioForge.DotNet.Core.AI.Whisper`) — now build and run cross-platform on Linux, macOS, iOS, and Android, including .NET MAUI, in addition to Windows. - [Media Blocks SDK .Net] On-device speech-to-text (`SpeechToTextBlock`, Whisper + Silero VAD) now runs on iOS and Android. - [Demos] Added three .NET MAUI sample apps: **YOLO Object Detection**, **OCR Text Recognition**, and **Live Subtitles** (on-device Whisper speech-to-text). The existing Live Subtitles console sample is now cross-platform (Windows, Linux, macOS). - [Media Blocks SDK .Net] Fixed a crash that could occur when stopping live speech-to-text with `SpeechToTextBlock` configured with `EnableVad = false` (fixed-window mode) — stopping the pipeline at end-of-stream while a transcription was in progress could terminate the process. Transcription of the in-progress window now completes cleanly during shutdown. - [Media Blocks SDK .Net] `SpeechToTextSettings.FixedWindowSeconds` is now clamped to 1–30 s and `SileroVadSettings.MaxSpeechMs` no longer accepts "0 = unlimited" (a non-positive value falls back to the 15 s cap), so a single transcription window — and the time a stop waits for it to finish — stays bounded. ## 2026.6.13 - [Media Blocks SDK .Net] Added **live speech-to-text / subtitles** — the new `SpeechToTextBlock` (in the new `VisioForge.DotNet.Core.AI.Whisper` package) transcribes the audio stream in real time with Whisper (Whisper.net / GGML) on a background worker, gated by Silero VAD so silence is skipped and not mis-transcribed. Audio passes through unchanged. It raises `OnSpeechRecognized`, can auto-render captions onto video via `SubtitleRenderer` + `OverlayManagerBlock`, and can write `.srt` / `.vtt` side-car files. Runs fully on-device (CPU or NVIDIA CUDA); Whisper and Silero models are downloaded at runtime. Includes a new WPF Live Subtitles demo. - [Media Blocks SDK .Net] Added **AI background removal (matting)** — the new `BackgroundRemovalBlock` runs an ONNX segmentation model (for example MODNet) to estimate a per-pixel foreground mask and replaces the background in real time with a blur of the original, a solid color, a static image, or transparency. Includes a new WPF Background Removal demo. The background is composited on every frame, so running the model less often (frame skipping) lowers CPU/GPU load without flicker. ## 2026.6.11 - [Media Blocks SDK .Net] Added **Object Analytics** — multi-object tracking with stable IDs, directed tripwire line crossing (In/Out counts), and polygon zone occupancy on top of ONNX object detection. Includes a turnkey `ObjectAnalyticsBlock`, a pure C# analytics API (`ByteTracker`, `LineZone`, `PolygonZone`), overlay rendering with traces and counters, a new analytics mode in the YOLO Object Detection demo, and separate Tripwire and Polygon Zone demo applications. ## 2026.6.8 - [Video Capture SDK .Net] Updated the bundled FFmpeg DirectShow source and encoder filters to **FFmpeg 8.1.1**, with refreshed codec libraries (VP8/VP9, Opus, Vorbis, Speex, SRT) and current OpenSSL — bringing newer format support and upstream security and stability fixes to FFmpeg-based capture and output. ## 2026.6.7 - [Media Blocks SDK .Net] Fixed a crash when reusing a `TSAnalyzerBlock` across runs: after the block is stopped, analyzing a second transport stream with the same instance in a new pipeline now works instead of failing during rebuild. - [Media Blocks SDK .Net] Fixed MPEG-TS output with KLV metadata aborting (no valid file produced) when a video frame arrived with an out-of-order/duplicate timestamp — the muxer now keeps the stream writable, so KLV-bearing transport streams record reliably. - [Core] Fixed native memory steadily growing while reading media information for many different files in sequence with `MediaInfoReaderX`; per-file discovery resources are now released after each read. ## 2026.6.6 - [Media Player SDK .Net] **New "Modern Player" MAUI demo.** A from-scratch cross-platform sample (Android, iOS, macCatalyst, Windows) built on `MediaPlayerCoreX` with a dark glassmorphism UI, a YouTube-style seek preview (a thumbnail popup follows the scrub bar — generated in the background from the opened file), a live video + audio effects drawer (brightness/contrast/saturation/hue, gamma, blur/sharpen, grayscale, edge, deinterlace, color presets, flip/rotate, 3D-LUT; plus gain, pitch, 10-band equalizer, reverb, echo, true-bass, and karaoke), frame snapshot, playback-speed control, and volume/mute. - [Media Player SDK .Net] [Media Blocks SDK .Net] Fixed opening local media files by absolute file path on Android, iOS, macOS, and Linux. A path starting with `/` (the form returned by the native file pickers) previously failed with a URI-format error; `MediaPlayerCoreX.OpenAsync(string)`, `MediaInfoReaderX`, and `UniversalSourceSettings.CreateAsync(string)` now open such files correctly. Windows paths were unaffected. - [Media Blocks SDK .Net] **OCR — text recognition:** new `OcrBlock` recognizes text in any video or image source using a multi-stage PaddleOCR (PP-OCRv5) ONNX pipeline — text detection, automatic 180° orientation handling, and text-line recognition. Runs on CPU or GPU (DirectML on Windows, CoreML on Apple, CUDA) and is fully cross-platform (Windows/Linux/macOS/Android). It raises the recognized regions per frame (text, confidence, and the text polygon) and can optionally draw the boxes and recognized text directly into the video. Works with the permissive Apache-2.0 PP-OCRv5 mobile models (100+ languages available); the models ship with the sample, not the package. - [Media Blocks SDK .Net] **ANPR — license plate recognition:** new `LicensePlateRecognizerBlock` reads vehicle number plates from a live stream or file using a specialized two-stage pipeline — a dedicated license-plate detector locates each plate, then a plate-specific OCR model (a global head covering the USA and 90+ countries, or a European head) reads its characters. Recognition runs on a background thread so live video never stalls; recognized plates (text, confidence, bounding box) are raised per frame and optionally drawn over the video. Cross-platform and GPU-accelerated (DirectML / CUDA / CoreML). The MIT-licensed models ship with the sample, not the package. ## 2026.6.4 - [Media Blocks SDK .Net] **AI inference package renamed:** the AI/ONNX inference package is now published as `VisioForge.DotNet.Core.AI` (previously `VisioForge.DotNet.Core.ONNX`). Update your `PackageReference` to the new id — the API and namespaces of the inference blocks are unchanged. - [Media Blocks SDK .Net] **Object detection: more models, permissive default.** `YOLOObjectDetectorBlock` now decodes three model families via the new `YoloDetectorSettings.Model` property — **YOLOX** and **RT-DETR / D-FINE** (both Apache-2.0) in addition to YOLOv8/v11. Each family's frame preprocessing (resize mode, normalization, channel order) and the model's input size are applied automatically, so you only pick the family and the `.onnx` file. The Object Detection demo now ships a ready-to-run **Apache-2.0** model (YOLOX-nano) and works out of the box without any third-party model download. RT-DETR / D-FINE detectors are end-to-end (NMS-free). - [Media Blocks SDK .Net] **TS analyzer — ETSI TR 101 290 monitoring:** `TSAnalyzerBlock` now reports a structured TR 101 290 Priority 1/2/3 check list (sync loss, sync-byte errors, PAT/PMT/PID errors, continuity-count errors, transport errors, CRC errors, PCR/PTS errors, and SI/SDT/EIT/TDT errors), each with its priority, error count, and pass/fail status — turning the block into a broadcast-grade transport-stream monitor. - [Media Blocks SDK .Net] **TS analyzer — service information:** the report now exposes per-program SDT service names, service provider, and service type, the network name, and the stream UTC time (TDT/TOT), so programs show up as their real service name instead of just a program number. - [Media Blocks SDK .Net] **TS analyzer — audio language:** elementary-stream entries now carry the ISO 639 audio language parsed from the PMT descriptors. - [Media Blocks SDK .Net] **TS analyzer — scrambling detection:** per-PID and per-program scrambling state is now reported (transport-scrambling-control and free\_CA\_mode), along with a scrambled-packet count. - [Media Blocks SDK .Net] **TS analyzer — null and effective bitrate:** the report adds the null-packet count, the null (stuffing) bitrate, and the effective (useful) bitrate, plus per-PID instantaneous and peak bitrate alongside the existing cumulative average. - [Media Blocks SDK .Net] **TS analyzer — PCR timing and PTS/DTS:** PCR statistics now include maximum jitter and PCR repetition errors, and the report tracks PTS/DTS presence per PID and audio/video synchronization offset. - [Media Blocks SDK .Net] **TS analyzer — codec details:** video elementary streams now report parsed codec details (resolution, frame rate, profile, level, chroma format, and display aspect ratio) for H.264, HEVC, and MPEG-2. Frame rate and aspect ratio are reported from the MPEG-1/2 sequence header. - [Media Blocks SDK .Net] **TS analyzer — optional EPG:** when enabled, the analyzer parses EIT events (event id, start time, duration, name, description) and exposes them as an EPG event list. The new analysis options (service info, EPG, scrambling, TR 101 290, PTS/DTS, codec details) are configurable on `TSAnalyzerSettings`. The WPF and console demos display all of the new information. - [Video Capture SDK .Net] Fixed audio capture failing to start with certain WDM capture cards (for example the Viewcast Osprey 460E) when the device was selected by its device path — the device enumerated correctly but capture aborted with an "audio output pin is null" error. Such devices now bind reliably. - [Media Blocks SDK .Net] Fixed a `MediaBlocksPipeline` becoming unusable after a media file played to its end. Once a source reached End-of-Stream, the next `StartAsync()` was permanently rejected with "Already starting or start in progress." and the pipeline could not be restarted without recreating it — for example when switching from a finished file back to a live camera. Playback now shuts down cleanly at end-of-stream exactly like an explicit `StopAsync()` (sources stopped, resources released), so the same pipeline can be started again. ## 2026.6.3 - [Media Blocks SDK .Net] **MPEG-TS analyzer:** new `TSAnalyzerBlock` analyzes a transport stream and reports the program/service line-up (PAT/PMT/PSI), the per-PID stream types and codecs, per-PID and total bitrate, continuity-counter errors, and PCR timing (interval min/avg/max and discontinuity count). It accepts a raw MPEG-TS byte stream from a file, UDP, or SRT source and can run terminal (`Input`) or inline passthrough (`InputOutput`); subscribe to `OnAnalysisUpdated` for periodic snapshots or call `GetReport()`. New WPF and console demos ("TS Analyzer Demo", "TS Analyzer CLI") show file and live UDP/SRT analysis. - [Media Blocks SDK .Net] **Raw MPEG-TS UDP source:** new `UDPRAWMPEGTSSourceBlock` receives a live UDP unicast or multicast transport stream and exposes the untouched MPEG-TS byte stream without demuxing — for analysis or passthrough remuxing/recording. The advertised packet size is configurable via `UDPRAWMPEGTSSourceSettings.PacketSize` (188 by default, or 192 for M2TS-style streams). - [Media Blocks SDK .Net] **Split-recording segment events:** `MP4SinkBlock`, `MPEGTSSinkBlock`, and `MP4OutputBlock` now raise `OnSegmentCreated` and `OnSegmentClosed` when configured for split recording (`MP4SplitSinkSettings` / `MPEGTSSplitSinkSettings`). The arguments carry the segment file path, fragment index, and timing (running time, plus start offset and duration on close) — so you can be notified when a segment file is finished and, for example, rename it to include its start/end time. - [Media Blocks SDK .Net] **Custom split-segment file names:** the same blocks add an `OnSegmentFileNameRequested` event, raised just before each new segment file is created, letting you supply a custom file name (for example one that embeds the segment start date/time). Leave it unset to keep the default name from the location pattern. - [Media Blocks SDK .Net] **New AI inference blocks:** `OnnxInferenceBlock` runs any ONNX Runtime model over the live video frames and raises an event with the raw model outputs, while `YOLOObjectDetectorBlock` performs YOLOv8/v11 object detection, draws bounding boxes and labels directly on the video (label text auto-scales to the frame resolution so it stays readable on 720p/1080p/4K, or pin a fixed size via `YoloDetectorSettings.LabelFontSize`), and raises a detections event (with class, confidence, and box for each object). Both support frame skipping to tune throughput. On Windows the package uses the DirectML ONNX Runtime build, so inference runs on any DirectX 12 GPU (NVIDIA, AMD, or Intel) out of the box; the execution provider defaults to `Auto`, which picks the fastest available backend (DirectML/CUDA/CoreML) and transparently falls back to the CPU. Use `OnnxInferenceEngine.GetAvailableProviders()` to detect what is available and the new `ActiveProvider` property on either block to see which provider engaged. The `VisioForge.DotNet.Core.ONNX` package targets the full SDK framework matrix (.NET Framework 4.6.1 through .NET 10); inference requires a 64-bit (x64 or ARM64) ONNX Runtime native build. ## 2026.6.2 - [Video Capture SDK .Net] Fixed KLV metadata progressively drifting out of sync with the video (about 2 seconds per source loop) on the receiving side when restreaming a looping KLV-bearing MPEG-TS via `UDP_FFMPEG_EXE`. KLV and video now stay aligned across source loop boundaries. - [Video Capture SDK .Net] Unity: new VideoCaptureCoreX samples — local webcam preview + MP4 recording (Windows, macOS) and IP/RTSP camera viewing (Windows, Android, macOS, iOS). - [Video Edit SDK .Net] Unity: new VideoEditCoreX sample — combine clips, apply effects, preview the timeline in Unity, and render to MP4. ## 2026.5.31 - [Media Blocks SDK .Net] **New `UDPRAWSourceBlock`:** receives a live UDP stream (MPEG-TS, RTP, or raw elementary) and exposes the parsed, still-encoded media without decoding — ideal for recording or remuxing without re-encoding. MPEG-TS feeds are auto-detected; RTP and raw modes let you set the codec, RTP payload type, and a multicast address. It exposes all common video and audio codecs (video: H264, H265, VP8, VP9, AV1, MPEG-2, MJPEG; audio: AAC, MP3/MPEG audio, AC-3, Opus, FLAC); RTP can also carry audio on a separate port (`AudioPort` / `AudioCodec`). A codec without a dedicated parser is passed through unchanged rather than dropped, so a connected recorder/muxer is never starved. - [Demos] **New WPF "UDP RAW Capture Demo" (Media Blocks SDK .Net):** records a live UDP H264/H265 feed to MP4 files **without re-encoding**, with selectable transport (Auto / MPEG-TS / RTP / raw), starting a new file on a configurable interval and splitting on key-frames so no data is lost between files, while previewing the stream. - [Media Player SDK .Net] Unity: new MediaPlayerCoreX sample — play files and network URLs with seek, pause and volume, rendered into a Unity `Texture2D`. ## 2026.5.29 - [Media Blocks SDK .Net] **Unity 6 (.NET Standard 2.1) build flavor:** the managed SDK now ships as a single `netstandard2.1` assembly compatible with Unity's IL2CPP backend (Api Compatibility Level = .NET Standard 2.1). This lets Unity projects target the SDK without requiring the .NET Framework 4.x compatibility surface. The existing net48 Unity package remains supported. - [Media Blocks SDK .Net] **Unity macOS Standalone player support (Universal arm64 + x86\_64):** the Unity 6 ns2.1 `.unitypackage` now ships a third platform flavor for macOS Standalone (in addition to Windows and Android). Includes pre-built P/Invoke for macOS `.dylib` names, the bundled CrossPlatform.Core.macOS native runtime (GStreamer dylibs + `libgioopenssl` TLS backend + `ca-certificates.crt`), and a one-time `Configure()` bootstrap that prunes any system / homebrew GStreamer from `DYLD_LIBRARY_PATH` before the loader runs. - [Core] **New API:** `VisioForgeX.StopMainLoop()` — explicit teardown of the internal GLib main loop independent of `DestroySDK()`, for scenarios that need to release the loop without tearing the SDK down. ## 2026.5.22 - [Demos] **Unity `.unitypackage` distribution:** the Unity 6 (net48) integration now ships as a single self-contained `.unitypackage` - [Demos] **New Unity 6 (net48) samples:** `SimplePlayer` (file playback) and `RTSPViewer` (live RTSP camera) render a `MediaBlocksPipeline` into a Unity `RawImage` via a reusable `VisioForgeVideoView` component (Stretch / Letterbox / Crop). The bundled native + managed runtime is set up automatically; a step-by-step setup guide is included. ## 2026.5.20 - [Media Blocks SDK .Net] **Fix:** native memory leak in `OverlayManagerFilter` and `PanZoomFilter` on iOS/AOT builds. ## 2026.5.19 - [Media Blocks SDK .Net] **Fix:** `CVMotionCellsBlock`, `CVFaceDetectBlock`, `CVHandDetectBlock`, `CVTemplateMatchBlock` — event subscriptions added after `StartAsync` sometimes were silently dropped. - [Media Blocks SDK .Net] **Fix:** `CVMotionCellsSettings.Gap` and `PostNoMotion` are now rounded and clamped to the ranges accepted by the underlying `motioncells` element (`Gap` → `[1, 60]` s, `PostNoMotion` → `[0, 180]` s). Previously sub-second values truncated to `0` and were silently rejected. - [Media Blocks SDK .Net] **Docs:** `CVMotionCellsSettings.GridSize` XML-doc clarified that the minimum is 8x8 (constraint of the underlying `motioncells` element); smaller values are silently rejected. ## 2026.5.18 - [Media Blocks SDK .Net] **New API:** `SRTSinkSettings.PreResolveHostname` and `SRTSourceSettings.PreResolveHostname` (`bool`, default `false`). When set to `true`, the SDK resolves any DNS hostname in the SRT URI to a literal IPv4 on the managed side (via `System.Net.Dns`) before handing the URI to the native code. ## 2026.5.16 - [Core] Public-API XML documentation is now validated for correct syntax across the shipped NuGet packages. ## 2026.5.15 - [Core] Added `D3D11Composable` WPF renderer mode: a pure FrameworkElement video panel built on a D3D11 shared texture + `D3DImage` bridge that composes natively with the WPF visual tree (transforms, opacity, z-order, rounded clips) and keeps frames GPU-resident end-to-end. New type: `D3D11ComposablePanel`. - [Core] Added true-peak (dBTP) metering per ITU-R BS.1770-4: new `TruePeakComputer` (4× polyphase FIR oversampling, per-channel running peak, NaN/Inf-safe) and `VUMeterXData.TruePeak[]` channel array fired alongside the existing sample-peak/RMS data. - [Core] Added `VolumeMeterLED` WPF control: segmented LED-bar VU meter with broadcast-style green/yellow/red zones, optional peak-hold marker (configurable fall time), optional dB scale labels, optional RMS overlay bar, horizontal/vertical orientation. - [Core] NuGet packages now ship XML documentation generated from real summaries for the full public API surface (previously the doc files were empty). ## 2026.5.14 - [Avalonia] Updated Avalonia, Avalonia.Desktop, Avalonia.Fonts.Inter, Avalonia.Themes.Fluent from 12.0.1 to 12.0.3. - [WinForms] Resolve issue with WinForms designer when using `VideoView` in .Net Framework 4.x projects - [Dependencies] Closed two transitive security advisories: pinned `System.Drawing.Common` per-TFM on bare/cross-platform `netN.0` (was 5.0.1 via DlibDotNet — GHSA-rxg9-xrhp-64gj, critical) and added explicit `SharpCompress 0.48.1` CPM pin to lift the transitive floor from MongoDB.Driver (was 0.30.1 — GHSA-6c8g-7p36-r338, moderate); bumped MongoDB.Driver 3.8.0 → 3.8.1. - [Breaking] `VisioForge.Core.CVD` and `VisioForge.Core.FaceAI` assemblies are no longer strong-named. The underlying `DlibDotNet` dependency is unsigned, so the strong-name chain was already broken at runtime; the `` flag was dropped to silence CS8002. Consumers that referenced these assemblies by fully-qualified strong name (`PublicKeyToken=...`) or used `[InternalsVisibleTo("VisioForge.Core.CVD, PublicKey=...")]` must remove the strong-name assertion when upgrading. ## 2026.5.10 - [Core] `CustomMixerSourceBlock`: reliability and throughput improvements under heavy load. ## 2026.5.8 - [Dependencies] Upgraded MongoDB.Driver.GridFS 2.30.0 to MongoDB.Driver 3.8.0; pinned Snappier 1.3.1 to resolve NU1903 high-severity vulnerability (GHSA-pggp-6c3x-2xmx) ## 2026.5.2 - [Core] Breaking change: licensing APIs now accept only raw certificate bytes. Removed file-path and stream-based certificate setters across shared licensing, public SDK wrappers, legacy Windows wrappers, tests, and licensing docs. Applications must load `.vflicense` files into memory and call `SetLicenseCertificateAsync(byte[])`. - [Core] `AudioMixerBlock`: `AudioMixerSettings.IgnoreInactivePads` is now opt-in (default `false`). The 2026.4.30 release briefly forced it `true`, which broke single-input mixers — silent live audio and corrupted MP4 output. Multi-stream consumers (`MediaPlayerCoreX` additional audio streams, `LiveVideoCompositor`, and `AudioMixerSourceSettings`-based multi-source capture) now opt in explicitly. If you wired a multi-stream `AudioMixerBlock` on 2026.4.30–2026.5.1 and relied on the implicit `true`, set `AudioMixerSettings.IgnoreInactivePads = true` explicitly. ## 2026.4.25 - [Core] Fixed WinForms designer exception on `VideoView` in net472 demos — SkiaSharp 3 migration regression - [Core] Added transitive `SkiaSharp.NativeAssets.Linux` dependency for bare cross-platform TFMs (`netcoreapp3.1`, `net5.0`–`net10.0`) so consumers publishing to `linux-x64`/`arm64` no longer need to add the package manually; main `SkiaSharp` already covers Win32/macOS/iOS/Android/MacCatalyst/tvOS via per-TFM nuspec groups - [Avalonia] Migrated SDK and all 28 demos from Avalonia 11.3.8 to **12.0.1**: replaced `Avalonia.Diagnostics` with `AvaloniaUI.DiagnosticsSupport 2.2.1`, switched to `ReactiveUI.Avalonia 12.0.1`, updated `RxApp.MainThreadScheduler` → `RxSchedulers.MainThreadScheduler` (ReactiveUI 23.x), new `UseReactiveUI(_ => { })` signature, moved Android `CustomizeAppBuilder` from `MainActivity` to new `MainApplication : AvaloniaAndroidApplication`, migrated `SaveFileDialog`/`OpenFileDialog`/`FileDialogFilter` to `IStorageProvider.SaveFilePickerAsync`/`OpenFilePickerAsync` in 4 demos. SkiaSharp pinned to 3.119.3-preview.1.1 (required by Avalonia.Skia 12). ## 2026.4.23 - [NuGet] Extracted Intel Quick Sync Video (QSV) plugin (`gstqsv.dll`) from `VisioForge.CrossPlatform.Core.Windows.x64/x86` into new optional packages `VisioForge.CrossPlatform.Core.Windows.Intel.x64` and `VisioForge.CrossPlatform.Core.Windows.Intel.x86`; each depends on the corresponding base Core package - [Video Capture SDK .Net] Fixed FFMPEG.exe pipe output argument ordering so resize/aspect options are emitted after all inputs, including KLV metadata pipe input ## 2026.4.21 - [Core] Added `AutoAV1EncoderSettings`: auto-selecting AV1 encoder that walks AMF → NVENC → QSV → SVT-AV1 via `EncoderRuntimeTracker`, mirroring `AutoH264EncoderSettings` / `AutoHEVCEncoderSettings`; AV1 sessions now participate in per-runtime slot accounting - [Core] Added typed `AV1Encoder.CanCreateSession(IAV1EncoderSettings, out string)` probe so AV1 runtime selection can detect driver rejections before wiring a pipeline - [Core] Added `MFH264EncoderSettings`, `D3D12H264EncoderSettings`, `D3D12HEVCEncoderSettings` — alternative Windows runtimes (`mfh264enc`, `d3d12h264enc`, `d3d12h265enc`) with independent per-adapter session counters for bypassing per-runtime caps (e.g., AMD iGPU 2-session ceiling) - [Core] Added `AutoH264EncoderSettings` / `AutoHEVCEncoderSettings`: auto-selecting encoder that probes runtimes in order (AMF → NVENC → QSV → MF → D3D12 → software), tracks in-flight sessions via `EncoderRuntimeTracker`, and falls back when a runtime's cap is reached - [Demo] Added `Encoder Concurrency Test` WPF demo (Media Blocks SDK): spawn multiple source→encoder→decoder→renderer pipelines with configurable resolution, frame rate, encoder runtime, and adapter to exercise concurrent-session limits end-to-end ## 2026.4.18 - [Media Blocks SDK] UniversalSourceBlock: added `VideoFlipRotate` option for automatic video orientation correction using image-orientation metadata - [Core] VOAACEncoderSettings deprecated in favor of `AVENCAACEncoderSettings` - [Core] RTSPXOutput: now accepts any `IAACEncoderSettings`, not just VOAAC - [Core] MediaInfoReaderCore: preserves image-orientation flip metadata during media info reading - [Core] H264Encoder: fixed thread-safety issue in KeyFrameDetected callback - [iOS] PhotoGalleryHelper: requests `PHAccessLevel.AddOnly` for iOS 26 compatibility - [Android] GStreamer Android NuGet rebuilt with zbar barcode plugin, bumped to 2026.4.18 - [Platform] macOS demos migrated from net9.0-macos to net10.0-macos - [Dependencies] Uno.Sdk bumped 6.4.24 → 6.5.31 - [Media Blocks SDK] LiveVideoCompositor V2: added `OnRenderStatistics` event with `ActualFps`, `ConfiguredFps`, `FramesDelivered`, and `LastFrameTimestamp` payload for detecting when the compositor falls behind the configured frame rate under heavy load - [Media Blocks SDK] LiveVideoCompositor V1 (`VisioForge.Core.LiveVideoCompositor`) marked `[Obsolete]` — migrate to `VisioForge.Core.LiveVideoCompositorV2` (identical class names, single-line `using` swap); V1 will be removed in a future release - [Demos] WPF LVC Demo and MAUI LVC Demo show the real vs configured output FPS in the UI; WinForms Video Mixer Player migrated from V1 to V2 ## 2026.4.11 - [Media Player SDK X] Added `Play_PauseAtFirstFrame` property to MediaPlayerCoreX — pauses at the first rendered frame for preview/thumbnail scenarios, matching the existing MediaPlayerCore API - [Core] Migrated SkiaSharp from 2.88.9 to 3.119.2 — updated text rendering to SKFont API, replaced SKFilterQuality with SKSamplingOptions, switched SVG library from SkiaSharp.Svg to Svg.Skia - [UI] Updated SkiaSharp.Views.WPF and SkiaSharp.Views.Maui.Controls to 3.119.2; WPF skins now use DrawImage with high-quality Mitchell resampling ## 2026.4.8 - [Android] Added live camera switching (SwitchCamera) to SystemVideoSourceBlock — switches between front/back cameras without recreating the GStreamer pipeline, preserving resolution and frame rate - [Video Capture SDK X] Added Video\_Source\_SwitchCamera for live camera switching on Android without pipeline restart - [Video Capture SDK X] Added Video\_Renderer\_IsSync and Audio\_Renderer\_IsSync properties (default false) for lower-latency live preview - [Android] New NuGet native version v2026.4.1 ## 2026.3.27 - [Core] Fixed UNC path media info reading failure: `MediaInfoReaderAlt` now correctly handles SDK initialization guard, null caps in `OnPadAdded`, and falls through to `MediaInfoReaderX` on failure. `IsSambaURL()` extended to detect `file://host/path` UNC URIs. `OpenAsync` uses `uri.LocalPath` for correct Windows UNC path. ## 2026.3.18 - [Media Blocks SDK .Net] Fixed missed context menu issue in WPF VideoView ## 2026.3.17 - [Media Blocks SDK .Net] Added UDPSinkBlock and MultiUDPSinkBlock for raw UDP streaming output with single and multi-destination support - [Media Blocks SDK .Net] Added UDPMPEGTSSinkBlock and MultiUDPMPEGTSSinkBlock for MPEG-TS multiplexed UDP streaming with single and multi-destination support - [Media Blocks SDK .Net] Added UDPSinkSettings, MultiUDPSinkSettings, and UDPSinkSettingsBase for UDP sink configuration with IPv6 support and URL parsing - [Media Blocks SDK .Net] Added UDP MPEG-TS streamer demo (screen capture to UDP output) ## 2026.3.11 - [Core] Device enumeration: Blackmagic ATEM and Web Presenter devices now appear in regular video/audio device lists instead of being filtered as Decklink hardware. These devices use standard USB/UVC drivers, not the Decklink SDK. Applies to both DirectShow and GStreamer enumeration paths. - [Core] RTSP info reader: Added audio channel count and sample rate parsing from SDP rtpmap and GStreamer pad caps. ## 2026.2.16 - [Media Blocks SDK .Net] Added PreEventRecordingBlock for circular buffer (pre-event) video recording with configurable buffer duration, keyframe-aware drain, and automatic post-event stop - [Video Capture SDK .Net] VideoCaptureCoreX: Added pre-event recording API with TriggerPreEventRecording, ExtendPreEventRecording, StopPreEventRecording, and state query methods - [Video Capture SDK .Net] VideoCaptureCoreX: Added PreEventRecordingOutput for configuring circular buffer recording with MP4, MPEG-TS, and MKV container support ## 2026.2.12 - [Media Blocks SDK .Net] Added OnNetworkSourceDisconnect event for detecting network source disconnections (RTSP, HTTP, SRT, NDI, RTMP, etc.) with detailed error information and source URI ## 2026.2.11 - [Media Player SDK .Net], [Media Blocks SDK .Net] Fixed audio effects pipeline routing ## 2026.2.10 - [Core] Added UNC (SMB/Samba) network path support for file sources across all X-engines, fixing File.Exists() failures on network shares - [Media Blocks SDK .Net], [Video Capture SDK .Net] Added mouse click highlight support for screen capture with auto-subscribe/unsubscribe, manual click input, and real-time settings update ## 2026.2.8 - [Media Blocks SDK .Net] Added OverlayManagerImageSequence: image sequence overlay with per-frame durations, looping, position/size animation, fade effects, and easing support - [Media Blocks SDK .Net] Added ImageSequenceItem data class for defining image sequence frames - [Media Blocks SDK .Net] OverlayManagerBlock: Added convenience methods for image sequence overlays (Video\_Overlay\_AddImageSequence, UpdateImageSequencePosition, AnimateImageSequence, ImageSequenceFadeIn/Out) - [Core] Extracted OverlayManagerEasingHelper: shared easing functions for all overlay animation types (Image, Fade, Pan, Squeezeback, ImageSequence) ## 2026.2.4 - [Media Blocks SDK .Net] Added H264PushSourceBlock for pushing raw H.264 encoded data into a decoding pipeline, with automatic AVC-to-byte-stream conversion and PTS rebasing - [Core] Added RtspDescribeClient: lightweight cross-platform RTSP DESCRIBE client for fast stream discovery (~100-200ms), with SDP parsing and Basic/Digest auth support - [Core] RTSPSourceSettings: Added fast RTSP discovery path using RtspDescribeClient - [Core] RTSPRAWSourceSettings: Added fast RTSP discovery path using RtspDescribeClient - [Core] UniversalSourceSettings: Added fast RTSP discovery path for rtsp:// and rtsps:// URIs ## 2026.2.2 - [Core] VideoCaptureDeviceInfo: Extended Windows device path population to support Media Foundation (MF) devices in addition to KS - [Core] VideoCaptureDeviceInfo: Fixed pre-existing bug where V4L2 device path validation checked wrong variable - [Core] VideoCaptureDeviceSourceSettings: Added FindByDevicePath() static methods for restoring saved camera profiles by device path - [Core] DeviceEnumerator: Added FindVideoSourceByDevicePathAsync() method for looking up devices by path - [Media Blocks SDK .Net] Added RIST (Reliable Internet Stream Transport) MPEG-TS sink output support - [Media Blocks SDK .Net] Added WebRTC WHIP (WebRTC-HTTP Ingestion Protocol) output support - [Video Capture SDK .Net] Added WebRTC WHIP streaming output - [Video Capture SDK .Net] Added RIST streaming output ## 2026.1.16 - [Media Blocks SDK .Net] BridgeVideoSourceSettings: Added DoTimestamp property to enable fresh timestamp generation for cross-pipeline scenarios ## 2026.1.15 - [Media Blocks SDK .Net] DecklinkVideoSinkSettings: Made Mode parameter required in constructor to prevent frame rate mismatch issues (was defaulting to Unknown mode causing unexpected 23.98fps output) - [Media Blocks SDK .Net] DecklinkVideoSinkSettings: Made DeviceNumber and Mode properties read-only for immutability - [Core] DecklinkVideoOutputDialog (WPF): Added Video Mode selector for configuring output frame rate ## 2026.1.12 - [Core] WPF VideoView: Fixed crash (System.ExecutionEngineException) when minimizing window during video overlay playback ## 2026.1.11 - [Media Blocks SDK .Net] RTSPSourceBlock: Fixed video freeze when audio capture is disabled for cameras with multiple audio streams - [Media Blocks SDK .Net] RTSPRAWSourceBlock: Added fakesink handling for disabled audio streams to prevent pipeline stalls - [Core] MediaInfoReaderCore: Added logging for discovered audio, video, and RTP streams - [Core] MediaInfoReaderCore: Fixed excessive block size (5MB) being set for RTSP sources, improving discovery speed ## 2026.1.10 - [Video Capture SDK .Net] DSFFMPEGEXEPipeOutput: Fixed preview lag during video capture with optimized pipe handling and queue processing - [Video Capture SDK .Net] FFMPEG EXE output: Added real-time encoding optimizations for VP8/VP9, fixed MJPEG quality mode, improved default H264MFSettings defaults ## 2026.1.6 - [Video Capture SDK .Net] VideoCaptureCoreX: Fixed video capture resolution issue when ResizeVideoEffect is applied ## 2025.12.12 - [Media Blocks SDK .Net] Added PitchBlock for audio pitch shifting with semitone control (-12 to +12 range) - [Media Player SDK X .Net] CDGSource: Added pitch shifting support with EnablePitchShifting option and real-time PitchSemitones control - [Media Player SDK X .Net / Media Blocks SDK .Net] CDGSourceSettings: Added ZIP archive support for karaoke files (MP3+CDG pairs inside ZIP) ## 2025.11.8 - [Media Blocks SDK .Net] OverlayManagerVideo and OverlayManagerDecklinkVideo: Changed AudioOutput property type from MediaBlock to AudioOutputDeviceInfo for direct audio device selection. Audio is now handled internally via AudioRenderer with automatic channel conversion support. ## 2025.11.4 - .Net 10 support for all SDKs ## 2025.11.3 - WPF VideoView update: Added RotationAngle, RotateCrop, and RotationStretch properties to support rotated video rendering ## 2025.11.1 - [Media Blocks SDK .Net] Add synchronized overlay group support for OverlayManagerBlock ## 2025.10.10 - [**Windows SDKs**] Updated VideoEffectRotate with no-crop option ## 2025.10.6 ### 🚀 Major Feature: Ultra-Low Latency RTSP Streaming - **[Media Blocks SDK .Net]** Revolutionary low latency mode for RTSP sources achieving **60-120ms total latency** (10-14x improvement over default 1-2 seconds) - Added `RTSPSourceSettings.LowLatencyMode` property for one-line enablement of optimized streaming - Automatic pipeline optimization: RTSP source (80ms), queue buffers (10-20ms), and renderer sync control - GStreamer integration: `latency=80ms`, `buffer-mode=0`, queue `max-size-buffers=2` with `leaky=downstream` - Perfect for real-time surveillance, security systems, live monitoring, and interactive video applications - **[Media Blocks SDK .Net]** Enhanced RTSPSourceBlock with comprehensive low latency configuration - Added `RTSPBufferMode` enum with 5 modes (None, Auto, Slave, Buffer, Synced) for fine-grained jitter buffer control - Added `RTSPNTPTimeSource` enum (NTP, RunningTime, Clock) for NTP timestamp synchronization in multi-camera scenarios - New properties: `LowLatencyMode`, `BufferMode`, `DropOnLatency`, `NTPSync`, `NTPTimeSource` - Optimized `QueueElement` with automatic low latency configuration (2 frame max, leaky downstream mode) - **[Video Capture SDK X .Net]** Full low latency mode support for RTSP sources - Compatible with `VideoCaptureCoreX` engine across all platforms - Same simple API: `RTSPSourceSettings.LowLatencyMode = true` - Works seamlessly with IP Capture demo and RTSP MultiView demo - **[Cross-Platform Support]** Low latency RTSP streaming now available on all platforms: - Windows (WPF, WinForms, Console, Blazor) - macOS (MAUI, Console) - Linux (Console, WPF with Mono) - Android (MAUI, Native) - iOS (MAUI) - **[Demo Applications]** Updated 6 demos with low latency mode UI controls: - Media Blocks SDK: RTSP Preview Demo (WPF), RTSP MultiView Demo (WinForms), MAUI RTSPViewer, Android RTSP Client - Video Capture SDK X: IP Capture (WPF), RTSP MultiView Demo (WinForms) - All demos include easy-to-use checkboxes or default-enabled low latency for optimal user experience - **[Documentation]** Official help documentation updated with a low-latency section and best practices. - **[Testing]** Validated on real IP cameras across all platforms. Performance benchmarks: Windows (85ms), macOS (95ms), Linux (80ms), Android (110ms), iOS (100ms). - **[Backward Compatibility]** 100% backward compatible implementation: - Default behavior unchanged - existing code works without modification - Low latency mode is opt-in via explicit property - No performance impact when not using low latency mode - Queue optimization only applied when `LowLatencyMode=true` ## 2025.10.3 - [Media Blocks SDK .Net] Added DASH (Dynamic Adaptive Streaming over HTTP) sink support with DASHSinkBlock and DASHOutput classes - [Media Blocks SDK .Net] Added UniversalSourceBlockV2 with improved memory usage and performance - [X-engines] Fixed uvch264src not starting on Linux by properly selecting the appropriate source pad based on video format (vidsrc for H264, vfsrc for raw/MJPEG) ## 2025.9.5 - [Video Fingerprinting SDK] Improved support for flipped videos ## 2025.9.3 - [Media Blocks SDK .Net] Added DataMatrix barcode support using DataMatrixDecoderBlock block ## 2025.9.1 - [Video Fingerprinting SDK] Improved support for flipped videos ## 2025.8.9 - [Video Capture SDK .Net] VideoCaptureCoreX: Resolved issue with Snapshot\_GetSK call on Android (wrong colorspace) ## 2025.8.6 - [X-engines] Updated RTSP RAW source block. Added WaitForKeyframe and SyncAudioWithKeyframe properties. Block can wait for keyframes because some cameras may not send them as first frames. ## 2025.8.4 - [X-engines] Added NDI source support in Live Video Compositor ## 2025.8.2 - [ALL] New ONVIF manager code in VisioForge.Core.ONVIFX. Full implementation of various ONVIF services including Device Management, Media v1/v2, PTZ, Events, Imaging, Analytics, Recording, and Replay services. ## 2025.8.1 - [Media Player SDK] Added PauseOnStop property to MediaPlayerCoreX ## 2025.6.30 - [X-engines] Added animated GIF support to `ImageVideoSourceBlock`/`ImageVideoSourceSettings` classes - [X-engines] Resolved issues with delayed file start in Live Video Compositor - [X-engines] Update video mixer API to use GUIDs instead of integer indexes for video sources ## 2025.6.27 - [Video Capture SDK] Resolved issue with RTSP Low Latency engine with some cameras ## 2025.6.5 - [X-engines] Resolved issue with NDI sources playback without audio streams ## 2025.6.3 - [X-engines] Updated GenICam source support for USB Vision cameras. Added GenTL source support. ## 2025.6.2 - [X-engines] Added deinterlace support for interlaced Decklink video sources ## 2025.6.1 - [Live Video Compositor] Resolved issue with file sources paused on start, and resumed with error ## 2025.5.1 - [ALL] Update NuGet dependency packages to the latest versions - [X-engines] Resolved issue with RTMP network streaming to a custom server ## 2025.4.8 - [ALL] Added Absolute Move API to the `ONVIFDeviceX` class. You can use this API to move the ONVIF camera to the specified absolute position. ## 2025.2.24 - [X-engine] By default, Media Foundation device enumeration is disabled. You can enable it using the `DeviceEnumerator.Shared.IsEnumerateMediaFoundationDevices` property. ## 2025.2.18 - [Media Player SDK.Net] Added loop support for the cross-platform engine. - [ALL] Updated RTSP-X engine output, fixed crash issue with RTSP output and VLC player frequent reconnects - [X-engines] Changed face detector support to use IFaceDetector interface - [Live Video Compositor] Fixed registration issues with custom video view attached to video input ## 2025.2.9 - [X-engines] Updated NDI connection speed ## 2025.2.4 - [X-engines] RTSP Server Media Block and RTSPServerOutput added to Video Capture SDK. You can use the RTSPServerBlock to create an RTSP server and stream video and audio to it. ## 2025.2.1 - [X-engines] Added NVENC and AMF AV1 encoders support ## 2025.1.25 - [Windows] Resolved HTTPS issue with the not loaded SSL certificates ## 2025.1.22 - [Windows] Resolved issue with missed ONVIF sources while enumerating on PC with multiple network interfaces - [Media Blocks SDK .Net] Added the `OnEOS` event to `MediaBlockPad` class. You can use this event to get the EOS (End of Stream) event from the media block. It can be useful if you have several file sources with a different duration and you need to stop the pipeline when the first source ends. - [Media Blocks SDK .Net] Added the `SendEOS` method to `MediaBlocksPipeline` class. You can use this method to send the EOS (End of Stream) event to the pipeline. ## 2025.1.18 - [NuGet] `VisioForge.Core.UI.Apple`, `VisioForge.Core.UI.Android`, and `VisioForge.Core.UI.WinUI` packages are merged into the `VisioForge.DotNet.Core` package. All namespaces are the same. - [Media Blocks SDK .Net] Added the `ZOrder` property to `LVCVideoInput` and `LVCVideoAudioInput` classes. You can use this property to set the Z-order for the video input. ## 2025.1.14 - [NuGet] `VisioForge.Core.UI.WPF` and `VisioForge.Core.UI.WinForms` packages are merged into the `VisioForge.DotNet.Core` package. In WPF projects you have to update the XAML code if the assembly names are used. All namespaces are the same. ## 2025.1.11 - [Video Capture SDK .Net] Resolved QSV H264 FFMPEG encoder issue with the wrong symbols in parameters ## 2025.1.7 - [Cross-platform] Added `libcamera` source support for Linux/Raspberry Pi. ## 2025.1.5 - [Cross-platform] Improved previous frame playback in Media Player SDK .Net (Cross-platform engine) ## 2025.1.4 - [Cross-platform] Resolved issue with AMD AMF plugin initialization ## 2025.1.1 - [Cross-platform] Resolved memory leak in `OverlayManagerImage` ## 2025.1.0 - [Cross-platform] Updated Live Video Compositor engine. Improved Decklink support for input and output. Improved performance. The new engine classes are located in the `VisioForge.Core.LiveVideoCompositorV2` namespace. ## 2025.0.29 - [Cross-platform] Default video renderer on Windows has been changed to DirectX 11 ## 2025.0.17 - [Media Blocks SDK .Net] Added libCamera source support (can be used on Raspberry Pi) ## 2025.0.16 - [Media Blocks SDK .Net] Resolved issue with adding several AudioRendererBlocks to the pipeline ## 2025.0.14 - [Media Blocks SDK .Net] Added the "PushJPEGSourceSettings" class to configure the JPEG source for the "PushSourceBlock". You can use this class to set the JPEG source settings for the "PushSourceBlock". Also "video-from-images" sample added. ## 2025.0.7 - [ALL] Resolved window capture issues in cross-platform SDKs - [Media Blocks SDK .Net] Added the Bridge Source Switch sample ## 2025.0.5 - [iOS] Resolved issues with playback speed for some video files - [iOS] Added iOS Simulator support for all SDKs. Camera source is not supported in the simulator. ## 2025.0.3 - [MacOS] Resolved wrong stride issue for vertical camera videos on MacOS - [Video Capture SDK .Net] Resolved background color issue for the scrolling text overlay ## 2025.0 - [ALL] .Net 9 support - [Media Blocks SDK .Net] Added `AVIOutputBlock` to save video and audio streams to the AVI file format - [Media Blocks SDK .Net] `TeeBlock` constructor now accepts the media type as a parameter - [Video Capture SDK .Net] Added `Video_CaptureDevice_SetDefault` and `Audio_CaptureDevice_SetDefault` methods to the `VideoCaptureCore` class. You can use this method to set the default video and audio capture devices - [Cross-platform] Improved `Metal` video rendering performance on Apple devices - [All] Improved performance of common video processing operations in Windows classic SDKs - [CV] Added DNN face detectors for the `Media Blocks SDK .Net` and `Video Capture SDK .Net` - [Mobile] Improved AOT compatibility for iOS and Android - [WinUI] Improved performance of the `WinUI` video rendering - [Media Blocks SDK .Net] Added the `GetLastFrameAsSKBitmap` and `GetLastFrameAsBitmap` methods to `VideoSampleGrabberBlock` to get the last frame as a `SkiaSharp.SKBitmap` or `System.Drawing.Bitmap` - [Video Capture SDK .Net] `VideoCaptureCore`: Added the `AddFakeAudioSource` property to `FFMPEGEXEOutput`. The `Network_Streaming_Audio_Enabled` property of `VideoCaptureCore` should be set to false to use this fake audio. - [ALL] Improved WinUI (and MAUI on Windows) VideoView performance - [Video Capture SDK .Net] `VideoCaptureCore`: Added the `PIP_Video_CaptureDevice_CameraControl_` API to control the camera settings for the Picture-in-Picture mode - [X-engines] Added the headers support for the HTTP sources created using the `HTTPSourceSettings` class - [X-engines] Updated Avalonia samples, with projects for macOS, Linux, and Windows - [X-engines] Added NuGet redist packages for macOS and MacCatalyst (including MAUI) - [Video Capture SDK .Net] `VideoCaptureCore`: Added device path support for `PIP_Video_CaptureDevice_CameraControl` API - [Video Capture SDK .Net] `VideoCaptureCore`: Added the `FFMPEG_MaxLoadTimeout` property for IP camera sources. It allows you to set the maximum time to wait for the FFMPEG source to load the stream - [X-engines] Updated Linux support for `ALSA`, `PulseAudio` and `PipeWire` audio devices - [X-engines] Updated Linux support for `V4L2` devices - [X-engines] Avalonia samples has be changed to a modern 1-project structure - [X-engines] Resolved issue with `MAUI` crashes on Windows after `SkiaSharp` update - [X-engines] Resolved issue with `TextureView` crashes on Android in `MAUI` applications - [X-engines] Resolved playback issue for http sources using the `UniversalSourceBlock` - [X-engines] Added Mobile Streamer sample for Android - [X-engines] Added `OverlayManagerBlock` support for Android (now it's available for all platforms) - [Video Capture SDK .Net] `VideoCaptureCoreX`: Added `CustomVideoProcessor`/`CustomAudioProcessor` properties for all output formats. You can use these properties to set custom video/audio processing blocks for the output format. - [Media Blocks SDK .Net] Added the `KeyFrameDetectorBlock` to detect key frames in video streams (H264, H265, VP8, VP9, AV1, etc.) - [Media Blocks SDK .Net] Fixed licensing issue for the `LiveVideoCompositor` class ## 15.10.0 - [Windows] Updated window capture API to capture only the specified parent window by default. Added the `UpdateHotkey` method to the `WindowCaptureForm` class to update the hotkey for the window capture form. - [X-engines] Better AOT compatibility for default MAUI settings in iOS. - [Media Blocks SDK .Net] Added the `DNNFaceDetectorBlock` to detect faces and blur/pixelate them using OpenCV and DNN models. - [Media Blocks SDK .Net] Added the `MKVOutputBlock` to save video and audio streams to the MKV file format. - [X-engines] Better support for video source size dynamic changing in MAUI applications. - [X-engines] Resolved an issue with two or more VU meters in the same pipeline. - [X-engines] Resolved volume/mute error issue with audio mixer in Live Video Compositor engine. - [X-engines] The `Spinnaker` source for `FLIR`/`Teledyne` cameras is included in the main package and no longer requires an additional plugin. - [Video Capture SDK .Net] Resolved the issue with the `SeparateCapture` API if no `VideoView` was used. - [X-engines] The `MediaBlocksPipeline` constructor no longer has the `live` parameter. For more customizable pipelines, video and audio renderers got the `IsSync` property (`true` by default). - [X-engines] Resolved `VideoViewTX` crash in MAUI Android applications. - [X-engines] `IVideoEncoder` interface added to the `MPEG2VideoEncoder` class. It allows the use of `MPEG2VideoEncoder` with `MPEGTSOutput`, `AVIOutput`, and other output classes. - [X-engines] Resolved the issue with window capture using the `ScreenCaptureD3D11SourceSettings` class. If the rectangle was incorrect or not specified, it caused an error. - [X-engines] `Metal` renderer was added to SDK for Apple devices and used by default for iOS and MAUI. - [Media Blocks SDK .Net] Added the MAUI Screen Capture sample. - [Video Capture SDK .Net] VideoCaptureCore: Added the `VLC_CustomDefaultFrameRate` property to `IPCameraSourceSettings` to set a custom frame rate for the VLC IP camera source if the source does not provide the correct frame rate. - [Media Blocks SDK .Net] `RTSPSourceBlock`: If the RTSP source has audio but you've disabled the audio stream in `RTSPSourceSettings`, SDK will add a null renderer automatically to prevent warnings. - [ALL] Resolved issue with `VideoFrameX.ToBitmap()` call (wrong color space) - [Windows] Updated KLV support in MPEG-TS output - [Windows] Resolved MediaPlayerCore serialization issue - [ALL] Video renderer settings class no longer contains background color. Use the VideoView background color property instead. - [X-engines] Updated GStreamer libraries - [X-engines] Resolved video rendering issues on Android and iOS - [X-engines] iOS crash fixed during VideoViewGL usage - [X-engines] Added default AAC encoder for iOS - [X-engines] iOS camera source update for high frame rate support - [Windows] Updated VLC source - improved file loading speed - [Media Blocks SDK .Net]: Added the `UniversalDemuxBlock` allows to demux video and audio streams from a file in MP4, MKV, AVI, MOV, TS, VOB, FLV, OGG, and WebM formats - [Windows] Resolved FFMPEG stability issues - [X-engines] Resolved issue with loopback audio source using VideoCaptureCoreX and audio capture to file - [X-engines] Added SRT source and sink support in Media Blocks SDK .Net and Video Capture SDK .Net - [Video Capture SDK .Net] VideoCaptureCore: The `IP_Camera_ONVIF_ListSourcesAsyncEx` method got an overload version with a callback for a more responsible UI - [X-engines] RTSP source compatibility update - [X-engines] `Breaking API change`. Starting with this update, the SDK uses `IAudioRendererSettings` interface implementations for audio output configuration. WASAPI output got the custom configuration classes. Output\_AudioDevice properties of `VideoCaptureCoreX`/`MediaPlayerCoreX` type have been changed to `IAudioRendererSettings`. You can create the `AudioRendererSettings` class instance from `AudioOutputDeviceInfo` using the default constructor. - [X-engines] Resolved problem with missed Media Foundation sources during device enumeration - [X-engines] Resolved RTSP source problems with audio connection in some situations - [X-engines] Added the RTSP Preview Demo to Media Blocks SDK .Net - [Windows] FFMPEG outputs and source updated to FFMPEG v7.0. - [X-engines] Fixed rare crashes in RTSP source when camera information is not available for some reason (network issue) - [X-engines] Resolved an issue with `WASAPI/WASAPI2` audio renderer usage - [X-engines] Resolved an issue with the audio loopback audio source on Windows - [X-engines] Improved iOS video rendering performance and stability - [X-engines] Added AWS S3 Sink output for Media Blocks SDK .Net - [X-engines] Added Allied Vision USB3/GigE cameras support in Media Blocks SDK .Net and Video Capture SDK .Net ## 15.9 - [X-engines] Resolved wrong aspect ratio with video resize effect/block - [X-engines] Updated GStreamer redist - [X-engines] Added Basler USB3/GigE cameras support in Media Blocks SDK .Net and Video Capture SDK .Net - [Video Edit SDK .Net] VideoEditCoreX: The TextOverlay class changed to use SkiaSharp-based font settings. Additionally, you can set the custom font file name or configure all rendering parameters using custom SKPaint. - [Windows] Added Stream support in `MediaInfoReader`. You can get the video/audio file information from a stream (DB, network, memory, etc.). - [X-engines] Updated Live Video Compositor engine, which improved support of the file sources - [Video Capture SDK .Net] Added camera-covered detector into the `Computer Vision Demo` and the `VisioForge.Core.CV` package - [X-engines] Added API to get snapshots from video files using MediaInfoReaderX: GetFileSnapshotBitmap, GetFileSnapshotSKBitmap, GetFileSnapshotRGB - [X-engines] iOS support in MAUI samples - [X-engines] Resolved memory leak issue for RTSP sources - [Media Player SDK .Net] MediaPlayerCore: Added support for data streams in video files using the FFMPEG source engine. Add the OnDataFrameBuffer event to get data frames (KLV or other) from the video file. - [Video Capture SDK .Net] VideoCaptureCore: Added support for data streams in video files using the IP Capture FFMPEG source engine. Add the OnDataFrameBuffer event to get data frames (KLV or other) from the MPEG-TS UDP network stream or other supported source. - [Video Capture SDK .Net] VideoCaptureCore: Added the FFMPEG\_CustomOptions property to the IPCameraSourceSettings class. This property allows you to set custom FFMPEG options for the IP camera source - [Windows] Fixed the hang problem with the FFMPEG source when a network connection is lost - [Media Blocks SDK .Net] Added RTSP MultiView in Sync Demo - [X-engines] Added support for FLIR/Teledyne cameras (USB3Vision/GigE) using the Spinnaker SDK - [Video Edit SDK .Net] VideoEditCoreX: Added support for .Net Stream usage as an input source - The IAsyncDisposable interface was added to all SDK's core classes. The `DisposeAsync` call should be used to dispose of the core objects using async methods. - [Video Capture SDK .Net] VideoCaptureCoreX: Resolved issues with Android video capture (sometimes started only one time) - [Media Blocks SDK .Net] Added HLS streaming sample - [Video Capture SDK .Net] VideoCaptureCore: Resolved crash if the `multiscreen` is enabled and screens added as window's handles (WinForms) - [X-engines] Improved MAUI video rendering speed - [X-engines] Resolved MAUI media playback issues (decoding) in MAUI Android - [X-engines] Resolved an issue with the H264 webcam sources (sometimes not connected) - [X-engines] Resolved an issue with audio stream playback in the Live VideoCompositor engine - [Media Blocks SDK .Net] Resolved a bad audio issue while mixing using the Live Video Compositor engine - [Media Blocks SDK .Net] Added Decklink output and file source into the Live Video Compositor sample - [Media Player SDK .Net] MediaPlayerCore: Added growing MPEG-TS file support for the VLC engine. You can play growing MPEG-TS files while it's recorded ## 15.8 - [X-engines] [API breaking change] DeviceEnumerator can now be used only by using `DeviceEnumerator.Shared` property. One enumerator per app is required. DeviceEnumerator objects used by API have been removed - [X-engines] [API breaking change] Android Activity is not required anymore to create SDK engines - [X-engines] [API breaking change] X-engines require additional initialization and de-initialization steps. To initialize SDK, use the `VisioForge.Core.VisioForgeX.InitSDK()` call. To de-initialize SDK, use the `VisioForge.Core.VisioForgeX.DestroySDK()` call. You need to initialize SDK before any SDK class usage and de-initialize SDK before the application exits. - [Windows] Improved MAUI video rendering performance in Windows - [Windows] Added a mouse highlight for screen capture sources - [Windows] Resolved a CallbackOnCollectedDelegate call issue with the BasicWindow class - [Avalonia] Resolved an issue with Avalonia VideoView resize - [X-engines] Added the StartPosition and StopPosition properties to UniversalSourceSettings. You can use these properties to set the start and stop positions for the file source. - [ALL] Resolved the issue with passwords with special characters used for RTSP sources - [ALL] Resolved the rare video flip issue with the Virtual Camera SDK engine - [ALL] The VisioForge MJPEG Decoder filter was removed from the SDK's NuGet packages. You can optionally add it to your project by file copying or COM registration deployment. - [X-engines] Fixed memory leak in the OverlayManager - [Media Blocks SDK .Net] Resolved issue with the VideoSampleGrabberBlock, SetLastFrame option - [Video Capture SDK .Net] VideoCaptureCoreX: WASAPI and WASAPI2 audio sources can be used now with the VideoCaptureCoreX engine - [X-engines] DeviceEnumerator got events to notify about devices added/removed: OnVideoSourceAdded, OnVideoSourceRemoved, OnAudioSourceAdded, OnAudioSourceRemoved, OnAudioSinkAdded, OnAudioSinkRemoved - [X-engines] Added custom error handler support for MediaBlocks, VideoCaptureCoreX, and MediaPlayerCoreX engines. Use the IMediaBlocksPipelineCustomErrorHandler interface and the SetCustomErrorHandler method to set a custom error handler. - [Video Capture SDK .Net] VideoCaptureCoreX: Resolved issue with incorrect device index error for KS video sources (Windows) - [Video Capture SDK .Net] VideoCaptureCore: Added Virtual\_Camera\_Output\_AlternativeAudioFilterName property to set a custom audio filter for the Virtual Camera SDK output - [Video Edit SDK .Net] VideoEditCore: Added Virtual\_Camera\_Output\_AlternativeAudioFilterName property to set a custom audio filter for the Virtual Camera SDK output - [Media Player SDK .Net] MediaPlayerCore: Added Virtual\_Camera\_Output\_AlternativeAudioFilterName property to set a custom audio filter for the Virtual Camera SDK output - [Video Capture SDK .Net] VideoCaptureCoreX: Added NDI streaming support and sample app. - [Media Blocks SDK .Net] Added the BufferSink block to get video/audio frames from the pipeline - [Media Blocks SDK .Net] Added the CustomMediaBlock class to create custom media blocks for any GStreamer element - [Media Blocks SDK .Net] Added the UpdateChannel method to update the channel of the bridge source or sink - [Media Player SDK .Net] MediaPlayerCore: Updated Tempo effect. - [X-engines] Updated device enumerator. Removed unwanted firewall dialog when listing NDI sources. - [X-engines] Fixed an issue with the video mixer when adding/removing video sources. - [Media Blocks SDK .Net] Added VideoCropBlock and VideoAspectRatioCropBlock blocks to crop video frames. - [Media Blocks SDK .Net] Resolved wrong frame rate issue with VideoRateBlock. - [All] Resolved an issue with the Tempo audio effect. - [Video Capture SDK .Net] VideoCaptureCore: Added WASAPI audio renderer support for the VideoCaptureCore engine. ## 15.7 - [ALL] .Net 8 support - [Video Capture SDK .Net] VideoCaptureCore: Fixed problem with the OnNetworkSourceDisconnect event being called twice. - [X-engines] Added the MPEG-2 video encoder. - [X-engines] Added the MP2 audio encoder. - [X-engines] Resolved Decklink enumeration issues. - [X-engines] Default VP8/VP9 settings changed to live recording. - [X-engines] Added DNxHD video encoder support. - [Video Capture SDK .Net] VideoCaptureCoreX: Fixed problem with audio source format setting (regression). - [Video Capture SDK .Net] VideoCaptureCoreX: Resolved WPF native rendering issue with a pop-up window. - [All] Avalonia 11.0.5 support. - [Video Capture SDK .Net] VideoCaptureCoreX: Resolved licensing issues. - [Video Capture SDK .Net] VideoCaptureCore: Start/StartAsync method will return false if the video capture device is already used by another application. - [All] Updated VLC source (libVLC 3.0.19). - [All] Updated FFMPEG sources and encoders. Resolved issue with missed MSVC dependencies. - [Video Capture SDK] Updated ONVIF engine. - [Cross-platform SDKs] Updated Decklink source. Resolved the issue with the incorrect device name. - [All] SkiaSharp security updates. - [Cross-platform SDKs] Updated Overlay Manager. Added OverlayManagerDateTime class to draw current date time and custom text. - [Cross-platform SDKs] Updated OverlayManagerImage. Resolved issue with System.Drawing.Bitmap usage. - [ALL] VideoCaptureCore: Resolved rare crash issue with WinUI VideoView - [Video Capture SDK .Net] VideoCaptureCore: Updated FFMPEG.exe output. Improved support of x264 and x265 encoders of custom FFMPEG builds. ## 15.6 - [Video Capture SDK .Net] VideoCaptureCore: Improved video crop performance on modern CPUs - [ALL] VideoCaptureCore, MediaPlayerCore, VideoEditCore: Added the static CreateAsync method that can be used instead of the constructor to create engines without UI lag. - [Video Capture SDK .Net] VideoCaptureCore: Resolved issues with video crop. - [Video Capture SDK .Net] VideoCaptureCoreX: Added video overlays API. The Overlay Manager Demo shows how to use it. - [Video Capture SDK .Net] Improved HW encoder detection. If you have several GPUs, sometimes only the major GPU can be used for video encoding. - [Cross-platform SDKs] Updated Avalonia VideoView. Resolved issue with VideoView recreation. - [Media Player SDK .Net] MediaPlayerCoreX: Resolved startup issue with the Android version of the MediaPlayerCoreX engine. - [Media Player SDK .Net] MediaPlayerCore: Video\_Stream\_Index property has been replaced with Video\_Stream\_Select/Video\_Stream\_SelectAsync methods. - [Media Player SDK .Net] MediaPlayerCoreX: Added Video\_Stream\_Select method. - [Video Capture SDK .Net] VideoCaptureCore: Network\_Streaming\_WMV\_Maximum\_Clients property moved to WMVOutput class. You can set the maximum number of clients for network WMV output. - [All] Updated WPF rendering. Improved performance for 4K and 8K videos. - [Video Capture SDK .Net] VideoCaptureCoreX: Resolved issue with multiple outputs used. - [Video Capture SDK .Net] VideoCaptureCoreX: Resolved issue with OnAudioFrameBuffer event. - [Video Capture SDK .Net] Decklink source changed to improve startup speed. The Decklink\_CaptureDevices method has been replaced by async Decklink\_CaptureDevicesAsync. - [Media Player SDK .Net] MediaPlayerCoreX: Added Custom\_Video\_Outputs/Custom\_Audio\_Outputs properties to set custom video/audio renderers - [Media Player SDK .Net] MediaPlayerCoreX: Added Decklink Output Player Demo (WPF) - [Video Edit SDK .Net] Added Multiple Audio Tracks Demo (WPF) - [Video Edit SDK .Net] Updated MP4 output for multiple audio tracks - [Cross-platform SDKs] Updated device enumerator - [Video Capture SDK .Net] Resolved issue with VU meter in cross-platform engine - [Cross-platform SDKs] Resolved issue with VU Meter (event not fired) - [Media Player SDK .Net] Updated memory playback - [ALL] Added IAsyncDisposable interface support for cross-platform core classes. It should be used to dispose of the core objects in async methods. - [Video Capture SDK .Net] Added madVR support for mutiscreen - [Video Capture SDK .Net] Resolved NDI enumerating issue in the VideoCaptureCore engine - [Media Player SDK .Net] Added madVR Demo - [Video Capture SDK .Net] Added madVR Demo - [ALL] Resolved madVR issues in all SDKs - [Media Blocks SDK .Net] Added NDI Source demo - [Video Capture SDK .Net] Added NDI support for cross-platform engine - [ALL] Resolve the "image not found" issue with the WinUI NuGet package - [Media Blocks SDK .Net/Media Player SDK .Net (cross-platform)] Added MP3+CDG Karaoke Player demo - [Media Blocks SDK .Net] Added CDGSourceBlock for MP3+CDG karaoke files playback - [ALL] Improved madVR support - WinUI VideoView updated to fix issues during audio file playback - [Video Capture SDK .Net] Improved VNC source support for the VideoCaptureCoreX engine. - [Video Capture SDK .Net] Added VNC source support for the VideoCaptureCoreX engine. You can use VNCSourceSettings class to configure Video\_Source. - [Media Blocks SDK .Net] Added VNC source support. You can use the VNCSourceBlock class as a video source block. - [Video Capture SDK .Net] Video\_Resize property has been changed to IVideoResizeSettings type. You can use the VideoResizeSettings class to perform classic resize the same as before or use MaxineUpscaleSettings/MaxineSuperResSettings to perform AI resizing on Nvidia GPU using Nvidia Maxine SDK (SDK or SDK models are required to deploy). - [ALL] Resolved issues with NDI source detection in the local network - [ALL] Added KLVParser class to read and decode data from KLV binary files. - [ALL] Added KLVFileSink block. You can export KLV data from MPEG-TS files. - [Media Blocks SDK .Net] Added KLV demo. - [Video Capture SDK .Net] Added MJPEG network streamer. - [ALL] Added WASAPI 2 support. - [Media Blocks SDK .Net] Updated Video Effects API. Added Grayscale media block. - [Media Blocks SDK .Net] Added Live Video Compositor API and sample. - [ALL] Updated Avalonia VideoView control. Resolved issues with video playback on Windows on HighDPI displays. - [Video Capture SDK .Net] Added CustomVideoFrameRate property to MFOutput. You can set a custom frame rate if your source provides an incorrect frame rate (IP camera, for example). - [Video Capture SDK .Net] Updated NVENC encoder. Resolved issue with high-definition video capture. - [Video Capture SDK .Net] Resolved issue with TV Tuning on Avermedia devices - [Media Blocks SDK .Net] Added OpenCV blocks: CVDewarp, CVDilate, CVEdgeDetect, CVEqualizeHistogram, CVErode, CVFaceBlur, CVFaceDetect, CVHandDetect, CVLaplace, CVMotionCells, CVSmooth, CVSobel, CVTemplateMatch, CVTextOverlay, CVTracker - [CV] Resolved the issue with wrong face coordinates. - [CV, Media Blocks SDK .Net] Added Face Detector block. - [Media Blocks SDK .Net] Added rav1e AV1 video encoder. - [Media Blocks SDK .Net] Added GIF video encoder. - [Media Blocks SDK .Net] Added NDI Sink and NDI source blocks. - [ALL] Resolved NDI SDK detection issues. - [Media Blocks SDK .Net] Updated Speex encoder. - [Media Blocks SDK .Net] Updated Video Mixer block. - [ALL] Added Save/Load methods for output format to serialize into JSON. - [Media Blocks SDK .Net] Added MJPEG HTTP Live streaming sink block. - [ALL] Resolved MP4 HW QSV H264 regression. - [ALL] WinForms and WPF VideoView stability updates. - [Media Player SDK .Net] Removed FilenamesOrURL legacy property. Please use the `Playlist` API instead. - [Media Blocks SDK .Net] Added fade-in/out feature for image overlay block. - [ALL] Telemetry update - [ALL] SDKs updated to use the `ObservableCollection` instead of the `List` in public API. - [ALL] Updated MP4 HW output. Improved NVENC performance. - [Media Blocks SDK .Net] Added Video Compositor sample. - [Media Blocks SDK .Net] Added YouTubeSink and FacebookLiveSink blocks with custom YouTube/Facebook configurations. The `RTMPSink` can stream to YouTube/Facebook in the same way as before. - [Media Blocks SDK .Net] Added SqueezeBack video mixer block. - [ALL] Updated scrolling text logo. We've added the Preload method to render a text overlay before playback. - [ALL] Updated scrolling text logo (performance) - [Media Blocks SDK .Net] Updated Decklink sink blocks - [ALL] Resolved crashes with a text logo with a custom resolution - [Media Blocks SDK .Net] Added Intel QuickSync H264, HEVC, VP9, and MJPEG encoders support. - [Video Edit SDK .Net] Added FastEdit\_ExtractAudioStreamAsync method to extract the audio stream from the video file. - [Video Edit SDK .Net] Added "Audio Extractor" WinForms sample. - [Media Blocks SDK .Net] Updated MP4SinkBlock. The sink can split output files by duration, file size, or timecode. Use MP4SplitSinkSettings instead of MP4SinkSettings to configure. - [Video Capture SDK .Net] Added the OnMJPEGLowLatencyRAWFrame event that fired when the MJPEG low latency engine received a RAW frame from a camera. - [Media Blocks SDK .Net] Added VideoEffectsBlock to use video effects, available in Windows SDKs - [Media Blocks SDK .Net] Updated Decklink source - [Media Blocks SDK .Net] Added Decklink Demo (WPF) - [ALL] Resolved the DeinterlaceBlend video effect crash - [ALL] Used 3rd-party libraries moved to VisioForge.Libs.External assembly/NuGet - [ALL] Added Nvidia Maxine Video Effects SDK (BETA) and sample app for Media Player SDK .Net and Video Capture SDK .Net - [Video Capture SDK .Net] Added Decklink\_Input\_GetVideoFramesCount/Decklink\_Input\_GetVideoFramesCountAsync API to get total and dropped frames for the Decklink source - [ALL] VisioForge HW encoders update ## 15.5 - .Net 7 support - Added NetworkDisconnect event support to MJPEG Low Latency IP camera engine - Added Linux support for the VideoEditCoreX-based demos - Added OnRTSPLowLatencyRAWFrame event to get RAW frames from RTSP stream, using RTSP Low Latency engine - Added AutoTransitions property to the VideoEditCoreX engine - System.Drawing.Rectangle and System.Drawing.Size types are replaced by VisioForge.Types.Rectangle and VisioForge.Types.Size in all crossplatform APIs - MAUI samples (BETA) are added - Improved compatibility with Snap Camera for MP4 HW encoding - Online licensing updated - Added Camera Light demo - Added segments support in Media Player SDK .Net (Cross-platform engine) - Added Playlist API in Media Player SDK .Net (Windows-only engine) - Resolved issues with the "rtsp\_source\_create\_audio\_resampler" call in the RTSP Low Latency engine in Video Capture SDK .Net (Windows-only engine) - Added support for multiple Decklink outputs in Video Capture SDK .Net and Video Edit SDK .Net (Windows-only engine) - Resolved issues with the reverse playback engine in Media Player SDK .Net (Windows-only engine) - ONVIFControl and other ONVIF-related APIs are available for all platforms - API breaking change: the frame rate changed from double to VideoFrameRate in all APIs - Added GPU HW decoding for VLC engine - Resolved issue with WPF HighDPI apps that use EVR - Resolved issue with MediaPlayerCore.Video\_Renderer\_SetCustomWindowHandle method - Added previous frame playback in Media Player SDK .Net (Cross-platform engine) - Added WPF Screen Capture Demo to Media Blocks SDK .Net ## 15.4 - Resolved an issue with ignored Play\_PauseAtFirstFrame property - Updated HighDPI support in WinForms samples - Resolved an issue with HighDPI support for the Direct2D video renderer - Added additional API to ONVIFControl class: GetDeviceCapabilities, GetMediaEndpoints - Resolved forced reencoding issue with FFMPEG files joining without reencoding - Sentry update - Added video interpolation settings for Zoom and Pan video effects - Added GtkSharp UI framework support for video rendering - FastEdit API has been changed to async - Resolved screen flip issue with Video\_Effects\_AllowMultipleStreams property of Video Capture SDK .Net core - Updated RTSP MultiView demo (added GPU decoding, added RAW stream access) - Added OnLoop event into Media Player SDK .Net - Added Loop feature into Media Blocks SDK .Net - Avalonia VideoView was downgraded to 0.10.12 because of Avalonia UI problems with NativeControl - Added File Encryptor demo for Video Edit SDK .Net ## 15.3 - App start-up time improved for PCs with Decklink cards - NDI SDK v5 support - Resolved an issue with MKV Legacy output (wrong cast exception). - Zoom and pan effects performance optimizations - Added basic Media Blocks API (WIP) - Added HLS network streaming to Video Edit SDK .Net - Added Rotate property to WPF VideoView. You can rotate the video by 90, 180, or 270 degrees. Also, you can use the GetImageLayer() method to get the Image layer and apply custom transforms - API change - FilterHelpers renamed to FilterDialogHelper - VisioForge.Types and VisioForge.MediaFramework assemblies merged into VisioForge.Core - UI classes moved to VisioForge.Core.UI.\* assemblies and independent NuGet packages - VisioForge.Types renamed to VisioForge.Core.Types - VisioForge.Core no longer depends on the Windows Forms framework ## 15.2 - Added HorizontalAlignment and VerticalAlignment properties to the text and image logos - Updated ONVIF support, resolved an issue with username and password specified in URL but not specified in source settings - Resolved an issue with the FFMPEG.exe output dialog - Resolved an issue with the separate capture in a service applications - SDK migrated to System.Text.Json from NewtonsoftJson - Updated DirectCapture output for IP cameras - Video processing performance optimizations - IPCameraSourceSettings.URL property type changed from string to a `System.Uri` - Added DirectCapture ASF output for IP cameras ## 15.1 - Disabled Sentry debug messages in the console - Added Icecast streaming - VideoStreamInfo.FrameRate property type changed to VideoFrameRate (with numerator and denominator) from double - Updated WPF VideoView, resolved the issue for IP camera stream playback - API breaking change: `VisioForge.Controls`, `VisioForge.Controls.UI`, `VisioForge.Controls.UI.Dialogs`, and `VisioForge.Tools` assemblies are merged inside the `VisioForge.Core` assembly - Audio effect API now uses string name instead of index - Added Android support in Media Player SDK .Net - Added a new GStreamer-based cross-platform engine to support Windows and other platforms within the v15 development cycle ## 15.0 - Added StatusOverlay property for VideoCapture class. Assign the `TextStatusOverlay` object to this property to add text status overlay, for example, to show "Connecting..." text during IP camera connecting. - RTSP Live555 IP camera engine has been removed. Please use RTSP Low Latency or FFMPEG engines. - Resolved SDK\_Version possible issue. - Added Settings\_Load API. You can load the settings file saved by Settings\_JSON. Be sure that device names are correct. - Resolved issue with an exception if separate capture started before Start/StartAsync method call. - RTP support for the VLC source engine. - API breaking change: SDK\_State property has been removed. We do not have TRIAL and FULL SDK versions anymore. - API breaking change: DirectShow\_Filters\_Show\_Dialog, DirectShow\_Filters\_Has\_Dialog, Audio\_Codec\_HasDialog, Audio\_Codec\_ShowDialog, Video\_Codec\_HasDialog, Video\_Codec\_ShowDialog, Filter\_Supported\_LAV, Filter\_Exists\_MatroskaMuxer, Filter\_Exists\_OGGMuxer, Filter\_Exists\_VorbisEncoder, Filter\_Supported\_EVR, Filter\_Supported\_VMR9 and Filter\_Supported\_NVENC has been moved to VisioForge.Tools.FilterHelpers class. - The `VFAudioStreamInfo`/`VFVideoStreamInfo` classes use the `Timespan` for the duration. - Decklink types from VisioForge.Types assembly moved to VisioForge.Types.Decklink namespace. - Telemetry updated. - Custom redist loader updated. - NDI update. - API breaking change: The `Status` property was renamed to the `State`. The property type is `PlaybackState` in all SDKs. - API breaking change: UI controls split into Core (VideoCaptureCore, MediaPlayerCore, VideoEditCore) and VideoView. - API breaking change: Video\_CaptureDevice... properties merged into Video\_CaptureDevice property of VideoCaptureSource type. - API breaking change: Audio\_CaptureDevice... properties merged into Audio\_CaptureDevice property of AudioCaptureSource type. - API breaking change: In the Media Player SDK, the `Source_Stream` API properties were merged into the `Source_MemoryStream` property of the `MemoryStreamSource` type - Updated DVD playback - Updated FFMPEG source - API breaking change: Media Player SDK types moved from VisioForge.Types namespace to VisioForge.Types.MediaPlayer - API breaking change: Video Capture SDK types moved from VisioForge.Types namespace to VisioForge.Types.VideoCapture - API breaking change: Video Edit SDK types moved from VisioForge.Types namespace to "VisioForge.Types.VideoEdit" - API breaking change: Output types moved from VisioForge.Types namespace to VisioForge.Types.Output - API breaking change: Video Effects types moved from VisioForge.Types namespace to VisioForge.Types.VideoEffects - API breaking change: Audio Effects types moved from VisioForge.Types namespace to VisioForge.Types.AudioEffects - API breaking change: Event types moved from VisioForge.Types namespace to VisioForge.Types.Events - Added Video\_Renderer\_SetCustomWindowHandle method to set custom video renderer by Win32 window/control HWND handle ## 14.4 - Windows 11 support - Telemetry update - Resolved issues with Picture-in-Picture in 2x2 mode - Resolved issues with MJPEG Low Latency source in .Net 5/.Net 6/.Net Core 3.1 - Resolved issue with UDP network streaming for Decklink source - VFMP4v11Output renamed to VFMP4HWOutput - Added Microsoft H265 encoder support - Added Intel QuickSync H265 encoder support - Added OnDecklinkInputDisconnected/OnDecklinkInputReconnected events - Updated Decklink output - Resolved issues with Separate capture for MP4 HW, MOV, MPEG-TS, and MKVv2 outputs - Added Video\_CaptureDevice\_CustomPinName property. You can use this property to set a custom output pin name for a video capture device with several output video pins - Custom redist configuration updated - Updated IP camera RTSP Low Latency engine ## 14.3 - An issue with Video Resize filter creation for NuGet redists has been resolved - Telemetry update - Updated VFDirectCaptureMP4Output output - .Net 6 (preview) support - Nvidia CUDA removed. NVENC is a modern alternative and is available for H264/HEVC encoding. - IP camera MJPEG Low Latency engine has been updated - The NDI source listing has been updated - Improved ONVIF support - Added .Net Core 3.1 support for RTSP Low Latency source engine - Resolved issues with Picture-in-Picture for 2x2 mode - Split project and solutions by independent files for .Net Framework 4.7.2, .Net Core 3.1, .Net 5 and .Net 6 ## 14.2 - An issue with audio stream capture with enabled Virtual Camera SDK output was resolved - VFMP4v8v10Output was replaced with VFMP4Output - The "CanStart" method was added for Video\_CaptureDevices items. The method returns true if the device can start and is not used exclusively in another app - Added async/await API to the ONVIFControl - An issue with wrong ColorKey processing in the Text Overlay video effect was resolved - Added forced frame rate support for the RTSP Low Latency IP camera source - MP4v11 AMD encoders were updated - The timestamp issue that happened during the MP4v11 separate capture pause/resume was resolved - FFMPEG.exe network streaming update - FFMPEG output was updated to the latest FFMPEG version - VC++ redist is no longer required to be installed. VC++ linking changed to static (except optional XIPH output) - Many base DirectShow filters moved to the VisioForge\_BaseFilters module ## 14.1 - Added WPF VideoView control. You can push video frames from the OnVideoFrameBuffer event to control to render them - Correct default transparency value for a text logo - ONVIF support added to .Net 5 / .Net Core 3.1 builds - Added IP\_Camera\_ONVIF\_ListSourcesAsync method to discover ONVIF cameras in the local network - (BREAKING API CHANGE) Changed video capture device API for frame rates enumerating to support modern 4K cameras - Updated MJPEG Decoder (improved performance) - Removed MP4 v8 legacy encoders - INotifyPropertyChanged support in WinForms/WPF wrappers to provide MVVM application support - Resolved issue with RTMPS streaming to Facebook - IP camera source added to the TimeShift demo - Added separate output support for MOV - Added fast-start FFMPEG flag for MP4v11 output that used FFMPEG MP4 muxer - Added GPU decoding for the IP Camera source in demo applications - Added CustomRedist\_DisableDialog property to disable the redist message dialog - Removed Kinect assemblies and demos. Please contact us if you still need Kinect packages - MP4v10 default profile has been changed to Baseline / 5.0 for better browser compatibility ## 14.0 - .Net 5.0 support - Resolved issue with not visible Decklink sources in NuGet SDK version - Resolved issue with device added/removed notifier - Added alternative NDI source in Video Capture SDK .Net - Added NDI streaming (server) in Video Capture SDK .Net - Resolved Separate Capture usage issue for NuGet deployment - Resolved issue with merged text/image logos - Updated device notifier - Added CameraPowerLineControl class to control webcam power line frequency option - Legacy audio effects have been removed. - Removed HTTP\_FFMPEG, RTSP\_UDP\_FFMPEG, RTSP\_TCP\_FFMPEG and RTSP\_HTTP\_FFMPEG from VFIPSource enumeration. You can use the Auto\_FFMPEG value - Updated HLS server. Correct error reporting about used port - Added NDI streaming (server) in Video Edit SDK .Net - Added NDI streaming (server) in Media Player SDK .Net - Added IP\_Camera\_CheckAvailable method in Video Capture SDK .Net - Updated FFMPEG Source filter, more supported codecs, and added GPU decoding ## 12.1 - Migrated to .Net 4.6 - Added Debug\_DisableMessageDialogs property to disable error dialog if OnError event is not implemented. - Fixed issue with resizing on the pause for WPF controls. - Updated ONVIF engine in Video Capture SDK .Net - Updated What You Hear source in Video Capture SDK .Net - Added OnPause/OnResume events - Updated YouTube demo in Media Player SDK .Net - Improved support of webcams with integrated H264 encoder in Video Capture SDK .Net - Updated VLC source - Removed unwanted warning in MP4 v11 output - One installer for TRIAL and FULL versions - Same NuGet packages for TRIAL and FULL versions - .Net Core NuGet packaged merged with .Net Framework package - Added NuGet redists. Deployment was never so simple! ## 12.0 - Async / await API for all SDKs - Breaking API change: All time-related API now uses TimeSpan instead of long (milliseconds) - Tag reader/writer - correct logo loading for some video formats - Removed legacy DirectX 9 video effects - Fixed audio conversion progress issue in Video Edit SDK .Net - Improved .Net Core compatibility - Virtual Camera SDK output added to Media Player SDK .Net (as one of the video renderers) - NewTek NDI devices support added to Video Capture SDK .Net as a new engine for IP cameras - Added Video\_Effects\_MergeImageLogos and Video\_Effects\_MergeTextLogos properties. If you have three or more logos, you can set these properties to true to optimize video effects' performance - Added playlist type option for HLS network streaming - Added integrated lightweight HTTP server for HLS network streaming - Added VR 360° video support in Media Player SDK .Net - Improved DirectX 11 video processing - Added MPEG-TS AAC-only no video support for MPEG-TS output - Improved What You Hear audio source - Several new demo applications - Improved MP4 v11 output - Separate capture for MP4 v11 can split files without frame lose - Many minor bugfixes - .Net Core assemblies updated to .Net Core 3.1 LTS - Updated demos repository on GitHub ## 11.4 - Added ASP.Net MVC video conversion demo app to Video Edit SDK .Net - Alternative OSD implementation to handle Windows 10 changes - Updated GPU video effects - Updated memory source in Media Player SDK .Net - Updated OSD API - Resolved issues with video encryption using binary keys - Update screen capture demos for Video Capture SDK .Net, added window selection to capture. You can capture any window, including windows in the background - Mosaic effect added for Computer Vision demo in Video Capture SDK .Net - Added Multiple IP Cameras Demo (WPF) in Video Capture SDK .Net - Added custom video resize option for MP4v11 output - Merge module (MSM) redists added to all SDKs - Updated FFMPEG.exe output using pipes instead of virtual devices - Resolved issue with PIP custom output resolution option in Video Capture SDK .Net - Resolved issue with file lock using LAV engine in Media Player SDK .Net - Added DirectX11-based GPU video processing ## 11.3 - Resolved issue with audio renderer connection if Virtual Camera SDK output enabled in Video Capture SDK - Improved subtitles support with autoloading in Media Player SDK .Net - Updated audio fade-in/fade-out effects - Added MIDI and KAR files support in Media Player SDK .Net - Added CDG karaoke files support (and new demo application) in Media Player SDK .Net - Added Async playback in Media Player SDK .Net - Updated integrated JSON serializer - Added optional GPU decoding in Media Player SDK .Net. Available decoding engines: DXVA2, Direct3D 11, nVidia CUVID, Intel QuickSync - Added .Net Core 3.0 support, including WinForms and WPF demo apps (Windows only) ## 11.2 - Added Loop property to Video Edit SDK .Net - Updated audio enhancer - Updated RTSP Low Latency source - Resolved crop issue for Decklink source - Added property to use TCP or UDP in RTSP Low Latency engine - Deployment without COM registration and admin rights for Video Edit SDK and Media Player SDK (BETA) - Updated video mixer with improved performance - Added YouTube playback code snippet - Added method to move OSD ## 11.1 - Fixed seeking issue with some MP4 files in Video Edit SDK - Fixed stretch/letterbox issue in the WPF version of all SDKs - Fixed issue with an equalizer on sample rate 16000 or less - Fixed problem with sample grabber for DirectShow source in Media Player SDK - Fixed encrypted files playback in Media Player SDK - Added DVDInfoReader class to read info about DVD files - Resolved issue with wrong file name in OnSeparateCaptureStopped event - Improved barcode detection quality for rotated images - The minimal .Net Framework version is .Net 4.5 now - Improved YouTube playback in Media Player SDK. Added OnYouTubeVideoPlayback event to select video quality for playback - Added the `Play_PauseAtFirstFrame` property to the Media Player SDK .Net. If true playback will be paused on the first frame - Multiple screen support in Screen Capture demo in Video Capture SDK .Net - Resolved issue with network stream playback in Media Player SDK .Net WPF applications - Added low latency HTTP MJPEG stream playback (IP cameras or other sources) in Video Capture SDK .Net - Added Fake Audio Source DirectShow filter, which produces a tone signal - Updated Computer Vision demo in Video Capture SDK .Net - Added Frame\_GetCurrentFromRenderer method to all SDKs. Using this method, you can get the currently rendered video frame directly from the video renderer. - Added low latency RTSP source playback in Video Capture SDK .Net ## 11.0 - Fixed bug with MP4 v11 output, custom GOP settings - Updated MJPEG Decoder - Fixed bug with MP4 v11 output. Added Windows 7 full support - OnStop event of Video Edit SDK returns a successful status - Video Capture SDK Main Demo update - multiscreen can automatically use connected external displays - Media Player SDK Main Demo update - multiscreen can automatically use connected external displays - Added fade-in / fade-out for text logo - Updated Decklink output - Video Edit SDK can fast-cut files from network sources (HTTP/HTTPS) - Added Computer Vision demo, with cars/pedestrian counter and face/eyes/nose/mouth detector/tracker - Updated MP4 output to use alternative muxer that provides constant frame rate - Added MPEG-TS output - Added MOV output ---END OF PAGE--- ## Deploy VisioForge .NET SDK on Android — NuGet & Setup **URL:** https://www.visioforge.com/help/docs/dotnet/deployment-x/Android/ **Description:** Deploy VisioForge .NET SDK apps on Android. NuGet packages, VideoView integration, ARM64/x86 architecture support, and permissions configuration. **Tags:** Video Capture SDK, Media Player SDK, Media Blocks SDK, Video Edit SDK, .NET, Android, C#, NuGet **API:** VideoView, VideoPlayerActivity # Android Implementation and Deployment Guide [Video Capture SDK .Net](https://www.visioforge.com/video-capture-sdk-net) [Video Edit SDK .Net](https://www.visioforge.com/video-edit-sdk-net) [Media Player SDK .Net](https://www.visioforge.com/media-player-sdk-net) [Media Blocks SDK .Net](https://www.visioforge.com/media-blocks-sdk-net) ## Introduction to VisioForge SDKs for Android Android developers working with .NET technologies can leverage the powerful capabilities of VisioForge SDKs to integrate advanced media functionality into their applications. The SDKs provide robust solutions for media manipulation, playback, capture, and editing on the Android platform using .NET technologies. The VisioForge SDK for Android offers powerful capabilities for video processing, capturing, editing, and playback, all optimized for the Android platform while maintaining a consistent cross-platform development experience. The Android deployment process requires special consideration for package management, device compatibility, permissions, and performance optimization. This document provides detailed instructions to ensure your application runs smoothly on Android devices. ## System Requirements Before beginning your Android implementation and deployment process, ensure your development environment meets the following requirements: ### Device Requirements - Android device running Android 9.0 (API level 28) or later - ARM or ARM64 processor architecture - Sufficient storage space for application assets and media processing - Camera and microphone hardware (if using video/audio capture features) ### Development Environment Requirements - Windows, Linux, or macOS computer - Visual Studio with .NET MAUI or Xamarin workloads installed, JetBrains Rider, or Visual Studio Code - .Net 8.0 SDK or later (latest stable version recommended) - Android SDK with appropriate API levels installed - Java Development Kit (JDK) 11 or later - Basic knowledge of .NET development for Android ## Architecture Support The VisioForge SDK for Android provides native support for common Android device architectures: ### ARM64 Support - Optimized for modern Android devices - Hardware-accelerated video processing - Enhanced performance for media operations - Primary target for most applications ### ARM/ARMv7 Support - Compatibility with older Android devices - Software fallbacks for hardware acceleration when needed - Balanced performance and compatibility approach ## Installation and Setup Process Follow these steps to properly set up and deploy your VisioForge-powered Android application: 1. Create a new Android project in your preferred IDE (Visual Studio or JetBrains Rider recommended). 2. Add the required NuGet packages to your project (detailed in the next section). 3. Configure necessary permissions in your AndroidManifest.xml file. 4. Implement your application logic using the VisioForge SDK components. 5. Build, sign, and deploy your application to test devices. ### NuGet Package Management The VisioForge SDK for Android is distributed through NuGet packages. Add the following packages to your Android project: - [VisioForge.DotNet.Core](https://www.nuget.org/packages/VisioForge.DotNet.Core) - Main managed SDK package (core classes, VideoCaptureCoreX / MediaPlayerCoreX / MediaBlocksPipeline). - [VisioForge.CrossPlatform.Core.Android](https://www.nuget.org/packages/VisioForge.CrossPlatform.Core.Android) - Contains the redistribution components (native libraries) required for Android applications. You can add these packages using the NuGet Package Manager in your IDE or by adding the following to your project file (use the latest versions): ``` ``` Note: Replace version numbers with the latest available releases on NuGet.org. The `VisioForge.CrossPlatform.Core.Android` package carries the native libraries for all four Android ABIs (`armeabi-v7a`, `arm64-v8a`, `x86`, `x86_64`) and wires them into the build automatically - no manual copy step is required. Two of them are only used by USB camera capture: - `libVisioForge_UVC.so` - the USB Video Class bridge, with libuvc (BSD 3-Clause) compiled in. - `libusb1.0.so` - libusb 1.0.30, dynamically linked and licensed under the LGPL v2.1 or later. The full notices, including both licence texts, ship with the package as `THIRD-PARTY-NOTICES.txt`. ### USB camera permissions Capturing from a USB (UVC) camera attached over OTG needs its own manifest entries in addition to the packages above: ``` ``` Android refuses to hand a USB video device to an app that does not hold `android.permission.CAMERA`, even when the Android camera API is never used. Declaring that permission also makes a built-in camera an implied *requirement*, which would hide the app on Google Play from devices whose only camera arrives over USB - hence the explicit `required="false"`. USB camera capture requires **Android 9 (API level 28) or newer**. For the full walkthrough see [USB camera capture on Android](../../general/guides/android-usb-camera/). ## Java Bindings Library Integration Android applications using VisioForge SDK require a custom Java Bindings Library for proper functionality. This essential step ensures proper communication between the .NET framework and Android's Java-based environment. Follow these detailed steps to integrate it: 1. Clone the binding-library repository from [GitHub](https://github.com/visioforge/.Net-SDK-s-samples/tree/master/AndroidDependency). 2. Pick the binding project that matches the .NET target you build against — the folder ships one `VisioForge.Core.Android.X{N}.csproj` per supported .NET version (e.g., `VisioForge.Core.Android.X9.csproj` for .NET 9, `VisioForge.Core.Android.X10.csproj` for .NET 10). If your .NET target isn't listed, pick the closest supported one. 3. Add a reference to the binding project from your app's .csproj: ``` ``` > **Note:** Make sure to adjust the relative path to match your project structure ## Implementing VideoView in Your Application ### Adding VideoView to Your Layout The `VideoView` control is the primary interface for displaying video content in your Android application. To integrate it into your app, follow these steps: 1. Open your Activity or Fragment layout file (typically an `.axml` or `.xml` file) 2. Add the VideoView element as shown in the example below: ``` ``` ### Initializing VideoView in Code After adding the VideoView to your layout, you'll need to initialize it in your Activity or Fragment code: ``` using VisioForge.Core.UI.Android; namespace YourApp { [Activity(Label = "VideoPlayerActivity")] public class VideoPlayerActivity : Activity { private VideoView _videoView; protected override void OnCreate(Bundle savedInstanceState) { base.OnCreate(savedInstanceState); SetContentView(Resource.Layout.your_layout); // Initialize the video view _videoView = FindViewById(Resource.Id.videoView); } } } ``` ## Performance Considerations Use physical Android devices for testing whenever possible. Simulators may not accurately represent real-world performance, especially for hardware-accelerated video operations. ## Application Signing and Publishing ### Application Signing For distributing your Android application, you need to sign it with a digital certificate: 1. Create a keystore file if you don't already have one: ``` keytool -genkey -v -keystore your-app-key.keystore -alias your-app-alias -keyalg RSA -keysize 2048 -validity 10000 ``` 1. Configure signing in your project: Add the following to your `android/app/build.gradle` file: ``` android { ... signingConfigs { release { storeFile file("your-app-key.keystore") storePassword "your-store-password" keyAlias "your-app-alias" keyPassword "your-key-password" } } buildTypes { release { signingConfig signingConfigs.release ... } } } ``` For .NET MAUI or Xamarin.Android projects, configure signing in your .csproj file: ``` True your-app-key.keystore your-store-password your-app-alias your-key-password ``` ### Publishing to Google Play Store 1. Generate an AAB (Android App Bundle) for distribution: ``` dotnet build -f net8.0-android -c Release /p:AndroidPackageFormat=aab ``` 1. Create a developer account on the Google Play Console if you don't already have one. 2. Create a new application on the Google Play Console. 3. Upload your AAB file to the production track. 4. Complete the store listing information. 5. Submit for review. ## Troubleshooting ### Common Issues 1. **Missing Permissions**: Ensure all required permissions are declared in the AndroidManifest.xml and requested at runtime. 2. **Architecture Compatibility**: Verify your application supports the target device's architecture (ARM/ARM64). 3. **Memory Constraints**: Monitor memory usage and implement proper resource management. 4. **Performance Issues**: Use hardware acceleration and optimize media operations for mobile devices. 5. **Java Bindings Errors**: When facing issues with Java bindings: 6. Confirm you're using the correct binding library version 7. Check for version mismatches between .NET and the binding library 8. Verify all dependencies are properly referenced ### Getting Help If you encounter issues with your VisioForge SDK deployment on Android, please consult: - [Support Portal](https://support.visioforge.com) - [GitHub Samples](https://github.com/visioforge/.Net-SDK-s-samples) ## Conclusion Implementing and deploying VisioForge SDK applications to Android devices requires careful attention to platform-specific considerations. By following the guidelines in this document, you can ensure a smooth development and deployment process and deliver high-quality video applications to your Android users. Remember to test thoroughly on target devices, especially for performance-intensive operations like video capture and processing. With proper implementation, the VisioForge SDK enables powerful media applications across the Android ecosystem. ---END OF PAGE--- ## VisioForge Computer Vision NuGet Packages for .NET **URL:** https://www.visioforge.com/help/docs/dotnet/deployment-x/computer-vision/ **Description:** Deploy VisioForge CV and CVD NuGet packages for .NET computer vision on Windows, Linux, and macOS. Face detection, object recognition, and more. **Tags:** Video Capture SDK, Media Player SDK, Video Edit SDK, .NET, Windows # Computer Vision Implementation Guide [Video Capture SDK .Net](https://www.visioforge.com/video-capture-sdk-net), [Video Edit SDK .Net](https://www.visioforge.com/video-edit-sdk-net), [Media Player SDK .Net](https://www.visioforge.com/media-player-sdk-net) ## Overview of Available Packages Our SDK provides two NuGet packages that deliver computer-vision capabilities for your applications: 1. **[VisioForge.DotNet.Core.CV](https://www.nuget.org/packages/VisioForge.DotNet.Core.CV/)** — Windows-only CV package. 2. **[VisioForge.DotNet.Core.CVD](https://www.nuget.org/packages/VisioForge.DotNet.Core.CVD/)** — Cross-platform CV package for Windows, Linux, and macOS. Both packages provide a consistent API for integrating computer-vision features directly into your .NET applications. ## Deployment Requirements ### Windows-Specific CV Package #### Installation Process The Windows-specific CV package is designed for seamless integration: - Simply install the NuGet package through your preferred package manager - No additional deployment steps are necessary - Ready to use immediately after installation ### Cross-Platform CVD Package Our cross-platform CVD package requires specific configurations based on your operating system: #### Windows Environment Setup When deploying on Windows systems: - Install the NuGet package through Visual Studio or the .NET CLI - No additional dependencies or configurations are required - Works out of the box with standard Windows installations #### Ubuntu Linux Configuration For Ubuntu Linux systems, install the following dependencies: ``` sudo apt-get install libgdiplus libopenblas-dev libx11-6 ``` These packages provide essential functionalities: - `libgdiplus`: Provides System.Drawing compatibility - `libopenblas-dev`: Optimizes matrix operations for computer vision algorithms - `libx11-6`: Handles X Window System protocol client library #### macOS Setup Instructions For macOS environments, use Homebrew to install the required dependencies: ``` brew install --cask xquartz brew install mono-libgdiplus ``` These components enable: - XQuartz: Provides X11 functionality on macOS - mono-libgdiplus: Ensures compatibility with System.Drawing ## Additional Resources For implementation examples and technical guidance: - Visit our [GitHub repository](https://github.com/visioforge/.Net-SDK-s-samples) for extensive code samples - Explore practical implementations across various use cases - Access community-contributed examples and solutions --- Visit our [GitHub](https://github.com/visioforge/.Net-SDK-s-samples) page to get more code samples. ---END OF PAGE--- ## VisioForge .NET SDK Cross-Platform Deployment Guide **URL:** https://www.visioforge.com/help/docs/dotnet/deployment-x/ **Description:** Deploy .NET applications on Windows, macOS, iOS, Android, and Linux with native libraries, platform dependencies, and UI framework integration. **Tags:** Video Capture SDK, Media Player SDK, Media Blocks SDK, Video Edit SDK, .NET, Windows, macOS, Linux, Android, iOS # Cross-Platform Deployment Guide for VisioForge .NET SDK [Video Capture SDK .Net](https://www.visioforge.com/video-capture-sdk-net) [Video Edit SDK .Net](https://www.visioforge.com/video-edit-sdk-net) [Media Player SDK .Net](https://www.visioforge.com/media-player-sdk-net) [Media Blocks SDK .Net](https://www.visioforge.com/media-blocks-sdk-net) ## Introduction to VisioForge SDK Deployment The VisioForge SDK suite provides powerful multimedia capabilities for .NET applications, supporting video capture, editing, playback, and advanced media processing across multiple platforms. Proper deployment is critical to ensure your applications function correctly and leverage the full potential of these SDKs. This comprehensive guide outlines the deployment process for applications built with VisioForge's cross-platform .NET SDKs, helping you navigate the specific requirements of each supported operating system. ## Deployment Overview Deploying applications built with VisioForge SDKs requires careful consideration of platform-specific dependencies and configurations. The deployment process varies significantly depending on your target platform due to differences in: - Native library requirements - Media framework dependencies - Hardware access mechanisms - Package distribution methods ### Key Deployment Considerations Before beginning the deployment process, consider these critical factors: 1. **Target Platform Architecture**: Ensure you select the appropriate architecture (x86, x64, ARM64) for your deployment platform 2. **Required Dependencies**: Some platforms require additional libraries that aren't included in NuGet packages 3. **Framework Compatibility**: Verify compatibility between your .NET version and the target operating system 4. **Native Library Integration**: Understand how native libraries are integrated and loaded on each platform 5. **UI Framework Selection**: Choose the appropriate UI integration package for your selected framework ## Platform-Specific Deployment ### Windows Deployment Windows deployment is the most straightforward, with comprehensive NuGet package support covering all dependencies: - **Package Distribution**: All components available via NuGet - **Architecture Support**: Both x86 and x64 architectures fully supported - **Native Libraries**: Automatically deployed alongside your application - **UI Framework Options**: Windows Forms, WPF, WinUI, Avalonia, Uno, and MAUI supported For detailed Windows deployment instructions, see the [Windows deployment guide](Windows/). ### Android Deployment Android deployment requires specific configuration for native library extraction and permissions: - **Package Distribution**: Core components available via NuGet - **Architecture Support**: ARM64, ARMv7, and x86\_64 architectures supported - **Native Libraries**: Requires proper configuration for extraction to the correct location - **Permissions**: Camera, microphone, and storage permissions must be explicitly requested - **UI Integration**: Android-specific video view controls required Android applications use a single native library that must be correctly deployed. Review the [Android deployment guide](Android/) for complete instructions. ### macOS Deployment macOS deployment requires additional GStreamer library installation: - **Package Distribution**: Core components available via NuGet, GStreamer requires manual installation - **Architecture Support**: Intel (x64) and Apple Silicon (ARM64) architectures supported - **Native Libraries**: Multiple unmanaged libraries required - **Framework Options**: Native macOS, MAUI, and Avalonia supported - **Bundle Integration**: Special attention needed for proper app bundle structure macOS deployments may require specific entitlements and permissions configurations. See the [macOS deployment guide](macOS/) for detailed instructions. ### iOS Deployment iOS deployment involves unique challenges related to Apple's platform restrictions: - **Package Distribution**: Core components available via NuGet - **Architecture Support**: ARM64 architecture supported - **App Store Guidelines**: Special considerations for App Store submissions - **Native Libraries**: Single unmanaged binary library to deploy - **UI Integration**: iOS-specific video view controls required iOS applications require proper provisioning profiles and entitlements. The [iOS deployment guide](iOS/) provides comprehensive instructions. ### Ubuntu/Linux Deployment Linux deployment requires manual installation of GStreamer dependencies: - **Package Distribution**: Core components available via NuGet, GStreamer requires system packages - **Architecture Support**: x64 architecture primarily supported - **System Dependencies**: Required packages must be installed on the target system - **Distribution Considerations**: Different Linux distributions may require different dependency packages - **UI Options**: Primarily Avalonia UI framework supported Linux deployment often involves distribution-specific package management. The [Ubuntu deployment guide](Ubuntu/) provides instructions for Ubuntu-based distributions. ### Uno Platform Deployment Uno Platform enables deploying applications from a single codebase to multiple platforms: - **Package Distribution**: Core components available via NuGet with platform-specific redistributables - **Supported Platforms**: Windows, Android, iOS, macOS (Catalyst), WebAssembly, and Linux Desktop - **Architecture Support**: Varies by target platform - **Native Libraries**: Platform-specific redistributables required for each target - **UI Integration**: Uno-specific VideoView control adapts to each platform Uno Platform simplifies multi-platform development while leveraging native capabilities. See the [Uno Platform deployment guide](uno/) for comprehensive instructions. ### Runtime Requirements Target devices must meet these minimum requirements: - **Windows**: Windows 7 or later (x86 or x64) - **macOS**: macOS 10.15 (Catalina) or later (x64 or ARM64) - **iOS**: iOS 14.0 or later (ARM64) - **Android**: Android 7.0 (API level 24) or later - **Linux**: Ubuntu 20.04 LTS or later (x64 or ARM64) ## Common Deployment Challenges ### Native Library Loading Issues One of the most common deployment problems involves native library loading failures: - **Symptoms**: Runtime exceptions mentioning DllNotFoundException or similar - **Causes**: Incorrect architecture, missing dependencies, or improper extraction - **Solutions**: Verify package references, check deployment configuration, ensure libraries are in the correct location ### Permission and Security Constraints Modern operating systems enforce strict security policies: - **Camera Access**: Requires explicit permission on all mobile platforms - **Storage Access**: File system restrictions vary by platform - **Network Usage**: May require specific entitlements or manifest entries - **Background Operation**: Platform-specific rules for background media processing ### Performance Considerations Media processing can be resource-intensive: - **CPU Usage**: Implement appropriate threading to avoid UI freezing - **Memory Management**: Monitor and optimize memory usage for large media files - **Power Consumption**: Balance quality settings with battery life considerations ## Deployment Checklist Use this checklist to ensure a successful deployment: - ✅ Correct NuGet packages selected for target platform and architecture - ✅ Platform-specific dependencies installed and configured - ✅ SDK properly initialized and cleaned up - ✅ Appropriate video view controls integrated - ✅ Required permissions requested and justified - ✅ Application tested on target platform under realistic conditions - ✅ Performance metrics validated for acceptable user experience - ✅ Error handling implemented for graceful recovery ## Computer Vision Deployment Computer Vision SDK is a separate NuGet package. Check the [Computer Vision deployment guide](computer-vision/) for more information. ## Additional Resources - [VisioForge GitHub Repository](https://github.com/visioforge/.Net-SDK-s-samples) - Code samples and example projects - [API Documentation](https://api.visioforge.org/dotnet/) - Comprehensive API reference - [Support Portal](https://support.visioforge.com/) - Technical support and knowledge base ---END OF PAGE--- ## iOS Deployment Guide for VisioForge .NET Video SDKs **URL:** https://www.visioforge.com/help/docs/dotnet/deployment-x/iOS/ **Description:** Deploy .NET apps to iOS with VisioForge SDK integration, permissions, architecture support, and cross-platform deployment best practices. **Tags:** Video Capture SDK, Media Player SDK, Media Blocks SDK, Video Edit SDK, .NET, VideoCaptureCoreX, iOS, MAUI, Capture, Encoding, C#, NuGet, Entitlements **API:** VideoView, IVideoView, VideoCaptureCoreX # Apple iOS Deployment Guide [Video Capture SDK .Net](https://www.visioforge.com/video-capture-sdk-net) [Video Edit SDK .Net](https://www.visioforge.com/video-edit-sdk-net) [Media Player SDK .Net](https://www.visioforge.com/media-player-sdk-net) [Media Blocks SDK .Net](https://www.visioforge.com/media-blocks-sdk-net) ## Overview This comprehensive guide walks you through the process of deploying VisioForge SDK-powered applications to Apple iOS devices. The VisioForge SDK provides a powerful framework for building media-rich applications on iOS, offering robust support for video capture, editing, playback, and processing capabilities. The iOS deployment process involves several key considerations, from package management to permission handling and performance optimization. This document will guide you through each step to ensure a smooth deployment experience. ## System Requirements Before beginning your iOS deployment process, ensure your development environment meets the following requirements: ### Hardware Requirements - Apple Mac computer for development (required for iOS app signing) - iOS device for testing (strongly recommended over simulators) - Sufficient storage space for development tools and application assets ### Software Requirements - Apple iOS device running iOS 12 or later (latest version recommended) - Xcode 12 or later with iOS SDK installed - Apple Developer account (required for app signing and distribution) - Visual Studio for Mac, JetBrains Rider, or Visual Studio Code - .Net 7.0 SDK or later (we recommend the latest stable version) ## Architecture Support The VisioForge SDK for iOS provides native support for both major iOS device architectures: ### ARM64 Support - Compatible with all modern iOS devices (iPhone X and newer) - Optimized native libraries for maximum performance - Hardware-accelerated video processing where supported by the device ## Installation Process Follow these steps to properly set up and deploy your VisioForge-powered iOS application: 1. Install the .Net SDK for iOS development 2. Create a new iOS project in your preferred IDE (Visual Studio for Mac or JetBrains Rider recommended) 3. Add the required NuGet packages to your project (detailed in the next section) 4. Configure the necessary permissions and entitlements in your app's Info.plist file 5. Implement your application logic using the VisioForge SDK components 6. Build, sign, and deploy your application to test devices ## NuGet Packages The VisioForge SDK for iOS is distributed through NuGet packages: ### Core Packages - [VisioForge.DotNet.Core](https://www.nuget.org/packages/VisioForge.DotNet.Core) - Core package containing core classes and UI controls, including video playback and display components. This is platform-independent and can be used in any .Net project. ### UI Packages Each UI package has the same VideoView controls but different implementations for the target platform: #### .Net iOS target platform - [VisioForge.Core](https://www.nuget.org/packages/VisioForge.DotNet.Core) - Contains UI controls and all core classes for the iOS platform. #### .Net MAUI target platform - [VisioForge.DotNet.Core.UI.MAUI](https://www.nuget.org/packages/VisioForge.DotNet.Core.UI.MAUI) - Contains UI controls for the MAUI platform. ### Redist Packages - [VisioForge.CrossPlatform.Core.iOS](https://www.nuget.org/packages/VisioForge.CrossPlatform.Core.iOS) - Contains the core redistribution components required for any iOS application using VisioForge technologies. You can add these packages using the NuGet Package Manager in your IDE or by adding the following to your project file (use the latest versions): ``` ``` Note: Replace version numbers with the latest available releases. ## Required Permissions and Entitlements iOS applications require explicit permissions for accessing device features like cameras, microphones, and the photo library. Configure these permissions in your app's Info.plist file: ### Camera Access Required for video capture functionality: ``` NSCameraUsageDescription This app requires camera access for video recording ``` ### Microphone Access Required for audio recording: ``` NSMicrophoneUsageDescription This app requires microphone access for audio recording ``` ### Photo Library Access Required for saving videos to the device's photo library: ``` NSPhotoLibraryUsageDescription This app requires access to the photo library to save videos ``` ### Example Info.plist Configuration Here's a complete example of an Info.plist file with all necessary permissions: ``` LSRequiresIPhoneOS UIDeviceFamily 1 2 UIRequiredDeviceCapabilities arm64 UISupportedInterfaceOrientations UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight UISupportedInterfaceOrientations~ipad UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight XSAppIconAssets Assets.xcassets/appicon.appiconset NSCameraUsageDescription Camera access is required for video recording NSMicrophoneUsageDescription Microphone access is required for audio recording NSPhotoLibraryUsageDescription Photo library access is required to save videos ``` ## Runtime Permission Handling In addition to declaring permissions in your Info.plist file, you should also request permissions at runtime. Here's an example of how to request camera and microphone permissions: ``` using System.Diagnostics; using Photos; // Request camera permission private async Task RequestCameraPermissionAsync() { var status = await Permissions.RequestAsync(); if (status != PermissionStatus.Granted) { // Handle permission denial Debug.WriteLine("Camera permission denied"); } } // Request microphone permission private async Task RequestMicrophonePermissionAsync() { var status = await Permissions.RequestAsync(); if (status != PermissionStatus.Granted) { // Handle permission denial Debug.WriteLine("Microphone permission denied"); } } // Request photo library permission (iOS specific) private void RequestPhotoLibraryPermission() { PHPhotoLibrary.RequestAuthorization(status => { if (status == PHAuthorizationStatus.Authorized) { Debug.WriteLine("Photo library access granted"); } else { Debug.WriteLine("Photo library access denied"); } }); } ``` ## SDK Initialization Properly initialize the VisioForge SDK in your application's lifecycle: ``` // In your AppDelegate or application startup code public override bool FinishedLaunching(UIApplication app, NSDictionary options) { // Initialize the VisioForge SDK VisioForge.Core.VisioForgeX.InitSDK(); // Your other initialization code return true; } // Clean up on application termination public override void WillTerminate(UIApplication application) { // Clean up VisioForge SDK resources VisioForge.Core.VisioForgeX.DestroySDK(); // Your other cleanup code } ``` ## Implementation Best Practices ### Using VideoView Controls The VisioForge SDK provides a `VideoView` control for displaying video content. On iOS `VideoView` is a Metal-accelerated `MTKView` subclass that implements `IVideoView` directly (use `VideoViewGL` if you need the legacy OpenGL-backed `UIView` variant): ``` // Create a VideoView instance — VideoView implements IVideoView, so no casting/helper call is needed var videoView = new VisioForge.Core.UI.Apple.VideoView(new CGRect(0, 0, UIScreen.MainScreen.Bounds.Width, UIScreen.MainScreen.Bounds.Height)); View.AddSubview(videoView); // Pass the videoView itself where an IVideoView is expected var captureCore = new VideoCaptureCoreX(videoView); ``` You can add the VideoView using a storyboard or code. ### Resource Management iOS devices have limited resources compared to desktop computers. Follow these best practices: 1. Release resources when not in use 2. Use lower resolution settings for real-time processing 3. Implement proper lifecycle management in your ViewControllers 4. Test on actual devices, not just simulators ## Testing and Debugging ### Physical Device Testing While the iOS simulator can be useful for basic interface testing, it has significant limitations for media applications: - Simulator may have performance issues during video encoding at high resolutions - Camera and microphone are not available in the simulator - Hardware acceleration features may not be available or may behave differently **Always test your media application on physical iOS devices before release.** ### Common Performance Considerations When deploying media applications to iOS, consider these performance factors: 1. **Resolution and frame rate:** Lower these settings for better performance on older devices 2. **Encoder selection:** Use hardware-accelerated encoders when available 3. **Memory management:** Implement proper disposal of large objects and monitor memory usage 4. **Battery impact:** Media processing is power-intensive; implement power-saving measures ## Troubleshooting Common Issues ### Permission Denials If your app can't access the camera or microphone: 1. Verify all required permissions are in your Info.plist 2. Check that you're requesting permissions at runtime before attempting to use the hardware 3. Test if the user has manually denied permissions in iOS Settings ### Library Loading Errors If you encounter errors loading native libraries: 1. Verify all required NuGet packages are properly installed 2. Check for conflicting package versions 3. Ensure you're targeting the correct iOS architecture (ARM64) ## Additional Resources - Visit the [VisioForge GitHub repository](https://github.com/visioforge/.Net-SDK-s-samples) for code samples and example projects - Browse the [VisioForge API documentation](https://api.visioforge.org/dotnet/api/index.html) for comprehensive SDK reference --- By following this deployment guide, you should be able to successfully create, configure, and deploy VisioForge-powered applications to iOS devices. For specific questions or advanced configuration needs, please contact VisioForge technical support. ---END OF PAGE--- ## Deploy VisioForge .NET SDK on macOS — Intel & Apple Silicon **URL:** https://www.visioforge.com/help/docs/dotnet/deployment-x/macOS/ **Description:** Deploy VisioForge .NET SDK apps on macOS. NuGet packages, NSView integration, App Store publishing, and native library setup for x64 and ARM64. **Tags:** Video Capture SDK, Media Player SDK, Media Blocks SDK, Video Edit SDK, .NET, macOS, MAUI, GStreamer, C#, NuGet, Entitlements **API:** VideoView, VideoViewGL # Apple macOS Deployment Guide [Video Capture SDK .Net](https://www.visioforge.com/video-capture-sdk-net) [Video Edit SDK .Net](https://www.visioforge.com/video-edit-sdk-net) [Media Player SDK .Net](https://www.visioforge.com/media-player-sdk-net) [Media Blocks SDK .Net](https://www.visioforge.com/media-blocks-sdk-net) ## Introduction VisioForge's powerful .NET SDKs provide comprehensive media processing capabilities for macOS developers. Whether you're building video capture applications, media players, video editors, or complex media processing pipelines, our SDKs offer the tools you need to deliver high-quality solutions on Apple's platforms. The VisioForge SDK provides comprehensive support for macOS application development using .NET technologies. You can leverage this SDK to build robust media processing applications that run natively on macOS, including support for both Intel (x64) and Apple Silicon (ARM64) architectures. This guide covers everything you need to know to set up, configure, and deploy applications for macOS and MacCatalyst environments using the VisioForge SDK. Whether you're building traditional macOS applications or cross-platform solutions using frameworks like MAUI or Avalonia, this document will help you navigate the installation and deployment process. ## System Requirements Before starting the installation and deployment process, ensure your development environment meets the following requirements: ### Hardware Requirements - Mac computer with Intel processor (x64) or Apple Silicon (ARM64) - Minimum 8GB RAM (16GB recommended for video processing) - Sufficient disk space for development tools and application assets ### Software Requirements - macOS 10.15 (Catalina) or later (latest version recommended) - macOS Monterey (12.x) - macOS Ventura (13.x) - macOS Sonoma (14.x) - Future macOS releases (with ongoing updates) - Xcode 12 or later with Command Line Tools installed - .NET 6.0 SDK or later - Visual Studio for Mac or JetBrains Rider (recommended IDEs) To install XCode Command Line Tools, run the following in Terminal: ``` xcode-select --install ``` ## Architecture Support The VisioForge SDK for macOS supports both major processor architectures: ### Intel (x64) Support - Compatible with all Intel-based Mac computers - Uses native x64 libraries for optimal performance - Full feature support across all SDK components ### Apple Silicon (ARM64) Support - Native support for M1, M2, and newer Apple Silicon chips - Optimized ARM64 native libraries for maximum performance - Hardware acceleration leveraging Apple's Neural Engine where applicable ### Universal Binary Considerations When targeting both architectures, consider building universal binaries that include both x64 and ARM64 code. This approach ensures your application runs natively on either platform without relying on Rosetta 2 translation. For universal binary builds targeting both Intel and Apple Silicon: ``` osx-x64;osx-arm64 true ``` ## Core Technologies VisioForge .NET SDKs leverage several key technologies to deliver high-performance media capabilities on macOS: ### GStreamer Integration All VisioForge SDKs utilize GStreamer as the underlying framework for video/audio playback and encoding. GStreamer provides: - Hardware-accelerated media processing - Broad format compatibility - Optimized playback pipeline - Efficient encoding capabilities The GStreamer components are automatically installed through our redistributable packages, eliminating the need for manual configuration. ## Installation and NuGet Package Deployment The primary method for deploying VisioForge SDK components to macOS applications is through NuGet packages. These packages include all necessary managed and unmanaged libraries required for your application. ### Essential NuGet Packages For native macOS applications, add these core packages: 1. **Main SDK Package** (based on your needs): 2. `VisioForge.DotNet.VideoCapture` for camera capture applications 3. `VisioForge.DotNet.VideoEdit` for video editing applications 4. `VisioForge.DotNet.MediaPlayer` for media playback applications 5. `VisioForge.DotNet.MediaBlocks` for advanced media processing pipelines 6. **UI Package**: 7. `VisioForge.DotNet.Core` includes Apple-specific UI controls 8. **Platform Redistributable**: 9. `VisioForge.CrossPlatform.Core.macOS` for native libraries and dependencies ### macOS Applications For standard macOS applications targeting the `netX.0-macos` framework (where X represents the .NET version), use the following NuGet package: - [VisioForge.CrossPlatform.Core.macOS](https://www.nuget.org/packages/VisioForge.CrossPlatform.Core.macOS) This package contains: - Native libraries for media processing - GStreamer components for media playback and encoding - Interface assemblies for .NET integration - Both x64 and ARM64 binaries ### Computer Vision with OpenCV For applications requiring advanced image processing and computer vision capabilities, add: - [VisioForge.CrossPlatform.OpenCV.macOS](https://www.nuget.org/packages/VisioForge.CrossPlatform.OpenCV.macOS) The package ships one universal (x64 + ARM64) GStreamer plugin with OpenCV linked into it, so there are no separate OpenCV libraries to deploy, plus the Haar cascade files `CVFaceDetectBlock`, `CVFaceBlurBlock` and `CVHandDetectBlock` load by default. It provides the Media Blocks in the `VisioForge.Core.MediaBlocks.OpenCV` namespace: - Image transformation: `CVDewarpBlock`, `CVDilateBlock`, `CVErodeBlock` - Edge and feature detection: `CVEdgeDetectBlock`, `CVLaplaceBlock`, `CVSobelBlock` - Face processing: `CVFaceBlurBlock`, `CVFaceDetectBlock` - Motion detection: `CVMotionCellsBlock` - Object recognition: `CVTemplateMatchBlock`, `CVHandDetectBlock` - Image enhancement: `CVEqualizeHistogramBlock`, `CVSmoothBlock` - Tracking and overlay: `CVTrackerBlock`, `CVTextOverlayBlock` - Stabilization: `VideoStabilizationBlock` ### Getting Started with Native macOS Projects To begin developing native macOS applications with VisioForge SDKs: 1. **Create a new macOS project** in your preferred IDE (Visual Studio for Mac or JetBrains Rider) 2. **Add required NuGet packages** (as detailed above) 3. **Configure project settings** for your target architecture ## MacCatalyst and MAUI Applications ### Cross-Platform Development with .NET MAUI .NET Multi-platform App UI (MAUI) enables developing applications that run seamlessly across macOS, iOS, Android, and Windows from a single codebase. VisioForge provides comprehensive support for MAUI development through specialized packages and controls. For MacCatalyst applications (including MAUI projects) targeting the `netX.0-maccatalyst` framework, use: - [VisioForge.CrossPlatform.Core.macCatalyst](https://www.nuget.org/packages/VisioForge.CrossPlatform.Core.macCatalyst) ### MAUI Package Configuration For MAUI projects targeting macOS (through MacCatalyst), add these packages: ``` ``` ### MAUI Project Setup 1. **Initialize SDK in MauiProgram.cs**: ``` builder .UseMauiApp() .UseSkiaSharp() .ConfigureMauiHandlers(handlers => handlers.AddVisioForgeHandlers()); ``` 1. **Add VideoView Control in XAML**: ``` xmlns:vf="clr-namespace:VisioForge.Core.UI.MAUI;assembly=VisioForge.Core.UI.MAUI" ``` MacCatalyst applications require additional configuration to ensure native libraries are properly included in the application bundle. Add the following custom build target to your project file: ``` $(OutputPath)$(AssemblyName).app $(AppBundleDir)/Contents/MonoBundle ``` This target performs several crucial tasks: 1. Identifies the application bundle directory 2. Creates the MonoBundle directory if it doesn't exist 3. Copies all `.dylib` and `.so` native libraries to the MonoBundle directory 4. Outputs diagnostic information for troubleshooting For complete MAUI integration details, see our dedicated [MAUI](../../install/maui/) documentation page. ## UI Framework Options The VisioForge SDK supports multiple UI frameworks for macOS development: ### Native macOS UI For traditional macOS applications, the SDK provides `VideoViewGL` controls that integrate with the native AppKit framework. These controls provide high-performance video rendering using OpenGL. ### MAUI For cross-platform MAUI applications, use the [VisioForge.DotNet.Core.UI.MAUI](https://www.nuget.org/packages/VisioForge.DotNet.Core.UI.MAUI) package, which provides MAUI-compatible video views. ### Avalonia For Avalonia UI applications, the [VisioForge.DotNet.Core.UI.Avalonia](https://www.nuget.org/packages/VisioForge.DotNet.Core.UI.Avalonia) package offers Avalonia-compatible video controls. ## Development Environment Setup ### JetBrains Rider Integration JetBrains Rider provides an excellent development experience for macOS and iOS applications using VisioForge SDKs: 1. Create a new project in Rider targeting macOS or iOS 2. Add the required NuGet packages through the Package Manager 3. Configure project settings for your target platform 4. Add UI controls and implement SDK functionality For detailed Rider setup instructions, see our [Rider integration guide](../../install/rider/). ### Visual Studio for Mac Setup Despite its deprecation, Visual Studio for Mac still works for developing macOS and iOS applications with VisioForge SDKs: 1. Create a new project in Visual Studio for Mac 2. Add NuGet packages through the NuGet Package Manager 3. Configure necessary build settings 4. Add UI controls to your application's interface For detailed Visual Studio for Mac instructions, see our [Visual Studio for Mac guide](../../install/visual-studio-mac/). ## SDK Initialization and Cleanup X-engines in the VisioForge SDK require explicit initialization and cleanup to manage resources properly: ``` // Initialize SDK at application startup VisioForge.Core.VisioForgeX.InitSDK(); // Use SDK components... // Clean up resources before application exit VisioForge.Core.VisioForgeX.DestroySDK(); ``` For asynchronous initialization and cleanup, use the async variants: ``` // Async initialization await VisioForge.Core.VisioForgeX.InitSDKAsync(); // Async cleanup await VisioForge.Core.VisioForgeX.DestroySDKAsync(); ``` ## Troubleshooting Common Issues ### Native Library Loading Failures If your application fails to load native libraries: 1. Verify all required NuGet packages are properly installed 2. Check the application bundle structure to ensure libraries are in the correct location 3. Use the `dtruss` or `otool` commands to diagnose library loading issues 4. Ensure XCode Command Line Tools are properly installed ### MacCatalyst-Specific Issues For MacCatalyst deployment problems: 1. Verify the CopyNativeLibrariesToMonoBundle target is correctly implemented 2. Check that the MonoBundle directory contains all necessary native libraries 3. Ensure the application has appropriate entitlements for media access ### Performance Optimization For optimal performance: 1. Enable hardware acceleration when available 2. Adjust video resolution based on device capabilities 3. Close and dispose of SDK objects when no longer needed ## Additional Resources For code samples, example projects, and more technical resources: - Visit the [VisioForge GitHub repository](https://github.com/visioforge/.Net-SDK-s-samples) for code samples - Join the VisioForge developer community for support and discussions Our samples repository contains comprehensive examples showing: - Video capture from cameras - Media playback implementations - Video editing workflows - Advanced media processing pipelines ## Conclusion VisioForge .NET SDKs provide powerful media capabilities for macOS and iOS developers, enabling the creation of sophisticated multimedia applications. By following this installation and deployment guide, you've established the foundation for building high-performance media applications across Apple's platforms. For any additional questions or support needs, please contact our technical support team or visit our forums for community assistance. --- *This documentation is regularly updated to reflect the latest SDK features and compatibility information.* ---END OF PAGE--- ## Deploy .NET Apps on Ubuntu with GStreamer and VisioForge SDK **URL:** https://www.visioforge.com/help/docs/dotnet/deployment-x/Ubuntu/ **Description:** Deploy .NET multimedia apps on Ubuntu Linux with GStreamer setup, hardware configuration, and cross-platform performance optimization. **Tags:** Video Capture SDK, Media Player SDK, Media Blocks SDK, Video Edit SDK, .NET, Linux, GStreamer, NuGet # Ubuntu Deployment Guide for VisioForge SDK Applications [Video Capture SDK .Net](https://www.visioforge.com/video-capture-sdk-net) [Video Edit SDK .Net](https://www.visioforge.com/video-edit-sdk-net) [Media Player SDK .Net](https://www.visioforge.com/media-player-sdk-net) [Media Blocks SDK .Net](https://www.visioforge.com/media-blocks-sdk-net) ## Introduction Deploying .NET applications with VisioForge SDKs on Ubuntu Linux offers multiple benefits, including cross-platform compatibility, access to Linux-specific hardware, and the ability to run your multimedia applications on environments ranging from server infrastructure to edge devices. This comprehensive guide will walk you through the complete process of configuring your Ubuntu environment, installing the necessary dependencies, and deploying your VisioForge-powered .NET application. The VisioForge SDK family works on Ubuntu and other Linux distributions that support `GStreamer` libraries. Additional supported platforms include `Nvidia Jetson` devices and `Raspberry Pi`, making it perfect for a wide range of applications from desktop multimedia software to IoT solutions. ## System Requirements Before deploying your application, ensure your Ubuntu environment meets these minimum requirements: - Ubuntu 20.04 LTS or later (22.04 LTS and later recommended) - .NET 7.0 or later runtime - At least 4GB RAM (8GB recommended for video processing) - x86\_64 or ARM64 architecture - Internet connection for package installation ## Installation and Setup ### Installing .NET Download the latest [.NET installer](https://dotnet.microsoft.com/en-us/download/dotnet) package from the Microsoft website and follow the installation instructions. ## GStreamer Installation GStreamer forms the multimedia backbone for VisioForge SDKs on Linux platforms. It provides essential functionality for audio and video capture, processing, and playback. ### Required GStreamer Packages Install the following GStreamer packages using apt-get. We require v1.22.0 or later, though v1.24.0+ is highly recommended for access to the latest features and optimizations: - `gstreamer1.0-plugins-base`: Essential baseline plugins - `gstreamer1.0-plugins-good`: High-quality, well-tested plugins - `gstreamer1.0-plugins-bad`: Newer plugins of varying quality - `gstreamer1.0-alsa`: ALSA audio support - `gstreamer1.0-gl`: OpenGL rendering support - `gstreamer1.0-pulseaudio`: PulseAudio integration - `libges-1.0-0`: GStreamer Editing Services - `gstreamer1.0-libav`: FFMPEG integration (OPTIONAL but recommended for broader format support) ### Complete Installation Script The following commands will update your package repositories and install all required GStreamer components: ``` sudo apt update ``` ``` sudo apt install gstreamer1.0-plugins-base gstreamer1.0-plugins-good gstreamer1.0-plugins-bad gstreamer1.0-alsa gstreamer1.0-gl gstreamer1.0-pulseaudio gstreamer1.0-libav libges-1.0-0 ``` ### Raspberry Pi Additional Requirements For Raspberry Pi, additionally, you need to install the following packages: ``` sudo apt install gstreamer1.0-libcamera ``` ### Verifying GStreamer Installation After installation, verify your GStreamer setup by running: ``` gst-inspect-1.0 --version ``` This should display the installed GStreamer version. Ensure it meets the minimum requirement (1.22.0+) or ideally shows 1.24.0 or later. ## Required NuGet Packages When deploying your .NET application to Ubuntu, you'll need to include additional platform-specific NuGet packages that provide the necessary native libraries and bindings. ### Additional Core Linux Package The [VisioForge.CrossPlatform.Core.Linux.x64](https://www.nuget.org/packages/VisioForge.CrossPlatform.Core.Linux.x64) package contains essential native libraries and bindings for the .NET Linux platform. This package is mandatory for all VisioForge SDK deployments on Ubuntu. ### Development Environment You can use Rider to develop your project in Linux. Please check the [Rider](../../install/rider/) installation page for more information. ## Application Deployment Follow these steps to deploy your application on Ubuntu: ### Publishing Your Application To create a self-contained deployment that includes all .NET runtime dependencies: ``` dotnet publish -c Release -r linux-x64 --self-contained true ``` For smaller deployments where the target machine already has .NET installed: ``` dotnet publish -c Release -r linux-x64 --self-contained false ``` ### Deployment Structure Your deployment folder should contain: - Your application executable - Application DLLs - VisioForge SDK assemblies - Native Linux libraries from the VisioForge NuGet packages ### Setting Execution Permissions Ensure your application executable has the proper permissions: ``` chmod +x ./YourApplicationName ``` ## Hardware Considerations ### Camera Support Ubuntu supports various camera types: - **USB Webcams**: Most USB webcams work out of the box - **IP Cameras**: Supported via RTSP, HTTP streams - **Professional Cameras**: Many professional cameras with Linux drivers are supported - **Virtual Devices**: v4l2loopback can be used for virtual camera creation To list available camera devices: ``` v4l2-ctl --list-devices ``` ### Audio Devices Audio capture and playback is supported through: - ALSA (Advanced Linux Sound Architecture) - PulseAudio To list available audio devices: ``` arecord -L # For recording devices aplay -L # For playback devices ``` ## Troubleshooting ### Permission Issues Camera or audio device access issues can often be resolved by adding your user to the appropriate groups: ``` sudo usermod -a -G video,audio $USER ``` Remember to log out and back in for group changes to take effect. ### Performance Optimization For optimal performance on Ubuntu: - Use the latest GStreamer version (1.24.0+) - Enable hardware acceleration where available - For NVIDIA GPUs, install the appropriate CUDA and nvcodec packages - Adjust process priority using `nice` for resource-intensive applications ## Conclusion Deploying VisioForge SDK applications on Ubuntu provides a powerful, flexible environment for multimedia applications. By following this guide, you can ensure that your .NET application leverages the full capabilities of the VisioForge SDK ecosystem on Linux platforms. For specific deployment scenarios or troubleshooting assistance, refer to the comprehensive documentation available on the VisioForge website or contact our technical support team. --- Visit our [GitHub](https://github.com/visioforge/.Net-SDK-s-samples) page to get more code samples. ---END OF PAGE--- ## Uno Platform Deployment Guide for VisioForge .NET SDKs **URL:** https://www.visioforge.com/help/docs/dotnet/deployment-x/uno/ **Description:** VisioForge .NET SDK Uno Platform deployment with VideoView integration, multi-platform support for Windows, Android, iOS, macOS, and Linux. **Tags:** Video Capture SDK, Media Player SDK, Media Blocks SDK, Video Edit SDK, .NET, C++, Windows, macOS, Linux, Android, iOS, Uno, GStreamer, Streaming, Webcam, C#, NuGet # Uno Platform Implementation and Deployment Guide [Video Capture SDK .Net](https://www.visioforge.com/video-capture-sdk-net) [Video Edit SDK .Net](https://www.visioforge.com/video-edit-sdk-net) [Media Player SDK .Net](https://www.visioforge.com/media-player-sdk-net) [Media Blocks SDK .Net](https://www.visioforge.com/media-blocks-sdk-net) ## Introduction to VisioForge SDKs for Uno Platform Uno Platform is a powerful cross-platform UI framework that enables developers to build native applications for Windows, Android, iOS, macOS, and Linux from a single codebase. VisioForge provides comprehensive support for Uno Platform applications through the `VisioForge.DotNet.Core.UI.Uno` package, which contains specialized UI controls designed specifically for the Uno Platform. The Uno Platform deployment process requires special consideration for each target platform. This document provides detailed instructions to ensure your application runs smoothly across all supported platforms. ## Supported Platforms VisioForge SDKs support the following Uno Platform targets: | Platform | Framework Target | Status | | --- | --- | --- | | Windows Desktop | net10.0-windows10.0.19041.0 | ✔ Full Support | | Android | net10.0-android | ✔ Full Support | | iOS | net10.0-ios | ✔ Full Support | | macOS (Catalyst) | net10.0-maccatalyst | ✔ Full Support | | Linux Desktop (Skia) | net10.0-desktop | ✔ Full Support | ## System Requirements Before beginning your Uno Platform implementation, ensure your development environment meets the following requirements: ### Development Environment Requirements - Windows, Linux, or macOS computer - Visual Studio 2022 with Uno Platform extension, JetBrains Rider, or Visual Studio Code - .NET 10.0 SDK or later (latest stable version recommended) - Uno Platform templates installed ### Platform-Specific Requirements #### Windows - Windows 10 version 17763 or later - Windows App SDK 1.4+ #### Android - Android SDK with appropriate API levels - Android 5.0 (API 21) or later device - Java Development Kit (JDK) 11 or later #### iOS/macOS - Mac computer with Xcode 15+ installed (for iOS/macOS builds) - Apple Developer account (for device deployment) - iOS 15.0 or later / macOS 10.15 or later #### Linux - GStreamer runtime installed - X11 or Wayland display server ## Installation and Setup Process Follow these steps to properly set up and deploy your VisioForge-powered Uno Platform application: ### 1. Install Uno Platform Templates ``` dotnet new install Uno.Templates ``` ### 2. Install Required Workloads ``` # For Android dotnet workload install android # For iOS/macOS dotnet workload install ios maccatalyst ``` ### 3. Create a New Uno Platform Project ``` dotnet new unoapp -o MyMediaApp ``` ### 4. Add VisioForge NuGet Packages Add the following packages to your project: ``` ``` ### Platform-Specific Redistributables Add platform-specific redistributable packages to your project: #### Windows ``` ``` #### Android ``` ``` Additionally, you'll need to add the Java Bindings Library. Clone it from our [GitHub repository](https://github.com/visioforge/.Net-SDK-s-samples/tree/master/AndroidDependency) and add a reference: ``` ``` #### iOS ``` ``` #### macOS (Catalyst) ``` ``` For macOS Catalyst, you also need to add a custom MSBuild target to copy native libraries to the app bundle: ``` $(OutputPath)$(AssemblyName).app $(AppBundleDir)/Contents/MonoBundle ``` #### Linux Desktop For Linux, you need to install GStreamer runtime on your system: ``` # Ubuntu/Debian sudo apt-get install gstreamer1.0-plugins-base gstreamer1.0-plugins-good gstreamer1.0-plugins-bad gstreamer1.0-plugins-ugly gstreamer1.0-libav # Fedora sudo dnf install gstreamer1-plugins-base gstreamer1-plugins-good gstreamer1-plugins-bad-free gstreamer1-plugins-ugly-free ``` ### Complete Sample Project File Here is a complete example `.csproj` file for an Uno Platform application with VisioForge SDK: ``` net10.0-windows10.0.19041;net10.0-android net10.0-maccatalyst;net10.0-ios;net10.0-android Exe true true MyMediaApp com.yourcompany.mymediaapp 1.0 1 Your Company Media application powered by Uno Platform and VisioForge. Apple Development $(OutputPath)$(AssemblyName).app $(AppBundleDir)/Contents/MonoBundle ``` ## Platform-Specific Configuration ### Windows Configuration Windows applications use native WinUI 3 rendering and support hardware acceleration via DirectX. #### Required Capabilities Add required capabilities to your `Package.appxmanifest`: ``` ``` ### Android Configuration #### Permissions Add the necessary permissions to your `AndroidManifest.xml`: ``` ``` #### Runtime Permission Requests Request permissions at runtime in your code: ``` private async Task RequestPermissionsAsync() { var status = await Permissions.RequestAsync(); if (status != PermissionStatus.Granted) { // Handle permission denial } status = await Permissions.RequestAsync(); if (status != PermissionStatus.Granted) { // Handle permission denial } } ``` ### iOS Configuration #### Info.plist Settings Add required usage descriptions to your `Info.plist`: ``` NSCameraUsageDescription This app requires camera access for video capture NSMicrophoneUsageDescription This app requires microphone access for audio recording NSPhotoLibraryUsageDescription This app requires photo library access to save media ``` #### App Transport Security For HTTP streaming sources, configure App Transport Security: ``` NSAppTransportSecurity NSAllowsArbitraryLoads ``` ### macOS (Catalyst) Configuration macOS Catalyst applications share configuration with iOS. Additionally, configure runtime identifiers for both Intel and Apple Silicon: ``` maccatalyst-x64 maccatalyst-arm64 ``` ### Linux Desktop Configuration For Linux desktop applications using Skia: 1. Ensure GStreamer is installed on the target system 2. Set appropriate environment variables if needed: ``` export GST_PLUGIN_PATH=/usr/lib/x86_64-linux-gnu/gstreamer-1.0 ``` ## Building for Different Platforms ### Windows ``` dotnet build -c Release -f net10.0-windows10.0.19041.0 ``` ### Android ``` dotnet build -c Release -f net10.0-android ``` ### iOS ``` dotnet build -c Release -f net10.0-ios ``` ### macOS ``` dotnet build -c Release -f net10.0-maccatalyst ``` ### Linux Desktop ``` dotnet build -c Release -f net10.0-desktop ``` ## Performance Considerations - **Hardware Acceleration**: Enable hardware-accelerated rendering where available (Windows DirectX, Apple VideoToolbox, Android MediaCodec) - **Physical Devices**: Always test on physical devices, especially for mobile platforms. Simulators may not accurately represent real-world performance - **Memory Management**: Monitor memory usage, particularly on mobile devices when processing large media files - **Network Streaming**: Use appropriate buffer sizes for network streaming to balance latency and smoothness ## Troubleshooting Common Issues ### Video Not Displaying 1. Verify the VideoView is properly initialized and added to the visual tree 2. Check that platform-specific redistributables are correctly installed 3. Ensure permissions are granted on mobile platforms ### Performance Issues 1. Check that hardware acceleration is enabled 2. Reduce video resolution for lower-powered devices 3. Monitor memory usage and optimize buffer sizes ### Build Errors 1. Verify all required workloads are installed 2. Check for NuGet package version compatibility 3. Ensure target framework versions match across all project references ---END OF PAGE--- ## Windows Deployment Guide for VisioForge Cross-Platform SDK **URL:** https://www.visioforge.com/help/docs/dotnet/deployment-x/Windows/ **Description:** VisioForge SDK .NET deployment for Windows with NuGet packages, dependencies, and x86/x64 architecture configuration for multimedia apps. **Tags:** Video Capture SDK, Media Player SDK, Media Blocks SDK, Video Edit SDK, .NET, Windows, USB3 Vision / GigE, NuGet **API:** AWSS3SinkBlock, CVDewarpBlock, CVDilateBlock, CVErodeBlock # Windows Installation and Deployment Guide for VisioForge Cross-Platform SDK [Video Capture SDK .Net](https://www.visioforge.com/video-capture-sdk-net) [Video Edit SDK .Net](https://www.visioforge.com/video-edit-sdk-net) [Media Player SDK .Net](https://www.visioforge.com/media-player-sdk-net) [Media Blocks SDK .Net](https://www.visioforge.com/media-blocks-sdk-net) ## Introduction to VisioForge SDK Installation and Deployment The VisioForge SDK suite provides powerful multimedia capabilities for your .NET applications, supporting video capture, editing, playback, and advanced media processing across multiple platforms. This comprehensive guide covers both installation and deployment for Windows applications. ## Installation SDKs are accessible in two forms: a setup file and NuGet packages. The setup file provides a straightforward installation process, ensuring that all necessary components are correctly configured. On the other hand, NuGet packages offer a flexible and modular approach to incorporating SDKs into your projects, allowing for easy updates and dependency management. We highly recommend utilizing NuGet packages due to their convenience and efficiency in managing project dependencies and updates. When building your application, you have the option to create both x86 and x64 versions. This allows your application to run on a wider range of systems, accommodating different hardware architectures. However, it's important to note that the setup file is exclusively available for the x64 architecture. This means that while you can develop and compile x86 builds, the initial setup and installation process will require an x64 system. ### IDEs For development, you can use powerful integrated development environments (IDEs) like JetBrains Rider or Visual Studio. Both IDEs offer robust tools and features to streamline the development process on Windows. To ensure a smooth setup, please refer to the respective installation guides. The [Rider installation page](../../install/rider/) provides detailed instructions for setting up JetBrains Rider, while the [Visual Studio installation page](../../install/visual-studio/) offers comprehensive guidance on installing and configuring Visual Studio. These resources will help you get started quickly and effectively, leveraging the full capabilities of these development environments. ## Distribution and Package Management VisioForge SDK components for Windows are distributed as NuGet packages, making integration straightforward with modern .NET development environments. You can add these packages to your project using any of the following tools: - Visual Studio Package Manager - JetBrains Rider NuGet Manager - Visual Studio Code with NuGet extensions - Direct command-line integration using the .NET CLI ## Required Base Packages Every Windows application built with VisioForge SDK requires the appropriate base package according to your application's target architecture. These packages contain the essential components for SDK functionality. ### Core Platform Packages - [VisioForge.CrossPlatform.Core.Windows.x86](https://www.nuget.org/packages/VisioForge.CrossPlatform.Core.Windows.x86) - For 32-bit Windows applications - [VisioForge.CrossPlatform.Core.Windows.x64](https://www.nuget.org/packages/VisioForge.CrossPlatform.Core.Windows.x64) - For 64-bit Windows applications > **Note**: For applications targeting multiple architectures, you should include both packages and implement appropriate runtime selection logic. ## Optional Component Packages Depending on your application's requirements, you may need to include additional packages for specialized functionality. These optional components extend the SDK's capabilities in various domains. ### FFMPEG Media Processing (Recommended) These packages provide comprehensive codec support for a wide range of media formats through the FFMPEG library integration: - [VisioForge.CrossPlatform.Libav.Windows.x86](https://www.nuget.org/packages/VisioForge.CrossPlatform.Libav.Windows.x86) - 32-bit FFMPEG support - [VisioForge.CrossPlatform.Libav.Windows.x64](https://www.nuget.org/packages/VisioForge.CrossPlatform.Libav.Windows.x64) - 64-bit FFMPEG support For applications with size constraints, compressed versions of these packages utilizing UPX compression are available: - [VisioForge.CrossPlatform.Libav.Windows.x86.UPX](https://www.nuget.org/packages/VisioForge.CrossPlatform.Libav.Windows.x86.UPX) - Compressed 32-bit FFMPEG support - [VisioForge.CrossPlatform.Libav.Windows.x64.UPX](https://www.nuget.org/packages/VisioForge.CrossPlatform.Libav.Windows.x64.UPX) - Compressed 64-bit FFMPEG support ### Cloud Integration - Amazon Web Services For applications requiring cloud storage integration with AWS S3: - [VisioForge.CrossPlatform.AWS.Windows.x86](https://www.nuget.org/packages/VisioForge.CrossPlatform.AWS.Windows.x86) - 32-bit AWS support - [VisioForge.CrossPlatform.AWS.Windows.x64](https://www.nuget.org/packages/VisioForge.CrossPlatform.AWS.Windows.x64) - 64-bit AWS support When using these packages, the following Media Block becomes available: - `AWSS3SinkBlock` - For storing media in S3 buckets ### Computer Vision with OpenCV For applications requiring advanced image processing and computer vision capabilities: - [VisioForge.CrossPlatform.OpenCV.Windows.x86](https://www.nuget.org/packages/VisioForge.CrossPlatform.OpenCV.Windows.x86) - 32-bit OpenCV support - [VisioForge.CrossPlatform.OpenCV.Windows.x64](https://www.nuget.org/packages/VisioForge.CrossPlatform.OpenCV.Windows.x64) - 64-bit OpenCV support The OpenCV integration provides access to Media Blocks in the `VisioForge.Core.MediaBlocks.OpenCV` namespace, including: - Image transformation: `CVDewarpBlock`, `CVDilateBlock`, `CVErodeBlock` - Edge and feature detection: `CVEdgeDetectBlock`, `CVLaplaceBlock`, `CVSobelBlock` - Face processing: `CVFaceBlurBlock`, `CVFaceDetectBlock` - Motion detection: `CVMotionCellsBlock` - Object recognition: `CVTemplateMatchBlock`, `CVHandDetectBlock` - Image enhancement: `CVEqualizeHistogramBlock`, `CVSmoothBlock` - Tracking and overlay: `CVTrackerBlock`, `CVTextOverlayBlock` ## Specialized Hardware Support Packages VisioForge SDK provides integration with professional camera systems and specialized hardware. Include the appropriate package when working with specific device types. ### Allied Vision Cameras For integrating with professional Allied Vision camera hardware: - [VisioForge.CrossPlatform.AlliedVision.Windows.x64](https://www.nuget.org/packages/VisioForge.CrossPlatform.AlliedVision.Windows.x64) ### Basler Cameras For applications working with Basler industrial cameras: - [VisioForge.CrossPlatform.Basler.Windows.x64](https://www.nuget.org/packages/VisioForge.CrossPlatform.Basler.Windows.x64) ### Teledyne/FLIR Cameras (Spinnaker SDK) For thermal imaging and specialized FLIR cameras: - [VisioForge.CrossPlatform.Spinnaker.Windows.x64](https://www.nuget.org/packages/VisioForge.CrossPlatform.Spinnaker.Windows.x64) ### GenICam Protocol Support (GigE/USB3 Vision) For cameras utilizing the standardized GenICam protocol: - [VisioForge.CrossPlatform.GenICam.Windows.x64](https://www.nuget.org/packages/VisioForge.CrossPlatform.GenICam.Windows.x64) ## Deployment Best Practices When deploying VisioForge-based applications for Windows, consider these recommendations: 1. Choose the appropriate architecture packages (x86 or x64) based on your target platform 2. Include the FFMPEG packages for comprehensive media format support 3. Only include specialized hardware packages when needed to minimize deployment size 4. For security-sensitive applications, consider using the UPX compressed versions to obfuscate native libraries 5. Always test your deployment on a clean system to ensure all dependencies are properly resolved ## The shared native plugin cache At start-up the SDK does not load its GStreamer libraries from your application's output folder directly. It mirrors that folder's `x64`, `x86` or `arm64` subfolder into a shared location and loads from there: ``` %PUBLIC%\.gstreamer\-\ ``` GStreamer keeps a plugin registry that records each plugin by its **absolute path**. A single canonical folder therefore lets every VisioForge application on the machine share one warm registry, so only the first start after an SDK upgrade pays the cost of scanning the plugin set; every later start on any application reuses it. The folder also stays writable, which an installed application's own directory under `Program Files` is not. The folder is keyed to the SDK version **and** to a stamp of the core and Libav redistributables the application actually deployed - the `VisioForge.CrossPlatform.*` packages version independently of the managed SDK - so applications carrying different redistributables no longer overwrite each other's libraries on every start. Two deployments differing only in a package neither marker covers (OpenCV, AWS, a camera vendor's) do still share a folder; the file names in those packages are disjoint from everything else, so the effect is a few files being re-copied, not a wrong library being loaded. A cache the SDK created and nothing has started for 30 days is removed; a folder left by an older SDK that used the previous shared layout is left alone, because applications built on that release still load from it. Two consequences worth knowing when you test a deployment: - The cache accumulates the libraries of every application of that SDK version on the machine. A development box that has run a fuller package set can therefore satisfy a dependency your application does not actually ship - and the same application then fails on a clean machine. - Clearing `%PUBLIC%\.gstreamer` is safe at any time; the next start rebuilds it. To take the shared cache out of the picture and load exactly what your application deployed, point `VisioForgeX.CacheFolder` at your own native folder **before** calling `InitSDK`: ``` VisioForgeX.CacheFolder = Path.Combine(AppContext.BaseDirectory, "x64"); VisioForgeX.InitSDK(); ``` This is the right setting for verifying that a redistributable is complete, and for an application that must not write outside its own directory. The cost is that the application no longer shares the machine-wide registry and scans the plugin set itself on every first start. MAUI, WinUI 3 and Unity applications always load in place and never use the shared cache. ## Troubleshooting Common Issues ### Deployment Issues If you encounter issues after deployment: 1. Verify all required NuGet packages are properly included 2. Check that the architecture (x86/x64) matches your application target 3. Ensure native libraries are being extracted to the correct locations 4. Review Windows security and permission settings that might restrict media functionality ### WinForms RESX Files Build Issue Sometimes you can get the following error: `Error MSB3821: Couldn't process file Form1.resx due to its being in the Internet or Restricted zone or having the mark of the web on the file. Remove the mark of the web if you want to process these files.` Error MSB3821 occurs when Visual Studio or MSBuild cannot process a `.resx` resource file because it is marked as untrusted. This happens when the file has the "Mark of the Web" (MOTW), a security feature that flags files downloaded from the internet or received from untrusted sources. The MOTW places the file in the Internet or Restricted security zone, preventing it from being processed during a build. #### How to Fix It To resolve this error, you need to remove the MOTW from the affected file: ##### Unblock the File Manually - Right-click on Form1.resx in File Explorer. - Select Properties. - In the General tab, check for an Unblock button or checkbox at the bottom. - Click Unblock, then click OK. ##### Unblock via PowerShell (for multiple files) - Open PowerShell. - Navigate to your project directory. - Run the command: Get-ChildItem -Path . -Recurse | Unblock-File ##### Unblock the ZIP Before Extraction - If you downloaded the project as a ZIP file, right-click the ZIP file. - Select Properties. - Click Unblock, then extract the files. By unblocking the file, you remove the MOTW, allowing Visual Studio to process it normally during the build. For additional assistance, visit the [VisioForge support site](https://support.visioforge.com/) or consult the [API documentation](https://api.visioforge.org/dotnet/api/index.html). --- Visit our [GitHub](https://github.com/visioforge/.Net-SDK-s-samples) page to get more code samples. ---END OF PAGE--- ## Audio Event Detection SDK for .NET — YAMNet AudioSet **URL:** https://www.visioforge.com/help/docs/dotnet/general/ai/audio-event-detection/ **Description:** Detect real-world sounds — siren, dog bark, glass break, alarm, music, speech — in live or file audio on-device with a YAMNet AudioSet classifier. **Tags:** .NET, AI, YAMNet, AudioSet, Audio Event Detection, Sound Classification, Sound Recognition, Surveillance, VideoCaptureCoreX, MediaPlayerCoreX **API:** AudioEventDetectorBlock, AudioEventDetectorSettings, AudioEventArgs, AudioEventScore, AudioScoresEventArgs # Audio Event Detection — AudioEventDetectorBlock `AudioEventDetectorBlock` is an audio-only Media Block from `VisioForge.DotNet.Core.AI`. It taps the audio stream, resamples it to 16 kHz mono, and runs a **YAMNet** (Google, AudioSet) ONNX classifier over short windows to recognize real-world sounds — siren, dog bark, glass break, alarm, music, speech and hundreds more (521 AudioSet classes). Audio passes through unchanged. The block implements `IAudioProcessingBlock`, so it can be inserted into a manual pipeline or registered on `VideoCaptureCoreX`/`MediaPlayerCoreX`. This is a natural companion to the object-analytics and PTZ features for surveillance and monitoring. ``` using VisioForge.Core.MediaBlocks; using VisioForge.Core.MediaBlocks.AI; using VisioForge.Core.MediaBlocks.Sources; using VisioForge.Core.MediaBlocks.Special; using VisioForge.Core.Types.X.AI; using VisioForge.Core.Types.X.Sources; ``` ## Basic block setup ``` var settings = new AudioEventDetectorSettings(yamnetModelPath) { Threshold = 0.5f, // confidence a class must reach to fire SmoothingWindows = 3, // moving average that suppresses one-window blips }; var detector = new AudioEventDetectorBlock(settings); detector.OnAudioEvent += (sender, e) => { // Raised on a background worker thread — marshal to the UI thread before touching UI. Console.WriteLine($"{e.Label} ({e.Confidence:F2}) [{e.Start:mm\\:ss} - {e.End:mm\\:ss}]"); }; ``` Wire it between an audio source and a sink (or any downstream audio block): ``` var source = new UniversalSourceBlock( await UniversalSourceSettings.CreateAsync(mediaFile, renderVideo: false, renderAudio: true)); // Unsynced: an offline file is analyzed as fast as the model allows. // Keep IsSync = true (the default) for a live source you also want to monitor. var sink = new NullRendererBlock(MediaBlockPadMediaType.Audio) { IsSync = false }; pipeline.Connect(source.AudioOutput, detector.Input); pipeline.Connect(detector.Output, sink.Input); await pipeline.StartAsync(); ``` ## Using it with VideoCaptureCoreX and MediaPlayerCoreX `AudioEventDetectorBlock` implements `IAudioProcessingBlock`, so instead of building a manual pipeline you can register it on an X engine. The block **must be added before the session starts** — the processing block list is consumed while the pipeline is built, and a block added later is ignored. For capture, terminate the audio chain with a non-synced null renderer if you want analysis without speaker monitoring or recording: ``` core.Audio_Source = microphoneSettings; core.Audio_OutputBlock = new NullRendererBlock(MediaBlockPadMediaType.Audio) { IsSync = false, }; var detector = new AudioEventDetectorBlock(settings); detector.OnAudioEvent += Detector_OnAudioEvent; core.Audio_Processing_AddBlock(detector); // before StartAsync await core.StartAsync(); ``` For playback, `Audio_Play` must be `true` for the audio chain to be built: ``` player.Audio_Play = true; player.Audio_OutputBlock = new NullRendererBlock(MediaBlockPadMediaType.Audio) { IsSync = false, }; var detector = new AudioEventDetectorBlock(settings); detector.OnAudioEvent += Detector_OnAudioEvent; player.Audio_Processing_AddBlock(detector); // before OpenAsync / PlayAsync await player.OpenAsync(source); await player.PlayAsync(); ``` See [Using AI blocks with VideoCaptureCoreX and MediaPlayerCoreX](../x-engines/) for the full `Audio_Processing_*`/`Audio_OutputBlock` API and lifecycle rules. ## How events are raised The block classifies each `WindowSeconds` window, averages the model's per-frame scores, and smooths them with a moving average over `SmoothingWindows` windows. A per-class **hysteresis** (Schmitt trigger) then collapses one continuous sound into a single event: a class enters at `Threshold` and leaves at `Threshold * ReleaseRatio` (0.7 by default). `OnAudioEvent` fires **once per sound**, when it ends (drops below the release threshold) or at end-of-stream, carrying the full `Start`..`End` span and the peak `Confidence`. This means one continuous siren yields a single event with a duration, not a stream of duplicates. `Start` and `End` are measured over the audio the block has actually analysed, counting from zero when the pipeline starts — they are not media positions. For straight-through playback or capture from the beginning the two are the same. They part company once audio is skipped or replayed underneath the block: seeking a `MediaPlayerCoreX` does not reset this clock, so after a seek the reported times no longer line up with positions in the file, and a gap in a live source leaves every later time early by the missing duration. Inference runs on a dedicated background worker fed by an **unbounded** sample queue, so the streaming thread is never blocked and **the queue never discards samples to bound its own growth**: a source that outruns the worker (a live source on a slow provider, or a file decoded at full speed by an unsynced renderer) simply grows the backlog — 64 KB per buffered second at 16 kHz mono — which drains as soon as the worker catches up. Two designed exits stop the analysis instead of quietly dropping a fraction of it; both are described in the notes below. YAMNet is tiny — on the CPU, roughly 0.6 ms for the default 0.975 s window and 1.8 ms for the 5 s maximum (the cost follows the window's frame count), over 1000× real time either way, so the CPU provider is usually sufficient. ## Key settings `AudioEventDetectorSettings(yamnetModelPath)`. Unlike the vision AI settings, this type does **not** derive from `OnnxInferenceSettings` — YAMNet consumes an audio waveform, not an image. Every property below is read **once, when the block is built** during `StartAsync` — set them before you start the pipeline; mutating the settings object afterwards has no effect. | Property | Default | Description | | --- | --- | --- | | `ModelPath` | — | Absolute path to the YAMNet ONNX model. Required. | | `Threshold` | 0.5 | Confidence a class must reach to start an event, clamped to 0.01–1 (a threshold of 0 could never be released and would latch every class). | | `ReleaseRatio` | 0.7 | An active event ends below `Threshold * ReleaseRatio` (hysteresis), clamped to 0.01–1 for the same reason. | | `SmoothingWindows` | 3 | Windows the scores are averaged over (1 disables smoothing). | | `WindowSeconds` | 0.975 | Inference window length — one 0.96 s YAMNet patch plus a small margin; clamped 0.96–5 s. | | `ClassFilter` | null | Optional allowlist of AudioSet class names (e.g. `"Siren"`, `"Dog"`). | | `Provider` | `Auto` | ONNX execution provider (CPU is usually enough). | | `EnableScoresEvent` | false | Raise `OnScores` (top-K) for every window, for a live meter. | | `TopK` | 5 | Number of classes reported in the scores event. | ## Filtering to specific sounds Pass a `ClassFilter` allowlist to report only the sounds you care about — for example an alarm watchdog that ignores everything else: ``` var settings = new AudioEventDetectorSettings(yamnetModelPath) { ClassFilter = new[] { "Siren", "Emergency vehicle", "Police car (siren)", "Alarm", "Glass", "Gunshot, gunfire" }, }; ``` Class names are the AudioSet display names and must match one exactly (case is ignored, but a typo, a singular/plural difference or an abbreviation is not). Unknown names are ignored with a warning **as long as at least one name resolves**. A non-empty filter in which **no** name resolves fails the block's build — `StartAsync` returns `false` and an error naming the unresolved entries is reported — rather than silently falling back to detecting all 521 classes. ## Live scores meter Enable `OnScores` to receive the top-K class scores for every processed window (useful for a live level meter or a debugging view): ``` var settings = new AudioEventDetectorSettings(yamnetModelPath) { EnableScoresEvent = true, // read once, when the pipeline starts — set it before StartAsync TopK = 5, }; var detector = new AudioEventDetectorBlock(settings); detector.OnScores += (sender, e) => { foreach (var s in e.Scores) { Console.WriteLine($" {s.Label}: {s.Confidence:F2}"); } }; ``` ## Model The block uses **YAMNet**, Google's MobileNet-v1 audio classifier trained on [AudioSet](https://research.google.com/audioset/), predicting 521 classes from the AudioSet ontology. The model consumes a 16 kHz mono waveform (the block handles resampling and down-mixing) and returns per-frame class scores. The weights are Apache-2.0. Your application supplies the model file and points `ModelPath` at it: the SDK NuGet packages ship neither the weights nor a downloader, and the block never fetches anything itself. The demo below has a **Download** button that fetches the model once and caches it; nothing is downloaded unless you click it. **For production, convert the official Google TF-Hub model to ONNX yourself** rather than relying on a third-party ONNX export. The conversion is a format change only and does not alter the Apache-2.0 weights license: ``` pip install tensorflow tensorflow-hub tf2onnx onnx python -c "import tensorflow_hub as hub, tensorflow as tf; m=hub.load('https://tfhub.dev/google/yamnet/1'); tf.saved_model.save(m, 'yamnet_tf')" python -m tf2onnx.convert --saved-model yamnet_tf --output yamnet.onnx --opset 13 ``` If you use a community ONNX export instead, pin it to an immutable revision and verify its SHA-256 — the WPF [Audio Event Detection Demo](#demos) downloads a pinned export of the Apache-2.0 weights and verifies the hash after download. > Sound event recognition uses the AudioSet ontology and the YAMNet model by Google, released under the Apache-2.0 license. ## Demos The `Audio Event Detection Demo` (WPF Media Blocks — model download with SHA-256 verification, class filter, live event log) is in the SDK's demo set and will be linked here once published to the public samples repository. ## Notes - `OnAudioEvent` and `OnScores` are raised on the inference worker thread; marshal to the UI thread before updating UI. A throwing handler is caught and logged, never propagated onto the worker. - At end-of-stream the trailing window and any still-active events are flushed before teardown. - Under normal operation the block never drops audio — neither from the *pass-through* path nor from the analysis path. The internal analysis queue is unbounded: a source that outruns the worker grows the backlog instead of discarding samples, and the audio still passes downstream untouched. - Two designed exits end the analysis rather than lose audio silently, and neither ever touches the *pass-through* path: if the backlog no longer fits in memory, the block reports an error once and stops analyzing that stream (use a GPU execution provider or faster hardware); and an explicit stop abandons the backlog the worker has not reached yet — only a natural end-of-stream drains it in full. ---END OF PAGE--- ## AI Video Auto-Reframe SDK for .NET — AutoReframeBlock **URL:** https://www.visioforge.com/help/docs/dotnet/general/ai/auto-reframe/ **Description:** AI auto-reframe SDK for .NET — turn landscape footage into vertical 9:16 Shorts/Reels/TikTok video that follows the subject, on-device with ONNX YOLO. **Tags:** .NET, AI, ONNX, Auto Reframe, Vertical Video, Reframe, YOLO, Shorts, Reels, Media Blocks SDK **API:** AutoReframeBlock, AutoReframeSettings, AutoReframeTargetSelection, ReframeEventArgs # AI Auto-Reframe (Subject-Following Vertical Video) — AutoReframeBlock `AutoReframeBlock` converts landscape footage into a fixed output aspect ratio — typically vertical 9:16 for Shorts, Reels, and TikTok — by dynamically cropping around a detected subject and scaling the crop to the configured output resolution. It runs object detection on a sampled stream, follows the selected subject, smooths the crop position over time so it glides instead of jittering, and eases back to the frame center when no subject is present. ``` graph LR; Source-->AutoReframeBlock; AutoReframeBlock-->H264EncoderBlock; H264EncoderBlock-->MP4SinkBlock; ``` The block lives in `VisioForge.Core.AI` (`VisioForge.DotNet.Core.AI`), uses `AutoReframeSettings`, and has one video `Input` and one video `Output`. Internally it is a chain of an RGBA sample grabber (for detection) → `videocrop` → `videoscale` → `capsfilter` (output size) → `videoconvert`. Detection runs on the pipeline streaming thread, so a slow model can throttle the pipeline; keep `DetectionInterval` at a few frames to spread the cost. ## How it works 1. On each frame the block taps the RGBA pixels. Every `DetectionInterval` frames it runs the YOLO detector and picks a subject according to `TargetSelection` and `ClassLabelFilter`. 2. A crop window is centered on that subject. The crop window size is fixed for the whole run (it depends only on the source size, the source **pixel aspect ratio**, and the **output aspect ratio**), so only the crop **position** moves and downstream caps do not renegotiate per frame. Anamorphic (non-square-pixel) sources are cropped PAR-aware: the crop is sized in pixel space so its display aspect matches the output aspect, and the scale to the square-pixel output restores true display proportions. 3. The crop position is smoothed with an exponential moving average (`Smoothing`) and a dead zone (`DeadZoneFraction`) that suppresses micro-jitter, then clamped so the crop stays fully inside the frame. 4. The crop is applied live to `videocrop`, and `videoscale` + `capsfilter` scale it to `OutputWidth` x `OutputHeight`. 5. When no subject has been seen for longer than `LostTargetTimeout`, the crop eases back to the frame center. ## Settings `AutoReframeSettings` is constructed with a `YoloDetectorSettings` (the detector used to locate subjects). | Property | Default | Description | | --- | --- | --- | | `OutputWidth` | `1080` | Output width in pixels (positive, even). | | `OutputHeight` | `1920` | Output height in pixels (positive, even). `1080x1920` is 9:16. | | `DetectionInterval` | `5` | Run detection every N frames; the smoothed crop keeps gliding in between. | | `Smoothing` | `0.85` | EMA retention factor in `[0, 1)`. Higher glides more slowly. | | `DeadZoneFraction` | `0.05` | Dead-zone half-width as a fraction of the frame dimension; suppresses micro-moves. | | `TargetSelection` | `Largest` | `Largest` (biggest box), `FirstDetected`, or `ClassLabel` (highest-confidence of the class). | | `ClassLabelFilter` | `"person"` | Only detections with this label are candidates; set to `null` to follow any class. | | `LostTargetTimeout` | `1 s` | How long the subject may be absent before the crop eases to center. | The detector's `ConfidenceThreshold` and `IoUThreshold` are used for detection. The block always runs detection with drawing disabled, so detection boxes are never baked into the output frame — `YoloDetectorSettings.DrawDetections` has no effect here. Model licenses The SDK does not ship model weights. Supply your own YOLO `.onnx` file and verify its license (training code, weights, and dataset) separately — the ONNX format does not change a model's license. ## Example: landscape file to vertical 9:16 MP4 ``` using VisioForge.Core.MediaBlocks; using VisioForge.Core.MediaBlocks.AI; using VisioForge.Core.MediaBlocks.Sinks; using VisioForge.Core.MediaBlocks.Sources; using VisioForge.Core.MediaBlocks.VideoEncoders; using VisioForge.Core.Types.X; using VisioForge.Core.Types.X.AI; using VisioForge.Core.Types.X.Sinks; using VisioForge.Core.Types.X.Sources; using VisioForge.Core.Types.X.VideoEncoders; var pipeline = new MediaBlocksPipeline(); // Video-only: the audio stream is not connected, so do not render it. var source = new UniversalSourceBlock( await UniversalSourceSettings.CreateAsync("landscape.mp4", renderVideo: true, renderAudio: false)); var detector = new YoloDetectorSettings(@"C:\models\yolox_nano.onnx") { Model = ObjectDetectorModel.YOLOX, }; var reframeSettings = new AutoReframeSettings(detector) { OutputWidth = 1080, OutputHeight = 1920, // 9:16 DetectionInterval = 5, Smoothing = 0.85, ClassLabelFilter = "person", TargetSelection = AutoReframeTargetSelection.Largest, }; var reframe = new AutoReframeBlock(reframeSettings); reframe.OnReframeUpdated += (s, e) => { if (e.HasTarget) { Console.WriteLine( $"Following {e.TrackedLabel} ({e.Confidence:P0}); crop {e.CropRect} at {e.Timestamp}"); } }; var h264 = new H264EncoderBlock(new OpenH264EncoderSettings()); var mp4 = new MP4SinkBlock(new MP4SinkSettings("vertical.mp4")); pipeline.Connect(source.VideoOutput, reframe.Input); pipeline.Connect(reframe.Output, h264.Input); pipeline.Connect(h264.Output, mp4.CreateNewInput(MediaBlockPadMediaType.Video)); var eosReached = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); pipeline.OnStop += (s, e) => eosReached.TrySetResult(true); if (!await pipeline.StartAsync()) { Console.WriteLine("Pipeline failed to start (check the model path and source file)."); await pipeline.DisposeAsync(); return; } // Wait for end-of-stream (the pipeline stops itself and the muxer finalizes the MP4), // then release the pipeline. await eosReached.Task; await pipeline.StopAsync(); await pipeline.DisposeAsync(); ``` ## The OnReframeUpdated event `OnReframeUpdated` fires on every processed frame with a `ReframeEventArgs`: | Member | Description | | --- | --- | | `CropRect` | The crop window applied to the source frame, in source-frame pixel coordinates (pre-PAR-correction). On anamorphic sources its width:height ratio deliberately differs from the output aspect ratio — account for this when drawing overlay geometry. | | `HasTarget` | Whether a subject was being followed on this frame. | | `TargetBox` | The followed subject box in source coordinates, or `null`. | | `TrackedLabel` | The followed subject class label, or `null`. | | `Confidence` | The followed subject confidence (0..1), or `0`. | | `Timestamp` | The source frame timestamp. | Use it to drive an on-screen overlay of the crop region, to log which subject is being followed, or to render a side-by-side preview of the original and the reframed output. ## Tips - **Aspect ratios.** `1080x1920` is 9:16; `1080x1080` is 1:1; `1080x1350` is 4:5. Any even `OutputWidth`/`OutputHeight` works. - **Smoothness vs. responsiveness.** Raise `Smoothing` (for example `0.9`) for slower, calmer motion; lower it (for example `0.7`) to track a fast-moving subject more tightly. - **Jitter.** If the crop twitches on a nearly-static subject, increase `DeadZoneFraction`. - **Class.** Set `ClassLabelFilter` to follow a specific class (for example `"person"`, `"dog"`, `"sports ball"`), or `null` to follow whatever is largest. - **Cost.** Detection is the main cost. Increase `DetectionInterval` to run it less often; the crop still glides on the frames in between. ---END OF PAGE--- ## Background Removal SDK for .NET — BackgroundRemovalBlock **URL:** https://www.visioforge.com/help/docs/dotnet/general/ai/background-removal/ **Description:** Background removal SDK for .NET — blur, replace, or make video backgrounds transparent on-device with BackgroundRemovalBlock and ONNX matting models. **Tags:** .NET, AI, ONNX, Background Removal, Background Removal SDK, Virtual Background, Matting, Green Screen, VideoCaptureCoreX, MediaPlayerCoreX **API:** BackgroundRemovalBlock, BackgroundRemovalSettings, BackgroundRemovalModel, BackgroundReplacementMode # AI Background Removal (Matting) — BackgroundRemovalBlock `BackgroundRemovalBlock` runs an ONNX segmentation or matting model on RGBA video frames, estimates a per-pixel foreground alpha mask, and composites a replacement background into the frame. Use it for portrait matting, virtual background blur, virtual green-screen output, static background replacement, or transparent RGBA output. ``` graph LR; Source-->BackgroundRemovalBlock; BackgroundRemovalBlock-->VideoRendererBlock; ``` The block lives in `VisioForge.Core.AI` (`VisioForge.DotNet.Core.AI`), uses `BackgroundRemovalSettings` (which extends `OnnxInferenceSettings`), and has one video `Input` and one video `Output`. It uses an internal sample grabber for RGBA frames and runs inference on the pipeline streaming thread, so a slow model can throttle the pipeline. It does not raise a recognition event — the output is the processed video frame. ## Models and licensing Set `BackgroundRemovalSettings.Model` to the family that matches the supplied `.onnx` file. The SDK does not ship model weights in the NuGet package; your application supplies the `.onnx` file. | Model | Expected input and output | Notes | | --- | --- | --- | | `BackgroundRemovalModel.MODNet` (default) | Square input, default `512x512`; direct resize; RGB normalized to -1..1; output alpha matte `[1, 1, H, W]` in 0..1. | Portrait matting, Apache-2.0. | | `BackgroundRemovalModel.PPMattingV2` | Model fixed size; direct resize; RGB normalized to -1..1; output alpha matte `[1, 1, H, W]` in 0..1. | Real-time human matting from PaddleSeg, Apache-2.0. | | `BackgroundRemovalModel.U2Net` | `320x320`; direct resize; RGB ImageNet mean/std normalization; first output is rescaled per frame to 0..1. | Salient-object / portrait segmentation, Apache-2.0. Set `InputWidth`/`InputHeight` to `320` if the model uses dynamic input dimensions. | | `BackgroundRemovalModel.BiRefNet` | Typically `1024x1024`; direct resize; RGB ImageNet mean/std normalization; raw logits are mapped through sigmoid to 0..1. | Higher accuracy and heavier. Code is MIT; verify the specific checkpoint because some weights are trained on non-commercial data. Set `InputWidth`/`InputHeight` to `1024` if the model uses dynamic input dimensions. | | `BackgroundRemovalModel.Custom` | Uses `InputWidth`, `InputHeight`, and `NormalizeTo01` from `BackgroundRemovalSettings`. | For a model that does not match the built-in conventions. | Model licenses A model's license is set by its origin (training code, weights, and dataset), not by the ONNX format. `MODNet`, `PPMattingV2`, and `U2Net` are Apache-2.0. `BiRefNet` code is MIT, but you must verify the license of the exact checkpoint you ship. ## How the matting pipeline works `BackgroundRemovalBlock` is a frame processor, not a separate source or renderer. The upstream block delivers RGBA frames to an internal sample grabber, the block runs the configured ONNX model when the frame is selected for inference, and the output frame is pushed downstream with the same video timing. The ONNX model input size is resolved from the model metadata when the model has fixed dimensions. If the model uses dynamic dimensions, `InputWidth` and `InputHeight` from `BackgroundRemovalSettings` are used instead — these default to `512x512` (tuned for `MODNet`) and are **not** adjusted per-model automatically, so set them yourself for `U2Net` (`320x320`) or `BiRefNet` (`1024x1024`). The frame is resized directly to that tensor size and converted from RGBA pixels to an RGB `NCHW` floating-point tensor. The model family controls the normalization: - `MODNet` and `PPMattingV2` use RGB values normalized to `-1..1`. - `U2Net` and `BiRefNet` use ImageNet-style RGB mean/std normalization. - `Custom` uses the generic `NormalizeTo01`, `InputWidth`, and `InputHeight` settings. After inference, the block reads the first float output as a foreground matte. The last two output dimensions are treated as matte height and width. `MODNet`, `PPMattingV2`, and `Custom` outputs are expected to already be in `0..1`; `U2Net` is min/max-normalized per frame; `BiRefNet` raw logits are converted with sigmoid. If `MaskFeatherAmount` is greater than `0`, the matte is blurred at model resolution before compositing. The compositor samples that matte back onto the original frame with bilinear interpolation. For `Blur`, `SolidColor`, and `Image`, each pixel is blended as `foreground * alpha + background * (1 - alpha)`. `MaskThreshold` can harden uncertain edges by forcing very low alpha values to background and very high values to foreground. For `Transparent`, the block keeps the foreground RGB pixels and writes the matte into the output alpha channel, so the visible result depends on the downstream renderer or encoder preserving RGBA alpha. ### Choosing a matting model Use `MODNet` or `PPMattingV2` first for real-time portrait background replacement. They are designed for human matting and have lower input sizes than high-accuracy salient-object models. `U2Net` is a good fallback when the subject is not always a person, but its output is a segmentation-style matte that may need `MaskFeatherAmount` for soft edges. `BiRefNet` is the heavier quality option: it can produce better fine detail, but its typical `1024x1024` input size is much more expensive, especially on CPU. Use `Custom` only when your ONNX model follows a different preprocessing or output convention and you have verified those settings against the exported model. ## Replacement modes `BackgroundRemovalSettings.ReplacementMode` selects how low-alpha background pixels are replaced. | Mode | Settings used | Result | | --- | --- | --- | | `BackgroundReplacementMode.Blur` (default) | `BlurRadius` | Replaces the background with a blurred copy of the original frame. | | `BackgroundReplacementMode.SolidColor` | `ReplacementColor` | Fills the background with a solid color; defaults to green (a virtual green screen). | | `BackgroundReplacementMode.Image` | `BackgroundImagePath`, `ReplacementColor` fallback | Loads a static image and scales it to the frame size. If the image cannot be loaded, the block falls back to `ReplacementColor`. | | `BackgroundReplacementMode.Transparent` | Foreground alpha mask | Writes the mask to the frame alpha channel. Use an RGBA renderer, encoder, or downstream compositor that preserves alpha. | Additional matte controls: | Property | Default | Description | | --- | --- | --- | | `MaskThreshold` | `0` | Optional edge hardening. Effective range 0..0.5 (values above 0.5 are clamped). Values at or below the threshold become background, and values at or above `1 - threshold` become foreground. `0` keeps the model's raw soft matte unchanged. | | `MaskFeatherAmount` | `0` | Optional matte-space blur radius, in matte (model-resolution) pixels, that softens foreground/background edges — the opposite control to `MaskThreshold`. | | `FramesToSkip` | `0` | Inherited from `OnnxInferenceSettings`. The model runs every `FramesToSkip + 1` frames, while the last matte is composited on every frame. | | `Provider` / `DeviceId` | `Auto` / `0` | ONNX execution provider and hardware device index. | | `InputWidth` / `InputHeight` | `512` / `512` | Used for dynamic-input matting models. Fixed-size models report their own input size. | ## Pipeline example ``` using VisioForge.Core.MediaBlocks; using VisioForge.Core.MediaBlocks.AI; using VisioForge.Core.MediaBlocks.VideoRendering; using VisioForge.Core.Types.X.AI; var settings = new BackgroundRemovalSettings(modelPath) { Model = BackgroundRemovalModel.PPMattingV2, ReplacementMode = BackgroundReplacementMode.Blur, BlurRadius = 15f, MaskFeatherAmount = 2, Provider = OnnxExecutionProvider.Auto, FramesToSkip = 2, MaskThreshold = 0.05f, }; var backgroundRemoval = new BackgroundRemovalBlock(settings); var videoRenderer = new VideoRendererBlock(pipeline, videoView) { IsSync = false }; pipeline.Connect(source.Output, backgroundRemoval.Input); pipeline.Connect(backgroundRemoval.Output, videoRenderer.Input); await pipeline.StartAsync(); Console.WriteLine($"Active provider: {backgroundRemoval.ActiveProvider}"); ``` Performance The model is not run on every frame when `FramesToSkip` is greater than `0`, but the block still composites the replacement background on every frame from the cached matte. This lowers CPU/GPU cost without flickering back to the original background between inference frames. ## Use with VideoCaptureCoreX and MediaPlayerCoreX ``` var backgroundRemoval = new BackgroundRemovalBlock(settings); core.Video_Processing_AddBlock(backgroundRemoval); // before StartAsync (VideoCaptureCoreX) // player.Video_Processing_AddBlock(backgroundRemoval); // before OpenAsync/PlayAsync (MediaPlayerCoreX) await core.StartAsync(); ``` See [Using AI blocks with VideoCaptureCoreX and MediaPlayerCoreX](../x-engines/) for the full processing-block API, insertion order, and lifecycle rules shared by every video AI block. ## Use cases - **Video conferencing and webcam apps** — virtual green screen or background blur without a physical green screen. - **Livestreaming and broadcast overlays** — composite a presenter over a branded background or scene. - **Virtual studio / product photography video** — replace a plain backdrop with a custom scene. - **Privacy blurring** — blur the background in a recording so only the foreground subject is sharp. ## Troubleshooting | Symptom | Likely cause | Fix | | --- | --- | --- | | Edges around hair/fingers look hard or blocky | Matte edges not softened | Raise `MaskFeatherAmount`. | | Background bleeds through solid areas (semi-transparent artifacts) | Matte is too soft for a high-contrast scene | Raise `MaskThreshold` (effective range 0..0.5) to harden the foreground/background split. | | Wrong crop/scale in the output | `InputWidth`/`InputHeight` don't match the model | For a dynamic-input model, set them to that model's expected size (`320` for `U2Net`, `1024` for `BiRefNet`); a fixed-size model reports and uses its own size regardless. | | `Transparent` mode shows an opaque background | Downstream renderer/encoder doesn't preserve alpha | Use an RGBA-capable renderer/encoder/compositor; `Transparent` only writes the alpha channel, it doesn't force the rest of the pipeline to honor it. | | High CPU/GPU usage | Matting model running on every frame | Raise `FramesToSkip` — the last matte is still composited every frame, so motion doesn't flicker back to the original background between inference frames. | ## Frequently Asked Questions ### Which matting model should I start with? `MODNet` (the default) or `PPMattingV2` for real-time portrait/webcam scenarios — both are tuned for human matting at a relatively low input size. Use `BiRefNet` only if you need higher fine-detail accuracy and can afford its heavier `1024x1024` input cost. ### Can I use a virtual green screen without a physical one? Yes — set `ReplacementMode = BackgroundReplacementMode.SolidColor` (it defaults to green) instead of `Blur`, `Image`, or `Transparent`. ### Does this block require a GPU? No, but a GPU execution provider reduces per-frame latency, which matters most for `BiRefNet`'s larger input size or for high frame-rate live video. ### Can I output a transparent (alpha) video instead of compositing a background? Yes — set `ReplacementMode = BackgroundReplacementMode.Transparent`. The block writes the foreground alpha into the frame's alpha channel; your renderer, encoder, or downstream compositor must preserve RGBA to make use of it. ## Demo - **[Background Removal Demo](https://github.com/visioforge/.Net-SDK-s-samples/tree/master/Media%20Blocks%20SDK/WPF/CSharp/Background%20Removal%20Demo)** — WPF demo with webcam, file, and RTSP sources, downloadable matting models, blur, solid color, image, and transparent replacement modes. ---END OF PAGE--- ## Face Recognition SDK for .NET and C# — FaceRecognitionBlock **URL:** https://www.visioforge.com/help/docs/dotnet/general/ai/face-recognition/ **Description:** Face Recognition SDK for .NET and C# — FaceRecognitionBlock detects and identifies faces on-device (YuNet + SFace/ArcFace ONNX), cross-platform, no cloud. **Tags:** .NET, AI, ONNX, Face Recognition, Face Recognition SDK, Face Detection, Facial Recognition, YuNet, SFace, Biometrics, VideoCaptureCoreX, MediaPlayerCoreX **API:** FaceRecognitionBlock, FaceRecognitionSettings, FaceGallery, FaceEmbeddingModel, FaceRecognitionResult # Face Recognition SDK for .NET — FaceRecognitionBlock `FaceRecognitionBlock` is the face recognition SDK component of VisioForge's .NET AI packages — it recognizes **who** is in the frame, on-device, with no cloud API. It runs a two-stage pipeline: a YuNet detector finds faces and their five landmarks, each face is aligned to a canonical 112x112 crop and turned into an embedding (SFace or ArcFace), and the embedding is matched 1:N against an enrolled `FaceGallery` by cosine similarity. Recognition runs on a background thread, so live video never stalls; the streaming thread only draws the most recent results. ``` graph LR; Source-->FaceRecognitionBlock; FaceRecognitionBlock-->VideoRendererBlock; FaceRecognitionBlock-. OnFacesIdentified .->App[Your app]; ``` ## Enroll and recognize ``` using VisioForge.Core.MediaBlocks.AI; using VisioForge.Core.Types.X.AI; var settings = new FaceRecognitionSettings( "face_detection_yunet_2023mar.onnx", "face_recognition_sface_2021dec.onnx") { EmbeddingModel = FaceEmbeddingModel.SFace, // or ArcFace for a 512-D recognizer RecognitionThreshold = 0.36f, // cosine similarity for a match DrawResults = true, }; var face = new FaceRecognitionBlock(settings); // Enroll identities from a file path or an in-memory SKBitmap (several photos per person are allowed). face.Enroll("Alice", "alice.jpg"); face.Enroll("Bob", "bob.jpg"); face.Gallery.Save("faces.dat"); // reload later with face.Gallery.Load("faces.dat") face.OnFacesIdentified += (sender, e) => { foreach (var f in e.Faces) { var who = string.IsNullOrEmpty(f.Identity) ? "Unknown" : f.Identity; Console.WriteLine($"{who} ({f.Similarity:P0}) at {f.BoundingBox}"); } }; pipeline.Connect(source.Output, face.Input); pipeline.Connect(face.Output, videoRenderer.Input); await pipeline.StartAsync(); ``` The default models — [YuNet](https://github.com/opencv/opencv_zoo) (MIT) and [SFace](https://github.com/opencv/opencv_zoo) (Apache-2.0) — are designed to work together (SFace aligns with YuNet's five landmarks). The embedding length is read from the model, so an ArcFace-style recognizer (for example [AuraFace](https://huggingface.co/fal/AuraFace-v1), Apache-2.0, 512-D) drops in by switching `EmbeddingModel` to `FaceEmbeddingModel.ArcFace`. Keep one gallery per embedding model — embeddings from different models are not comparable. Model weights are not shipped in the NuGet package. Each `FaceRecognitionResult` carries the matched `Identity` (`null` when unknown), `Similarity` (cosine similarity of the best gallery match), `DetectionScore`, the axis-aligned `BoundingBox`, the box-corner `Polygon`, the five facial `Landmarks`, and the raw L2-normalized `Embedding` vector. ## Face recognition settings `FaceRecognitionSettings(detectorModelPath, embeddingModelPath)`: | Property | Default | Description | | --- | --- | --- | | `DetectorModelPath` | — | Face detection ONNX model path, usually YuNet. Required. | | `EmbeddingModelPath` | — | Face embedding ONNX model path, usually SFace or ArcFace-style. Required. | | `EmbeddingModel` | `SFace` | Selects the aligned-crop preprocessing for the embedding model family (`SFace` or `ArcFace`). | | `Gallery` | `null` | Enrolled identities used for 1:N matching. When `null`/empty, faces are detected and embedded but reported as unknown. `FaceRecognitionBlock.Gallery` exposes the active gallery. | | `Provider` / `DeviceId` | `Auto` / `0` | ONNX execution provider and hardware device index. | | `FramesToSkip` | `0` | Skip frames between recognition runs on live video. | | `DetectionInputSize` | `320` | Square detector input size. YuNet requires a multiple of 32; non-multiples are rounded up internally. | | `DetectionConfidenceThreshold` | `0.6` | Minimum face detector score. | | `NmsThreshold` | `0.3` | IoU threshold for suppressing overlapping face boxes. | | `MaxFaces` | `20` | Maximum faces detected per frame. | | `RecognitionThreshold` | `0.36` | Minimum cosine similarity for reporting a known identity (the SFace same-identity threshold). | | `DrawResults` / `DrawLandmarks` | `true` / `false` | Draw boxes, labels, and optionally the five facial landmarks. | | `BoxColor` / `BoxThickness` / `LabelFontSize` | LimeGreen / `2` / `0` | Overlay styling; `LabelFontSize = 0` auto-scales to frame height. | ## FaceGallery `FaceGallery` is a thread-safe, in-memory gallery of enrolled identities. Each identity can hold several L2-normalized embeddings (enroll multiple photos per person for robustness); a query matches by the maximum cosine similarity across all stored embeddings of all identities. - `Add(name, embedding)` — enrolls a normalized copy of the embedding; throws if its length doesn't match the embeddings already in the gallery (a different embedding model). - `Identify(embedding, threshold, out score)` — returns the best-matching identity name when its score meets `threshold`, otherwise `null`; `score` always receives the best score found. - `Remove(name)`, `Clear()`, `Count`, `GetNames()`. - `Save(path)` / `Load(path)` — persist to and restore from a versioned binary file. `FaceRecognitionBlock.Enroll(name, imagePath)` and `Enroll(name, SKBitmap)` compute the embedding for you and call `Gallery.Add` internally. Privacy Face recognition processes biometric data. Ensure your use complies with the applicable privacy and data-protection laws (GDPR, BIPA, CCPA, and similar) in your jurisdiction. ## Use with VideoCaptureCoreX and MediaPlayerCoreX ``` var face = new FaceRecognitionBlock(settings); face.Enroll("Alice", "alice.jpg"); face.OnFacesIdentified += Face_OnFacesIdentified; core.Video_Processing_AddBlock(face); // before StartAsync (VideoCaptureCoreX) // player.Video_Processing_AddBlock(face); // before OpenAsync/PlayAsync (MediaPlayerCoreX) await core.StartAsync(); ``` See [Using AI blocks with VideoCaptureCoreX and MediaPlayerCoreX](../x-engines/) for the full processing-block API, insertion order, and lifecycle rules shared by every video AI block. ## Use cases - **Access control and attendance** — recognize enrolled employees or residents at a door camera or kiosk, on-device, without sending faces to a third-party cloud service. - **Personalization** — greet a returning, enrolled user by name in a kiosk or smart-mirror app. - **VIP / watchlist alerts** — raise an application event when a specific enrolled identity is seen. - **Deduplicating footage** — group video segments by which enrolled identities appear in them. `FaceRecognitionBlock` is a *1:N identification* component (who is this, out of a known gallery), not a *1:1 verification* or liveness/anti-spoofing system — build additional checks on top if your scenario needs them (for example, payment authorization). ## Troubleshooting | Symptom | Likely cause | Fix | | --- | --- | --- | | Everyone is reported as "Unknown" | `RecognitionThreshold` too high, or the gallery is empty/not assigned | Confirm `Gallery` has enrolled identities; lower `RecognitionThreshold` slightly if enrollment photos are lower quality. | | Wrong identity reported for a known face | Embedding model mismatch between the gallery and the recognizer, or too few enrollment photos | Never mix embeddings from different `EmbeddingModel` values in one gallery; enroll 2-3 photos per person from different angles/lighting. | | Faces are missed entirely | `DetectionConfidenceThreshold` too high, or faces smaller than `DetectionInputSize` can resolve | Lower `DetectionConfidenceThreshold`; raise `DetectionInputSize` (must stay a multiple of 32) for small/distant faces. | | `FaceGallery.Load` throws `InvalidDataException` | The file wasn't written by `FaceGallery.Save`, or is from an incompatible SDK version | Only load files your own app wrote with `Save`; the format is versioned and rejects corrupt/foreign files by design. | | High CPU usage with several faces on screen | Recognition runs per detected face | Lower `MaxFaces`, raise `FramesToSkip`, or use a GPU execution provider. | ## Frequently Asked Questions ### Is this face recognition SDK cloud-based or on-device? Fully on-device. `FaceRecognitionBlock` runs YuNet detection and SFace/ArcFace embedding through local ONNX Runtime inference — no frame or embedding is sent to an external service. ### Can I use this face recognition SDK from C#? Yes — the entire SDK, including `FaceRecognitionBlock`, `FaceRecognitionSettings`, and `FaceGallery`, is a native C#/.NET API (`VisioForge.DotNet.Core.AI`), usable from any .NET application on Windows, macOS, Linux, Android, or iOS. ### How do I enroll a new person? Call `FaceRecognitionBlock.Enroll(name, imagePath)` or `Enroll(name, SKBitmap)` with one or more clear photos of the person; the block computes the embedding and adds it to `Gallery` for you. Persist the gallery with `FaceGallery.Save(path)` and restore it later with `FaceGallery.Load(path)`. ### Does the SDK include face detection without recognition? Yes, indirectly — `FaceRecognitionResult` reports `DetectionScore` and `BoundingBox` for every detected face, whether or not it matches a gallery entry. Leave `Gallery` empty to use the block as a pure face detector. ### Is SFace or ArcFace better? SFace (the default, 128-D, Apache-2.0) pairs directly with the YuNet detector's five landmarks and is lighter. ArcFace-style recognizers (for example AuraFace, 512-D) can be more accurate for some datasets. Benchmark both against your own enrollment photos and target hardware before choosing. ## Demos - **[Face Recognition Demo](https://github.com/visioforge/.Net-SDK-s-samples/tree/master/Media%20Blocks%20SDK/WPF/CSharp/Face%20Recognition%20Demo)** — WPF Media Blocks demo with enrollment and live 1:N face identity. - **[Face Recognition MB](https://github.com/visioforge/.Net-SDK-s-samples/tree/master/Media%20Blocks%20SDK/MAUI/Face%20Recognition%20MB)** — the same Media Blocks demo for MAUI (Android, iOS, Windows, macOS). - **[Face Recognition CLI](https://github.com/visioforge/.Net-SDK-s-samples/tree/master/Media%20Blocks%20SDK/Console/Face%20Recognition%20CLI)** — headless console demo. Dedicated `VideoCaptureCoreX`/`MediaPlayerCoreX` face-recognition demos (`Capture Face Recognition X`, `Capture Face Recognition X WPF`, `Player Face Recognition X`, `Player Face Recognition X WPF`) are in the SDK's demo set and will be linked here once published to the public samples repository. ---END OF PAGE--- ## AI SDK for .NET — On-Device Video AI and Speech-to-Text **URL:** https://www.visioforge.com/help/docs/dotnet/general/ai/ **Description:** On-device AI SDK for .NET — OCR, object detection, face recognition, ANPR, background removal, and Whisper speech-to-text. Cross-platform, no cloud. **Tags:** .NET, AI, AI SDK, Computer Vision, ONNX, Whisper, Media Blocks, VideoCaptureCoreX, MediaPlayerCoreX, Windows, macOS, Linux, Android, iOS **API:** OcrBlock, YOLOObjectDetectorBlock, ObjectAnalyticsBlock, FaceRecognitionBlock, LicensePlateRecognizerBlock, PIIRedactionBlock, OpenVocabularyDetectorBlock, VLMBlock, VideoEmbeddingBlock, BackgroundRemovalBlock, AutoReframeBlock, OnnxInferenceBlock, SpeechToTextBlock # AI in VisioForge .NET SDK VisioForge AI support is implemented as ordinary Media Blocks. The same block instances can be placed in a manual `MediaBlocksPipeline`, inserted into `VideoCaptureCoreX`, or inserted into `MediaPlayerCoreX`. The AI packages do not replace the media engines. They add pass-through processing blocks: media continues downstream, optional overlays are drawn into the frame, and the block raises its own event with recognition results. ## Why on-device AI Every block on this page runs locally, in-process, on ONNX Runtime (video) or Whisper.net/GGML (speech) — there is no cloud API call, no per-request billing, and no network dependency at inference time. That matters for three common scenarios: - **Privacy and compliance** — video and audio frames never leave the device, which simplifies GDPR/CCPA/BIPA reviews for camera and microphone applications (see the [privacy note](face-recognition/) on face recognition specifically). - **Offline and edge deployments** — kiosks, industrial cameras, vehicles, and field devices can run recognition without connectivity. - **Predictable cost and latency** — throughput depends on the hardware you run on, not on a third-party API's rate limits or per-call pricing. Each block accepts an `OnnxExecutionProvider` (`Auto`, `CPU`, `CUDA`, `DirectML`, `CoreML`) and a `DeviceId`, so the same code can run CPU-only in a CI pipeline and take advantage of an NVIDIA, DirectX 12, or Apple GPU on a deployed machine without a code change. `Auto` picks the best provider present in the loaded ONNX Runtime native build at run time. ## Packages | Package | Main purpose | | --- | --- | | `VisioForge.DotNet.Core.AI` | ONNX video AI: OCR, object detection, analytics, face recognition, license plates, background removal, and custom inference. | | `VisioForge.DotNet.Core.AI.Whisper` | Local speech-to-text with Whisper ASR and Silero VAD. | Both packages reference the core SDK types. Add the same native runtime packages that your host application already uses for Media Blocks, Video Capture X, or Media Player X. ## Blocks | Block | Media | Event | Typical use | Details | | --- | --- | --- | --- | --- | | `OcrBlock` | Video | `OnTextDetected` | Recognize text regions with PaddleOCR models. | [OCR](ocr/) | | `YOLOObjectDetectorBlock` | Video | `OnObjectsDetected` | Run standalone object detection on each frame. | [Object detection](object-detection/) | | `ObjectAnalyticsBlock` | Video | `OnAnalyticsUpdated` | Track objects over time, count line crossings, and monitor polygon zones. | [Object analytics](object-analytics/) | | `FaceRecognitionBlock` | Video | `OnFacesIdentified` | Detect faces and match them against an enrolled gallery. | [Face recognition](face-recognition/) | | `LicensePlateRecognizerBlock` | Video | `OnPlateRecognized` | Detect and read license plates. | [License plate recognition](license-plate-recognition/) | | `PIIRedactionBlock` | Video | `OnRegionsRedacted` | Blur, pixelate, or fill faces, license plates, and on-screen text. | [PII redaction](pii-redaction/) | | `OpenVocabularyDetectorBlock` | Video | `OnObjectsDetected` | Detect objects by free-text prompt (zero-shot). | [Open vocabulary detection](open-vocabulary-detection/) | | `VLMBlock` | Video | `OnResultGenerated` | Caption, describe, ground, or OCR frames with a vision-language model. | [VLM captioning](vlm-captioning/) | | `VideoEmbeddingBlock` | Video | `OnFrameEmbedding` | Embed frames with CLIP for semantic video search. | [Semantic video search](semantic-video-search/) | | `BackgroundRemovalBlock` | Video | none | Replace, blur, or make the background transparent. | [Background removal](background-removal/) | | `AutoReframeBlock` | Video | `OnReframeUpdated` | Reframe landscape footage into subject-following vertical 9:16 video. | [Auto reframe](auto-reframe/) | | `OnnxInferenceBlock` | Video | `OnInference` | Run a custom ONNX model and receive raw output tensors. | [ONNX inference](onnx-inference/) | | `SpeechToTextBlock` | Audio | `OnSpeechRecognized` | Transcribe live or file audio with Whisper. | [Speech-to-text](speech-to-text/) | ## Video understanding and search Three of the AI blocks turn raw footage into something you can search and act on — the difference is whether you want to *detect*, *describe*, or *find* content: - **Detect** specific things, even ones no model was trained on, with [open-vocabulary detection](open-vocabulary-detection/) — or [object detection](object-detection/) for known classes at high frame rate. - **Describe** what's on screen — captions, descriptions, and in-frame text — with [VLM captioning](vlm-captioning/). - **Search** recorded video by meaning, jumping straight to a moment you describe in plain text, with [semantic video search](semantic-video-search/). They compose: index a library for [semantic search](semantic-video-search/), then run a [detector](open-vocabulary-detection/) or a [VLM](vlm-captioning/) on the moments it surfaces to confirm or label them. ## Choosing the right AI block - **Need to read text in a frame** (signage, documents, screens)? Use [`OcrBlock`](ocr/). - **Need to read a specific vehicle license plate**, not general text? Use [`LicensePlateRecognizerBlock`](license-plate-recognition/) — it runs a dedicated plate detector plus a plate-specific OCR head, which is both more accurate and faster than pointing generic OCR at a whole scene. - **Need to anonymize video for privacy or compliance** (blur faces, plates, or on-screen text)? Use [`PIIRedactionBlock`](pii-redaction/) — it detects and obscures all three PII categories in-place, on-device, and never identifies or exports the content. - **Need boxes and labels for objects, one frame at a time**? Use [`YOLOObjectDetectorBlock`](object-detection/). - **Need to detect objects you can only describe in words** (not a fixed trained class list)? Use [`OpenVocabularyDetectorBlock`](open-vocabulary-detection/) — it detects anything you name in a text prompt, at a higher per-frame cost than YOLO. - **Need a natural-language description, caption, or in-frame reading** of the scene? Use [`VLMBlock`](vlm-captioning/) — a Florence-2 vision-language model that captions, detects, grounds phrases, and reads text. - **Need to search recorded video by meaning** ("find where someone rides a bicycle")? Use [`VideoEmbeddingBlock`](semantic-video-search/) — it indexes frames as CLIP embeddings you can query with plain text. - **Need to count people/vehicles crossing a line, or track dwell time in a zone**, not just per-frame boxes? Use [`ObjectAnalyticsBlock`](object-analytics/) — it adds ByteTrack tracking, tripwires, and polygon zones on top of the same detector families. - **Need to know *who* is in frame**, not just *that* a person is in frame? Use [`FaceRecognitionBlock`](face-recognition/). - **Need a virtual background, blur, or transparent output** for a call or stream? Use [`BackgroundRemovalBlock`](background-removal/). - **Have a custom ONNX model** that isn't one of the built-in detector or matting families? Use [`OnnxInferenceBlock`](onnx-inference/) and own the post-processing yourself. - **Need a transcript, live captions, or SRT/VTT subtitles** from audio? Use [`SpeechToTextBlock`](speech-to-text/). ## Supported integration paths Use a manual Media Blocks pipeline when you need full topology control: ``` flowchart LR Source["Source block"] --> AI["AI processing block"] AI --> Sink["Renderer or output block"] AI -. "event" .-> App["Application code"] ``` Use `VideoCaptureCoreX` when the application already uses the high-level capture engine and only needs to insert one or more AI blocks into the capture graph. Register video or audio blocks before `StartAsync`. Use `MediaPlayerCoreX` when the application already uses the high-level playback engine. Register video or audio blocks before `OpenAsync` / `PlayAsync`. ## Lifecycle rules AI blocks must be registered before the engine builds the pipeline: - `VideoCaptureCoreX`: add blocks before `StartAsync`. - `MediaPlayerCoreX`: add blocks before `OpenAsync` / `PlayAsync`. - Manual Media Blocks: connect the block before `StartAsync`. After the pipeline starts, the pipeline owns wired block instances and disposes them when the session stops. Create a fresh block instance for the next capture or playback session. Block events are raised from pipeline or block worker threads. Keep handlers short and marshal UI updates to the UI dispatcher or main thread. ## More detail Video AI blocks (`VisioForge.DotNet.Core.AI`): - [OCR — text recognition](ocr/) - [Object detection](object-detection/) - [Object analytics — tracking, tripwires, and polygon zones](object-analytics/) - [Face recognition](face-recognition/) - [License plate recognition (ANPR)](license-plate-recognition/) - [PII redaction — blur faces, plates, and on-screen text](pii-redaction/) - [Open vocabulary detection](open-vocabulary-detection/) - [VLM captioning](vlm-captioning/) - [Semantic video search](semantic-video-search/) - [Background removal (matting)](background-removal/) - [Auto reframe — subject-following vertical video](auto-reframe/) - [Generic ONNX inference](onnx-inference/) Speech-to-text (`VisioForge.DotNet.Core.AI.Whisper`): - [Speech-to-text and live subtitles](speech-to-text/) Engine integration: - [Using AI blocks with VideoCaptureCoreX and MediaPlayerCoreX](x-engines/) ## Frequently Asked Questions ### Do the AI blocks require an internet connection to run? No. Inference is entirely local, using ONNX Runtime (video blocks) or Whisper.net/GGML (`SpeechToTextBlock`). No frame or audio sample is sent to a cloud service at inference time. ### Which platforms do the AI blocks support? The same cross-platform blocks used in Media Blocks pipelines, `VideoCaptureCoreX`, and `MediaPlayerCoreX` — Windows, macOS, Linux, Android, and iOS. ### Do I need a GPU? No. Every block defaults to `OnnxExecutionProvider.Auto`, which runs on the CPU when no GPU provider is available. Setting `Provider` to `CUDA`, `DirectML`, or `CoreML` accelerates inference when the corresponding GPU and ONNX Runtime build are present. ### Where do I get the ONNX and Whisper model files? Model weights are not shipped inside the `VisioForge.DotNet.Core.AI` / `VisioForge.DotNet.Core.AI.Whisper` NuGet packages. Your application supplies the `.onnx` / `.bin` files — point the block's settings at a local path. The SDK's own demos download the models they use from GitHub Releases on first run and cache them locally. ### What license applies to the models the demos use? It varies by model family and is independent of the SDK's own license — see the "Models and licensing" section on each block's page ([OCR](ocr/#models-and-licensing), [object detection](object-detection/#supported-detector-families), [face recognition](face-recognition/), [background removal](background-removal/#models-and-licensing)). In short: PP-OCR, YOLOX, RT-DETR, YuNet, SFace, and the FastALPR ANPR models are Apache-2.0/MIT; stock Ultralytics YOLOv8 weights are AGPL-3.0 and need a commercial Ultralytics license in a closed-source product; Whisper GGML weights are MIT. ### Can I run more than one AI block in the same pipeline? Yes. Chain multiple video blocks (for example `OcrBlock` then `BackgroundRemovalBlock`) by connecting `Output` to `Input` in sequence, or register several video/audio blocks on `VideoCaptureCoreX`/`MediaPlayerCoreX` with `Video_Processing_AddBlock`/`Audio_Processing_AddBlock`. Each block adds its own inference cost to the pipeline, so measure end-to-end performance on your target hardware when combining several. ---END OF PAGE--- ## ANPR/LPR SDK for .NET — LicensePlateRecognizerBlock **URL:** https://www.visioforge.com/help/docs/dotnet/general/ai/license-plate-recognition/ **Description:** ANPR/LPR SDK for .NET — read vehicle license plates with LicensePlateRecognizerBlock (FastALPR detector + plate-OCR ONNX models), on-device, cross-platform. **Tags:** .NET, AI, ONNX, ANPR, ANPR SDK, LPR, License Plate Recognition, Vehicle Recognition, VideoCaptureCoreX, MediaPlayerCoreX **API:** LicensePlateRecognizerBlock, LicensePlateRecognizerSettings, LicensePlateResult # License Plate Recognition (ANPR) — LicensePlateRecognizerBlock `LicensePlateRecognizerBlock` reads vehicle license plates with a specialized two-stage pipeline: a dedicated license-plate detector (YOLO) locates plates in the frame, then a plate-specific OCR model reads the characters of each cropped plate. Both models come from the FastALPR family (MIT): a YOLOv9-T plate detector and a `fast-plate-ocr` recognition head. A global head covers the USA and 90+ countries; a European head is tuned for EU plates. The recognition model's geometry and alphabet are read from the model itself, so selecting a region is simply a matter of pointing `RecognitionModelPath` at that head. ``` graph LR; Source-->LicensePlateRecognizerBlock; LicensePlateRecognizerBlock-->VideoRendererBlock; LicensePlateRecognizerBlock-. OnPlateRecognized .->App[Your app]; ``` ## Usage ``` using VisioForge.Core.MediaBlocks.AI; using VisioForge.Core.Types.X.AI; var settings = new LicensePlateRecognizerSettings(detectorModelPath, recognitionModelPath) { Provider = OnnxExecutionProvider.Auto, DetectionConfidenceThreshold = 0.35f, OcrConfidenceThreshold = 0.3f, DrawResults = true, }; var anpr = new LicensePlateRecognizerBlock(settings); anpr.OnPlateRecognized += (sender, e) => { foreach (var plate in e.Plates) { Console.WriteLine($"Plate: {plate.Text} ({plate.Confidence:P0}) at {plate.BoundingBox}"); } }; pipeline.Connect(source.Output, anpr.Input); pipeline.Connect(anpr.Output, videoRenderer.Input); await pipeline.StartAsync(); ``` Each `LicensePlateResult` carries the recognized `Text` (normalized: uppercased, non-alphanumeric characters stripped), the mean `Confidence` (0..1), the axis-aligned `BoundingBox`, and the detection `Polygon` (four `OcrPoint` vertices), all in source-frame pixels. ## Key settings `LicensePlateRecognizerSettings(detectorModelPath, recognitionModelPath)`: | Property | Default | Description | | --- | --- | --- | | `DetectorModelPath` | — | License-plate detection ONNX model (FastALPR YOLOv9-T end-to-end). Required. | | `RecognitionModelPath` | — | Plate-OCR ONNX model (FastALPR `fast-plate-ocr` head, global or EU). Required. | | `Provider` / `DeviceId` | `Auto` / `0` | ONNX execution provider and hardware device index. | | `FramesToSkip` | `0` | Skip frames between recognition runs on live video. | | `DetectionInputSize` | `640` | Square input size for the detection model (dynamic-shape models). | | `DetectionConfidenceThreshold` | `0.35` | Minimum detector score a plate box must reach. | | `OcrConfidenceThreshold` | `0.3` | Minimum mean OCR confidence a recognized plate must reach to be reported. | | `MaxDetections` | `10` | Maximum plates detected per frame. | | `DrawResults` | `true` | Draw plate boxes and text into the video frame. | | `BoxColor` / `BoxThickness` | Yellow / `3` | Overlay styling. | | `LabelFontSize` | `0` | `0` auto-scales to frame height. | ## Models and licensing Both the detector and the recognition head are MIT-licensed FastALPR models; the SDK does not ship model weights in the NuGet package. For higher accuracy on busy scenes with many small or distant plates, run a dedicated general-purpose vehicle detector (for example [`YOLOObjectDetectorBlock`](../object-detection/)) upstream to crop vehicle regions before ANPR. ## Use with VideoCaptureCoreX and MediaPlayerCoreX ``` var anpr = new LicensePlateRecognizerBlock(settings); anpr.OnPlateRecognized += Anpr_OnPlateRecognized; core.Video_Processing_AddBlock(anpr); // before StartAsync (VideoCaptureCoreX) // player.Video_Processing_AddBlock(anpr); // before OpenAsync/PlayAsync (MediaPlayerCoreX) await core.StartAsync(); ``` See [Using AI blocks with VideoCaptureCoreX and MediaPlayerCoreX](../x-engines/) for the full processing-block API, insertion order, and lifecycle rules shared by every video AI block. ## Use cases - **Parking access and payment** — recognize a plate at a gate camera to open a barrier or start a parking session. - **Toll and access-control logging** — record which plates passed a fixed camera and when. - **Fleet and yard management** — track vehicles entering/leaving a private lot or depot. - **Traffic enforcement support tooling** — flag plates for manual review (final enforcement decisions should always have a human-review step). ## Troubleshooting | Symptom | Likely cause | Fix | | --- | --- | --- | | Plates aren't detected at all | `DetectionConfidenceThreshold` too high, or plate too small relative to `DetectionInputSize` | Lower `DetectionConfidenceThreshold`; raise `DetectionInputSize` for distant/small plates, or crop closer to the vehicle upstream. | | Plate detected but text is wrong/empty | `OcrConfidenceThreshold` too high, or wrong regional recognition head | Lower `OcrConfidenceThreshold`; confirm `RecognitionModelPath` matches your region (global vs. EU head). | | Only some plates in a busy scene are reported | `MaxDetections` reached | Raise `MaxDetections` if you expect more than 10 plates per frame. | | Plate text includes stray characters | Read directly from `LicensePlateResult.Text`, expecting raw OCR | `Text` is already normalized (uppercased, non-alphanumeric characters stripped) — if you still see noise, check that the correct regional recognition head is loaded. | ## Frequently Asked Questions ### Does this ANPR SDK work outside the USA and Europe? The FastALPR global recognition head covers the USA and 90+ countries; a separate European head is tuned for EU plates. Point `RecognitionModelPath` at whichever head matches your target region. ### Do I need to train my own plate-detection model? No — `LicensePlateRecognizerBlock` uses the FastALPR YOLOv9-T detector and `fast-plate-ocr` recognition head out of the box; you only need to supply the two `.onnx` files. ### Can I use LicensePlateRecognizerBlock on a wide traffic scene with many vehicles? Yes, up to `MaxDetections` plates per frame (default 10, configurable). For very busy scenes with small/distant plates, consider running a vehicle detector ([`YOLOObjectDetectorBlock`](../object-detection/)) upstream to crop vehicle regions first. ### Is license plate data considered personal/biometric data? License plates are commonly treated as personal data under privacy regulations (though not biometric in the same sense as a face embedding). Review the applicable regulations (GDPR, state ANPR laws, and similar) for your jurisdiction and use case before deploying. ## Demos - **[License Plate Recognition Demo](https://github.com/visioforge/.Net-SDK-s-samples/tree/master/Media%20Blocks%20SDK/WPF/CSharp/License%20Plate%20Recognition%20Demo)** — WPF Media Blocks pipeline demo. ---END OF PAGE--- ## Object Tracking SDK for .NET — ObjectAnalyticsBlock **URL:** https://www.visioforge.com/help/docs/dotnet/general/ai/object-analytics/ **Description:** Object tracking SDK for .NET — ByteTrack multi-object tracking, line-crossing tripwires, and polygon-zone occupancy with ObjectAnalyticsBlock. **Tags:** .NET, AI, ONNX, Object Tracking, Object Tracking SDK, ByteTrack, Tripwire, Polygon Zone, People Counting, VideoCaptureCoreX, MediaPlayerCoreX **API:** ObjectAnalyticsBlock, ObjectAnalyticsSettings, ByteTrackerSettings, DetectionFilterSettings, ObjectAnalyticsOverlaySettings, LineZoneSettings, PolygonZoneSettings, LineCrossingResult, PolygonZoneSnapshot # Object Analytics — Multi-Object Tracking, Tripwires, and Polygon Zones `ObjectAnalyticsBlock` performs stable multi-object tracking (ByteTrack), directed tripwire line crossing, and polygon-zone occupancy on top of any supported ONNX object detector (YOLOv8, YOLOX, RT-DETR). It draws overlays (boxes, labels, track IDs, traces, lines, zones, counters) and raises an `OnAnalyticsUpdated` event with tracked objects, crossing events, and zone snapshots. ``` graph LR; Source-->ObjectAnalyticsBlock; ObjectAnalyticsBlock-->VideoRendererBlock; ObjectAnalyticsBlock-. OnAnalyticsUpdated .->App[Your app]; ``` ## Usage ``` using SkiaSharp; using VisioForge.Core.MediaBlocks; using VisioForge.Core.MediaBlocks.AI; using VisioForge.Core.Types.X.AI; // Detector settings — reuse any supported YOLO model. var detector = new YoloDetectorSettings("yolox_nano.onnx") { Model = ObjectDetectorModel.YOLOX, ConfidenceThreshold = 0.6f, DrawDetections = false, // The analytics renderer draws instead. }; var settings = new ObjectAnalyticsSettings(detector); // Add a tripwire line (directed Start -> End). settings.Lines.Add(new LineZoneSettings { Id = "door", Start = new SKPoint(200, 200), End = new SKPoint(400, 200), Anchor = DetectionAnchor.BottomCenter, // Feet contact. }); // Add a polygon zone. settings.Zones.Add(new PolygonZoneSettings { Id = "area", Points = new[] { new SKPoint(100, 100), new SKPoint(300, 100), new SKPoint(300, 300), new SKPoint(100, 300), }, }); var analytics = new ObjectAnalyticsBlock(settings); analytics.OnAnalyticsUpdated += (s, e) => { foreach (var obj in e.Objects) Console.WriteLine($"ID #{obj.TrackerId}: {obj.Label} {obj.Confidence:P0}"); foreach (var c in e.LineCrossings) Console.WriteLine($"{c.LineId}: {c.Label}#{c.TrackerId} {c.Direction}"); }; pipeline.Connect(source.Output, analytics.Input); pipeline.Connect(analytics.Output, videoRenderer.Input); await pipeline.StartAsync(); ``` The block runs inference synchronously on the pipeline streaming thread. Use `FramesToSkip` on the detector settings to reduce inference frequency; on skipped frames only static geometry and counters are redrawn — no stale object boxes or traces. ## Polygon zones — occupancy from tracked boxes Polygon zones are part of `ObjectAnalyticsBlock`, not standalone `YOLOObjectDetectorBlock` output — the detector produces ordinary `OnnxDetection` objects with an axis-aligned box, not a polygon per object. The polygon describes an application-defined area, such as a doorway, queue area, parking bay, or restricted region. ``` settings.Zones.Add(new PolygonZoneSettings { Id = "checkout", Points = new[] { new SKPoint(0.15f, 0.25f), new SKPoint(0.85f, 0.25f), new SKPoint(0.80f, 0.80f), new SKPoint(0.20f, 0.80f), }, UseNormalizedCoordinates = true, Anchor = DetectionAnchor.BottomCenter, Color = SKColors.Cyan, }); ``` `Points` must contain at least three finite, distinct vertices and must form a non-zero-area, non-self-intersecting polygon. By default points are source-frame pixel coordinates. Set `UseNormalizedCoordinates = true` for `0..1` coordinates, resolved to frame pixels on every processed frame, so the same zone works across different source resolutions. For each tracked object, the block resolves the selected `DetectionAnchor` (`Center` or the default `BottomCenter`, which better represents a person's feet or a vehicle's contact point) from the object's bounding box and tests it against the polygon. A point on the polygon edge counts as inside. Zone state is tracker-based: when a track's anchor moves from outside to inside, its tracker ID is reported in `PolygonZoneSnapshot.EnteredTrackerIds`; when it moves from inside to outside, it appears in `ExitedTrackerIds`. `TrackerIds` and `CurrentCount` describe the tracks currently inside the zone. If a track disappears while still inside, it is reported in `ExpiredTrackerIds` (see `ZoneExitReason.TrackExpired`) — this avoids silently leaving the zone occupied forever when the detector loses an object. The overlay renderer draws configured polygons and counters when `ObjectAnalyticsOverlaySettings` `DrawZones` and `DrawZoneCounts` are enabled (both default `true`). ## Line crossings Line zones are directed tripwires. The direction is defined by `LineZoneSettings.Start -> End`. When a tracked object's anchor crosses the finite segment from the negative side to the positive side, the result is `LineCrossingDirection.In`; the opposite movement is `Out`. Reversing `Start` and `End` reverses the reported direction. `LineZoneSettings.DeadbandPixels` suppresses jitter near the line by keeping the last stable side until the anchor moves far enough away from the tripwire. `ObjectAnalyticsEventArgs` contains: | Property | Description | | --- | --- | | `Objects` | Tracked `OnnxDetection[]` observed in the current processed frame; each `TrackerId` is assigned by ByteTrack. | | `LineCrossings` | `LineCrossingResult[]` with `LineId`, `TrackerId`, `ClassId`, `Label`, and `Direction`. | | `Zones` | `PolygonZoneSnapshot[]` with `ZoneId`, `CurrentCount`, `TrackerIds`, `EnteredTrackerIds`, `ExitedTrackerIds`, and `ExpiredTrackerIds`. | ## Analytics settings `ObjectAnalyticsSettings(YoloDetectorSettings detector)` combines detector, tracker, filter, overlay, and zone configuration; `Tracker`, `Filter`, and `Overlay` each default to a new settings instance. Detector confidence is overridden At runtime the analytics block lowers the effective detector confidence to `ByteTrackerSettings.LowConfidenceThreshold` (default `0.1`) so ByteTrack can use low-confidence detections in its second association pass — a high-confidence-only detector would miss recovering temporarily occluded tracks. `ByteTrackerSettings` (ByteTrack multi-object tracker): | Property | Default | Description | | --- | --- | --- | | `LowConfidenceThreshold` | `0.1` | Minimum confidence for a detection to be considered at all. | | `HighConfidenceThreshold` | `0.25` | Confidence above which a detection joins the first (high-confidence) association stage. | | `NewTrackThreshold` | `0.35` | Minimum confidence a high-confidence detection must reach to start a new track. | | `FirstAssociationThreshold` | `0.8` | Maximum accepted cost for the first association stage. | | `SecondAssociationThreshold` | `0.5` | Maximum accepted cost for the second (low-confidence) association stage. | | `UnconfirmedAssociationThreshold` | `0.7` | Maximum accepted cost for matching unconfirmed tracks against remaining high-confidence detections. | | `LostTrackBuffer` | `30` | Number of tracker `Update` calls (not seconds) a track may stay lost before it expires. | | `FuseDetectionScore` | `true` | Fuse detection confidence into the association cost (`1 - IoU * confidence`). | | `ClassAwareMatching` | `true` | When enabled, a track and a detection with different class IDs get an unmatchable cost. | `DetectionFilterSettings` (applied before tracking; confidence filtering belongs to the tracker): | Property | Default | Description | | --- | --- | --- | | `IncludedClassIds` | `null` | When non-empty, only these class IDs are retained. | | `ExcludedClassIds` | `null` | Class IDs to reject. Exclusion wins when an ID appears in both lists. | | `MinimumBoxArea` | `0` | Minimum bounding-box pixel area (`width * height`); smaller boxes are rejected. | `ObjectAnalyticsOverlaySettings` (controls only the rendered overlay — events are still raised when drawing is disabled): | Property | Default | Description | | --- | --- | --- | | `DrawBoxes` / `DrawLabels` / `DrawTrackIds` | `true` / `true` / `true` | Draw boxes, labels + confidence, and tracker IDs. | | `DrawTraces` | `true` | Draw movement traces. | | `DrawLines` / `DrawZones` / `DrawZoneCounts` | `true` / `true` / `true` | Draw tripwire lines, polygon zones, and occupancy counts. | | `BoxThickness` / `LineThickness` / `TraceThickness` | `2` / `3` / `2` | Overlay stroke thicknesses, in pixels. | | `LabelFontSize` | `0` | `0` auto-scales to `max(20, frame.Height / 16)`. | | `TraceLength` | `30` | Maximum points kept in a movement trace. | `LineZoneSettings` (`Id`, `Start`, `End`, `Anchor`, `DeadbandPixels`, `UseNormalizedCoordinates`, `Color`) and `PolygonZoneSettings` (`Id`, `Points`, `Anchor`, `UseNormalizedCoordinates`, `Color`) configure individual zones as shown above. ## Direct C# analytics API The pure C# analytics types (`ByteTracker`, `LineZone`, `PolygonZone`, `DetectionFilter`) are also available directly, without a Media Blocks pipeline: ``` using SkiaSharp; using VisioForge.Core.AI; using VisioForge.Core.AI.Analytics; using VisioForge.Core.AI.Analytics.Tracking; using VisioForge.Core.AI.Analytics.Zones; using VisioForge.Core.Types.X.AI; var tracker = new ByteTracker(new ByteTrackerSettings()); var filtered = DetectionFilter.Apply(detections, new DetectionFilterSettings { IncludedClassIds = new[] { (int)CocoClass.Person }, MinimumBoxArea = 1200, }); var update = tracker.Update(filtered); var zone = new PolygonZone(new PolygonZoneSettings { Id = "area", Points = new[] { new SKPoint(100, 100), new SKPoint(500, 100), new SKPoint(500, 400), new SKPoint(100, 400) }, }); var snapshot = zone.Update(update); Console.WriteLine($"Inside: {snapshot.CurrentCount}"); ``` ## Use with VideoCaptureCoreX and MediaPlayerCoreX ``` var analytics = new ObjectAnalyticsBlock(settings); analytics.OnAnalyticsUpdated += Analytics_OnAnalyticsUpdated; core.Video_Processing_AddBlock(analytics); // before StartAsync (VideoCaptureCoreX) // player.Video_Processing_AddBlock(analytics); // before OpenAsync/PlayAsync (MediaPlayerCoreX) await core.StartAsync(); ``` See [Using AI blocks with VideoCaptureCoreX and MediaPlayerCoreX](../x-engines/) for the full processing-block API, insertion order, and lifecycle rules shared by every video AI block. ## Use cases - **People counting and footfall analytics** — count entries/exits through a doorway with a [line zone](#line-crossings), or occupancy in a room/aisle with a [polygon zone](#polygon-zones-occupancy-from-tracked-boxes). - **Queue and dwell-time monitoring** — track how long a `TrackerId` stays inside a zone using the `CurrentCount`/`TrackerIds` snapshot each frame. - **Vehicle counting and traffic direction** — a directed tripwire reports `In`/`Out` per lane or driveway. - **Restricted-area / perimeter alerts** — raise an alert in your app when `EnteredTrackerIds` is non-empty for a zone that should stay empty. - **Retail heat-mapping** — accumulate `Objects` positions over time from `OnAnalyticsUpdated` to build a movement heat-map outside the block itself. ## Troubleshooting | Symptom | Likely cause | Fix | | --- | --- | --- | | Tracker IDs keep changing for the same object | `LostTrackBuffer` too low for the occlusion length, or `ClassAwareMatching` rejecting a borderline detection | Raise `ByteTrackerSettings.LostTrackBuffer`; confirm the detector reports a consistent `ClassId` for the object. | | Objects flicker in and out of a zone at the boundary | No deadband/anchor mismatch | For lines, raise `LineZoneSettings.DeadbandPixels`. For zones, confirm `Anchor` matches your scenario (`BottomCenter` for feet/ground contact, `Center` otherwise). | | A zone never reports an exit for an object that clearly left | The track was lost before it could report `Out`/exit — check `ExpiredTrackerIds` | This is expected: `PolygonZoneSnapshot.ExpiredTrackerIds` reports tracks that disappeared while still inside, distinct from `ExitedTrackerIds` (movement-based exits). | | Line crossing direction is reversed from what you expect | `Start`/`End` order defines direction | Swap `Start` and `End` on the `LineZoneSettings`. | | Overlay draws boxes/labels you don't want | Default `ObjectAnalyticsOverlaySettings` draws everything | Set the specific `Draw*` flags (`DrawBoxes`, `DrawTraces`, `DrawZoneCounts`, ...) to `false`; events are still raised regardless of overlay settings. | | Coordinates don't line up across different camera resolutions | Zone/line points defined in fixed pixels | Set `UseNormalizedCoordinates = true` on the `LineZoneSettings`/`PolygonZoneSettings` and use `0..1` fractions instead. | ## Frequently Asked Questions ### What's the difference between a line zone and a polygon zone? A line zone (`LineZoneSettings`) is a directed tripwire that reports a crossing event (`LineCrossingResult`) the instant a tracked object's anchor crosses it. A polygon zone (`PolygonZoneSettings`) is an area whose current occupancy (`PolygonZoneSnapshot`) is reported every update — use lines for counting crossings, zones for "who/how many are inside right now". ### Does ObjectAnalyticsBlock work with any object detector? It works with any detector supported by `YoloDetectorSettings` — `YOLOv8`, `YOLOX`, and `RTDETR` — by wrapping that detector's settings in `ObjectAnalyticsSettings(detector)`. ### Can I use the tracker without a Media Blocks pipeline? Yes — `ByteTracker`, `LineZone`, `PolygonZone`, and `DetectionFilter` are public C# types you can call directly against your own detections; see [Direct C# analytics API](#direct-c-analytics-api). ### How many lines and zones can one block track at once? There's no fixed limit in the API — `ObjectAnalyticsSettings.Lines` and `.Zones` are plain lists you can add as many entries to as your scenario needs; each is evaluated independently against the same tracked objects every frame. ## Demos - **[YOLO Object Detection Demo](https://github.com/visioforge/.Net-SDK-s-samples/tree/master/Media%20Blocks%20SDK/WPF/CSharp/YOLO%20Object%20Detection%20Demo)** — includes both standalone object detection and object analytics modes. - **[Polygon Zone Demo](https://github.com/visioforge/.Net-SDK-s-samples/tree/master/Media%20Blocks%20SDK/WPF/CSharp/Polygon%20Zone%20Demo)** — polygon occupancy with live current, entered, exited, and expired track events. - **[Tripwire Analytics Demo](https://github.com/visioforge/.Net-SDK-s-samples/tree/master/Media%20Blocks%20SDK/WPF/CSharp/Tripwire%20Analytics%20Demo)** — directed line crossing and track IDs. ---END OF PAGE--- ## Object Detection SDK for .NET — YOLOObjectDetectorBlock **URL:** https://www.visioforge.com/help/docs/dotnet/general/ai/object-detection/ **Description:** Object detection SDK for .NET — detect objects in video with YOLOObjectDetectorBlock. YOLOv8, YOLOX, and RT-DETR ONNX models, cross-platform, CPU or GPU. **Tags:** .NET, AI, ONNX, YOLO, Object Detection, Object Detection SDK, Computer Vision, VideoCaptureCoreX, MediaPlayerCoreX **API:** YOLOObjectDetectorBlock, YoloDetectorSettings, ObjectDetectorModel, OnnxDetection # Object Detection — YOLOObjectDetectorBlock `YOLOObjectDetectorBlock` detects objects directly in the video stream. It taps RGBA frames with an internal sample grabber, runs the configured ONNX detector, optionally draws boxes and labels into the frame, and raises `OnObjectsDetected` for processed frames that contain detections. Use it when you need boxes and labels without tracking, tripwires, or zone analytics — see [Object analytics](../object-analytics/) for tracked, zone-aware detection. ``` graph LR; Source-->YOLOObjectDetectorBlock; YOLOObjectDetectorBlock-->VideoRendererBlock; YOLOObjectDetectorBlock-. OnObjectsDetected .->App[Your app]; ``` ## Supported detector families Set `YoloDetectorSettings.Model` to match the ONNX model layout. | Model | Decoder and preprocessing | Licensing note | | --- | --- | --- | | `ObjectDetectorModel.YOLOv8` (default) | Ultralytics YOLOv8 / YOLO11 layout `[1, 4 + numClasses, numAnchors]`; centered letterbox, RGB, normalized to 0..1, class-wise NMS. | Ultralytics models are AGPL-3.0; a closed-source product requires a commercial Ultralytics license. | | `ObjectDetectorModel.YOLOX` | YOLOX layout `[1, numAnchors, 5 + numClasses]`; top-left letterbox, BGR, no 0..1 normalization, class-wise NMS. | YOLOX model family is Apache-2.0. | | `ObjectDetectorModel.RTDETR` | RT-DETR / D-FINE transformer layout with `logits` and `pred_boxes`; direct resize, RGB, normalized to 0..1, NMS-free. | RT-DETR / D-FINE model families are Apache-2.0. | The SDK does not ship detector weights in the NuGet package. The `IoUThreshold` setting applies only to the NMS-based families (YOLOv8, YOLOX); RT-DETR is NMS-free and ignores it. `NormalizeTo01` is honored only by YOLOv8 — YOLOX and RT-DETR fix their normalization to their training convention. Model licenses A model's license is set by its origin (training code + published weights), not by the ONNX format. Avoid AGPL/GPL-licensed models (for example stock Ultralytics YOLO weights) in a closed-source product without a commercial license. ## Standalone or ObjectAnalyticsBlock? Use `YOLOObjectDetectorBlock` when each frame can be handled independently: draw boxes, collect labels, trigger simple alerts, or feed detections into your own logic. Use [`ObjectAnalyticsBlock`](../object-analytics/) when you need stable tracker IDs, line-crossing events, polygon-zone occupancy, object traces, and counters. `ObjectAnalyticsBlock` internally reuses `YoloDetectorSettings` for its detector, but its renderer and event model are built around tracked objects rather than raw per-frame detections. ## Usage ``` using VisioForge.Core.MediaBlocks; using VisioForge.Core.MediaBlocks.AI; using VisioForge.Core.MediaBlocks.VideoRendering; using VisioForge.Core.Types.VideoProcessing; using VisioForge.Core.Types.X.AI; var detectorSettings = new YoloDetectorSettings(modelPath) { Model = ObjectDetectorModel.YOLOX, ConfidenceThreshold = 0.6f, IoUThreshold = 0.45f, DrawDetections = true, DrawLabels = true, FramesToSkip = 0, Provider = OnnxExecutionProvider.Auto, }; var detector = new YOLOObjectDetectorBlock(detectorSettings); detector.OnObjectsDetected += (sender, e) => { foreach (OnnxDetection obj in e.Objects) { Console.WriteLine($"{obj.Label} #{obj.ClassId} {obj.Confidence:P0} at {obj.Box}"); } }; var videoRenderer = new VideoRendererBlock(pipeline, videoView) { IsSync = false }; pipeline.Connect(source.Output, detector.Input); pipeline.Connect(detector.Output, videoRenderer.Input); await pipeline.StartAsync(); Console.WriteLine($"Active provider: {detector.ActiveProvider}"); ``` Each `OnnxDetection` contains the bounding `Box` in source-frame pixel coordinates, `ClassId`, `Label`, `Confidence`, and `TrackerId`. In standalone detection `TrackerId` is always `-1` because no tracker has assigned an identity. ## Key settings `YoloDetectorSettings` extends `OnnxInferenceSettings`. | Property | Default | Description | | --- | --- | --- | | `ModelPath` | — | Absolute path to the detector `.onnx` file. Required. | | `Model` | `ObjectDetectorModel.YOLOv8` | Selects the decoder and preprocessing convention. | | `ConfidenceThreshold` | `0.60` | Minimum confidence for a reported detection. | | `IoUThreshold` | `0.45` | Non-maximum suppression threshold for YOLOv8 and YOLOX. RT-DETR is NMS-free. | | `Labels` | `null` | Optional class names. When `null`, the detector uses the default COCO-80 labels. | | `DrawDetections` | `true` | Draw detection boxes into the video frame. | | `BoxColor` / `BoxThickness` | Lime / `2` | Box overlay styling. | | `DrawLabels` / `LabelFontSize` | `true` / `0` | Draw labels and confidence values. `0` auto-scales label text to frame height. | | `InputWidth` / `InputHeight` | `640` / `640` | Used for dynamic-input models. Fixed-size models report their own input size. | | `NormalizeTo01` | `true` | Honored by the YOLOv8 family only. | | `Provider` / `DeviceId` | `Auto` / `0` | ONNX execution provider and hardware device index. | | `FramesToSkip` | `0` | Skip frames between inference runs to reduce CPU/GPU load. | `YOLOObjectDetectorBlock.ActiveProvider` reports the provider actually engaged after the block is built. ## Use with VideoCaptureCoreX and MediaPlayerCoreX ``` var detector = new YOLOObjectDetectorBlock(detectorSettings); detector.OnObjectsDetected += Detector_OnObjectsDetected; core.Video_Processing_AddBlock(detector); // before StartAsync (VideoCaptureCoreX) // player.Video_Processing_AddBlock(detector); // before OpenAsync/PlayAsync (MediaPlayerCoreX) await core.StartAsync(); ``` See [Using AI blocks with VideoCaptureCoreX and MediaPlayerCoreX](../x-engines/) for the full processing-block API, insertion order, and lifecycle rules shared by every video AI block. ## Use cases - **Security and surveillance** — flag the presence of people, vehicles, or specific object classes in a camera feed. - **Retail analytics** — detect products, baskets, or people in a store aisle for a downstream business-logic layer. - **Industrial and safety monitoring** — detect required PPE items, obstacles, or equipment in a frame (with a model trained for those classes). - **Wildlife and traffic monitoring** — detect animals or vehicles in a fixed camera feed. - **Pre-filtering for a heavier pipeline** — use standalone detection as a cheap first pass, and only run a more expensive block (OCR, face recognition) on frames or regions where something was detected. Need identities that persist across frames, line-crossing counts, or zone occupancy instead of raw per-frame boxes? Use [Object analytics](../object-analytics/) — it wraps the same detector families with ByteTrack tracking, tripwires, and polygon zones. ## Troubleshooting | Symptom | Likely cause | Fix | | --- | --- | --- | | No detections at all | `ConfidenceThreshold` too high for the model/scene, or the wrong `Model` family selected for the ONNX file | Lower `ConfidenceThreshold`; confirm `Model` matches the exported model's layout (YOLOv8 vs YOLOX vs RT-DETR). | | Too many false positives / duplicate boxes | `IoUThreshold` too high (weak suppression) — NMS-based families only | Lower `IoUThreshold`. Note RT-DETR is NMS-free and ignores this setting. | | Boxes are offset from the real object | Wrong `Model` family for the ONNX file — each family uses a different letterbox/color-order convention | Set `Model` to match the exported model exactly; a mismatched decoder silently produces plausible-looking but wrong boxes. | | Labels show numbers instead of names | `Labels` is `null` and the model isn't COCO-80 | Set `Labels` to the class-name array your model was trained with. | | High CPU/GPU usage on live video | Inference running on every frame | Raise `FramesToSkip`; the block still passes every frame through, it just infers less often. | ## Frequently Asked Questions ### Which detector family should I start with? `YOLOv8` (the default) if you're using stock Ultralytics-exported weights, but check the AGPL-3.0 licensing note first. `YOLOX` and `RT-DETR` are Apache-2.0 alternatives with no commercial-license requirement. ### Can I use my own trained YOLO model? Yes — as long as it was exported in the layout of one of the three supported families (`YOLOv8`/`YOLOX`/`RTDETR`) and you set `Model` and `Labels` to match your training classes. ### Does YOLOObjectDetectorBlock track objects across frames? No — each detection is independent per frame (`TrackerId` is always `-1`). Use [`ObjectAnalyticsBlock`](../object-analytics/) when you need stable identities, tripwires, or zones. ### Is a GPU required for real-time detection? No, but a GPU execution provider (`CUDA`, `DirectML`, or `CoreML`) lowers per-frame latency compared to CPU, which matters most for high frame rates or larger detector models. ## Demos - **[YOLO Object Detection Demo](https://github.com/visioforge/.Net-SDK-s-samples/tree/master/Media%20Blocks%20SDK/WPF/CSharp/YOLO%20Object%20Detection%20Demo)** — WPF Media Blocks demo covering both standalone detection and object analytics modes. - **[YOLO Object Detection MB](https://github.com/visioforge/.Net-SDK-s-samples/tree/master/Media%20Blocks%20SDK/MAUI/YOLO%20Object%20Detection%20MB)** — the same Media Blocks demo for MAUI. Dedicated `VideoCaptureCoreX`/`MediaPlayerCoreX` object-detection demos (`Capture Object Detection X`, `Capture Object Detection X WPF`, `Player Object Detection X`, `Player Object Detection X WPF`) are in the SDK's demo set and will be linked here once published to the public samples repository. ---END OF PAGE--- ## OCR SDK for .NET — OcrBlock Text Recognition (PaddleOCR) **URL:** https://www.visioforge.com/help/docs/dotnet/general/ai/ocr/ **Description:** OCR SDK for .NET — recognize text in video and images with OcrBlock (ONNX Runtime + PaddleOCR). Cross-platform C# on Windows, macOS, Linux, Android, iOS. **Tags:** .NET, AI, OCR, OCR SDK, ONNX, PaddleOCR, Text Recognition, Computer Vision, VideoCaptureCoreX, MediaPlayerCoreX **API:** OcrBlock, OcrSettings, OcrTextRegion, OcrPoint # OCR Text Recognition — OcrBlock `OcrBlock` recognizes text in any video or image source. Internally it runs the multi-stage PP-OCR pipeline — text detection (DBNet) → optional 0°/180° angle classification → text-line recognition (CRNN/SVTR + CTC decoding) — on each processed frame, raises the recognized regions, and optionally draws them into the video. The block lives in `VisioForge.Core.AI` (`VisioForge.DotNet.Core.AI`), implements `IVideoProcessingBlock`, and has one video `Input` and one video `Output`. ``` graph LR; Source-->OcrBlock; OcrBlock-->VideoRendererBlock; OcrBlock-. OnTextDetected .->App[Your app]; ``` ## Usage ``` using VisioForge.Core.MediaBlocks; using VisioForge.Core.MediaBlocks.AI; using VisioForge.Core.Types.X.AI; var ocrSettings = new OcrSettings( detectionModelPath: "ch_PP-OCRv5_mobile_det.onnx", recognitionModelPath: "latin_PP-OCRv5_rec_mobile_infer.onnx", characterDictionaryPath: "ppocrv5_latin_dict.txt", classificationModelPath: "ch_ppocr_mobile_v2.0_cls_infer.onnx") { Provider = OnnxExecutionProvider.Auto, // CPU / CUDA / DirectML / CoreML FramesToSkip = 3, // run OCR every 4th frame on live video DrawResults = true, // burn boxes + text into the frame }; var ocr = new OcrBlock(ocrSettings); ocr.OnTextDetected += (sender, e) => { foreach (var region in e.Regions) { Console.WriteLine($"{region.Text} ({region.Confidence:P0}) at {region.BoundingBox}"); } }; pipeline.Connect(source.Output, ocr.Input); pipeline.Connect(ocr.Output, videoRenderer.Input); await pipeline.StartAsync(); ``` Each `OcrTextRegion` carries the recognized `Text`, an average `Confidence` (0..1), an axis-aligned `BoundingBox` (`Rect`), and the detection `Polygon` — the detector's four `OcrPoint` vertices (top-left, top-right, bottom-right, bottom-left, in source-frame pixels), which may be rotated for slanted text. ## Key settings `OcrSettings(detectionModelPath, recognitionModelPath, characterDictionaryPath, classificationModelPath = null)` sets `UseAngleClassifier` from whether a classification model path was supplied. | Property | Default | Description | | --- | --- | --- | | `DetectionModelPath` | — | Text-detection (DBNet) ONNX model. Required. | | `RecognitionModelPath` | — | Text-recognition (CRNN/SVTR) ONNX model. Required. | | `CharacterDictionaryPath` | — | Recognizer character dictionary; must match the recognition model's language. Required. | | `ClassificationModelPath` | `null` | Optional 0°/180° angle classifier. | | `UseAngleClassifier` | `true` | Apply the angle classifier (needs `ClassificationModelPath`). | | `Provider` | `Auto` | ONNX execution provider. | | `DeviceId` | `0` | Device index for hardware execution providers. | | `FramesToSkip` | `0` | Frames skipped between OCR runs. Use a non-zero value for live video. | | `MaxSideLength` | `1024` | Detector input's longer side is resized to this value. `0` or negative uses the adaptive PP-OCRv5 resize path instead. | | `BoxThreshold` | `0.3` | Binarization threshold applied to the detector probability map. | | `BoxScoreThreshold` | `0.5` | Minimum mean probability a detected region must reach to be kept. | | `UnclipRatio` | `1.6` | Expansion ratio used to grow detected text polygons. | | `TextScoreThreshold` | `0.5` | Minimum average per-character recognition score for a line to be reported. | | `DrawResults` | `true` | Draw boxes + text into the frame. | | `BoxColor` | Lime | Region box/text color when `DrawResults` is enabled. | | `BoxThickness` | `2` | Region box stroke thickness, in pixels. | | `LabelFontSize` | `0` | Label font size in pixels; `0` auto-scales to frame height. | ## Models and licensing `OcrBlock` runs third-party ONNX models; the SDK does not ship weights in the NuGet package. The demos ship the Apache-2.0 **PP-OCRv5 mobile** models (detection, angle classification, Latin recognition) and a Latin dictionary next to the sample executables. PP-OCR supports 100+ languages — download the matching recognition model and dictionary for other languages. Model licenses A model's license is set by its origin (training code + published weights), not by the ONNX format. Verify the license of any model — code, weights, and dataset — before shipping it. The bundled PP-OCR models are Apache-2.0. ## Use with VideoCaptureCoreX and MediaPlayerCoreX `OcrBlock` implements `IVideoProcessingBlock`, so it can be registered directly on `VideoCaptureCoreX` or `MediaPlayerCoreX` instead of building a manual Media Blocks pipeline: ``` var ocr = new OcrBlock(ocrSettings); ocr.OnTextDetected += Ocr_OnTextDetected; core.Video_Processing_AddBlock(ocr); // before StartAsync (VideoCaptureCoreX) // player.Video_Processing_AddBlock(ocr); // before OpenAsync/PlayAsync (MediaPlayerCoreX) await core.StartAsync(); ``` See [Using AI blocks with VideoCaptureCoreX and MediaPlayerCoreX](../x-engines/) for the full processing-block API, insertion order, and lifecycle rules shared by every video AI block. ## Use cases - **Document and screen capture** — recognize text from scanned documents, ID cards, forms, or shared screens in a video conferencing pipeline. - **Retail and warehouse automation** — read product labels, barcodes' printed text, or shelf tags from a fixed overhead or handheld camera. - **Industrial inspection** — read serial numbers, batch codes, or printed labels on a production line. - **Signage and broadcast monitoring** — verify that on-screen text (lower thirds, tickers, digital signage) matches expected content. - **Accessibility tooling** — extract on-screen text for text-to-speech or translation pipelines. For a specific, narrower case — reading vehicle license plates — use the purpose-built [License plate recognition (ANPR)](../license-plate-recognition/) block instead of general OCR; it is both more accurate and faster because it runs a plate-specific detector and OCR head rather than scanning the whole frame for any text. ## Troubleshooting | Symptom | Likely cause | Fix | | --- | --- | --- | | `OnTextDetected` never fires | No handler subscribed, or `FramesToSkip` combined with a very short clip | Subscribe before `StartAsync`/`OpenAsync`; lower `FramesToSkip`. | | Recognized text is empty or garbled | `CharacterDictionaryPath` doesn't match `RecognitionModelPath`'s language | Use the dictionary shipped with that specific recognition model. | | Slanted or rotated text is missed | `UseAngleClassifier` is `false`, or `ClassificationModelPath` wasn't supplied | Provide `ClassificationModelPath` and leave `UseAngleClassifier` at its default `true`. | | Small text is missed on a large frame | `MaxSideLength` too low for the source resolution | Raise `MaxSideLength`, or set it to `0` to use the adaptive PP-OCRv5 resize path. | | High CPU usage on live video | OCR running on every frame | Set `FramesToSkip` to a non-zero value; OCR is heavier per frame than a single-model detector. | | `Provider = CUDA`/`DirectML` silently falls back to CPU | The corresponding native ONNX Runtime execution-provider package isn't referenced, or no compatible GPU is present | Add the matching native runtime package for your platform, or use `Auto` and let the block pick what's actually available. | ## Frequently Asked Questions ### What's the difference between OcrBlock and LicensePlateRecognizerBlock? `OcrBlock` reads arbitrary text anywhere in the frame. `LicensePlateRecognizerBlock` is a dedicated two-stage pipeline (a plate detector plus a plate-specific OCR head) tuned only for vehicle plates — use it instead of `OcrBlock` for ANPR/LPR scenarios. ### Does OcrBlock support languages other than English? Yes. PP-OCR supports 100+ languages. Point `RecognitionModelPath` and `CharacterDictionaryPath` at the recognition model and dictionary for your target language; both must match. ### Can I run OCR on a still image instead of a live video stream? Yes — connect a file/image source to `OcrBlock.Input` in a `MediaBlocksPipeline`, or feed a single frame through the pipeline; the block processes whatever frames reach its input pad, live or file-based. ### Does OcrBlock need a GPU to run in real time? No, but a GPU execution provider (`CUDA`, `DirectML`, or `CoreML`) reduces per-frame latency compared to CPU. For live video, combining `FramesToSkip` with CPU inference is also a common, GPU-free way to keep OCR from becoming the pipeline bottleneck. ## Demos - **[OCR Text Recognition Demo](https://github.com/visioforge/.Net-SDK-s-samples/tree/master/Media%20Blocks%20SDK/WPF/CSharp/OCR%20Text%20Recognition%20Demo)** — WPF Media Blocks pipeline demo. - **[OCR Text Recognition MB](https://github.com/visioforge/.Net-SDK-s-samples/tree/master/Media%20Blocks%20SDK/MAUI/OCR%20Text%20Recognition%20MB)** — the same Media Blocks demo for MAUI. Dedicated `VideoCaptureCoreX`/`MediaPlayerCoreX` OCR demos (`Capture OCR X`, `Capture OCR X WPF`, `Player OCR X`, `Player OCR X WPF`) are in the SDK's demo set and will be linked here once published to the public samples repository. ---END OF PAGE--- ## ONNX Runtime SDK for .NET — OnnxInferenceBlock Guide **URL:** https://www.visioforge.com/help/docs/dotnet/general/ai/onnx-inference/ **Description:** Run any custom ONNX Runtime model over live video frames in .NET with OnnxInferenceBlock and get raw tensor outputs for your own post-processing. **Tags:** .NET, AI, ONNX, ONNX Runtime, Inference, Custom Model, VideoCaptureCoreX, MediaPlayerCoreX **API:** OnnxInferenceBlock, OnnxInferenceSettings, OnnxInferenceEventArgs, OnnxInferenceEngine # Generic ONNX Inference — OnnxInferenceBlock `OnnxInferenceBlock` is the lowest-level video AI block in `VisioForge.Core.AI` (`VisioForge.DotNet.Core.AI`). It taps RGBA video frames, preprocesses them into an ONNX Runtime input tensor, runs your model, and raises `OnInference` with the raw float outputs. The video frame passes through unchanged; the block does not draw overlays or interpret model-specific tensors. Use this block when you have a custom ONNX model and want to own the decoder/post-processing logic in your application. Use [`YOLOObjectDetectorBlock`](../object-detection/) instead when the model is a supported object detector family, because the YOLO block already maps boxes back to the source frame and applies the correct decoder. ``` graph LR; Source-->OnnxInferenceBlock; OnnxInferenceBlock-->VideoRendererBlock; OnnxInferenceBlock-. OnInference .->App[Your app decoder]; ``` ## Pipeline example ``` using VisioForge.Core.AI; using VisioForge.Core.MediaBlocks; using VisioForge.Core.MediaBlocks.AI; using VisioForge.Core.MediaBlocks.VideoRendering; using VisioForge.Core.Types.X.AI; var settings = new OnnxInferenceSettings(modelPath) { InputWidth = 224, InputHeight = 224, NormalizeTo01 = true, Provider = OnnxExecutionProvider.Auto, FramesToSkip = 2, }; var inference = new OnnxInferenceBlock(settings); inference.OnInference += (sender, e) => { foreach (var output in e.Outputs) { var name = output.Key; var values = output.Value; var shape = e.Shapes[name]; Console.WriteLine($"{name} shape [{string.Join(",", shape)}], {values.Length} values"); } }; var videoRenderer = new VideoRendererBlock(pipeline, videoView) { IsSync = false }; pipeline.Connect(source.Output, inference.Input); pipeline.Connect(inference.Output, videoRenderer.Input); await pipeline.StartAsync(); ``` Inference is demand-driven If no handler is attached to `OnInference`, the block skips inference because the frame is passed through unmodified and the output would be unobservable. ## How preprocessing works The block uses `OnnxInferenceEngine` internally: - The model file is loaded into an ONNX Runtime `InferenceSession`. - `Provider = Auto` chooses CUDA, then DirectML, then CoreML, then CPU, from whichever providers are present in the loaded ONNX Runtime native build. One documented exception: open-vocabulary detection skips CoreML under `Auto`, because ONNX Runtime cannot map those graphs to it in fewer than a hundred partitions — see [Open-vocabulary detection](../open-vocabulary-detection/#why-does-auto-not-use-coreml-for-this-block). - If the model declares a fixed input tensor size, that size overrides `InputWidth` and `InputHeight`. - RGBA source frames are resized with a centered letterbox into the model input size. - Pixels are converted to an RGB `NCHW` float tensor. - `NormalizeTo01 = true` divides pixel values by 255; otherwise values stay in the 0..255 range. The event payload keeps the model-specific work in your code. `OnnxInferenceEventArgs.Outputs` maps each output tensor name to a flattened row-major `float[]`, and `Shapes` maps the same name to the tensor dimensions. The meaning of those dimensions depends entirely on your model. ## Key settings | Property | Default | Description | | --- | --- | --- | | `ModelPath` | — | Absolute path to the `.onnx` file. Required. | | `InputWidth` / `InputHeight` | `640` / `640` | Used for dynamic-input models. Fixed-size models report their own input size. | | `NormalizeTo01` | `true` | Divide RGB values by 255 during preprocessing. | | `Provider` | `Auto` | ONNX execution provider. `Auto` tries hardware providers before CPU. | | `DeviceId` | `0` | Hardware device index for CUDA/DirectML. | | `FramesToSkip` | `0` | Run inference every `FramesToSkip + 1` frames. | `OnnxInferenceBlock.ActiveProvider` reports the provider actually engaged after the block is built. `OnnxInferenceEngine.GetAvailableProviders()` can be called before building a pipeline to inspect the ONNX Runtime providers available in the current process. ## Direct engine API Advanced integrations can use `OnnxInferenceEngine` directly outside a Media Blocks pipeline. It exposes `Initialize()`, `Preprocess(...)`, `Run(...)`, `OutputNames`, `InputWidth`, `InputHeight`, and `ActiveProvider`. `YoloDetector` is a public direct helper over the same engine for the supported detector families. Most applications should prefer the MediaBlocks wrappers because they handle pipeline pads, frame grabbing, and lifetime management. ## Use with VideoCaptureCoreX and MediaPlayerCoreX ``` var inference = new OnnxInferenceBlock(settings); inference.OnInference += Inference_OnInference; core.Video_Processing_AddBlock(inference); // before StartAsync (VideoCaptureCoreX) // player.Video_Processing_AddBlock(inference); // before OpenAsync/PlayAsync (MediaPlayerCoreX) await core.StartAsync(); ``` See [Using AI blocks with VideoCaptureCoreX and MediaPlayerCoreX](../x-engines/) for the full processing-block API, insertion order, and lifecycle rules shared by every video AI block. ## Use cases - **Custom classification models** — image classifiers, quality-control pass/fail models, or scene classifiers exported to ONNX from PyTorch/TensorFlow/scikit-learn. - **Detector families the SDK doesn't decode yet** — run your model's raw tensors through `OnnxInferenceBlock` and write the decoder in your own code, exactly as [`YOLOObjectDetectorBlock`](../object-detection/) does internally for its three supported families. - **Segmentation, depth, or pose models** — any single-input, tensor-output ONNX model can be wired up, as long as you own interpreting its output shape. - **Prototyping** — validate a newly exported ONNX model against live or file video before committing to a purpose-built decoder. ## Troubleshooting | Symptom | Likely cause | Fix | | --- | --- | --- | | `OnInference` never fires | No handler subscribed | The block skips inference entirely when nothing observes the event — subscribe before `StartAsync`/`OpenAsync`. | | Output values look wrong/saturated | `NormalizeTo01` doesn't match how the model was trained | Toggle `NormalizeTo01`; some models expect raw 0..255 pixel values instead of 0..1. | | Model loads but every output is the same shape you didn't expect | The model has a fixed input size that overrides `InputWidth`/`InputHeight` | Check the model's declared input shape — a fixed-size model reports and uses its own size regardless of your settings. | | `Provider = CUDA`/`DirectML` doesn't seem to engage | Missing native execution-provider package, or no compatible GPU | Check `OnnxInferenceBlock.ActiveProvider` after `StartAsync`, or call `OnnxInferenceEngine.GetAvailableProviders()` beforehand to see what's actually available in-process. | | Boxes/keypoints look shifted from the source frame | Frame is letterbox-resized into the model's input size before inference | Map your model's normalized/model-space output coordinates back through the same letterbox transform before drawing on the source frame. | ## Frequently Asked Questions ### Can I use OnnxInferenceBlock for a model that isn't a YOLO detector? Yes — that's exactly what it's for. Unlike `YOLOObjectDetectorBlock`, `OnnxInferenceBlock` doesn't assume any output layout; it hands you the raw named output tensors and shapes for any single-input model. ### Does OnnxInferenceBlock draw anything on the frame? No. It passes the frame through unchanged and never draws overlays — your application interprets `OnnxInferenceEventArgs.Outputs`/`Shapes` and draws whatever it needs downstream. ### How do I know which ONNX Runtime execution providers are available? Call the static `OnnxInferenceEngine.GetAvailableProviders()` before building a pipeline, or read `OnnxInferenceBlock.ActiveProvider` after the block is built to see which provider was actually engaged. ### My model has multiple inputs — does OnnxInferenceBlock support that? `OnnxInferenceSettings`/`OnnxInferenceBlock` are built around a single RGBA video-frame input tensor. For a multi-input model, use `OnnxInferenceEngine` directly outside the Media Blocks pipeline, where you control the full `Run(...)` call. ## Demos `OnnxInferenceBlock` doesn't have a dedicated sample yet — it's exercised indirectly through the `OnnxInferenceEngine` used internally by [`YOLOObjectDetectorBlock`](../object-detection/) and [`ObjectAnalyticsBlock`](../object-analytics/). If you're prototyping a custom model, adapt the "Pipeline example" above with your own model path and output decoder. ---END OF PAGE--- ## Detect Objects Without Training — Open Vocabulary .NET **URL:** https://www.visioforge.com/help/docs/dotnet/general/ai/open-vocabulary-detection/ **Description:** Detect any object in video by naming it in text — zero-shot, no training data. On-device open-vocabulary detection for .NET (OWLv2, Grounding DINO). **Tags:** .NET, AI, ONNX, Open Vocabulary Detection, Zero-Shot Detection, OWLv2, Grounding DINO, Computer Vision, VideoCaptureCoreX, MediaPlayerCoreX **API:** OpenVocabularyDetectorBlock, OpenVocabularyDetectorSettings, OpenVocabularyModel, OnnxDetection # Open Vocabulary Detection — OpenVocabularyDetectorBlock You need to detect an object that no off-the-shelf model was trained on — a specific tool, product, or uniform — but you have no labeled dataset and no time to train and deploy a custom detector. **Open-vocabulary detection** solves this: name what you're looking for in plain text and the model finds it, with no training and no fixed class list. It runs on-device via ONNX (OWLv2 or Grounding DINO), and you can change what it detects at any time by editing the text prompts. `OpenVocabularyDetectorBlock` detects objects described by **free-text prompts** instead of a fixed class list. You give it phrases like `"a person"`, `"a red backpack"`, or `"a forklift"`, and it finds them in the video stream — no retraining, no fixed label set. It taps RGBA frames, runs an open-vocabulary ONNX model (OWLv2 or Grounding DINO), optionally draws boxes and labels into the frame, and raises `OnObjectsDetected` for frames that contain detections. Because open-vocabulary models are heavier than a fixed-class detector, inference runs on a background, latest-wins worker: the streaming thread submits a frame copy and only redraws the most recent cached detections, so the pipeline never stalls. Each detection's `Label` is the matched prompt string and its `ClassId` is that prompt's zero-based index. ``` graph LR; Source-->OpenVocabularyDetectorBlock; OpenVocabularyDetectorBlock-->VideoRendererBlock; OpenVocabularyDetectorBlock-. OnObjectsDetected .->App[Your app]; ``` Need a fixed set of classes at maximum speed (COCO-80, or your own trained labels)? Use [`YOLOObjectDetectorBlock`](../object-detection/) instead — it is far faster but cannot detect a class it was not trained on. Open-vocabulary detection trades throughput for the ability to detect anything you can name. ## How open-vocabulary detection works Open-vocabulary detection is a form of **zero-shot detection**: the model detects classes it was never explicitly trained on, specified at run time as text. Each frame goes through four steps: 1. **Encode the prompts.** Every prompt string is tokenized and turned into a text embedding. This is cheap and cached until you call `SetPrompts`, so it is not repeated per frame. 2. **Encode the frame.** The frame is preprocessed to the model's convention (OWLv2 pads to a square and resizes to 960x960; Grounding DINO resizes to its fixed size) and encoded into per-region image features. 3. **Score regions against prompts.** Each candidate region is scored against each prompt embedding; regions scoring above `ConfidenceThreshold` become detections, labeled with the matched prompt (`Label`) and its index (`ClassId`). 4. **Suppress overlaps.** Class-wise non-maximum suppression (`IoUThreshold`) removes duplicate boxes, and the top `MaxDetections` results are returned. Steps 2–4 run on a background, latest-wins worker so the video never stalls — the streaming thread draws the most recent completed result while the next inference is still running. ## Supported model families Set `OpenVocabularyDetectorSettings.Model` to match the ONNX model layout. Each family uses a different tokenizer and preprocessing convention. | Model | Tokenizer and preprocessing | Notes | | --- | --- | --- | | `OpenVocabularyModel.OWLv2` (default) | CLIP byte-level BPE tokenizer (`vocab.json` + `merges.txt`). Frame padded to a square (top-left) and resized to 960x960; per-query sigmoid logits over a fixed patch grid. | Requires both `VocabFilePath` and `MergesFilePath`. Ignores `TextThreshold`. | | `OpenVocabularyModel.GroundingDINO` | BERT WordPiece tokenizer (`vocab.txt` only). Prompts joined into a `prompt1 . prompt2 .` caption, lowercased; frame resized to the model's fixed input size; per-query token-span scores over 900 queries. | `MergesFilePath` is not used. `TextThreshold` filters weak per-token contributions. | The SDK does not ship detector weights in the NuGet package — supply the `.onnx` model and its tokenizer files as local paths (see [Models](#models)). The inherited `InputWidth`/`InputHeight` are **ignored**: OWLv2 always runs at 960x960 and Grounding DINO uses the fixed size baked into its ONNX model. ## Usage ``` using VisioForge.Core.MediaBlocks; using VisioForge.Core.MediaBlocks.AI; using VisioForge.Core.MediaBlocks.VideoRendering; using VisioForge.Core.Types.Events; using VisioForge.Core.Types.VideoProcessing; using VisioForge.Core.Types.X.AI; var settings = new OpenVocabularyDetectorSettings( "owlv2-base-ensemble.onnx", "owlv2-vocab.json", "owlv2-merges.txt", new[] { "a person", "a car", "a red backpack" }) { Model = OpenVocabularyModel.OWLv2, ConfidenceThreshold = 0.25f, IoUThreshold = 0.5f, DrawDetections = true, Provider = OnnxExecutionProvider.Auto, }; var detector = new OpenVocabularyDetectorBlock(settings); detector.OnObjectsDetected += (sender, e) => { foreach (OnnxDetection obj in e.Objects) { // obj.Label is the matched prompt; obj.ClassId is its index in the prompt array. Console.WriteLine($"{obj.Label} {obj.Confidence:P0} at {obj.Box}"); } }; var videoRenderer = new VideoRendererBlock(pipeline, videoView) { IsSync = false }; pipeline.Connect(source.Output, detector.Input); pipeline.Connect(detector.Output, videoRenderer.Input); await pipeline.StartAsync(); Console.WriteLine($"Active provider: {detector.ActiveProvider}"); ``` Each `OnObjectsDetected` fires only when the frame has detections. `ObjectsDetectedEventArgs` carries `Objects` (an `OnnxDetection[]`) and the frame `Timestamp`. Each `OnnxDetection` has the bounding `Box` in source-frame pixel coordinates, `ClassId` (the prompt index), `Label` (the matched prompt), and `Confidence`. `TrackerId` is always `-1` — this block does not track objects across frames. ### Changing prompts and thresholds at runtime Prompts and thresholds can be updated live without rebuilding the pipeline — the change applies on the next processed frame: ``` detector.SetPrompts(new[] { "a delivery truck", "a bicycle" }); detector.SetConfidenceThreshold(0.30f); detector.SetIoUThreshold(0.45f); ``` ## Key settings `OpenVocabularyDetectorSettings` extends `OnnxInferenceSettings`. | Property | Default | Description | | --- | --- | --- | | `ModelPath` | — | Absolute path to the open-vocabulary `.onnx` file. Required. | | `Prompts` | `null` | Free-text detection prompts. Each becomes a detectable class; `Label` = prompt, `ClassId` = its index. | | `VocabFilePath` | `null` | Tokenizer vocab: `vocab.json` (OWLv2) or `vocab.txt` (Grounding DINO). Required. | | `MergesFilePath` | `null` | Byte-level BPE `merges.txt`. Required for OWLv2; leave `null` for Grounding DINO. | | `Model` | `OpenVocabularyModel.OWLv2` | Selects the tokenizer, preprocessing, and output decoder. | | `ConfidenceThreshold` | `0.25` | Minimum confidence (0..1) for a reported detection. | | `TextThreshold` | `0.25` | Per-token text-score threshold for Grounding DINO. Ignored by OWLv2. | | `IoUThreshold` | `0.5` | Non-maximum-suppression threshold for class-wise NMS. | | `MaxDetections` | `100` | Maximum detections returned per frame, highest confidence first. | | `DrawDetections` | `true` | Draw detection boxes into the video frame. | | `DrawLabels` | `true` | Draw the prompt label and confidence next to each box. | | `BoxColor` / `BoxThickness` | Lime / `2` | Box overlay styling. | | `LabelFontSize` | `0` | Label text size in px. `0` auto-scales to frame height. | | `Provider` / `DeviceId` | `Auto` / `0` | ONNX execution provider and hardware device index. | | `FramesToSkip` | `0` | Skip frames between inference runs to reduce load. | `InputWidth`/`InputHeight` and `NormalizeTo01` are inherited from `OnnxInferenceSettings` but the input size is ignored (each family fixes its own). `OpenVocabularyDetectorBlock.ActiveProvider` reports the provider actually engaged after the block is built; `LastInferenceTimeMs` and `DroppedFrameCount` expose live inference cost. ## Models Model weights are not bundled with the SDK. The demos download them on first run from GitHub Releases and cache them under `%USERPROFILE%\VisioForge\models\openvocab`. | Model | Files | | --- | --- | | OWLv2 | `owlv2-base-ensemble.onnx`, `owlv2-vocab.json`, `owlv2-merges.txt` | | Grounding DINO | `grounding-dino-tiny.onnx`, `bert-vocab.txt` (no merges file) | A model's license is set by its origin (training code and published weights), not by the ONNX format or the SDK's own license. Confirm the license of the specific weights you deploy before shipping a closed-source product. ## Writing effective prompts Prompt phrasing directly affects recall and precision. A few practical rules: - **Use short noun phrases** — `"a person"`, `"a delivery truck"`, `"a cardboard box"`. Full sentences and long qualifiers narrow recall. - **One concept per prompt.** Each prompt is a separate class; don't combine ("a person or a bag"). - **Start broad, then narrow.** `"a car"` detects more than `"a red sports car"`. Add descriptors only when you need to filter. - **Grounding DINO lowercases prompts** and joins them into a single `.`-separated caption — keep phrases distinct and unambiguous. - **Each prompt adds text-encoding cost** at prompt-change time (not per frame), so a huge live vocabulary is fine to index but trim it if `SetPrompts` calls feel slow. ## Performance and tuning Open-vocabulary models are heavier than a fixed-class detector, so throughput is lower — plan for it rather than fighting it: - **The pipeline never stalls.** Inference is asynchronous and latest-wins, so live video keeps playing; boxes reflect the most recent completed inference. - **Lower the inference rate** with `FramesToSkip` when you don't need a result on every frame — the block still passes every frame through. - **Use a GPU provider** (`CUDA` or `DirectML`) via `Provider`/`DeviceId` for a large latency drop over CPU. **Do not set `CoreML` for these models on Apple hardware** — see the note below. - **Input size is fixed per family** (OWLv2 960x960; Grounding DINO its baked-in size) and cannot be lowered to trade accuracy for speed — pick the lighter model instead if you need more headroom. - **Watch live cost** with `LastInferenceTimeMs` and `DroppedFrameCount`, and read the engaged provider from `ActiveProvider` after the block is built. ## Use with VideoCaptureCoreX and MediaPlayerCoreX The same block instance drops into either high-level engine. Register it before the session starts: ``` var detector = new OpenVocabularyDetectorBlock(settings); detector.OnObjectsDetected += Detector_OnObjectsDetected; core.Video_Processing_AddBlock(detector); // VideoCaptureCoreX — before StartAsync // player.Video_Processing_AddBlock(detector); // MediaPlayerCoreX — before OpenAsync/PlayAsync await core.StartAsync(); // Prompts and thresholds are still live-updatable while the session runs: detector.SetPrompts(new[] { "a person wearing a hard hat" }); ``` `SetPrompts` makes open-vocabulary detection especially useful on a live camera feed: an operator can change what to look for on the fly. See [Using AI blocks with VideoCaptureCoreX and MediaPlayerCoreX](../x-engines/) for the full processing-block API, insertion order, and lifecycle rules shared by every video AI block. ## Open-vocabulary detection vs training your own model The choice comes down to whether you have labeled data and how much the target classes change. | Situation | Best choice | | --- | --- | | No labeled data, and you need results now | **Open-vocabulary** — describe the class in text, zero training. | | The target classes change often, or the user picks them at run time | **Open-vocabulary** — swap prompts live with `SetPrompts`, no redeploy. | | A large labeled dataset and a need for maximum accuracy on fixed classes | **Train a model** — YOLO / RT-DETR; see [object detection](../object-detection/). | | The highest possible frame rate on a few well-known classes | **Trained fixed-class detector** — it's faster; open-vocabulary trades speed for flexibility. | A common pattern is to prototype with open-vocabulary detection to confirm a class is even detectable in your footage, then train a fixed-class model later only if you need the extra speed. ## Use cases - **Ad-hoc surveillance queries** — search a camera feed for "a person carrying a bag" or "a white van" without training a custom model. - **Retail and inventory** — detect an arbitrary product described in words, or empty shelf space, for a downstream business layer. - **Prototyping and triage** — validate that a class is detectable in your footage before investing in a trained, fixed-class YOLO model for production speed. - **Long-tail and rare classes** — detect objects that have no off-the-shelf trained detector by simply naming them. - **Interactive tools** — let an end user type what to find, and update `SetPrompts` from the UI. ## Troubleshooting | Symptom | Likely cause | Fix | | --- | --- | --- | | No detections at all | `ConfidenceThreshold` too high, prompts too specific, or the wrong `Model` family for the ONNX file | Lower `ConfidenceThreshold`; use simpler prompts ("a car" before "a red sports car"); confirm `Model` matches the exported model. | | Tokenizer / startup error | Missing or mismatched tokenizer files | OWLv2 needs `VocabFilePath` **and** `MergesFilePath`; Grounding DINO needs only `VocabFilePath` (`vocab.txt`). | | Duplicate or overlapping boxes | `IoUThreshold` too high (weak suppression) | Lower `IoUThreshold` (or call `SetIoUThreshold`). | | Grounding DINO returns noisy tokens | `TextThreshold` too low | Raise `TextThreshold` — OWLv2 ignores this setting. | | High CPU/GPU usage on live video | Inference running on every frame | Raise `FramesToSkip`; the block still passes every frame through, it just infers less often. | | Boxes appear only after a delay | Expected — inference is asynchronous and latest-wins | The frame is never stalled; boxes reflect the most recent completed inference. | ## Frequently Asked Questions ### How do I detect a custom object without a dataset? Name it in a text prompt — for example `new OpenVocabularyDetectorSettings(modelPath, vocabPath, mergesPath, new[] { "a forklift", "a safety vest" })`. There are no images to collect, no labeling, and no training run. If a plain noun phrase under-detects, make it slightly more specific (`"an orange safety vest"`). See [Writing effective prompts](#writing-effective-prompts). ### Do I need to train or fine-tune anything? No. Open-vocabulary models are pre-trained to detect arbitrary text-described classes, so you supply only the prompt text plus the ONNX model and tokenizer files — there is no training or fine-tuning step. ### Which model should I start with? `OWLv2` (the default) gives strong open-vocabulary accuracy and takes both a vocab and a merges file. `GroundingDINO` (tiny) is a lighter alternative that uses only a `vocab.txt` and phrase-grounds a `.`-separated caption. Try OWLv2 first; switch to Grounding DINO if you need a smaller model. ### How is this different from YOLOObjectDetectorBlock? [`YOLOObjectDetectorBlock`](../object-detection/) detects a **fixed** set of classes it was trained on, very fast. Open-vocabulary detection detects **anything you describe in text**, at a higher per-frame cost. Use YOLO for known classes at high frame rates; use open-vocabulary for flexible or rare queries. ### Can I change what it looks for while it's running? Yes — call `SetPrompts` at any time. The new prompts apply on the next processed frame, with no pipeline rebuild. `SetConfidenceThreshold` and `SetIoUThreshold` are also live. ### Does it track objects across frames? No — each detection is independent per frame and `TrackerId` is always `-1`. For persistent identities, tripwires, or zone counting, see [Object analytics](../object-analytics/). ### Is a GPU required? No. `Provider` defaults to `Auto`, which runs on the CPU when no GPU provider is present. A `CUDA` or `DirectML` provider lowers per-frame latency, which matters most for these heavier models. ### Why does `Auto` not use CoreML for this block? On Apple hardware `Auto` picks CPU for open-vocabulary detection even though CoreML is available, and that is deliberate. ONNX Runtime cannot map these graphs to CoreML in one piece: it splits OWLv2 into 126 partitions and Grounding DINO into 255, each compiled and held as a separate CoreML model. The result is not slow, it is unusable — measured on a 24 GB Mac, the session grew past 5.8 GB resident plus several GB of swap and never settled, while the same model on CPU peaks at about 4 GB and returns a frame in roughly 1.3 s. Only the `Auto` default is redirected. Setting `Provider = OnnxExecutionProvider.CoreML` explicitly still does exactly what you ask, and it is not recommended for these two model families. Other AI blocks are unaffected — models that CoreML maps in a handful of partitions still use it. ### Is open-vocabulary detection the same as zero-shot object detection? Yes. "Open-vocabulary" and "zero-shot" describe the same capability here: detecting object classes the model was not explicitly trained on, chosen at run time by text prompt rather than by a fixed label set. OWLv2 and Grounding DINO are two well-known open-vocabulary (zero-shot) detector families. ### How many prompts can I detect at once? There is no hard limit on the number of prompts — each becomes its own class. `MaxDetections` (default `100`) caps how many boxes are returned per frame, not how many prompts you supply. More prompts add text-encoding cost when you set them, not on every frame. ### Can it run completely offline? Yes. Inference is entirely local ONNX — no cloud call at run time. Only the initial model download needs a network, and you can ship the `.onnx` and tokenizer files with your app to avoid even that. ### Why are detections labeled with my prompt text? By design. Unlike a fixed-class detector that emits numeric class ids, each open-vocabulary detection's `Label` is the exact prompt it matched and its `ClassId` is that prompt's zero-based index in the array you supplied — so you always know which query produced each box. ### Can I use my own open-vocabulary ONNX model? Yes, as long as it matches one of the supported layouts (`OWLv2` or `GroundingDINO`) and you point `VocabFilePath`/`MergesFilePath` at the matching tokenizer files and set `Model` accordingly. ## Demos Dedicated demos built on Media Blocks, `VideoCaptureCoreX`, and `MediaPlayerCoreX` (`Open Vocabulary Detection Demo`, `Open Vocabulary Detection MB`, `Capture Open Vocabulary Detection X`, `Capture Open Vocabulary Detection X WPF`, `Player Open Vocabulary Detection X`, `Player Open Vocabulary Detection X WPF`) are in the SDK's demo set and will be linked here once published to the public samples repository. ---END OF PAGE--- ## PII Redaction SDK for .NET — Blur Faces & License Plates **URL:** https://www.visioforge.com/help/docs/dotnet/general/ai/pii-redaction/ **Description:** Redact PII in video on-device with PIIRedactionBlock — blur or pixelate faces, license plates, and on-screen text. GDPR/CCPA/BIPA-friendly, no cloud. **Tags:** .NET, AI, ONNX, PII Redaction, Video Anonymization, Face Blur, License Plate Redaction, GDPR, Privacy, VideoCaptureCoreX, MediaPlayerCoreX **API:** PIIRedactionBlock, PIIRedactionSettings, PIIFaceRedactionSettings, PIIPlateRedactionSettings, PIITextRedactionSettings, PIIRedactionStyle, PIIRegionsRedactedEventArgs, PIIRegion # PII Redaction — Blur Faces, License Plates, and On-Screen Text `PIIRedactionBlock` automatically obscures personally identifiable information in a video stream: it detects **faces** (YuNet), **vehicle license plates** (FastALPR), and **on-screen text** (PaddleOCR), then blurs, pixelates, or fills each region in-place — before the frame reaches a renderer, an encoder, or a file. Every model runs locally on ONNX Runtime, so there is no cloud API call, no per-frame billing, and no video ever leaves the device. The block only *removes* PII — it never identifies a person or outputs a plate's characters, and recognized content is never exported: faces and plates are located by detection alone, while on-screen text runs OCR internally only to confirm (and optionally filter) what to redact. Any of the three categories can be enabled independently, and the redaction style, blur strength, and enabled categories can all be changed while the pipeline is running. ``` graph LR; Source-->PIIRedactionBlock; PIIRedactionBlock-->VideoRendererBlock; PIIRedactionBlock-. OnRegionsRedacted .->App[Your app]; ``` ## Usage The block sits in the middle of a Media Blocks pipeline: it takes video from a source, redacts it, and passes the cleaned frames on to the next block — a renderer, an encoder, or a file sink. The full example below reads a file, blurs all three PII categories, previews the result, and reports what was covered on each frame. ``` using System; using VisioForge.Core.MediaBlocks; using VisioForge.Core.MediaBlocks.AI; using VisioForge.Core.MediaBlocks.Sources; using VisioForge.Core.MediaBlocks.VideoRendering; using VisioForge.Core.Types.X.AI; using VisioForge.Core.Types.X.Sources; // 1. Create the pipeline and a source. A file is used here; a webcam (SystemVideoSourceBlock) or an // IP camera (RTSPSourceBlock) plugs in exactly the same way — only the source block changes. var pipeline = new MediaBlocksPipeline(); var sourceSettings = await UniversalSourceSettings.CreateAsync( "input.mp4", renderVideo: true, renderAudio: false); var source = new UniversalSourceBlock(sourceSettings); // 2. Configure which PII categories to redact and how they are obscured. var settings = new PIIRedactionSettings { Style = PIIRedactionStyle.GaussianBlur, // GaussianBlur (default), Pixelate, or SolidFill BlurRadius = 20f, // blur strength for GaussianBlur }; // Faces — YuNet detector (detection only, no identity recognition). settings.Faces.ModelPath = "face_detection_yunet_2023mar.onnx"; // License plates — FastALPR YOLOv9-T detector (detection only, plate characters are never read). settings.LicensePlates.ModelPath = "yolo-v9-t-640-license-plates-end2end.onnx"; // On-screen text — PaddleOCR PP-OCR (detection + recognition). Needs three files. settings.Text.DetectionModelPath = "ch_PP-OCRv5_mobile_det.onnx"; settings.Text.RecognitionModelPath = "latin_PP-OCRv5_rec_mobile_infer.onnx"; settings.Text.CharacterDictionaryPath = "ppocrv5_latin_dict.txt"; // Turn off any category you don't need — a disabled category needs no model: // settings.Text.Enabled = false; var redaction = new PIIRedactionBlock(settings); // 3. Optional: report what was covered. The event fires on a background detection thread, so marshal to the // UI thread before touching UI. Only the category and box are reported — never the recognized content. redaction.OnRegionsRedacted += (sender, e) => { int faces = 0, plates = 0, text = 0; foreach (var region in e.Regions) { switch (region.Category) { case PIICategory.Face: faces++; break; case PIICategory.LicensePlate: plates++; break; case PIICategory.Text: text++; break; } } Console.WriteLine($"[{e.Timestamp:hh\\:mm\\:ss}] redacted {faces} face(s), {plates} plate(s), {text} text region(s)"); }; // 4. Wire source -> redaction -> renderer and start. VideoView1 is your VideoView control (WPF/WinForms/etc.). var videoRenderer = new VideoRendererBlock(pipeline, VideoView1); pipeline.Connect(source.Output, redaction.Input); pipeline.Connect(redaction.Output, videoRenderer.Input); await pipeline.StartAsync(); // 5. When the ONNX sessions are up, confirm which hardware backend engaged. Console.WriteLine($"PII redaction running on: {redaction.ActiveProvider}"); // ... later, on shutdown: // await pipeline.StopAsync(); // await pipeline.DisposeAsync(); ``` Key points about how the block behaves: - **Redaction always runs**, even with no `OnRegionsRedacted` subscriber — covering the pixels *is* the block's output, so the event is purely for reporting/telemetry. - **At least one category must be enabled with a valid model path**, or `Build` fails and the pipeline does not start. Enable only the categories you need; a disabled category loads no model and costs nothing. - **Each `PIIRegion`** in the event carries only its `Category` (`Face`, `LicensePlate`, or `Text`), the padded `BoundingBox` in source-frame pixels, and the detection `Score` (0..1) — never the recognized content. - **Detection runs on a background worker**, not the streaming thread, so live video never stalls; every frame is redacted with the most recent regions while the detector catches up (see [Privacy and compliance](#privacy-and-compliance) for the live-latency implication). - **To redact straight to a file** instead of previewing, replace `VideoRendererBlock` with an encoder + sink (for example an `MP4OutputBlock`); the source → redaction → sink wiring is identical. ## Redaction categories and models | Category | Detector | Model (license) | Notes | | --- | --- | --- | --- | | `Faces` | YuNet | `face_detection_yunet_2023mar.onnx` (MIT) | Detection only — no face is identified or matched. | | `LicensePlates` | FastALPR YOLOv9-T | `yolo-v9-t-640-license-plates-end2end.onnx` (MIT) | Detection only — the plate characters are never read. | | `Text` | PaddleOCR PP-OCR | detection + recognition + dictionary (Apache-2.0) | Recognition runs only to filter the detector's false positives; by default every recognized text region is redacted. | The SDK does not ship model weights in the NuGet package — see [Getting the models](#getting-the-models). Text redaction needs three files (detection model, recognition model, and character dictionary) whenever the category is enabled. Recognition is required because a text *detector* alone fires on textures and edges, so detection without recognition would redact most of a real scene; recognition confirms which boxes are actually text. An optional `ClassificationModelPath` corrects 180°-rotated text. ## Redaction styles `PIIRedactionSettings.Style` selects how each detected region is obscured: | `PIIRedactionStyle` | Effect | Related setting | | --- | --- | --- | | `GaussianBlur` (default) | Region is replaced with a Gaussian-blurred copy of itself. | `BlurRadius` (sigma, default 20). | | `Pixelate` | Region is replaced with a coarse mosaic. | `PixelateBlockSize` (cell size in px, default 16). | | `SolidFill` | Region is painted over with a solid color. | `FillColor` (default black). | `Style`, `BlurRadius`, `PixelateBlockSize`, and `FillColor` can all be changed while the pipeline runs. ## Key settings `PIIRedactionSettings`: | Property | Default | Description | | --- | --- | --- | | `Faces` / `LicensePlates` / `Text` | enabled | The three per-category sub-settings objects (see below). | | `Style` | `GaussianBlur` | Redaction style applied to every region. | | `BlurRadius` | `20` | Gaussian blur sigma for `GaussianBlur`. | | `PixelateBlockSize` | `16` | Mosaic cell size, in pixels, for `Pixelate`. | | `FillColor` | Black | Fill color for `SolidFill`. | | `RegionPaddingPercent` | `0.15` | Expands each detected box per side (0.15 = 15%) to cover motion between detection cycles. | | `RegionHoldTimeMs` | `700` | Keeps a region covered this long after the detector stops reporting it, so detector flicker never flashes PII through. | | `FramesToSkip` | `0` | Frames to skip between detections on live video (`0` submits every frame). Detection always runs on a background worker. | | `Provider` / `DeviceId` | `Auto` / `0` | ONNX execution provider and hardware device index. | Each category exposes its own detector tuning. Faces (`PIIFaceRedactionSettings`): | Property | Default | | --- | --- | | `Enabled` | `true` | | `ModelPath` | — | | `DetectionInputSize` | `320` | | `ConfidenceThreshold` | `0.5` | | `NmsThreshold` | `0.3` | | `MaxFaces` | `50` | License plates (`PIIPlateRedactionSettings`): | Property | Default | | --- | --- | | `Enabled` | `true` | | `ModelPath` | — | | `DetectionInputSize` | `640` | | `ConfidenceThreshold` | `0.3` | | `MaxDetections` | `20` | `Text` (`PIITextRedactionSettings`): `Enabled` (`true`), `DetectionModelPath`, `RecognitionModelPath`, `CharacterDictionaryPath`, optional `ClassificationModelPath`, `TextFilterRegex` (see below), `MaxSideLength` (`1024`), `BoxThreshold` (`0.3`), `BoxScoreThreshold` (`0.5`), `UnclipRatio` (`1.6`). The block also exposes read-only diagnostics after it is built: `ActiveProvider` (the execution provider that actually engaged), `LastInferenceTimeMs` (wall-clock of the most recent detection cycle), and `DroppedFrameCount` (frames that arrived while the detector was busy — still redacted, just not re-detected). ## Redact only specific text By default every recognized text region is redacted. Set `Text.TextFilterRegex` to redact only the regions whose recognized text matches a pattern — for example, blur e-mail addresses and phone numbers while leaving signage and captions visible: ``` settings.Text.TextFilterRegex = @"(\b[\w.%+-]+@[\w.-]+\.[A-Za-z]{2,}\b)|(\+?\d[\d\s().-]{7,}\d)"; ``` Recognition still runs regardless (it is what filters non-text detections); the regex only narrows which recognized regions are covered. ## Getting the models The SDK does not bundle model weights. Supply your own `.onnx` files, or reuse the ones the demos download on first run from the samples release into `%UserProfile%/VisioForge/models`: | File | Category | License | | --- | --- | --- | | `face_detection_yunet_2023mar.onnx` | Faces | MIT | | `yolo-v9-t-640-license-plates-end2end.onnx` | License plates | MIT | | `ch_PP-OCRv5_mobile_det.onnx` | Text (detection) | Apache-2.0 | | `latin_PP-OCRv5_rec_mobile_infer.onnx` | Text (recognition) | Apache-2.0 | | `ppocrv5_latin_dict.txt` | Text (dictionary) | Apache-2.0 | These are downloaded from the `onnx-models-v1` release on the [samples repository](https://github.com/visioforge/.Net-SDK-s-samples/releases/tag/onnx-models-v1). To read the provider that ONNX Runtime actually selected, check `redaction.ActiveProvider` after the pipeline starts. ## Use with VideoCaptureCoreX and MediaPlayerCoreX `PIIRedactionBlock` is a video processing block, so it plugs directly into the capture and playback engines — no manual `MediaBlocksPipeline` required. Add it before you start: ``` var redaction = new PIIRedactionBlock(settings); redaction.OnRegionsRedacted += Redaction_OnRegionsRedacted; core.Video_Processing_AddBlock(redaction); // VideoCaptureCoreX — before StartAsync // player.Video_Processing_AddBlock(redaction); // MediaPlayerCoreX — before OpenAsync/PlayAsync await core.StartAsync(); ``` With VideoCaptureCoreX this anonymizes a webcam, IP camera, or capture-card feed as it is previewed, recorded, or streamed. See [Using AI blocks with VideoCaptureCoreX and MediaPlayerCoreX](../x-engines/) for the shared processing-block API, insertion order, and lifecycle rules. ## Privacy and compliance Because every detector runs locally on ONNX Runtime, video and audio frames never leave the device, which simplifies GDPR / CCPA / BIPA reviews for camera applications. Redaction is destructive — pixels in each region are overwritten in the frame, so there is no reversible mapping to recover the original. The `OnRegionsRedacted` event carries only categories and boxes; the recognized content of a region (a plate number, a text string) is intentionally never included. One caveat matters for live pipelines: detection runs on a background worker to keep the stream flowing, so **frames that arrive before the first detection cycle completes pass through unredacted**, and if the source resolution jumps mid-stream (for example adaptive HLS/RTSP), a newly exposed area can briefly leak until the next detection cycle. For **zero-leak** anonymization, process the file offline at reduced speed rather than live, so every frame is detected before it is written. ## Use cases - **Dashcam / bodycam footage** — blur bystander faces and plates before publishing or sharing an incident clip. - **CCTV and surveillance exports** — anonymize recorded video before handing it to a third party. - **Video conferencing and screen sharing** — pixelate on-screen text (documents, badges) in a shared feed. - **FOIA / court / insurance disclosure** — redact identities in released video to satisfy privacy rules. - **User-generated content** — automatically obscure faces and plates in uploaded videos. - **Street-level mapping and analytics** — anonymize faces and plates in captured drive footage. ## Troubleshooting | Symptom | Likely cause | Fix | | --- | --- | --- | | First frames show PII before redaction kicks in | Detection is asynchronous; frames before the first cycle pass through | Expected on live sources. For zero-leak, process files offline at reduced speed. | | Too much of the frame is blurred (text) | Detector false positives, or every text region is being redacted | Raise `Text.BoxScoreThreshold`; set `Text.TextFilterRegex` to redact only the patterns you care about. | | A face or plate is missed | `ConfidenceThreshold` too high, or the object is too small for `DetectionInputSize` | Lower the category's `ConfidenceThreshold`; raise `DetectionInputSize` for small/distant objects. | | A region flickers in and out | Detection cadence too sparse or hold time too short | Lower `FramesToSkip`; raise `RegionHoldTimeMs`; raise `RegionPaddingPercent` for fast motion. | | Runs on CPU when a GPU is present | Requested provider unavailable in the loaded ONNX Runtime build | Check `redaction.ActiveProvider`; install the matching ONNX Runtime GPU package; set `Provider`/`DeviceId`. | | Live video stutters | Detection too slow for the frame rate on this hardware | Raise `FramesToSkip`; watch `LastInferenceTimeMs` and `DroppedFrameCount` while tuning. | ## Frequently Asked Questions ### Does PIIRedactionBlock identify people or read license plates? No. The block never runs face recognition and never outputs a license plate's characters — faces and plates are located by detection alone. On-screen text is recognized internally only to decide what to redact (and to apply `TextFilterRegex`), and that recognized text is never emitted: the `OnRegionsRedacted` event carries only categories and boxes. ### Is this GDPR / CCPA / BIPA compliant? Inference runs entirely on-device, so frames never leave the machine — which is the hard part for camera and microphone privacy reviews. For guaranteed zero-leak output, process files offline at reduced speed so every frame is detected before it is written; on live streams the first frames before the first detection cycle can pass through unredacted. Compliance also depends on your overall data handling — review the applicable regulations for your jurisdiction. ### Which models do I need, and where do I get them? Faces need one YuNet model; license plates need one FastALPR model; on-screen text needs a PaddleOCR detection model, a recognition model, and a character dictionary. Weights are not shipped in the NuGet package — see [Getting the models](#getting-the-models). ### Can I redact only e-mail addresses and phone numbers, not all text? Yes. Set `Text.TextFilterRegex` to a pattern; only regions whose recognized text matches are redacted, and all other on-screen text stays visible. ### Can I turn a category on or off while the video is running? You can toggle a category off (and back on) live **if it was enabled when the block was built** — the detector for a category is created only when that category is enabled at build time. To add a category that was disabled at start, rebuild the block. Style, blur radius, and fill color are all live-adjustable. ### Can I run redaction on the GPU? Yes. Set `Provider` to `CUDA`, `DirectML`, or `CoreML` (or leave it `Auto`), with `DeviceId` for the GPU index. If the requested provider is unavailable, ONNX Runtime falls back to CPU; check `ActiveProvider` to confirm what engaged. ### Is the redaction reversible? No. Redaction overwrites the pixels in each region directly in the frame, so the original content cannot be recovered from the output. ## Demos - **[PII Redaction Demo](https://github.com/visioforge/.Net-SDK-s-samples/tree/master/Media%20Blocks%20SDK/WPF/CSharp/PII%20Redaction%20Demo)** — WPF Media Blocks pipeline demo (webcam, file, or RTSP source). - **[Player PII Redaction X](https://github.com/visioforge/.Net-SDK-s-samples/tree/master/Media%20Player%20SDK%20X/WPF/Player%20PII%20Redaction%20X%20WPF)** — MediaPlayerCoreX redaction on file playback (WPF). - **[Capture PII Redaction X](https://github.com/visioforge/.Net-SDK-s-samples/tree/master/Video%20Capture%20SDK%20X/WPF/CSharp/Capture%20PII%20Redaction%20X%20WPF)** — VideoCaptureCoreX redaction on a live camera (WPF). ---END OF PAGE--- ## PTZ Auto-Tracking SDK for .NET — ONVIF Camera Control **URL:** https://www.visioforge.com/help/docs/dotnet/general/ai/ptz-auto-tracking/ **Description:** PTZ auto-tracking for .NET: make an ONVIF PTZ camera follow a detected object with proportional pan/tilt/zoom, a dead zone, and sticky tracking. **Tags:** .NET, AI, ONVIF, PTZ, Auto-Tracking, Object Tracking, ObjectAnalyticsBlock, VideoCaptureCoreX, MediaBlocksPipeline **API:** PTZAutoTrackingController, PTZAutoTrackingSettings, PTZTargetSelection, IPTZMoveTransport, OnvifPTZMoveTransport, PTZMoveCommandEventArgs # PTZ Auto-Tracking — Follow a Detected Object with an ONVIF Camera `PTZAutoTrackingController` turns object detections into continuous PTZ velocity commands, so an ONVIF PTZ camera automatically follows a tracked object. It plugs into the detections raised by [`ObjectAnalyticsBlock`](../object-analytics/) (multi-object tracking, stable tracker IDs) or the [`YOLOObjectDetectorBlock`](../object-detection/), and drives the camera over ONVIF through `OnvifPTZMoveTransport`. The control law is a simple proportional (P) controller: the error is the target box center relative to the frame center; inside a configurable dead zone the camera holds, and outside it the camera pans/tilts (and optionally zooms) at a speed proportional to how far off-center the target is. ``` graph LR; Camera[ONVIF camera]-->Source[RTSP source]; Source-->ObjectAnalyticsBlock; ObjectAnalyticsBlock-. OnAnalyticsUpdated .->Controller[PTZAutoTrackingController]; Controller-. ContinuousMove/Stop .->Transport[OnvifPTZMoveTransport]; Transport-->Camera; ``` ## Requirements - An **ONVIF PTZ camera** (the device must advertise the PTZ service — verify with `OnvifPTZMoveTransport.IsPTZSupportedAsync(onvif)`, which falls back to a media-profile `PTZConfiguration` probe when the camera's ONVIF service cache is empty). A fixed camera cannot be driven. - An ONNX object-detection model (YOLOv8 / YOLOX / RT-DETR) for the detector. ## Usage ``` using System.Drawing; using VisioForge.Core; using VisioForge.Core.AI.PTZ; using VisioForge.Core.MediaBlocks.AI; using VisioForge.Core.ONVIFX; using VisioForge.Core.Types.X.AI; // 0. Initialize the SDK once, before creating any engine object. await VisioForgeX.InitSDKAsync(); // 1. Connect to the ONVIF camera and build the PTZ transport. var onvif = new ONVIFClientX(); if (!await onvif.ConnectAsync("http://192.168.1.22/onvif/device_service", "admin", "password")) { // Connection failed — check the address/credentials before proceeding. return; } if (!await OnvifPTZMoveTransport.IsPTZSupportedAsync(onvif)) { // The camera has no PTZ service — auto-tracking is not possible. return; } var transport = await OnvifPTZMoveTransport.CreateAsync(onvif); // resolves a PTZ-capable media profile if (transport == null) { // No usable media profile on the device — auto-tracking is not possible. return; } // 2. Configure the detector + analytics (ObjectAnalyticsBlock gives stable tracker IDs). var detector = new YoloDetectorSettings("yolox_nano.onnx") { Model = ObjectDetectorModel.YOLOX, ConfidenceThreshold = 0.4f, }; var analyticsBlock = new ObjectAnalyticsBlock(new ObjectAnalyticsSettings(detector)); // 3. Create the controller and attach it to the analytics block. // The frame size is the source (camera) resolution the detection boxes are expressed in. var settings = new PTZAutoTrackingSettings { TargetSelection = PTZTargetSelection.ByClassLabel, ClassLabelFilter = "person", MaxSpeed = 0.5f, Gain = 1.2f, DeadZone = 0.1f, }; var controller = new PTZAutoTrackingController(settings, transport); controller.OnTargetAcquired += (s, det) => Console.WriteLine($"Following {det.Label} #{det.TrackerId}"); controller.OnTargetLost += (s, e) => Console.WriteLine("Target lost."); controller.OnMoveCommand += (s, cmd) => Console.WriteLine(cmd.IsStop ? "PTZ: stop" : $"PTZ: pan={cmd.Pan} tilt={cmd.Tilt} zoom={cmd.Zoom}"); controller.AttachTo(analyticsBlock, new Size(1920, 1080)); controller.Start(); // 4. The analytics block only takes effect once it is added to your capture engine. Insert it into your // configured VideoCaptureCoreX (a MediaBlocksPipeline works the same way) and start streaming. core.Video_Processing_AddBlock(analyticsBlock); await core.StartAsync(); // On shutdown: stop the controller (halts the camera), then dispose. await controller.StopAsync(); controller.Dispose(); ``` `AttachTo` also has an overload for `YOLOObjectDetectorBlock`. Because a plain detector carries no tracker IDs, sticky tracking is only available with `ObjectAnalyticsBlock`; with a plain detector the controller reacquires a target every frame per the selection policy. ### Using it in a Media Blocks pipeline The controller is engine-agnostic: `AttachTo` subscribes to the analytics block's detection event, which fires the same way whether the block runs inside `VideoCaptureCoreX` or a hand-built `MediaBlocksPipeline`. To wire it into a pipeline, connect the analytics block between your source and renderer and attach the controller to it exactly as above: ``` using System.Drawing; using VisioForge.Core.AI.PTZ; using VisioForge.Core.MediaBlocks; using VisioForge.Core.MediaBlocks.AI; using VisioForge.Core.MediaBlocks.Sources; using VisioForge.Core.MediaBlocks.VideoRendering; using VisioForge.Core.Types.X.AI; using VisioForge.Core.Types.X.Sources; var pipeline = new MediaBlocksPipeline(); var source = new RTSPSourceBlock( await RTSPSourceSettings.CreateAsync(new Uri("rtsp://192.168.1.22/..."), "admin", "password", audioEnabled: false)); // Detector + analytics block (same configuration as the Usage example above). var analyticsBlock = new ObjectAnalyticsBlock( new ObjectAnalyticsSettings(new YoloDetectorSettings("yolox_nano.onnx"))); var renderer = new VideoRendererBlock(pipeline, VideoView1) { IsSync = false }; // VideoView1 = your WPF VideoView // source -> analytics (detection + tracking) -> renderer pipeline.Connect(source.VideoOutput, analyticsBlock.Input); pipeline.Connect(analyticsBlock.Output, renderer.Input); // The controller attaches to the same analytics block and drives the camera as a side-car. // (transport is the OnvifPTZMoveTransport built in the Usage example above.) var controller = new PTZAutoTrackingController(new PTZAutoTrackingSettings(), transport); controller.AttachTo(analyticsBlock, new Size(1920, 1080)); controller.Start(); await pipeline.StartAsync(); ``` ## How the control law works For each processed frame the controller: 1. **Selects a target** per `TargetSelection` (see below). Once a target with a valid tracker ID is locked, it stays sticky on that ID and ignores other objects. 2. **Computes the error**: the target box center minus the frame center, normalized to `[-1, 1]` on each axis. 3. **Applies the dead zone**: if an axis error is within `DeadZone`, that axis is not driven. 4. **Computes the speed**: `clamp(Gain * error, -MaxSpeed, MaxSpeed)` per axis. Positive pan is right, positive tilt is up. 5. **Drives zoom** (when `ZoomEnabled`): zooms in when the target box height is below `TargetBoxHeightRatio` and out when it is above. 6. **Rate limits**: at most one move command per `CommandInterval`; a single stop is emitted (no spam) when the camera enters the dead zone or the target disappears. If the target is absent, the camera is stopped immediately. If it stays absent for longer than `LostTargetTimeout`, `OnTargetLost` fires, the camera optionally returns to `HomePresetToken`, and the next matching detection reacquires a target. Camera commands are actuated on a dedicated background worker, so the detection thread is never blocked by network I/O. ## Target selection modes | `PTZTargetSelection` | Behavior | | --- | --- | | `Largest` | Follow the object with the largest bounding-box area (default). | | `FirstDetected` | Follow the first object in the detection array. | | `ByTrackerId` | Follow only the object whose tracker ID equals `ManualTrackerId`. | | `ByClassLabel` | Follow the largest object whose label matches `ClassLabelFilter` (case-insensitive). | ## Settings | Property | Default | Description | | --- | --- | --- | | `TargetSelection` | `Largest` | Strategy used to pick a target when none is locked. | | `ClassLabelFilter` | `null` | Label to follow for `ByClassLabel` (e.g. `"person"`). | | `ManualTrackerId` | `-1` | Tracker ID to follow for `ByTrackerId`. | | `DeadZone` | `0.1` | Centered dead-zone half-width, as a fraction of the frame half-size (0..1). | | `MaxSpeed` | `0.5` | Maximum absolute speed on any axis (0..1). | | `Gain` | `1.2` | Proportional gain applied to the normalized error. | | `ZoomEnabled` | `false` | Drive zoom to keep the target height near `TargetBoxHeightRatio`. | | `TargetBoxHeightRatio` | `0.5` | Desired target box height as a fraction of the frame height (0..1). | | `ZoomDeadZone` | `0.05` | Zoom dead zone on the height-ratio difference (0..1). | | `LostTargetTimeout` | `2 s` | How long the target may be absent before it is declared lost. | | `HomePresetToken` | `null` | Optional ONVIF preset to return to when the target is lost. | | `CommandInterval` | `200 ms` | Minimum interval between move commands (stops are not rate limited). | | `PatrolPresetTokens` | `null` | Ordered ONVIF preset tokens to cycle as an idle patrol. Patrol is enabled only when this is non-empty. | | `PatrolStartDelay` | `30 s` | How long to wait after the target is lost, with none reappearing, before starting the patrol. | | `PatrolDwellTime` | `10 s` | How long to dwell at each patrol preset before advancing to the next. | ## Idle patrol When the camera would otherwise sit idle, it can automatically cycle through a set of ONVIF presets until a new target appears. Set `PatrolPresetTokens` to the ordered preset tokens you want to visit (patrol is enabled only when this array is non-empty): ``` var settings = new PTZAutoTrackingSettings { TargetSelection = PTZTargetSelection.ByClassLabel, ClassLabelFilter = "person", HomePresetToken = "1", // return home first when the target is lost PatrolPresetTokens = new[] { "1", "2", "3" }, // then patrol these presets in order PatrolStartDelay = TimeSpan.FromSeconds(30), // ... after 30 s with no new target PatrolDwellTime = TimeSpan.FromSeconds(10), // dwell 10 s at each preset }; controller.OnPatrolPreset += (s, token) => Console.WriteLine($"Patrol: preset {token}"); ``` Sequence of events once the target disappears: 1. The camera stops immediately, and after `LostTargetTimeout` the target is declared lost (`OnTargetLost`) and — if `HomePresetToken` is set — the camera returns home. 2. If no new target reappears for `PatrolStartDelay`, the patrol begins: the camera recalls each token in `PatrolPresetTokens` in order, dwelling `PatrolDwellTime` at each, wrapping around the list. 3. The moment a new target is acquired, the patrol is aborted immediately and normal tracking resumes. The next patrol restarts from the first preset. Patrol timing is measured against the frame timestamps supplied to the controller, so it stays in step with the video clock. Get the preset tokens for your device with `ONVIFClientX.GetPresetsAsync`. ## Events - `OnTargetAcquired(OnnxDetection)` — a new target was locked. - `OnTargetLost()` — the current target was absent longer than `LostTargetTimeout`. - `OnMoveCommand(PTZMoveCommandEventArgs)` — every command sent to the camera (`Pan`, `Tilt`, `Zoom`, `IsStop`); useful for a status bar or diagnostics. - `OnPatrolPreset(string)` — the idle patrol moved to the given preset token. ## Custom transport `OnvifPTZMoveTransport` is the built-in ONVIF implementation. To drive a non-ONVIF PTZ device, implement `IPTZMoveTransport` (`ContinuousMoveAsync`, `StopAsync`, `GoToPresetAsync`) and pass your implementation to the controller. ## Demo Complete WPF samples are available in the SDK samples: - **[PTZ Auto Tracking (Video Capture SDK X)](https://github.com/visioforge/.Net-SDK-s-samples/tree/master/Video%20Capture%20SDK%20X/WPF/CSharp/PTZ%20Auto%20Tracking)** — auto-tracking with the `VideoCaptureCoreX` engine. - **[PTZ Auto Tracking (Media Blocks SDK)](https://github.com/visioforge/.Net-SDK-s-samples/tree/master/Media%20Blocks%20SDK/WPF/CSharp/PTZ%20Auto%20Tracking%20MB)** — the same feature built on a low-level `MediaBlocksPipeline`. ---END OF PAGE--- ## Search Video by Text — Semantic Video Search for .NET **URL:** https://www.visioforge.com/help/docs/dotnet/general/ai/semantic-video-search/ **Description:** Find any moment in recorded video by describing it in plain text. On-device semantic video search for .NET with CLIP embeddings — no tags, no cloud. **Tags:** .NET, AI, ONNX, CLIP, Semantic Search, Video Search, Embeddings, Vector Search, MediaPlayerCoreX, Media Blocks **API:** VideoEmbeddingBlock, VideoEmbeddingSettings, FrameEmbeddingIndex, ClipEmbeddingEngine, FrameEmbeddingSearchResult # Semantic Video Search — VideoEmbeddingBlock You have hours of recorded video and need to jump to one moment — *"someone entering the lobby"*, *"a red truck at the gate"* — without scrubbing through the footage or tagging it first. **Semantic video search** solves this: index the video once, then find matching moments by describing them in plain text. It runs on-device with OpenAI's CLIP model — no manual metadata, no cloud service, no per-object detector to train. `VideoEmbeddingBlock` turns video frames into **CLIP embeddings** so you can search a video by meaning: index a file once, then find the moments that match a natural-language query like `"a person riding a bicycle"` — no fixed labels, no per-object detector. It samples frames at a configurable interval, encodes each with the CLIP vision tower, raises `OnFrameEmbedding`, and (when an index is attached) stores each embedding with its timestamp. Search embeds the query text with the same CLIP text tower and ranks frames by similarity. This feature has two halves: - **Indexing** — run `VideoEmbeddingBlock` over a file (or live source) to fill a `FrameEmbeddingIndex` with one embedding per sampled frame. - **Search** — embed a text query (`ClipEmbeddingEngine.EncodeText` or `VideoEmbeddingBlock.EncodeText`) and call `FrameEmbeddingIndex.Search` to get the best-matching timestamps. ``` graph LR; Source-->VideoEmbeddingBlock; VideoEmbeddingBlock-->NullRendererBlock; VideoEmbeddingBlock-. OnFrameEmbedding .->Index[(FrameEmbeddingIndex)]; Query["Text query"]-. EncodeText .->Search{{Search}}; Index-->Search; Search-->Results["Ranked timestamps"]; ``` Because indexing only needs the embeddings, the video is decoded at full speed to a non-synced sink (no real-time playback) — see [Fast offline indexing](#fast-offline-indexing-on-mediaplayercorex). ## How semantic video search works Semantic search matches by **meaning**, not keywords or metadata — so "someone riding a bike" finds cyclists in footage that was never tagged. It works because CLIP has two encoders that map images and text into one shared vector space: 1. **Index the frames.** The CLIP vision tower encodes each sampled frame into an embedding (a fixed-length vector, ~512 numbers) stored with its timestamp in a `FrameEmbeddingIndex`. 2. **Embed the query.** The CLIP text tower encodes your query string into an embedding in the *same* space, so images and text are directly comparable. 3. **Rank by similarity.** Cosine similarity scores every indexed frame against the query; the highest scores are the best-matching moments. 4. **Sharpen with a contrastive margin.** Generic frames score moderately against almost any query, so the demos subtract each frame's best generic-baseline score — see [Contrastive margin](#contrastive-margin-recommended-ranking). ### Key concepts | Term | Meaning | | --- | --- | | **Embedding** | A fixed-length vector that captures the meaning of a frame or a phrase. | | **Shared embedding space** | CLIP maps images and text into the same space, so a text vector can be compared to an image vector directly. | | **Cosine similarity** | An angle-based similarity between two vectors; higher means closer in meaning. | | **Contrastive margin** | The query score minus the best generic-baseline score for a frame — removes a scene-independent bias in raw cosine and makes true matches stand out. | ## Build a video search feature Turning the two halves into a working "search my footage" feature is four steps — each maps to a section below, so this is the recipe, not new code: 1. **Get the CLIP model** — the vision tower, text tower, and tokenizer files. See [Model](#model). 2. **Index the video** into a `FrameEmbeddingIndex`, decoding at full speed so a long file indexes in a fraction of its runtime. See [Indexing](#indexing) and [Fast offline indexing on MediaPlayerCoreX](#fast-offline-indexing-on-mediaplayercorex). 3. **Persist the index** to a `.vfei` file so you index once and search across sessions. See [Persisting the index](#persisting-the-index). 4. **Search by text** — embed the user's query and rank the index, ideally with the [contrastive margin](#contrastive-margin-recommended-ranking). See [Search](#search). Use each hit's `Timestamp` to seek the player or render a thumbnail. A typical application indexes new videos in the background as they arrive, keeps one `.vfei` per video (or a shared index tagged by `SourceTag`), and runs search interactively against the loaded index. ## Indexing Attach a `FrameEmbeddingIndex` to the settings and the block adds every sampled frame to it automatically. `SourceTag` records which file the frame came from (used later for thumbnails and result grouping). ``` using VisioForge.Core.MediaBlocks; using VisioForge.Core.MediaBlocks.AI; using VisioForge.Core.MediaBlocks.Sources; using VisioForge.Core.MediaBlocks.Special; using VisioForge.Core.Types.Events; using VisioForge.Core.Types.X; using VisioForge.Core.Types.X.AI; var index = new FrameEmbeddingIndex(); var settings = new VideoEmbeddingSettings( "clip-vitb32-vision.onnx", "clip-vitb32-text.onnx", "clip-vocab.json", "clip-merges.txt") { Index = index, SourceTag = filePath, SampleInterval = TimeSpan.FromSeconds(1), // one embedding per second of video BackpressureNoDrop = true, // capture every sampled frame (offline file indexing) Provider = OnnxExecutionProvider.Auto, }; var embedding = new VideoEmbeddingBlock(settings); var indexSource = new UniversalSourceBlock( await UniversalSourceSettings.CreateAsync(filePath, renderVideo: true, renderAudio: false)); var nullRenderer = new NullRendererBlock(MediaBlockPadMediaType.Video) { IsSync = false }; pipeline.Connect(indexSource.Output, embedding.Input); pipeline.Connect(embedding.Output, nullRenderer.Input); pipeline.OnStop += (s, e) => Console.WriteLine($"Indexed {index.Count} frames."); await pipeline.StartAsync(); ``` `OnFrameEmbedding` raises a `FrameEmbeddingEventArgs { Timestamp, Embedding }` per sampled frame (the `Embedding` is L2-normalized). You usually don't need the event when an `Index` is attached — it is useful for a live progress counter or to store embeddings yourself. Live sources drop instead of backpressuring Set `BackpressureNoDrop = true` only for offline file indexing, where blocking the decoder to capture every interval is the goal. For a **live camera**, leave it `false` — a camera cannot be backpressured without stalling capture, so a sampled frame is dropped when the encoder is busy. ## Search Embed the query text in the same space and rank the index by cosine similarity: ``` using VisioForge.Core.AI.Clip; using var engine = new ClipEmbeddingEngine(settings); engine.Init(); float[] queryVector = engine.EncodeText("a person riding a bicycle"); FrameEmbeddingSearchResult[] hits = index.Search(queryVector, topK: 10); foreach (var hit in hits) Console.WriteLine($"{hit.Timestamp:hh\\:mm\\:ss} score {hit.Score:F3} ({hit.SourceTag})"); ``` Each `FrameEmbeddingSearchResult` has `Timestamp`, `SourceTag`, and `Score` (cosine similarity, roughly −1..1, higher is more similar). You can also call `VideoEmbeddingBlock.EncodeText` on a built block to embed a query with the same session — but a standalone `ClipEmbeddingEngine` lets you search after the indexing pipeline has stopped and been disposed. ### Contrastive margin (recommended ranking) Raw cosine similarity has a scene-independent bias: generic frames score moderately against almost any query. The demos rank by a **contrastive margin** instead — the query score minus the best score from a set of generic baseline prompts — which sharply separates true matches from background frames: ``` static readonly string[] BaselinePrompts = { "a photo", "a picture", "an image", "a screenshot", "a random background", }; float[] queryVec = engine.EncodeText(query); var queryHits = index.Search(queryVec, index.Count); // Best baseline cosine per frame. var baseline = new Dictionary<(string, TimeSpan), float>(); foreach (var neg in BaselinePrompts) foreach (var h in index.Search(engine.EncodeText(neg), index.Count)) { var key = (h.SourceTag, h.Timestamp); if (!baseline.TryGetValue(key, out var cur) || h.Score > cur) baseline[key] = h.Score; } var ranked = queryHits .Select(h => { baseline.TryGetValue((h.SourceTag, h.Timestamp), out var nb); return (hit: h, margin: h.Score - nb); }) .Where(r => r.margin >= minMargin) // minMargin is a UI threshold .OrderByDescending(r => r.margin) .Take(24); ``` ### Persisting the index `FrameEmbeddingIndex` saves and loads to a compact binary `.vfei` file, so you index once and search across sessions: ``` index.Save("frames.vfei"); // later, or in another process: var loaded = new FrameEmbeddingIndex(); loaded.Load("frames.vfei"); index.Clear(); // empty the index and reset its dimension ``` ## Key settings `VideoEmbeddingSettings` is a standalone settings class. | Property | Default | Description | | --- | --- | --- | | `ImageEncoderPath` | `null` | CLIP vision-tower ONNX (with projection head). Required for indexing. | | `TextEncoderPath` | `null` | CLIP text-tower ONNX (with projection head). Required for `EncodeText`. | | `VocabFilePath` / `MergesFilePath` | `null` | CLIP tokenizer files. Required for `EncodeText`. | | `SampleInterval` | `1 second` | Minimum time between two encoded frames. | | `Index` | `null` | The `FrameEmbeddingIndex` each sampled embedding is auto-added to. When `null`, frames are only raised via `OnFrameEmbedding`. | | `SourceTag` | `null` | Source identifier stored with every indexed frame (file name or camera id). | | `BackpressureNoDrop` | `false` | `true` blocks the decoder to capture every interval (offline file indexing); `false` drops when the encoder is busy (live sources). | | `Provider` / `DeviceId` | `Auto` / `0` | ONNX execution provider and hardware device index. | `VideoEmbeddingBlock.ActiveProvider` reports the engaged provider, `Dimension` the CLIP embedding size (typically 512), and `LastInferenceTimeMs` the per-frame encode cost. ## Index size and choosing SampleInterval `SampleInterval` decides how many frames you embed, which drives both index size and indexing time. Each stored frame is roughly the embedding vector (~512 floats × 4 bytes ≈ 2 KB) plus its timestamp and source tag — so the math is predictable: | Content | `SampleInterval` | Frames per hour | Approx. index size / hour | | --- | --- | --- | --- | | Static or slow footage | 2 s | 1,800 | ~3.5 MB | | General footage (default) | 1 s | 3,600 | ~7 MB | | Fast cuts / brief moments | 0.5 s | 7,200 | ~14 MB | Pick the interval by how short the moments you need to find are: 1 second catches most scenes; use 0.5 second or finer for rapid cuts, and a coarser interval for long, static recordings to keep the index small and indexing fast. The index is in-memory during a session and persisted to a compact `.vfei` file with `Save`, so size mostly matters for very long libraries. ## Model Indexing and search use the OpenAI **CLIP ViT-B/32** dual-tower model — a vision tower and a text tower that map images and text into the same embedding space. Both include the projection head, so their outputs share the same dimension and can be compared directly by cosine similarity. Model weights are not bundled with the SDK; the demos download them on first run and cache them under `%USERPROFILE%\VisioForge\models\clip`: | Role | File | | --- | --- | | Vision tower | `clip-vitb32-vision.onnx` | | Text tower | `clip-vitb32-text.onnx` | | Tokenizer | `clip-vocab.json`, `clip-merges.txt` | A model's license is set by its origin, independent of the SDK's own license — confirm the license of the weights you deploy. ## Fast offline indexing on MediaPlayerCoreX To index a file with `MediaPlayerCoreX`, register the block and turn off video-renderer clock sync so the file decodes **at full speed instead of real time**. Combined with `BackpressureNoDrop = true`, every sampled interval is captured with no dropped frames: ``` player.Video_Renderer_IsSync = false; // decode at full speed, not real time — set BEFORE OpenAsync player.Video_Play = true; player.Audio_Play = false; var source = await UniversalSourceSettings.CreateAsync(filePath, renderVideo: true, renderAudio: false); var settings = new VideoEmbeddingSettings(visionPath, textPath, vocabPath, mergesPath) { Index = index, SourceTag = filePath, SampleInterval = TimeSpan.FromSeconds(1), BackpressureNoDrop = true, }; var embedding = new VideoEmbeddingBlock(settings); embedding.OnFrameEmbedding += (s, e) => UpdateProgress(index.Count); player.Video_Processing_AddBlock(embedding); // before OpenAsync / PlayAsync player.OnStop += (s, e) => FinalizeIndexing(); // end-of-file finalizes the index await player.OpenAsync(source); await player.PlayAsync(); ``` `Video_Renderer_IsSync` is a nullable override on `MediaPlayerCoreX`: `null` (default) syncs to the clock for normal playback, `false` decodes as fast as possible for offline analysis, `true` forces real-time. When the file reaches EOS, `OnStop` fires; the engine has already torn down and disposed the inserted block by then, so finalize the index there. Search keeps working after the pipeline stops because it runs on a standalone `ClipEmbeddingEngine`, not the disposed block. Indexing is Media Player / Media Blocks only Semantic video search indexes a **file** (or Media Blocks source). There is no `VideoCaptureCoreX` capture variant — index recorded footage with `MediaPlayerCoreX` or a manual Media Blocks pipeline. (A live camera can still be embedded with `BackpressureNoDrop = false`, but the feature is designed around searching stored video.) See [Using AI blocks with VideoCaptureCoreX and MediaPlayerCoreX](../x-engines/) for the shared processing-block API and lifecycle rules. ## Semantic search vs manual tagging and keyword search Teams usually reach for one of three ways to make video findable. Semantic search wins when the moments you need aren't known in advance and the footage isn't already labeled. | Approach | How you find a moment | Breaks down when | | --- | --- | --- | | **Manual tagging / metadata** | Someone labels clips or timestamps up front; you search the labels. | Nobody tagged what you're now looking for, or the library is too large to tag by hand. | | **Keyword search** (file names, subtitles, ASR transcripts) | Match text you already have. | The thing you want isn't spoken or written down — it's *visual* ("a person in a red jacket"). | | **Semantic search** (this feature) | Describe the moment in plain text; CLIP ranks frames by visual meaning. | You need exact object counts or bounding boxes — pair it with [object detection](../object-detection/) or a [VLM](../vlm-captioning/). | The three are complementary, not exclusive: index once, then combine a text query with your existing filters (date, camera, tag) to narrow the results. ## Use cases - **Search recorded footage by description** — jump to "a person entering the lobby" across hours of video without watching it. - **Media asset management** — build a searchable embedding index for a video library and query it with plain language. - **Highlight and clip discovery** — find candidate moments matching a described scene for editing or review. - **Deduplication and similarity** — compare frames or clips by embedding distance. - **Pre-filtering for heavier AI** — locate candidate frames semantically, then run a detector or VLM only on those. ## Troubleshooting | Symptom | Likely cause | Fix | | --- | --- | --- | | Indexing runs at real-time speed | `Video_Renderer_IsSync` left at default (`null`) on `MediaPlayerCoreX`, or a synced renderer on Media Blocks | Set `player.Video_Renderer_IsSync = false` before `OpenAsync`, or use a `NullRendererBlock { IsSync = false }` on Media Blocks. | | Some frames missing from the index | Encoder couldn't keep up and dropped frames | Set `BackpressureNoDrop = true` for offline file indexing. | | Search returns weak or generic matches | Ranking by raw cosine | Use the [contrastive margin](#contrastive-margin-recommended-ranking) with baseline prompts. | | `EncodeText` throws | Text tower or tokenizer files not provided | Set `TextEncoderPath`, `VocabFilePath`, and `MergesFilePath`. | | `Search` returns empty | Empty index, or query/index dimension mismatch | Confirm indexing finished (`index.Count > 0`) and the same CLIP model is used for both. | | Fewer results than expected | Sampling interval too coarse | Lower `SampleInterval` to embed more frames (at higher index and compute cost). | ## Frequently Asked Questions ### How do I find a specific scene in a long video? Index the video once with `VideoEmbeddingBlock`, then call `FrameEmbeddingIndex.Search` with your scene described in plain text (for example `"a car pulling into the driveway"`). Each result carries a `Timestamp` you can seek to — so you jump straight to the scene instead of scrubbing. Ranking with the [contrastive margin](#contrastive-margin-recommended-ranking) makes the top hit much more reliable than raw similarity. ### Can I build a video search engine in .NET with this? Yes — that's the intended use. Index your library into one or more `FrameEmbeddingIndex` files (`.vfei`), tag each frame with its `SourceTag`, and query the loaded index with text at run time. It's fully on-device (OpenAI CLIP via ONNX), so there is no cloud service or per-query cost. See [Build a video search feature](#build-a-video-search-feature) for the end-to-end recipe. ### How do I index faster than real time? On `MediaPlayerCoreX`, set `Video_Renderer_IsSync = false` before `OpenAsync`; on a manual Media Blocks pipeline, send the block's output to a `NullRendererBlock { IsSync = false }`. Both decode the file as fast as the CPU/GPU allows. Keep `BackpressureNoDrop = true` so no sampled frame is dropped. ### Can I search a live camera? The feature targets stored video. You can embed a live camera (`BackpressureNoDrop = false` so it doesn't stall), but there is no dedicated `VideoCaptureCoreX` search demo — indexing and search are built around files. ### How is the index stored? `FrameEmbeddingIndex.Save` writes a compact binary `.vfei` file (magic `VFEI`, timestamps + source tags + float embeddings). `Load` restores it, so you can index once and search later or in another process. ### What does the contrastive margin do? It subtracts each frame's best generic-baseline score from its query score, which removes a scene-independent bias in raw cosine similarity and makes true matches stand out. It's the ranking the demos use — see the [Search](#contrastive-margin-recommended-ranking) section. ### Do I need a GPU? No. `Provider` defaults to `Auto` and runs on CPU when no GPU is present. A GPU provider speeds up per-frame encoding, which matters most when indexing long files at a fine `SampleInterval`. ### Can I search across multiple videos at once? Yes. Index several files into the same `FrameEmbeddingIndex` (give each its own `SourceTag`), then one `Search` ranks frames across all of them — each `FrameEmbeddingSearchResult` reports the `SourceTag` so you know which file (and timestamp) a hit came from. ### How is this different from object detection or a VLM? Object detection and VLMs answer "what is in this frame" (boxes, labels, captions). Semantic search answers "which frames match this description" by ranking whole frames against a text query. It finds moments; it does not draw boxes. Use it to locate candidate frames, then run a detector or [`VLMBlock`](../vlm-captioning/) on them if you need per-object detail. ### Is this keyword search over video metadata? No. It compares the *meaning* of frames and your query in CLIP's embedding space, so it works with no tags, filenames, or transcripts — "a person in a red jacket" matches on appearance, not on text metadata that may not exist. ### Does the index work in another process or session? Yes. `Save` writes a `.vfei` file and `Load` restores it, so you can index once and search later, in a different run, or ship a prebuilt index with your application. ### Do I have to keep the video to search it? No — once frames are indexed, search runs entirely on the `FrameEmbeddingIndex` and the CLIP text tower. You need the original file again only to show thumbnails or to seek to a matching timestamp. ## Demos Dedicated demos built on Media Blocks and `MediaPlayerCoreX` (`Semantic Video Search Demo`, `Semantic Video Search MB`, `Player Semantic Video Search X`, `Player Semantic Video Search X WPF`) are in the SDK's demo set and will be linked here once published to the public samples repository. ---END OF PAGE--- ## Speaker Diarization SDK for .NET — SpeakerDiarizationBlock **URL:** https://www.visioforge.com/help/docs/dotnet/general/ai/speaker-diarization/ **Description:** On-device speaker diarization for .NET — find **Tags:** .NET, AI, Speaker Diarization, Diarization SDK, Who Spoke When, Speaker Segmentation, Speaker Embedding, VideoCaptureCoreX, MediaPlayerCoreX **API:** SpeakerDiarizationBlock, SpeakerDiarizationSettings, SpeakerSegment, SpeakerSegmentEventArgs, DiarizedTranscriptBuilder, DiarizedTranscriptSegment # Speaker Diarization — SpeakerDiarizationBlock `SpeakerDiarizationBlock` is an audio-only Media Block that lives in the `VisioForge.Core.MediaBlocks.AI` namespace (assembly `VisioForge.Core.AI`, NuGet package `VisioForge.DotNet.Core.AI`). It answers "who spoke when": it taps the audio stream, finds speech turns with a pyannote segmentation ONNX model, turns each turn into a voiceprint with a WeSpeaker/3D-Speaker embedding ONNX model, and — once the recording has finished — groups the voiceprints into speakers and publishes the timeline. Audio passes through the block: the tap forces a 32-bit float interleaved sample format, but the sample rate and channel count are left unchanged. The block implements `IAudioProcessingBlock`, so it can be inserted into a manual pipeline or registered directly on `VideoCaptureCoreX`/`MediaPlayerCoreX`. The implementation follows the reference [sherpa-onnx](https://github.com/k2-fsa/sherpa-onnx) offline speaker-diarization pipeline, which uses these same two models. ``` using VisioForge.Core.MediaBlocks.AI; using VisioForge.Core.Types.X.AI; ``` ## Diarization is offline — the answer arrives at end-of-stream **The block reports nothing while the audio is still playing.** This is not a limitation of the implementation, it is what the problem allows: - The segmentation model separates the voices **inside one 10-second window** and numbers them locally. Window 5's "speaker 1" and window 6's "speaker 1" are unrelated — the model never claims otherwise. - The only thing that can tie a voice heard at minute 1 to the same voice at minute 40 is **clustering every voiceprint of the recording together**, and that cannot be done until every voiceprint exists. So the block analyses continuously as audio flows (that work is real, and it is why the answer appears almost immediately after the last sample), but it raises `OnSpeakerSegment` — once per turn, in start-time order — only after end-of-stream. **It suits files and finite streams.** An endless live source never reaches the moment at which an answer exists. ## Basic block setup ``` var settings = new SpeakerDiarizationSettings(segmentationModelPath, embeddingModelPath) { Provider = OnnxExecutionProvider.CPU, }; var diarization = new SpeakerDiarizationBlock(settings); // Raised for every turn, in order, after the stream ends. diarization.OnSpeakerSegment += (sender, e) => { var turn = e.Segment; Console.WriteLine($"speaker_{turn.SpeakerId:D2}: {turn.Start:c} - {turn.End:c} (conf {turn.Confidence:F2})"); }; ``` The same timeline is available in one piece from `GetTimeline()`. Check `IsTimelineComplete` first — an empty timeline means "we never got to work out who spoke", not "nobody spoke": ``` if (!diarization.IsTimelineComplete) { // The run never reached the clustering step: the pipeline was stopped before end-of-stream, // or the analysis worker faulted. The timeline is empty, and that emptiness is not an answer. Console.WriteLine("No diarization result — the recording was not heard to the end."); return; } Console.WriteLine($"{diarization.SpeakerCount} speaker(s)."); if (diarization.UnattributedTurns > 0) { // Speech the models found but could not voiceprint: those turns carry no speaker id and // never reach the timeline, even though their audio WAS analysed. Console.WriteLine($"{diarization.UnattributedTurns} turn(s) could not be attributed to a speaker."); } foreach (var turn in diarization.GetTimeline()) { Console.WriteLine(turn); // speaker_00 [00:00:01.583 --> 00:00:03.405] (conf=0.98) } ``` ## Models — download at runtime Two ONNX models are required, both downloaded at runtime (neither is shipped in the SDK NuGet packages). Both are exported by the [sherpa-onnx](https://github.com/k2-fsa/sherpa-onnx) project: | Model | Role | License | Source | | --- | --- | --- | --- | | pyannote `segmentation-3.0` | Local speech-turn segmentation (10 s window, up to 3 local speakers, powerset activity) | MIT | Extract `model.onnx` from the [`sherpa-onnx-pyannote-segmentation-3-0.tar.bz2`](https://github.com/k2-fsa/sherpa-onnx/releases/download/speaker-segmentation-models/sherpa-onnx-pyannote-segmentation-3-0.tar.bz2) release asset. | | WeSpeaker `voxceleb_resnet34_LM` (English, **default**) | Speaker embedding (80-bin fbank in, 256-d voiceprint out) | Apache-2.0 | [`wespeaker_en_voxceleb_resnet34_LM.onnx`](https://github.com/k2-fsa/sherpa-onnx/releases/download/speaker-recongition-models/wespeaker_en_voxceleb_resnet34_LM.onnx) release asset. | | 3D-Speaker `eres2netv2_sv_zh-cn_16k-common` (**multilingual**) | Speaker embedding (80-bin fbank in, 192-d voiceprint out); much better speaker separation on non-English speech | Apache-2.0 | [`3dspeaker_speech_eres2netv2_sv_zh-cn_16k-common.onnx`](https://github.com/k2-fsa/sherpa-onnx/releases/download/speaker-recongition-models/3dspeaker_speech_eres2netv2_sv_zh-cn_16k-common.onnx) release asset. | The segmentation model is **language-independent** — only the embedding model needs to match your language. The default `SegmentationModelUrl` / `EmbeddingModelUrl` on `SpeakerDiarizationSettings` point at the pyannote and WeSpeaker English release assets. They are informational — the SDK never downloads anything itself; the files actually loaded are `SegmentationModelPath` and `EmbeddingModelPath`. Any 80-bin-fbank WeSpeaker or 3D-Speaker embedding model with commercially usable weights can be substituted; the fbank feature front-end configures itself (sample scaling and feature normalization) from the model's ONNX metadata, so no manual tuning is needed when you swap it. ## Multilingual diarization The default WeSpeaker embedding is trained on English (VoxCeleb) and under-detects speakers on other languages. For non-English or mixed-language content, use the Apache-2.0 **3D-Speaker ERes2NetV2** multilingual embedding model instead: point `EmbeddingModelPath` at its ONNX file and set `EmbeddingModel = SpeakerEmbeddingModel.ERes2NetV2Multilingual`. The segmentation model is unchanged. ``` var settings = new SpeakerDiarizationSettings(segmentationModelPath, eres2netv2ModelPath) { EmbeddingModel = SpeakerEmbeddingModel.ERes2NetV2Multilingual, // Retune the threshold for this embedding — see below. The default (0.5) over-splits it. ClusterThreshold = 0.8f, Provider = OnnxExecutionProvider.CPU, }; var diarization = new SpeakerDiarizationBlock(settings); ``` Retune `ClusterThreshold` when you switch embedding models Each embedding model has its own cosine geometry, and the default `ClusterThreshold` of `0.5` is the right distance for **WeSpeaker**. The ERes2NetV2 voiceprints are spread further apart, so that same distance splits one speaker into several — on a four-speaker reference clip it yields six. A value around **`0.8`** is the starting point for ERes2NetV2. If you know the speaker count, setting `NumSpeakers` sidesteps the question entirely. `EmbeddingModel` is a declarative hint: it selects the recommended download URL, while the file actually loaded is always `EmbeddingModelPath`. Because the front-end reads its feature configuration from the model's ONNX metadata, switching between the two models needs no other code change. Download URLs are also exposed as constants: `SpeakerDiarizationSettings.WeSpeakerEnglishModelUrl` and `SpeakerDiarizationSettings.ERes2NetV2MultilingualModelUrl`. ## Key settings `SpeakerDiarizationSettings(segmentationModelPath, embeddingModelPath)`. Unlike the vision AI settings, this type does **not** derive from `OnnxInferenceSettings` — those describe video-frame preprocessing, which does not apply to an audio model pair. The defaults are the reference implementation's own and are a sound starting point for arbitrary content. | Property | Default | Description | | --- | --- | --- | | `SegmentationModelPath` | — | Absolute path to the pyannote `segmentation-3.0` ONNX model. Required. | | `EmbeddingModelPath` | — | Absolute path to the speaker-embedding ONNX model (for example WeSpeaker `voxceleb_resnet34_LM` or 3D-Speaker `eres2netv2`). Required. | | `EmbeddingModel` | `WeSpeakerEnglish` | Which embedding model the settings are configured for (`WeSpeakerEnglish` or `ERes2NetV2Multilingual`). A declarative hint that picks the default URL; the file loaded is always `EmbeddingModelPath`, and feature extraction is auto-configured from its ONNX metadata. | | `SegmentationModelUrl` | sherpa-onnx pyannote release | Informational download URL for the segmentation model. | | `EmbeddingModelUrl` | sherpa-onnx WeSpeaker release | Informational download URL for the embedding model. | | `NumSpeakers` | `-1` | The **exact** number of speakers, when you know it. A positive value pins the result to that many speakers and `ClusterThreshold` is ignored. `-1` means "work it out from the voices" — the right setting whenever the count is not certain. | | `ClusterThreshold` | `0.5` | The cosine **DISTANCE** at which two voiceprints stop being the same person. Note the direction: this is a distance (0 = identical voices), **not** a similarity — a **smaller** value is stricter and yields **more** speakers. Ignored when `NumSpeakers` is positive. | | `MinDurationOn` | `0.3` | The shortest turn, in seconds, that is reported. Shorter ones are dropped as noise. | | `MinDurationOff` | `0.5` | The longest pause, in seconds, that still counts as the same turn. Two turns of one speaker closer than this are joined, so a speaker pausing for breath stays one turn. | | `Provider` | `Auto` | Execution provider for both ONNX sessions. `Auto` uses the fastest provider in the loaded ONNX Runtime native build and falls back to CPU. | | `DeviceId` | `0` | Hardware device id when a GPU provider is selected. | ## Speaker turns Each `SpeakerSegment` (from `SpeakerSegmentEventArgs.Segment` and `GetTimeline()`): | Property | Description | | --- | --- | | `SpeakerId` | Stable, zero-based speaker identifier for this run. | | `Start` / `End` | `TimeSpan` on the media timeline. | | `Duration` | `End - Start`. | | `Confidence` | How strongly the overlapping analysis windows agreed on this speaker for this turn (0..1). `1` means every window that saw the moment named the same speaker. | Speaker ids are stable **within a run**, not across separate pipeline runs (there is no cross-run speaker re-identification in this version). ## Diarized transcript — "who said what" `DiarizedTranscriptBuilder` merges a speech-to-text transcript with the diarization timeline, labeling each transcript segment with the speaker who overlaps it the most (ties go to the lower speaker id). It is pure data processing — no model or media dependency — so it pairs a [`SpeechToTextBlock`](../speech-to-text/) with a `SpeakerDiarizationBlock`. Build it after end-of-stream, when the diarization timeline exists. ``` using VisioForge.Core.Types.X.AI; // transcript: (start, end, text) tuples from SpeechToTextBlock.OnSpeechRecognized // timeline: diarization.GetTimeline() var labeled = DiarizedTranscriptBuilder.Build(transcript, timeline); foreach (DiarizedTranscriptSegment seg in labeled) { // "[00:00:01.000 --> 00:00:03.000] speaker_00: A pencil with black lead writes best." Console.WriteLine(seg); } ``` Each `DiarizedTranscriptSegment` carries `Start`, `End`, `Text`, and the attributed `SpeakerId` (`-1` when no diarization turn overlaps the segment — for example a silent gap). ## Manual Media Blocks pipeline Place `SpeakerDiarizationBlock` in the audio chain before the audio renderer or output: ``` var diarization = new SpeakerDiarizationBlock(settings); diarization.OnSpeakerSegment += Diarization_OnSpeakerSegment; pipeline.Connect(audioSource.Output, diarization.Input); pipeline.Connect(diarization.Output, audioRenderer.Input); ``` ## MediaPlayerCoreX file diarization For playback, `Audio_Play` must be `true` for the audio chain to be built: ``` player.Audio_Play = true; var diarization = new SpeakerDiarizationBlock(settings); diarization.OnSpeakerSegment += Diarization_OnSpeakerSegment; player.Audio_Processing_AddBlock(diarization); // before OpenAsync / PlayAsync await player.OpenAsync(source); await player.PlayAsync(); ``` Let the file play to its end: stopping playback early skips the clustering step and leaves the timeline empty. Diarization reads only the audio, so to index a file as fast as the hardware allows rather than in real time, give the player an unsynced audio sink — `player.Audio_OutputBlock = new NullRendererBlock(MediaBlockPadMediaType.Audio) { IsSync = false };` — so the audio is not paced by the clock. (`Video_Renderer_IsSync = false` only unpaces a video renderer, so it has no effect on an audio-only file.) See [Using AI blocks with VideoCaptureCoreX and MediaPlayerCoreX](../x-engines/) for the full `Audio_Processing_*` API and lifecycle rules. The engine owns the wired block after start and disposes it when the session stops — create a new block for the next session. ## How it works Understanding these three stages explains every setting above, and why the result cannot arrive earlier. 1. **Segmentation, as the audio flows.** The audio is resampled to mono 16 kHz and cut into 10-second windows that advance 1 second at a time — so the windows overlap by 90%, and every instant of audio is seen by about ten of them. The pyannote model labels, for each of its ~59 output frames per second, which of up to three *window-local* speakers are talking. 2. **Voiceprints, as the audio flows.** For each window and each speaker active in it, the audio of that speaker is collected — **minus every frame where somebody else is talking too** — and turned into a voiceprint. Overlapped speech is excluded deliberately: a voiceprint taken from two voices at once sits between them and looks similar to both, which welds two speakers into one. Turns with less than ~0.17 s of clean speech are skipped for the same reason. 3. **Speakers and the timeline, at end-of-stream.** All the voiceprints of the recording are clustered together (agglomerative, complete linkage, cosine distance — `ClusterThreshold` / `NumSpeakers`). The window-local speaker numbers are rewritten into global ones, all the overlapping windows are laid on one frame grid, and **every frame is decided by a vote among the ~10 windows covering it**: how many people are talking is the average those windows report, and who they are is the most-voted. A window that mislabels a moment is outvoted by its neighbours. Finally the frames become turns, short pauses are bridged (`MinDurationOff`) and fragments are dropped (`MinDurationOn`). ## Threading, performance, and lifetime Analysis runs on a **dedicated background worker**, not the streaming thread: the tap resamples the audio to mono 16 kHz and pushes it into an **unbounded queue**, and the worker consumes it in overlapping windows. Because analysis is off the streaming thread, audio is never paced to the models — a source that runs faster than they do (a file decoded at full speed, or a live source on a slow execution provider) simply makes the worker fall behind. **A backlog is never dropped.** The queue grows instead — at 16 kHz mono that is 64 KB per buffered second — and it drains as soon as the worker catches up. If a machine is permanently slower than its source, the backlog keeps growing, and that is the honest signal: the answer is faster hardware or a GPU execution provider, never analysing a fraction of the audio. At end-of-stream the pipeline waits for the worker to drain the backlog and publish the timeline before tearing down. `OnSpeakerSegment` is raised on the worker thread — never touch UI directly from the handler; marshal to the UI dispatcher or main thread. Memory scales with the recording: the voiceprints are kept until the end (they are the clustering's input), and clustering builds a pairwise distance matrix over them. ## Result completeness | Member | Description | | --- | --- | | `IsTimelineComplete` | `true` when the run actually produced an answer: the stream reached end-of-stream, the worker drained, and the speakers were clustered and published. **Check it before reading `GetTimeline()`** — when it is `false` the timeline is EMPTY, and that emptiness means "we never got to work out who spoke", not "nobody spoke". | | `SpeakerCount` | How many distinct speakers were found. `0` until the timeline is published. | | `UnattributedTurns` | Speech turns the segmentation model **found** but the embedding model could not voiceprint. Their audio *was* analysed, but they carry no speaker id and are absent from the timeline. | | `ActiveProvider` | The execution provider the ONNX sessions actually engaged. Stays valid after the run, so it can be logged at the end. | **A timeline is fully trustworthy when `IsTimelineComplete` is `true` AND `UnattributedTurns` is `0`.** ## Use cases - **Meeting and interview transcription** — label a diarized transcript with per-speaker turns. - **Call-center analytics** — separate agent and customer speech for talk-time and turn-taking metrics. - **Media indexing** — index recorded video/audio by speaker for search and navigation. - **Podcast and broadcast tooling** — auto-generate speaker-labeled show notes with speech-to-text. ## Troubleshooting | Symptom | Likely cause | Fix | | --- | --- | --- | | No turns are ever raised, and `IsTimelineComplete` is `false` | The stream never ended — the pipeline was stopped early, or the source is an endless live stream | Let the source reach end-of-stream. Diarization needs the complete recording; there is no partial answer to give. | | No turns are raised although the file played to the end | A model path is invalid, or the audio chain isn't built | Confirm both ONNX files exist at their paths; for playback confirm `Audio_Play = true`. | | Too many speakers detected | `ClusterThreshold` too small for this audio/model | **Raise** `ClusterThreshold` (it is a distance — a larger value merges more), or set `NumSpeakers` to the known count. | | Speakers merged into one | `ClusterThreshold` too large | **Lower** `ClusterThreshold` (a smaller distance splits more eagerly), or set `NumSpeakers`. | | Analysis lags a fast file source, and memory grows | The overlapping windows are compute-heavy, so the worker falls behind and the (unbounded) backlog grows — no audio is lost, but it is buffered | Use `Provider = OnnxExecutionProvider.CUDA` / `DirectML` on a GPU. A buffered second costs 64 KB. | | Speech is missing although `IsTimelineComplete` is `true` | The embedding model failed to voiceprint some detected turns, so they got no speaker id | Check `UnattributedTurns`; look for the `SpeakerEmbeddingEngine` error in the log for the cause (typically a GPU out-of-memory or provider fallback). | ## Frequently Asked Questions ### Why do I get no speaker turns until the file ends? Because until then there is no such thing as "speaker 2" to report. The segmentation model separates voices only inside a single 10-second window and numbers them locally; tying a voice at minute 1 to the same voice at minute 40 requires clustering every voiceprint of the recording at once. The block does all the work it can as the audio flows, and publishes the moment the last sample is in. ### Can I diarize an endless live stream? No. A live stream has no end-of-stream, so the clustering step never runs. Diarize finite recordings — or segment a live stream into finite chunks and diarize each (speaker ids are not comparable between chunks). ### Does SpeakerDiarizationBlock require an internet connection? No — diarization runs fully on-device through ONNX Runtime. Your application downloads the two model files once (or bundles them); nothing is called per-request over the network. ### Can I combine it with speech-to-text to get a speaker-labeled transcript? Yes — run a [`SpeechToTextBlock`](../speech-to-text/) and a `SpeakerDiarizationBlock` on the same audio, then merge the transcript with `diarization.GetTimeline()` using `DiarizedTranscriptBuilder.Build` after end-of-stream. ### Are speaker ids the same across two separate runs? No — ids are stable within a single run only. This version does not re-identify a speaker across runs. ### Which languages does it work with? The segmentation model is language-independent, so it works with any language out of the box. The default WeSpeaker embedding model is trained on English (VoxCeleb) and under-detects speakers on other languages; for non-English or mixed-language audio, switch `EmbeddingModelPath` to the Apache-2.0 3D-Speaker ERes2NetV2 multilingual model and set `EmbeddingModel = SpeakerEmbeddingModel.ERes2NetV2Multilingual` (see [Multilingual diarization](#multilingual-diarization)). The front-end adapts its feature extraction to the chosen model automatically from the ONNX metadata. ---END OF PAGE--- ## Speech-to-Text SDK for .NET — SpeechToTextBlock (Whisper) **URL:** https://www.visioforge.com/help/docs/dotnet/general/ai/speech-to-text/ **Description:** Speech-to-text SDK for .NET — transcribe live or file audio on-device with Whisper ASR and Silero VAD, plus SRT/VTT and live subtitle helpers. **Tags:** .NET, AI, Whisper, Speech-to-Text, Speech-to-Text SDK, Speech Recognition, Live Subtitles, Transcription, VideoCaptureCoreX, MediaPlayerCoreX **API:** SpeechToTextBlock, SpeechToTextSettings, SileroVadSettings, SpeechSegment, SubtitleWriter, SubtitleRenderer, SubtitleStyle # Speech-to-Text and Live Subtitles — SpeechToTextBlock `SpeechToTextBlock` is an audio-only Media Block from `VisioForge.DotNet.Core.AI.Whisper`. It taps the audio stream, segments speech with Silero VAD, transcribes it with Whisper (Whisper.net / GGML), and raises `OnSpeechRecognized`. Audio passes through unchanged. The block implements `IAudioProcessingBlock`, so it can be inserted into a manual pipeline or registered directly on `VideoCaptureCoreX`/`MediaPlayerCoreX`. ``` using VisioForge.Core.MediaBlocks.AI; using VisioForge.Core.Types.X.AI; ``` ## Basic block setup ``` var settings = new SpeechToTextSettings(whisperModelPath) { Language = "auto", Task = SpeechToTextTask.Transcribe, EnableVad = true, EmitInterim = false, }; settings.Vad.ModelPath = sileroVadModelPath; var stt = new SpeechToTextBlock(settings); stt.OnSpeechRecognized += (sender, e) => { foreach (var segment in e.Segments) { Console.WriteLine($"{segment.StartTime:c} - {segment.EndTime:c}: {segment.Text}"); } }; ``` `SpeechToTextTask.Transcribe` keeps the source language. `SpeechToTextTask.Translate` translates supported source speech to English text. ## Key settings `SpeechToTextSettings(whisperModelPath)`. Unlike the vision AI settings, this type does **not** derive from `OnnxInferenceSettings` — Whisper runs through Whisper.net (whisper.cpp / GGML), not ONNX Runtime, so the ONNX-specific input-size/normalization knobs don't apply. | Property | Default | Description | | --- | --- | --- | | `WhisperModelPath` | — | Absolute path to the Whisper GGML model file (`ggml-*.bin`). Required. | | `ModelSize` | `WhisperModelSize.Base` | Informational label for the model variant at `WhisperModelPath` (see below). | | `Language` | `"auto"` | ISO 639-1 code (`"en"`, `"es"`, `"fr"`, ...), or `"auto"` to let Whisper detect it. | | `Task` | `Transcribe` | `Transcribe` (source language) or `Translate` (to English). | | `Provider` | `Auto` | Only `CPU` and `CUDA` are meaningful for the GGML backend (no DirectML); `Auto` picks CUDA when present, else CPU. | | `DeviceId` | `0` | Hardware device id when a GPU provider is selected. | | `Threads` | `0` | CPU threads Whisper uses. `0` lets Whisper.net choose from the available processor count. | | `EnableVad` | `true` | Segment speech with Silero VAD before transcription. When `false`, audio is transcribed in fixed windows, which is prone to hallucinating text during silence. | | `Vad` | new `SileroVadSettings` | VAD settings used when `EnableVad` is `true`. | | `FixedWindowSeconds` | `5` | Fixed transcription window length when `EnableVad` is `false`. Clamped to 1–30 s. | | `EmitInterim` | `false` | Reserved for a future interim-hypothesis capability; currently has no effect — only final segments are emitted. | | `OutputSrtPath` | `null` | Optional `.srt` side-car path the block writes as final segments are recognized. | | `OutputVttPath` | `null` | Optional `.vtt` (WebVTT) side-car path the block writes as final segments are recognized. | ## VAD settings When `EnableVad` is `true`, `SpeechToTextSettings.Vad` controls Silero speech segmentation. Silero VAD is a tiny (~2 MB, MIT) ONNX model that classifies short audio windows as speech or non-speech, used as a real-time pre-filter so the (much heavier) Whisper model only runs on actual speech. ``` settings.Vad = new SileroVadSettings { ModelPath = sileroVadModelPath, SpeechThreshold = 0.5f, MinSilenceMs = 100, MinSpeechMs = 250, SpeechPadMs = 30, MaxSpeechMs = 15000, Provider = OnnxExecutionProvider.CPU, }; ``` | Property | Default | Description | | --- | --- | --- | | `ModelPath` | — | Absolute path to `silero_vad.onnx`. | | `SpeechThreshold` | `0.5` | Speech-probability threshold (0..1). Raise it in noisy environments to reduce false triggers. | | `MinSilenceMs` | `100` | Minimum trailing silence, in ms, that ends a speech segment. | | `MinSpeechMs` | `250` | Minimum speech-run duration, in ms, to be emitted (discards spurious blips). | | `SpeechPadMs` | `30` | Onset padding, in ms, prepended to each detected segment. | | `MaxSpeechMs` | `15000` | Maximum segment length, in ms, before the segmenter force-cuts an ongoing run. | | `Provider` | `CPU` | Execution provider for the VAD session — the model is tiny (~1 ms/window on CPU), so GPU adds latency without benefit. | | `DeviceId` | `0` | Hardware device id when a GPU provider is selected. | The Whisper GGML weights and the Silero VAD model are downloaded at runtime; neither is shipped in the SDK NuGet packages. ### Whisper model sizes `WhisperModelSize` is informational — it names well-known Whisper GGML weight files so an application can pick one to download. The file actually loaded is always `SpeechToTextSettings.WhisperModelPath`. | Value | Approx. size | Notes | | --- | --- | --- | | `Tiny` | ~75 MB | Fastest, lowest accuracy. Good for real-time CPU transcription. | | `Base` (default) | ~142 MB | A good real-time CPU default. | | `Small` | ~466 MB | Noticeably more accurate; real-time with a GPU or a fast CPU. | | `Medium` | ~1.5 GB | High accuracy; typically needs a GPU for real-time. | | `LargeV3` | ~3 GB | Highest accuracy; GPU strongly recommended. | | `LargeV3Turbo` | ~1.6 GB | Near-large accuracy at a fraction of the cost. | | `TinyQuantized` | ~31 MB | `Tiny`, Q5\_1-quantized. | | `BaseQuantized` | ~57 MB | `Base`, Q5\_1-quantized. | | `SmallQuantized` | ~181 MB | `Small`, Q5\_1-quantized. | | `MediumQuantized` | ~514 MB | `Medium`, Q5\_0-quantized. | | `LargeV3TurboQuantized` | ~547 MB | `LargeV3Turbo`, Q5\_0-quantized. Recommended quantized accuracy/speed balance. | English-only (`*.en`) variants aren't enumerated; supply their path directly. Weights are MIT-licensed. ## Recognized segments Each `SpeechSegment` in `SpeechRecognizedEventArgs.Segments`: | Property | Description | | --- | --- | | `Text` | The recognized text for the segment. | | `StartTime` / `EndTime` | `TimeSpan`, relative to the start of the stream — ready to use for SRT/VTT or on-screen scheduling. | | `IsFinal` | Reserved to distinguish interim vs. final hypotheses once interim results exist; segments are currently always final (`true`). | | `Language` | Detected/used ISO 639-1 code, or `null` if unknown. | | `Confidence` | Average token confidence (0..1), or `0` when the model doesn't report token probabilities. | ## Subtitle helpers ### SubtitleWriter — SRT/VTT files `SubtitleWriter` writes recognized speech segments to a SubRip (`.srt`) or WebVTT (`.vtt`) side-car file, appending one cue per final segment. It is thread-safe; interim (non-final) segments are ignored. ``` using VisioForge.Core.AI.Whisper.Subtitles; using var writer = new SubtitleWriter("captions.srt", SubtitleFormat.Srt); stt.OnSpeechRecognized += (sender, e) => { foreach (var segment in e.Segments) { writer.Add(segment); } }; ``` If you only need files, it's simpler to set `OutputSrtPath` and/or `OutputVttPath` on `SpeechToTextSettings` — the block creates and drives its own `SubtitleWriter` instance(s) internally as final segments are recognized, and disposes them for you. ### SubtitleRenderer — on-screen captions `SubtitleRenderer` drives a single text overlay on an `OverlayManagerBlock`: it shows the latest caption and auto-hides it after the segment's display duration. ``` using SkiaSharp; using VisioForge.Core.AI.Whisper.Subtitles; var style = new SubtitleStyle { FontName = "Arial", FontSize = 32, Color = SKColors.White, X = 50, Y = 50, MinDisplay = TimeSpan.FromSeconds(1.5), MaxDisplay = TimeSpan.FromSeconds(6), }; var subtitleRenderer = new SubtitleRenderer(overlayManagerBlock, style); stt.OnSpeechRecognized += subtitleRenderer.OnSpeechRecognized; // ... later, when tearing down: subtitleRenderer.Dispose(); // removes the overlay and stops the auto-hide timer ``` Wire `SubtitleRenderer.OnSpeechRecognized` directly as the block's event handler. It clamps the on-screen time into `[MinDisplay, MaxDisplay]` based on the segment's duration and calls `OverlayManagerBlock.Video_Overlay_Update` from whatever thread invokes it — marshal the call if your UI framework requires it. `SubtitleStyle` defaults: `FontName = "Arial"`, `FontSize = 32`, `Color = White`, `X = 50`, `Y = 50`, `MinDisplay = 1.5 s`, `MaxDisplay = 6 s`. No shipping demo yet `SubtitleRenderer` exists in the SDK and is documented from its source, but no bundled demo currently uses it — the Live Subtitles X demos update a UI label directly from `OnSpeechRecognized` instead. Use `SubtitleWriter` or `OutputSrtPath`/`OutputVttPath` if you only need a subtitle file. ## Manual Media Blocks pipeline Place `SpeechToTextBlock` in the audio chain before the audio renderer or output: ``` var stt = new SpeechToTextBlock(settings); stt.OnSpeechRecognized += SpeechToText_OnSpeechRecognized; pipeline.Connect(audioSource.Output, stt.Input); pipeline.Connect(stt.Output, audioRenderer.Input); ``` ## VideoCaptureCoreX live microphone transcription For capture, an audio source is required. If you want analysis without speaker monitoring or recording, terminate the audio chain with a non-synced null renderer: ``` core.Audio_Source = microphoneSettings; core.Audio_OutputBlock = new NullRendererBlock(MediaBlockPadMediaType.Audio) { IsSync = false, }; var stt = new SpeechToTextBlock(settings); stt.OnSpeechRecognized += SpeechToText_OnSpeechRecognized; core.Audio_Processing_AddBlock(stt); // before StartAsync await core.StartAsync(); ``` `Audio_OutputBlock` builds and terminates the audio chain without enabling speaker playback or file recording. The engine owns the assigned output block after start. ## MediaPlayerCoreX file transcription For playback, `Audio_Play` must be `true` for the audio chain to be built. A non-synced null renderer lets the source run without real-time speaker output: ``` player.Audio_Play = true; player.Audio_OutputBlock = new NullRendererBlock(MediaBlockPadMediaType.Audio) { IsSync = false, }; var stt = new SpeechToTextBlock(settings); stt.OnSpeechRecognized += SpeechToText_OnSpeechRecognized; player.Audio_Processing_AddBlock(stt); // before OpenAsync / PlayAsync await player.OpenAsync(source); await player.PlayAsync(); ``` See [Using AI blocks with VideoCaptureCoreX and MediaPlayerCoreX](../x-engines/) for the full `Audio_Processing_*`/`Audio_OutputBlock` API and lifecycle rules. ## Threading, pacing, and lifetime VAD and Whisper run **synchronously on the GStreamer streaming thread**: audio is segmented and transcribed in place, and the trailing segment is flushed at end-of-stream. Nothing is dropped — the whole input is transcribed losslessly, and the pipeline position tracks the transcription frontier (useful for a progress bar). Because transcription runs inline, the source is paced to Whisper: if Whisper is slower than real time, the upstream (including a live capture device) is throttled rather than losing audio. In practice Whisper Base runs well above real time, so it is not the bottleneck for a typical source. `OnSpeechRecognized` is raised on that same streaming thread — never touch UI directly from the handler; marshal to the UI dispatcher or main thread. After a capture or playback session starts, the engine owns wired `SpeechToTextBlock` instances and disposes them when the session stops. Create a new block for the next session. ## Use cases - **Live captioning** — real-time subtitles for a live stream, webinar, or accessibility overlay. - **Meeting and call transcription** — transcribe a microphone feed alongside `VideoCaptureCoreX` capture. - **Media indexing and search** — batch-transcribe recorded video/audio files to make their content searchable. - **Subtitle authoring** — generate `.srt`/`.vtt` side-car files from source video without a third-party transcription service. - **Translation captions** — set `Task = SpeechToTextTask.Translate` to caption non-English speech in English. ## Troubleshooting | Symptom | Likely cause | Fix | | --- | --- | --- | | No segments are ever recognized | `WhisperModelPath` invalid, or the audio chain isn't built | Confirm the GGML model file exists at that path; for capture/playback, confirm the audio chain is active (see `Audio_OutputBlock` below). | | Whisper "hallucinates" text during silence | `EnableVad` is `false` | Enable VAD (`EnableVad = true`, the default) so Whisper only runs on detected speech, not fixed windows that may be silent. | | Transcription lags behind live audio | Whisper is slower than real time on the current hardware/model size | Choose a smaller `WhisperModelSize`/model file, or use `Provider = CUDA` on a machine with an NVIDIA GPU. | | Segments are cut off mid-sentence | `SileroVadSettings.MaxSpeechMs` force-cuts a long continuous utterance | This is a deliberate bound (default 15 s) so one in-flight transcription can't grow unbounded; raise `MaxSpeechMs` if your scenario needs longer uninterrupted segments and can tolerate the larger bound. | | No audio reaches the block on `VideoCaptureCoreX`/`MediaPlayerCoreX` | Audio chain not built (missing `Audio_Source`/`Audio_Play`) | See [VideoCaptureCoreX live microphone transcription](#videocapturecorex-live-microphone-transcription) and [MediaPlayerCoreX file transcription](#mediaplayercorex-file-transcription) above. | | `.srt`/`.vtt` file is empty | Segments never finalized, or wrong path | Confirm `OutputSrtPath`/`OutputVttPath` point to a writable path and that speech was actually detected; only final segments are written. | ## Frequently Asked Questions ### Does SpeechToTextBlock require an internet connection? No — transcription runs fully on-device through Whisper.net/GGML; the model files are downloaded once by your application (or bundled), not called per-request over the network. ### Which languages does it support? Whisper is multilingual — set `Language` to an ISO 639-1 code, or leave it `"auto"` to let Whisper detect the spoken language automatically. ### Can I translate speech to English captions instead of transcribing the source language? Yes — set `SpeechToTextSettings.Task = SpeechToTextTask.Translate`. ### How do I get live on-screen subtitles instead of just an event? Wire `SubtitleRenderer.OnSpeechRecognized` as the block's event handler against an `OverlayManagerBlock` — see [SubtitleRenderer — on-screen captions](#subtitlerenderer-on-screen-captions). If you only need SRT/VTT files, set `OutputSrtPath`/`OutputVttPath` instead. ### Which Whisper model size should I use? Start with `Base` (the default) for real-time CPU transcription. Move to `Small`/`Medium`/`LargeV3` (or their quantized variants) for higher accuracy if you have a GPU or can tolerate slower-than-real-time processing; see the [Whisper model sizes](#whisper-model-sizes) table for the full trade-off. ## Demos - **[Live Subtitles Demo](https://github.com/visioforge/.Net-SDK-s-samples/tree/master/Media%20Blocks%20SDK/WPF/CSharp/Live%20Subtitles%20Demo)** — WPF Media Blocks pipeline demo. - **[Live Subtitles MB](https://github.com/visioforge/.Net-SDK-s-samples/tree/master/Media%20Blocks%20SDK/MAUI/Live%20Subtitles%20MB)** — the same Media Blocks demo for MAUI. - **[Live Subtitles](https://github.com/visioforge/.Net-SDK-s-samples/tree/master/Media%20Blocks%20SDK/Console/Live%20Subtitles)** — headless console demo (downloads models on first run). Dedicated `VideoCaptureCoreX`/`MediaPlayerCoreX` live-subtitles demos (`Capture Live Subtitles X`, `Capture Live Subtitles X WPF`, `Player Live Subtitles X`, `Player Live Subtitles X WPF`) are in the SDK's demo set and will be linked here once published to the public samples repository. ---END OF PAGE--- ## Describe and Caption Video Frames in .NET — Florence-2 **URL:** https://www.visioforge.com/help/docs/dotnet/general/ai/vlm-captioning/ **Description:** Generate captions, descriptions, OCR, and grounded regions from video frames with one model. On-device vision-language AI for .NET (Florence-2). **Tags:** .NET, AI, ONNX, VLM, Vision Language Model, Florence-2, Image Captioning, Phrase Grounding, VideoCaptureCoreX, MediaPlayerCoreX **API:** VLMBlock, VLMSettings, VLMTask, VLMResultGeneratedEventArgs # VLM Captioning — VLMBlock You need human-readable output from video — a caption for accessibility, a description to index or moderate footage, or the text on a sign — but standing up and maintaining separate captioning, object-detection, and OCR pipelines is a lot of moving parts. A **vision-language model** does all of it with one model: give it a frame and a task, get back text (and, for grounding tasks, boxes). `VLMBlock` runs Microsoft Florence-2 on-device via ONNX — no cloud, no per-call cost. `VLMBlock` runs a **vision-language model** (Microsoft Florence-2) over the video stream to produce natural-language output: a caption of the scene, a detailed description, detected objects with labels, region descriptions, OCR text, or phrases grounded to image regions. It is a pass-through video block: frames flow through untouched, optional overlays are drawn in place, and each processed frame raises `OnResultGenerated` with the model's text and any regions. Inference runs on a background worker throttled by `ProcessingInterval` — at most one frame per interval is captioned, and other frames simply redraw the cached result, so the pipeline is never stalled. A single block instance switches tasks at runtime through its `Task` property. ``` graph LR; Source-->VLMBlock; VLMBlock-->VideoRendererBlock; VLMBlock-. OnResultGenerated .->App[Your app]; ``` Florence-2 runs on the CPU The block forces the `CPU` execution provider — the DirectML backend mis-executes Florence-2's autoregressive merged decoder and returns garbage. There is no `Provider`/`DeviceId` knob on `VLMSettings`. Control cost with `ProcessingInterval` (how often a frame is processed) and `MaxNewTokens` (how much text is generated). ## How Florence-2 works A vision-language model (VLM) is a single network that takes an image plus a text instruction and generates a text answer. `VLMBlock` runs Microsoft **Florence-2** as a four-stage ONNX pipeline: 1. **Vision encoding.** The frame is resized to 768x768 and encoded into image features. 2. **Task prompting.** The chosen `VLMTask` maps to a Florence-2 task token (for example `` or ``), joined with `TextInput` for phrase grounding, then tokenized and embedded. 3. **Fusion.** The text encoder fuses the task with the image features. 4. **Decoding.** The decoder generates tokens greedily (argmax, no beam search) up to `MaxNewTokens`. The output string is parsed into `Text` and, for region tasks, `` coordinate tokens are converted into pixel `Box` values in `Regions`. One model covers captioning, detection, region description, OCR, and phrase grounding — you switch behavior by changing `Task`, not by loading a different model. ## Tasks Set `VLMSettings.Task` (or `VLMBlock.Task` at runtime) to choose what the model does per processed frame. | `VLMTask` | Output | Produces regions | | --- | --- | --- | | `Caption` (default) | A short one-sentence caption describing the frame. | No | | `DetailedCaption` | A more detailed caption. | No | | `MoreDetailedCaption` | A paragraph-length, highly detailed caption. | No | | `ObjectDetection` | Objects with a category label and bounding box each. | Yes | | `DenseRegionCaption` | Regions with a short description and bounding box each. | Yes | | `Ocr` | All text in the frame as a single string. | No | | `OcrWithRegion` | Text blocks, each with its region. | Yes | | `PhraseGrounding` | Grounds the phrases of the caption in `TextInput` to image regions. | Yes | `PhraseGrounding` requires `VLMSettings.TextInput` — the caption whose phrases are located (for example `"a person next to a red car"`). The region-producing tasks fill `VLMResultGeneratedEventArgs.Regions`; the caption-only tasks return text only. ### Which task should I use? | Goal | Task | | --- | --- | | A quick one-line label of the scene | `Caption` | | A rich description for indexing, accessibility, or search metadata | `DetailedCaption` / `MoreDetailedCaption` | | Read on-screen or in-scene text | `Ocr` (string) / `OcrWithRegion` (text + boxes) | | Boxes and labels without a trained detector | `ObjectDetection` / `DenseRegionCaption` | | Confirm and locate a described situation | `PhraseGrounding` (set `TextInput`) | Longer descriptions and grounding generate more tokens, so they take longer per frame than a short `Caption` — raise `MaxNewTokens` for them and keep `ProcessingInterval` comfortable. ## Usage ``` using VisioForge.Core.MediaBlocks; using VisioForge.Core.MediaBlocks.AI; using VisioForge.Core.MediaBlocks.VideoRendering; using VisioForge.Core.Types.Events; using VisioForge.Core.Types.X.AI; // All model files resolve from one folder by their conventional names. var settings = new VLMSettings(modelFolder) { Task = VLMTask.DetailedCaption, ProcessingInterval = TimeSpan.FromSeconds(1), MaxNewTokens = 256, DrawResults = true, }; var vlm = new VLMBlock(settings); vlm.OnResultGenerated += (sender, e) => { var text = e.Text; if (string.IsNullOrEmpty(text) && e.Regions.Length > 0) text = string.Join(", ", e.Regions.Select(r => r.Label)); Console.WriteLine($"[{e.Timestamp:hh\\:mm\\:ss}] {e.Task}: {text} ({e.InferenceTimeMs:F0} ms)"); }; var videoRenderer = new VideoRendererBlock(pipeline, videoView) { IsSync = false }; pipeline.Connect(source.Output, vlm.Input); pipeline.Connect(vlm.Output, videoRenderer.Input); await pipeline.StartAsync(); Console.WriteLine($"Running on: {vlm.ActiveProvider}"); // always CPU for Florence-2 ``` `VLMResultGeneratedEventArgs` carries the `Task` that produced the result, the generated `Text`, a `Regions` array (`VLMRegion { Label, Box }`, boxes in source-frame pixels; empty for caption-only tasks), the source-frame `Timestamp`, and `InferenceTimeMs`. Handlers are raised on the block's worker thread — marshal UI updates to the UI thread. ### Switching task and grounding text at runtime ``` vlm.Task = VLMTask.Ocr; // switch to OCR on the fly vlm.Task = VLMTask.PhraseGrounding; vlm.TextInput = "a person next to a red car"; // required for phrase grounding ``` ## Key settings `VLMSettings` is a standalone settings class (it does **not** derive from `OnnxInferenceSettings`). | Property | Default | Description | | --- | --- | --- | | `Task` | `VLMTask.Caption` | The task performed per processed frame. Runtime-changeable. | | `TextInput` | `null` | Auxiliary caption used only by `PhraseGrounding`. Runtime-changeable. | | `MaxNewTokens` | `256` | Maximum tokens the decoder generates per frame. | | `ProcessingInterval` | `1 second` | Minimum interval between two inferences. Other frames redraw the cached result. | | `DrawResults` | `true` | Draw grounded regions and the caption bar into the frame. | | `BoxColor` / `BoxThickness` | LimeGreen / `2` | Region-box overlay styling. | | `LabelFontSize` | `0` | Label/caption font size in px. `0` auto-scales to frame height. | | `VisionEncoderPath`, `EmbedTokensPath`, `EncoderModelPath`, `DecoderModelPath` | `null` | The four Florence-2 ONNX models. Set directly, or use the `VLMSettings(modelFolder)` constructor. | | `VocabFilePath`, `MergesFilePath`, `AddedTokensFilePath` | `null` | BART tokenizer assets. `AddedTokensFilePath` is required for grounding tasks; caption tasks work without it. | There is no `Provider`, `DeviceId`, or `FramesToSkip` — Florence-2 is CPU-only and throttling is time-based via `ProcessingInterval`. `VLMBlock.ActiveProvider` always reports `CPU`; `DroppedFrameCount` stays `0` by design (frames are sampled, never dropped). ## Model The block runs Microsoft **Florence-2 (base)** as a four-session ONNX pipeline — vision encoder, token embedder, text encoder, and a merged autoregressive decoder — plus a BART byte-level BPE tokenizer. Decoding is greedy (argmax). Model weights are not bundled with the SDK; the demos download them on first run from GitHub Releases and cache them under `%USERPROFILE%\VisioForge\models\vlm`: | Role | File | | --- | --- | | Vision encoder | `florence2-base-vision-encoder.onnx` | | Token embedder | `florence2-base-embed-tokens.onnx` | | Text encoder | `florence2-base-encoder.onnx` | | Merged decoder | `florence2-base-decoder-merged.onnx` | | Tokenizer | `florence2-vocab.json`, `florence2-merges.txt`, `florence2-added-tokens.json` | A model's license is set by its origin, independent of the SDK's own license — confirm the license of the weights you deploy. ## Performance and tuning Florence-2 runs on the CPU and generates text token-by-token, so it is designed for periodic frame understanding, not high-frame-rate real-time captioning. Tune it with two knobs: - **`ProcessingInterval`** (default 1 second) sets how often a frame is captioned. Frames between inferences reuse the last result for the overlay, so live video never stalls. - **`MaxNewTokens`** (default 256) bounds per-frame latency. Short-caption tasks finish in far fewer tokens than `MoreDetailedCaption` or grounding — lower it if you only need brief output, raise it if long output is being cut off. `DroppedFrameCount` stays `0` by design (frames are sampled, never dropped), and `ActiveProvider` always reports `CPU`. There is no GPU or `FramesToSkip` knob — throttle with `ProcessingInterval`. ## Use with VideoCaptureCoreX and MediaPlayerCoreX Register the block before the session starts. On `MediaPlayerCoreX`, open the file with audio rendering off if you only want captions: ``` var settings = new VLMSettings(modelFolder) { Task = VLMTask.Caption, DrawResults = true, }; var vlm = new VLMBlock(settings); vlm.OnResultGenerated += Vlm_OnResultGenerated; // VideoCaptureCoreX (live camera): core.Video_Processing_AddBlock(vlm); // before StartAsync await core.StartAsync(); // MediaPlayerCoreX (file): var source = await UniversalSourceSettings.CreateAsync(filePath, renderVideo: true, renderAudio: false); player.Video_Processing_AddBlock(vlm); // before OpenAsync / PlayAsync player.Video_Play = true; player.Audio_Play = false; await player.OpenAsync(source); await player.PlayAsync(); ``` `Task` and `TextInput` remain live-updatable while the session runs. See [Using AI blocks with VideoCaptureCoreX and MediaPlayerCoreX](../x-engines/) for the shared processing-block API and lifecycle rules. ## One model vs separate OCR, detection, and captioning `VLMBlock` can replace three separate pipelines — but the specialized blocks are faster at their one job. Pick by what you need: | You need | Best fit | | --- | --- | | A caption or description of the scene | `VLMBlock` (`Caption` / `DetailedCaption`) — no specialized block produces this. | | Text read from the frame | `VLMBlock` (`Ocr`), or [`OcrBlock`](../ocr/) when you need it faster (PaddleOCR). | | Boxes and labels for objects | `VLMBlock` (`ObjectDetection`), or [`YOLOObjectDetectorBlock`](../object-detection/) for much higher speed on fixed classes. | | Highest frame rate / real-time | A specialized block — `VLMBlock` is CPU-only and runs periodically. | | Several of the above from one model | `VLMBlock` — switch `Task` at runtime, a single model download. | Reach for `VLMBlock` when you want rich, flexible, natural-language output — or several of these results from one model at a relaxed cadence. Reach for the specialized blocks when you need one specific output at high frame rate. They compose: run a VLM for descriptions and a detector for real-time boxes in the same pipeline. ## Use cases - **Automatic scene descriptions** — caption a live camera or a recorded file for accessibility, logging, or search metadata. - **Content indexing** — run `DetailedCaption` at intervals to build a text summary track for a video archive. - **In-frame text extraction** — read on-screen text with `Ocr` / `OcrWithRegion` without a separate OCR pipeline. - **Visual question checks** — use `PhraseGrounding` to confirm whether a described situation ("a person wearing a helmet") is present and where. - **Lightweight object and region labeling** — `ObjectDetection` / `DenseRegionCaption` for label-and-box output when a trained detector isn't available. ## Troubleshooting | Symptom | Likely cause | Fix | | --- | --- | --- | | Startup error about a missing model file | Not all seven files are present in the model folder | Ensure the four `.onnx` models and three tokenizer files are downloaded before constructing `VLMSettings(modelFolder)`. | | `PhraseGrounding` returns nothing | `TextInput` is empty | Set `TextInput` to the caption whose phrases should be grounded. | | Grounding tasks produce no regions | `AddedTokensFilePath` missing | Grounding tasks need `florence2-added-tokens.json`; caption tasks do not. | | High CPU usage / low responsiveness | Frames captioned too often, or `MaxNewTokens` too high | Raise `ProcessingInterval`; lower `MaxNewTokens`. | | No GPU acceleration | By design | Florence-2 is CPU-only here; tune throughput with `ProcessingInterval` and `MaxNewTokens`. | ## Frequently Asked Questions ### How do I generate a description of a video frame in C#? Add a `VLMBlock` with `Task = VLMTask.DetailedCaption`, subscribe to `OnResultGenerated`, and read `e.Text` — that string is the frame's description. See [Usage](#usage). Use `ProcessingInterval` to control how often a description is produced. ### Can one model do both OCR and captioning? Yes — Florence-2 handles captioning, description, object detection, region description, OCR, and phrase grounding. Switch between them with the `Task` property (even at runtime) instead of loading separate models. See [Tasks](#tasks). ### Can I change the task without restarting the pipeline? Yes — set `VLMBlock.Task` (and `TextInput` for phrase grounding) at any time. The change applies on the next processed frame. ### Why doesn't setting a GPU provider speed it up? `VLMSettings` intentionally exposes no provider setting. The DirectML backend mis-executes Florence-2's merged decoder, so the block forces CPU. Throttle with `ProcessingInterval` instead. ### How often is a caption generated? At most once per `ProcessingInterval` (default 1 second). Frames arriving between inferences reuse the last result for the overlay, so live video never stalls waiting on the model. ### How is this different from OCR or object detection? [`OcrBlock`](../ocr/) and [`YOLOObjectDetectorBlock`](../object-detection/) are specialized, fast, and single-purpose. `VLMBlock` is a general model that can caption, describe, detect, ground, and read text — more flexible but heavier, and CPU-only. Use the specialized blocks when you need one of their exact outputs at speed; use `VLMBlock` for rich descriptions or when you want several of these outputs from one model. ### Can I ask a free-form question about the frame? Not as open-ended visual question answering — `VLMBlock` runs Florence-2's fixed `VLMTask` set (caption, describe, detect, region-caption, OCR, phrase grounding). The closest to a question is `PhraseGrounding`: put a described situation in `TextInput` and the model locates its phrases in the frame. For descriptions, use the caption tasks. ### What language is the output? Florence-2 generates English text for captions, descriptions, and OCR. ### How do I turn captions into a subtitle or metadata track? Each `OnResultGenerated` gives you the `Text` and the source-frame `Timestamp`. Collect those pairs as the file plays (or as the camera runs) and write them to your own SRT/VTT or a metadata index — the block produces the per-frame text and timing; assembling a track is your application's job. ### Does it need an internet connection? No. Inference is fully local ONNX. Only the first-run model download needs a network, and you can ship the model files with your app instead. ## Demos Dedicated demos built on Media Blocks, `VideoCaptureCoreX`, and `MediaPlayerCoreX` (`VLM Captioning Demo`, `VLM Captioning MB`, `Capture VLM Captioning X`, `Capture VLM Captioning X WPF`, `Player VLM Captioning X`, `Player VLM Captioning X WPF`) are in the SDK's demo set and will be linked here once published to the public samples repository. ---END OF PAGE--- ## AI Blocks with VideoCaptureCoreX and MediaPlayerCoreX **URL:** https://www.visioforge.com/help/docs/dotnet/general/ai/x-engines/ **Description:** Insert AI Media Blocks — OCR, object detection, face recognition, ANPR, background removal, speech-to-text — into VideoCaptureCoreX and MediaPlayerCoreX. **Tags:** .NET, AI, VideoCaptureCoreX, MediaPlayerCoreX, Media Blocks **API:** VideoCaptureCoreX, MediaPlayerCoreX, IVideoProcessingBlock, IAudioProcessingBlock, NullRendererBlock # AI Blocks with VideoCaptureCoreX and MediaPlayerCoreX `VideoCaptureCoreX` and `MediaPlayerCoreX` can host user-supplied Media Blocks inside their high-level pipelines. Use this path when you want the convenience of the X engines and only need to add AI processing to the video or audio chain — no manual `MediaBlocksPipeline` topology required. ``` using VisioForge.Core.MediaBlocks; using VisioForge.Core.MediaBlocks.AI; using VisioForge.Core.MediaBlocks.Special; using VisioForge.Core.Types.X.AI; ``` ## Public API Both engines expose the same processing-block API: | API | Purpose | | --- | --- | | `Video_Processing_AddBlock(IVideoProcessingBlock block)` | Add a video processing block for the next session. | | `Video_Processing_RemoveBlock(IVideoProcessingBlock block)` | Remove a registered video block before the session starts. | | `Video_Processing_Clear()` | Clear registered video blocks before the session starts. | | `Video_Processing_Blocks` | Snapshot of registered video blocks. | | `Audio_Processing_AddBlock(IAudioProcessingBlock block)` | Add an audio processing block for the next session. | | `Audio_Processing_RemoveBlock(IAudioProcessingBlock block)` | Remove a registered audio block before the session starts. | | `Audio_Processing_Clear()` | Clear registered audio blocks before the session starts. | | `Audio_Processing_Blocks` | Snapshot of registered audio blocks. | | `Audio_OutputBlock` | Replace the default audio sink with a custom `MediaBlock`, commonly a non-synced `NullRendererBlock` for speech-to-text. | Every video AI block (`OcrBlock`, `YOLOObjectDetectorBlock`, `ObjectAnalyticsBlock`, `FaceRecognitionBlock`, `LicensePlateRecognizerBlock`, `OpenVocabularyDetectorBlock`, `VLMBlock`, `VideoEmbeddingBlock`, `BackgroundRemovalBlock`, `OnnxInferenceBlock`) implements `IVideoProcessingBlock`. `SpeechToTextBlock` implements `IAudioProcessingBlock`. `VideoEmbeddingBlock` (semantic video search) is designed to index a **file** — use it with `MediaPlayerCoreX` (or a manual Media Blocks pipeline), typically with `Video_Renderer_IsSync = false` for full-speed offline indexing. There is no `VideoCaptureCoreX` capture demo for it; see [Semantic video search](../semantic-video-search/). ## Lifecycle rules Register blocks before the engine builds its pipeline: before `StartAsync` on `VideoCaptureCoreX`, before `OpenAsync`/`PlayAsync` on `MediaPlayerCoreX`. Adding, removing, or clearing processing blocks after the pipeline build has started is ignored and logged as a `Warning`: - `VideoCaptureCoreX`: *"Cannot add a processing block while capture is running. Add it before Start()."* - `MediaPlayerCoreX`: *"Cannot add a processing block while playback is running. Add it before Play()."* (The log text uses the classic `Start()`/`Play()` names even though the public API you call is `StartAsync()`/`PlayAsync()` — the warning strings predate the async wrappers and are quoted here verbatim so you can grep for them.) If you see one of these messages in the log, the block call happened after the session was already started (or starting) — move it earlier. Once the session starts, the engine owns wired processing blocks and disposes them when the session stops. Create a fresh block instance before each new session; block events are raised on pipeline or block worker threads — keep handlers non-blocking and marshal UI changes to the UI dispatcher or main thread. If a chain is inactive, its registered blocks don't run — for example, an audio processing block requires an audio source and a built audio chain. ## Pipeline insertion order - **`VideoCaptureCoreX`**: video AI blocks are inserted after video effects and before the sample grabber, overlay, tee, renderer, and outputs — so overlays the AI block draws reach both the preview and every recording/streaming output. - **`MediaPlayerCoreX`**: video AI blocks are inserted after video effects and before the sample grabber, renderer, and custom video outputs. ## VideoCaptureCoreX video AI ``` var detector = new YOLOObjectDetectorBlock(new YoloDetectorSettings(modelPath) { Model = ObjectDetectorModel.YOLOv8, DrawDetections = true, }); detector.OnObjectsDetected += (sender, e) => { // Raised from the streaming thread. Console.WriteLine($"Detected {e.Objects.Length} objects."); }; core.Video_Processing_AddBlock(detector); // before StartAsync await core.StartAsync(); ``` The same pattern applies to `OcrBlock`, `ObjectAnalyticsBlock`, `FaceRecognitionBlock`, `LicensePlateRecognizerBlock`, `OpenVocabularyDetectorBlock`, `VLMBlock`, `VideoEmbeddingBlock`, `BackgroundRemovalBlock`, and `OnnxInferenceBlock` — see each block's own page for its settings and event payload. ## VideoCaptureCoreX speech-to-text ``` core.Audio_Source = microphoneSettings; core.Audio_OutputBlock = new NullRendererBlock(MediaBlockPadMediaType.Audio) { IsSync = false, }; var sttSettings = new SpeechToTextSettings(whisperModelPath) { EnableVad = false, // or keep EnableVad = true and set sttSettings.Vad.ModelPath = sileroVadModelPath; }; var stt = new SpeechToTextBlock(sttSettings); stt.OnSpeechRecognized += SpeechToText_OnSpeechRecognized; core.Audio_Processing_AddBlock(stt); // before StartAsync await core.StartAsync(); ``` `EnableVad` defaults to `true`, which requires `SileroVadSettings.ModelPath` — the pipeline build fails if VAD is enabled but no model path is set. Either disable VAD or set `sttSettings.Vad.ModelPath` before registering the block. For capture, an audio source is required. `Audio_OutputBlock` can activate and terminate the audio chain without `Audio_Play`, `Audio_Record`, speaker monitoring, or a recording output. ## MediaPlayerCoreX video AI ``` var ocr = new OcrBlock(new OcrSettings( detectionModelPath, recognitionModelPath, characterDictionaryPath, classificationModelPath) { DrawResults = true, }); ocr.OnTextDetected += Ocr_OnTextDetected; player.Video_Processing_AddBlock(ocr); // before OpenAsync / PlayAsync await player.OpenAsync(source); await player.PlayAsync(); ``` ## MediaPlayerCoreX speech-to-text ``` player.Audio_Play = true; player.Audio_OutputBlock = new NullRendererBlock(MediaBlockPadMediaType.Audio) { IsSync = false, }; var sttSettings = new SpeechToTextSettings(whisperModelPath) { EnableVad = false, // or keep EnableVad = true and set sttSettings.Vad.ModelPath = sileroVadModelPath; }; var stt = new SpeechToTextBlock(sttSettings); stt.OnSpeechRecognized += SpeechToText_OnSpeechRecognized; player.Audio_Processing_AddBlock(stt); // before OpenAsync / PlayAsync await player.OpenAsync(source); await player.PlayAsync(); ``` For playback, `Audio_Play` must be `true` for the audio chain to be built. Replacing the sink with a non-synced null renderer avoids speaker output and does not pace transcription to real-time playback. ## Troubleshooting | Symptom | Likely cause | Fix | | --- | --- | --- | | Block's events never fire, no warning logged | Block registered after the session was already running | Register with `Video_Processing_AddBlock`/`Audio_Processing_AddBlock` before `StartAsync` (`VideoCaptureCoreX`) or before `OpenAsync`/`PlayAsync` (`MediaPlayerCoreX`). | | Log shows *"Cannot add a processing block while capture/playback is running..."* | Same as above — the call happened after the pipeline started building | Move the `Video_Processing_AddBlock`/`Audio_Processing_AddBlock` call earlier in your startup sequence. | | `SpeechToTextBlock` never receives audio on `VideoCaptureCoreX` | No `Audio_Source` configured | An audio processing block requires a built audio chain — set `Audio_Source` (and, if you don't want speaker output, `Audio_OutputBlock` to a non-synced `NullRendererBlock`). | | `SpeechToTextBlock` never receives audio on `MediaPlayerCoreX` | `Audio_Play` left at its default | Set `player.Audio_Play = true` before `OpenAsync`; the audio chain isn't built otherwise, regardless of registered audio blocks. | | AI block's overlay doesn't appear in the recorded/streamed output, only the preview | Block registered on the wrong chain, or inserted after the point the engine builds outputs | Video AI blocks are inserted before the sample grabber/overlay/tee/renderer/outputs — see [Pipeline insertion order](#pipeline-insertion-order) — so this is usually a registration-timing issue, not a topology one. | | Block instance reused across a second `StartAsync`/`PlayAsync` throws or behaves oddly | The engine already disposed the previous session's block instance | Create a fresh block instance (and re-subscribe to its events) for every new capture/playback session. | ## Frequently Asked Questions ### Do I need to rebuild a manual MediaBlocksPipeline to use AI blocks with VideoCaptureCoreX/MediaPlayerCoreX? No — that's the point of this integration. `Video_Processing_AddBlock`/`Audio_Processing_AddBlock` insert the same AI block instances into the engine's existing internal pipeline; you don't construct or manage any `MediaBlocksPipeline` yourself. ### Can I add or remove AI blocks while capture/playback is running? No — additions/removals/clears are ignored (and logged as a warning) once the pipeline build has started. Register everything you need before `StartAsync` / `OpenAsync`+`PlayAsync`, and start a new session with fresh block instances if the set of blocks needs to change. ### Do video AI blocks slow down recording or streaming outputs? They add their own inference cost to the video chain, since they run in-line before the renderer and outputs. Use `FramesToSkip` (available on every video AI block's settings) and, where available, a GPU execution provider to keep that cost bounded. ### Can I combine multiple AI blocks — for example object detection and speech-to-text — in one session? Yes — register one or more `IVideoProcessingBlock`s with `Video_Processing_AddBlock` and, separately, an `IAudioProcessingBlock` (like `SpeechToTextBlock`) with `Audio_Processing_AddBlock`, all before the session starts. Video and audio processing chains are independent. ## Demos Every block covered on this page also has focused Media Blocks pipeline demos — see the **Demos** section on each block's own page ([OCR](../ocr/#demos), [Object detection](../object-detection/#demos), [Object analytics](../object-analytics/#demos), [Face recognition](../face-recognition/#demos), [License plate recognition](../license-plate-recognition/#demos), [Background removal](../background-removal/#demo), [Speech-to-text](../speech-to-text/#demos)). The SDK's demo set additionally ships 16 demos built directly on `VideoCaptureCoreX` / `MediaPlayerCoreX` using the API on this page — Object Detection, OCR, Face Recognition, and Live Subtitles, each for both WPF and MAUI, on both the capture and playback engines (`Capture Object Detection X`, `Capture Object Detection X WPF`, `Capture OCR X`, `Capture OCR X WPF`, `Capture Face Recognition X`, `Capture Face Recognition X WPF`, `Capture Live Subtitles X`, `Capture Live Subtitles X WPF`, `Player Object Detection X`, `Player Object Detection X WPF`, `Player OCR X`, `Player OCR X WPF`, `Player Face Recognition X`, `Player Face Recognition X WPF`, `Player Live Subtitles X`, `Player Live Subtitles X WPF`). GitHub links will be added here once these demos are published to the public samples repository. ---END OF PAGE--- ## Audio Sample Grabber for .NET - Capture Raw Audio Frames **URL:** https://www.visioforge.com/help/docs/dotnet/general/audio-effects/audio-sample-grabber/ **Description:** Capture and process real-time audio frames using Audio Sample Grabber with X-engines and Classic engines in .NET SDK applications. **Tags:** Video Capture SDK, Media Player SDK, Media Blocks SDK, Video Edit SDK, .NET, VideoEditCore, Windows, Editing, C# **API:** AudioFrameBufferEventArgs, AudioSampleGrabberBlock # Working with Audio Sample Grabber in .NET SDKs [Video Capture SDK .Net](https://www.visioforge.com/video-capture-sdk-net) [Video Edit SDK .Net](https://www.visioforge.com/video-edit-sdk-net) [Media Player SDK .Net](https://www.visioforge.com/media-player-sdk-net) [Media Blocks SDK .Net](https://www.visioforge.com/media-blocks-sdk-net) ## Introduction to Audio Sample Grabber The Audio Sample Grabber is a powerful feature available across our .NET SDKs that enables developers to access raw audio frames directly from both live sources and media files. This capability opens up a wide range of possibilities for audio processing, analysis, and manipulation in your applications. When working with audio processing, gaining access to individual audio frames is essential for tasks such as: - Real-time audio visualization - Custom audio effects processing - Speech recognition integration - Audio analysis and metrics - Custom audio format conversion - Sound detection algorithms The `OnAudioFrameBuffer` event is the core mechanism that provides access to these raw audio frames. This event fires each time a new audio frame is available, giving you direct access to unmanaged memory containing the decoded audio data. ## How Audio Sample Grabber Works The Audio Sample Grabber intercepts the audio pipeline during playback or capture, providing you with the raw audio data before it's rendered to the output device. This data is typically in PCM (Pulse Code Modulation) format, which is the standard format for uncompressed digital audio, but can occasionally be in IEEE floating-point format depending on the audio source. Each time the `OnAudioFrameBuffer` event fires, it provides an `AudioFrameBufferEventArgs` object containing critical information about the audio frame: - `Frame.Data`: An `IntPtr` pointing to the unmanaged memory block containing the raw audio data - `Frame.DataSize`: The size of the audio data in bytes - `Frame.Info`: A structure containing detailed information about the audio format, including: - Channel count (mono, stereo, etc.) - Sample rate (typically 44.1kHz, 48kHz, etc.) - Bits per sample (16-bit, 24-bit, etc.) - Audio format type (PCM, IEEE, etc.) - Timestamp information - Block alignment and other format-specific details ## Setting Up Audio Sample Grabber The setup process varies slightly depending on whether you're using our newer X-engines or the Classic engines. Let's explore both approaches: X-enginesClassic enginesMedia Blocks SDK For X-engines, setting up the Audio Sample Grabber is straightforward. You simply need to create an event handler for the `OnAudioFrameBuffer` event: ``` VideoCapture1.OnAudioFrameBuffer += OnAudioFrameBuffer; ``` The X-engines architecture automatically enables audio sample grabbing when you subscribe to this event, with no additional configuration required. When using Classic engines, you need to explicitly enable the Audio Sample Grabber functionality before creating the event handler: ``` VideoCapture1.Audio_Sample_Grabber_Enabled = true; ``` Then, as with X-engines, create your event handler: ``` VideoCapture1.OnAudioFrameBuffer += OnAudioFrameBuffer; ``` **Note**: The `Audio_Sample_Grabber_Enabled` property is not required for the VideoEditCore component, which has audio sample grabbing enabled by default. The Media Blocks SDK also supports audio sample grabbing. Use the `AudioSampleGrabberBlock` component to capture audio frames. ``` private AudioSampleGrabberBlock _audioSampleGrabberSink; ``` Then, as with X-engines, create your event handler, and specify the audio format: ``` _audioSampleGrabberBlock = new AudioSampleGrabberBlock(VisioForge.Core.Types.X.AudioFormatX.S16LE); _audioSampleGrabberBlock.OnAudioFrameBuffer += OnAudioFrameBuffer; ``` ## Processing Audio Frames Once you've set up the event handler, you can process the audio frames as they arrive. Here's a basic example of how to handle the `OnAudioFrameBuffer` event: ``` using VisioForge.Types; using System.Diagnostics; private void OnAudioFrameBuffer(object sender, AudioFrameBufferEventArgs e) { // Log audio frame information Debug.WriteLine($"Audio frame: {e.Frame.DataSize} bytes; Format: {e.Frame.Info}"); // Access to raw audio data through the unmanaged pointer IntPtr rawAudioData = e.Frame.Data; // Get audio format details. RAWBaseAudioInfo carries four fields: // Channels, SampleRate, BPS (bits-per-sample), Format (AudioFormat enum). int channelCount = e.Frame.Info.Channels; int sampleRate = e.Frame.Info.SampleRate; int bitsPerSample = e.Frame.Info.BPS; AudioFormat format = e.Frame.Info.Format; // Your custom audio processing code here // ... } ``` ## Working with Audio Data ### Converting Unmanaged Memory to Managed Arrays While the `e.Frame.Data` provides a pointer to unmanaged memory, you often need to work with the data in a more convenient form. The `AudioFrame` class provides a helpful `GetDataArray()` method that returns a copy of the audio data as a byte array: ``` private void VideoCapture1_OnAudioFrameBuffer(object sender, AudioFrameBufferEventArgs e) { // Get a managed copy of the audio data byte[] audioData = e.Frame.GetDataArray(); // Now you can work with the data using standard C# array operations // ... } ``` ### Converting PCM Data to Samples For many audio processing tasks, you'll want to convert the raw PCM bytes into actual audio sample values. Here's a helper method to convert a PCM byte array to an array of audio samples (assuming 16-bit samples): ``` private short[] ConvertBytesToSamples(byte[] audioData) { short[] samples = new short[audioData.Length / 2]; for (int i = 0; i < samples.Length; i++) { // Combine two bytes into one 16-bit sample samples[i] = (short)(audioData[i * 2] | (audioData[i * 2 + 1] << 8)); } return samples; } ``` ### Handling Multi-Channel Audio When working with stereo or multi-channel audio, the samples are typically interleaved. For a stereo stream, the data is arranged as: [Left0, Right0, Left1, Right1, ...]. You may want to separate these channels for processing: ``` private void ProcessStereoAudio(short[] samples, int channelCount) { if (channelCount != 2) return; // Create arrays for each channel int samplesPerChannel = samples.Length / 2; short[] leftChannel = new short[samplesPerChannel]; short[] rightChannel = new short[samplesPerChannel]; // Separate the channels for (int i = 0; i < samplesPerChannel; i++) { leftChannel[i] = samples[i * 2]; rightChannel[i] = samples[i * 2 + 1]; } // Process each channel separately // ... } ``` ## Common Audio Processing Scenarios ### Audio Level Metering A common use case for the Audio Sample Grabber is to implement audio level metering: ``` private void CalculateAudioLevel(short[] samples) { double sum = 0; // Calculate RMS (Root Mean Square) value foreach (short sample in samples) { sum += sample * sample; } double rms = Math.Sqrt(sum / samples.Length); // Convert to decibels double db = 20 * Math.Log10(rms / 32768); // Update UI with the level (you'll need to invoke if on a different thread) Debug.WriteLine($"Audio level: {db} dB"); } ``` ### Real-time FFT for Spectrum Analysis For frequency spectrum analysis, you might want to perform an FFT (Fast Fourier Transform) on the audio data: ``` // Note: You'll need a library for FFT calculation // This is a simplified example private void PerformFFTAnalysis(short[] samples) { // Typically you would use a library like Math.NET Numerics // Convert samples to complex numbers Complex[] complex = samples.Select(s => new Complex(s, 0)).ToArray(); // Perform FFT (pseudocode) // Complex[] fftResult = FFT.Forward(complex); // Process FFT results // ... } ``` ## Performance Considerations When working with the Audio Sample Grabber, keep these performance considerations in mind: 1. **Minimize Processing Time**: The `OnAudioFrameBuffer` event is called on the audio processing thread. Long-running operations can cause audio glitches. 2. **Consider Thread Safety**: If you need to update UI elements or interact with other components, use proper thread synchronization methods. 3. **Avoid Memory Allocations**: Frequent memory allocations in the event handler can lead to garbage collection pauses. Reuse arrays where possible. 4. **Buffer Copying**: The `GetDataArray()` method creates a copy of the audio data. For very high-performance scenarios, consider working directly with the unmanaged pointer. ## Conclusion The Audio Sample Grabber provides a powerful way to access and process raw audio data in real-time from both live sources and media files. By leveraging this functionality, you can implement sophisticated audio processing features in your applications, from simple level metering to complex audio analysis and effects processing. Whether you're building a professional audio application, implementing audio visualization, or integrating with speech recognition services, the Audio Sample Grabber gives you the raw data you need to bring your audio processing ideas to life. --- Visit our [GitHub](https://github.com/visioforge/.Net-SDK-s-samples) page to get more code samples. ---END OF PAGE--- ## Audio Effects in C# and .NET - EQ, Reverb, Filters, and More **URL:** https://www.visioforge.com/help/docs/dotnet/general/audio-effects/ **Description:** Apply real-time audio effects in C# and .NET with VisioForge SDKs. Equalizer, reverb, echo, noise reduction, pitch shift, and 30+ effects. **Tags:** Video Capture SDK, Media Blocks SDK, Video Edit SDK, .NET, Windows, macOS, Linux, Android, iOS, Capture, Playback, Streaming, Editing **API:** VolumeAudioEffect, Equalizer10AudioEffect, VideoCaptureCoreX, MediaPlayerCoreX, CompressorExpanderAudioEffect # Real-Time Audio Effects for .NET Applications [Video Capture SDK .Net](https://www.visioforge.com/video-capture-sdk-net) [Video Edit SDK .Net](https://www.visioforge.com/video-edit-sdk-net) [Media Blocks SDK .Net](https://www.visioforge.com/media-blocks-sdk-net) VisioForge Media Framework provides over 30 audio effects for real-time audio processing in C# and .NET applications. Built on GStreamer, the cross-platform effects include equalizers, reverb, echo, dynamic compression, filters, pitch shifting, AI-based noise reduction, and more — all running on Windows, macOS, Linux, iOS, and Android. ## SDKs and Platforms ### Cross-Platform Effects - **SDKs**: Media Blocks SDK, Video Capture SDK (VideoCaptureCoreX), Media Player SDK (MediaPlayerCoreX) - **Platforms**: Windows, macOS, Linux, iOS, Android - **Namespace**: `VisioForge.Core.Types.X.AudioEffects` ### Classic DSP Effects - **SDKs**: Video Capture SDK (VideoCaptureCore), Media Player SDK (MediaPlayerCore), Video Edit SDK (VideoEditCore) - **Platforms**: Windows only - **Namespace**: `VisioForge.Core.DSP` ### DirectSound Effects - **SDKs**: Video Capture SDK, Media Player SDK, Video Edit SDK (Classic cores) - **Platforms**: Windows only - **Namespace**: `VisioForge.Core.Types.X._Windows.AudioEffects` For detailed parameters and properties of each effect, see [Audio Effects Reference](reference/). ## Effect Categories ### Volume and Dynamics - **VolumeAudioEffect** — Basic volume control with mute functionality - **AmplifyAudioEffect** — Audio signal amplification with clipping control - **CompressorExpanderAudioEffect** — Dynamic range compression and expansion - **DynamicAmplifyAudioEffect** — Adaptive gain control with attack/release times ### Equalization - **Equalizer10AudioEffect** — 10-band graphic equalizer with fixed frequencies - **EqualizerParametricAudioEffect** — Parametric equalizer with configurable bands - **TrebleEnhancerAudioEffect** — High-frequency boost - **TrueBassAudioEffect** — Low-frequency boost ### Filters - **HighPassAudioEffect** — High-pass filter for removing low frequencies - **LowPassAudioEffect** — Low-pass filter for removing high frequencies - **BandPassAudioEffect** — Band-pass filter for specific frequency ranges - **NotchAudioEffect** — Notch filter for removing specific frequencies - **ChebyshevLimitAudioEffect** — Chebyshev low/high-pass filters with sharp cutoffs - **ChebyshevBandPassRejectAudioEffect** — Chebyshev band-pass/reject filters ### Spatial and Stereo - **BalanceAudioEffect** — Stereo balance control (pan left/right) - **WideStereoAudioEffect** — Stereo width enhancement - **Sound3DAudioEffect** — 3D spatial audio effects - **HRTFRenderAudioEffect** — Head-Related Transfer Function spatial audio - **PhaseInvertAudioEffect** — Phase inversion for polarity correction ### Time-Based Effects - **EchoAudioEffect** — Echo and delay effects - **RSAudioEchoAudioEffect** — Enhanced echo with advanced controls - **ReverberationAudioEffect** — Room reverberation (Freeverb algorithm) - **FadeAudioEffect** — Fade in/out volume automation ### Modulation Effects - **PhaserAudioEffect** — Phaser effect with LFO modulation - **FlangerAudioEffect** — Flanging effect with delay modulation ### Pitch and Tempo - **PitchShiftAudioEffect** — Pitch shifting without tempo change - **ScaleTempoAudioEffect** — Tempo change without pitch shift ### Special Effects - **KaraokeAudioEffect** — Vocal removal for karaoke - **RemoveSilenceAudioEffect** — Automatic silence detection and removal - **CsoundAudioEffect** — Advanced Csound-based audio processing ### Noise Reduction and Measurement - **AudioRNNoiseAudioEffect** — AI-based noise reduction using RNN - **AudioLoudNormAudioEffect** — EBU R128 loudness normalization - **EbuR128LevelAudioEffect** — EBU R128 loudness measurement ### Channel Management - **ChannelOrderAudioEffect** — Channel remapping and routing - **DownMixAudioEffect** — Multi-channel to stereo/mono downmixing ### DirectSound Effects (Windows Only, Classic SDKs) - **DS Chorus** — Multiple delayed and modulated copies - **DS Distortion** — Audio distortion/overdrive - **DS Gargle** — Gargling/tremolo modulation - **DS Reverb (I3DL2)** — Professional reverb with environmental modeling - **DS Waves Reverb** — Simplified reverb ## GStreamer Elements All cross-platform audio effects are built on top of GStreamer multimedia framework. Each effect wraps one or more GStreamer elements: | Category | GStreamer Elements | | --- | --- | | Volume/Dynamics | volume, audioamplify, audiodynamic | | Equalization | equalizer-10bands, equalizer-nbands | | Filters | audiocheblimit, audiochebband, audioiirfilter | | Spatial | audiopanorama, stereo, hrtfrender | | Time-Based | audioecho, rsaudioecho, freeverb | | Modulation | Custom phaser/flanger implementations | | Pitch/Tempo | scaletempo, pitch (SoundTouch) | | Special | audiokaraoke, csoundfilter, removesilence | | Noise Reduction | audiornnoise, audioloudnorm, ebur128level | | Channels | audioconvert, custom routing | ## Common Usage Patterns ### Adding Effects (Cross-Platform SDKs) ``` // Create an audio effect var volumeEffect = new VolumeAudioEffect(1.5); // 150% volume // VideoCaptureCoreX / MediaPlayerCoreX core.Audio_Effects_AddOrUpdate(volumeEffect); ``` ### Combining Multiple Effects Effects are processed in the order they are added: ``` // Create a processing chain core.Audio_Effects_AddOrUpdate(new HighPassAudioEffect(80)); // Remove rumble core.Audio_Effects_AddOrUpdate(new CompressorExpanderAudioEffect()); // Compress dynamics core.Audio_Effects_AddOrUpdate(new Equalizer10AudioEffect(levels)); // EQ adjustments core.Audio_Effects_AddOrUpdate(new ReverberationAudioEffect()); // Add reverb ``` ### Real-Time Parameter Updates Most effects support real-time parameter changes: ``` var volumeEffect = new VolumeAudioEffect(1.0); core.Audio_Effects_AddOrUpdate(volumeEffect); // Later, during playback: volumeEffect.Level = 0.5; // Reduce volume to 50% volumeEffect.Mute = true; // Mute audio core.Audio_Effects_AddOrUpdate(volumeEffect); // Apply changes ``` ### Media Blocks SDK Usage For Media Blocks SDK pipeline-based usage with dedicated audio effect blocks, see [Audio Processing and Effect Blocks](../../mediablocks/AudioProcessing/). ## Performance Considerations - **CPU Usage**: Complex effects like reverberation, Csound, and multiple equalizers can be CPU-intensive - **Effect Order**: Place computationally expensive effects after simpler ones to reduce processing load - **Real-Time Processing**: All effects are designed for real-time audio streaming ## Frequently Asked Questions What audio effects are available in VisioForge .NET SDKs? VisioForge provides 30+ audio effects including volume control, 10-band and parametric equalizers, reverb, echo, compressor/expander, high/low/band-pass filters, pitch shift, noise reduction (RNN-based), karaoke vocal removal, 3D spatial audio, and more. All cross-platform effects work on Windows, macOS, Linux, iOS, and Android. How do I add audio effects to my C# application? Create an effect instance and add it using `Audio_Effects_AddOrUpdate()`. For example: ``` // 10-band EQ: all bands at 0 dB (neutral) var eq = new Equalizer10AudioEffect(new double[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }); core.Audio_Effects_AddOrUpdate(eq); ``` Effects can be added, updated, and removed during playback. For Media Blocks SDK, use the `AudioEffectsBlock`. Can I chain multiple audio effects together? Yes. Effects are processed in the order they are added. You can create complex processing chains combining filters, EQ, compression, reverb, and other effects. Each effect processes the audio output of the previous one. Do audio effects work in real-time during playback? Yes. All VisioForge audio effects support real-time parameter changes. You can adjust volume, EQ bands, reverb levels, and other parameters while audio is playing without interrupting the stream. What is the difference between cross-platform and DirectSound effects? Cross-platform effects (namespace `VisioForge.Core.Types.X.AudioEffects`) work on all platforms using GStreamer. DirectSound effects are Windows-only and available in the classic SDK cores. Cross-platform effects cover the same functionality and more. ## See Also - [Audio Effects Reference](reference/) - [Audio Sample Grabber](audio-sample-grabber/) - [Audio Encoders](../audio-encoders/) - [Audio Processing Blocks (Media Blocks SDK)](../../mediablocks/AudioProcessing/) ---END OF PAGE--- ## Audio Effects API Reference for .NET - Parameters & Examples **URL:** https://www.visioforge.com/help/docs/dotnet/general/audio-effects/reference/ **Description:** API reference for 30+ audio effects in VisioForge .NET SDKs. Volume, EQ, compressor, reverb, echo, filters, pitch shift, and noise reduction with C# examples. **Tags:** Video Capture SDK, Media Blocks SDK, Video Edit SDK, .NET, MediaPlayerCoreX, VideoCaptureCoreX, VideoEditCore, Windows, macOS, Linux, Android, iOS, GStreamer, Capture, Playback, Streaming, Editing, Effects, C# **API:** VolumeAudioEffect, Equalizer10AudioEffect, BandPassAudioEffect, BalanceAudioEffect, WideStereoAudioEffect # Audio Effects API Reference [Video Capture SDK .Net](https://www.visioforge.com/video-capture-sdk-net) [Video Edit SDK .Net](https://www.visioforge.com/video-edit-sdk-net) [Media Blocks SDK .Net](https://www.visioforge.com/media-blocks-sdk-net) Complete parameter reference for all audio effects available in VisioForge .NET SDKs. Each cross-platform effect wraps a GStreamer element and supports real-time parameter changes from C# code during playback. Cross-platform effects work on Windows, macOS, Linux, iOS, and Android. For an overview of effect categories and usage patterns, see [Audio Effects](../). ## Volume and Dynamics Effects ### VolumeAudioEffect **GStreamer Element**: `volume` **Purpose**: Control audio volume level with optional mute. **Parameters**: - `Level` (double): Volume multiplier - Range: 0.0 to unlimited - Default: 1.0 (100%) - Examples: 0.5 = 50%, 2.0 = 200% - `Mute` (bool): Mute audio output - Default: false **Usage**: ``` var effect = new VolumeAudioEffect(1.5); // 150% volume effect.Mute = true; // Temporarily mute ``` --- ### AmplifyAudioEffect **GStreamer Element**: `audioamplify` **Purpose**: Amplify audio with clipping control. **Parameters**: - `Level` (double): Amplification level - Range: 1.0 to 10.0 - Default: 1.0 - `ClippingMethod` (AmplifyClippingMethod): How to handle peaks - Options: Normal, WrapNegative, WrapPositive, NoClip - Default: Normal **Usage**: ``` var effect = new AmplifyAudioEffect(2.0); effect.ClippingMethod = AmplifyClippingMethod.NoClip; ``` --- ### CompressorExpanderAudioEffect **GStreamer Element**: `audiodynamic` **Purpose**: Dynamic range compression or expansion. **Parameters**: - `Threshold` (double): Activation threshold - Range: 0.0 to 1.0 - Default: 0.0 - `Ratio` (double): Compression/expansion ratio - Range: 1.0+ - Default: 1.0 - Typical: 2:1 to 10:1 for compression - `Mode` (AudioCompressorMode): Compressor or Expander - Default: Compressor - `Characteristics` (AudioDynamicCharacteristics): HardKnee or SoftKnee - Default: SoftKnee **Usage**: ``` var effect = new CompressorExpanderAudioEffect(); effect.Threshold = 0.5; effect.Ratio = 4.0; // 4:1 compression effect.Characteristics = AudioDynamicCharacteristics.SoftKnee; ``` --- ### DynamicAmplifyAudioEffect **Purpose**: Adaptive gain control. **Parameters**: - `AttackTime` (uint): Response time in ms - Typical: 10-100 ms - `MaxAmplification` (uint): Maximum gain - 10000 = 1x (no change) - 20000 = 2x amplification - Default: 10000 - `ReleaseTime` (TimeSpan): Time before resuming amplification - Typical: 100-1000 ms **Usage**: ``` var effect = new DynamicAmplifyAudioEffect(50, 20000, TimeSpan.FromMilliseconds(500)); ``` --- ## Equalization Effects ### Equalizer10AudioEffect **GStreamer Element**: `equalizer-10bands` **Purpose**: 10-band graphic equalizer with fixed frequencies. **Frequency Bands**: 1. 29 Hz (Sub-bass) 2. 59 Hz (Bass) 3. 119 Hz (Bass) 4. 237 Hz (Low midrange) 5. 474 Hz (Midrange) 6. 947 Hz (Midrange) 7. 1889 Hz (Upper midrange) 8. 3770 Hz (Presence) 9. 7523 Hz (Brilliance) 10. 15011 Hz (Air) **Parameters**: - `Levels` (double[]): Gain for each band in dB - Range per band: -24 to +12 dB - Array must contain exactly 10 values **Usage**: ``` var levels = new double[] { 3.0, // 29 Hz: +3 dB 2.0, // 59 Hz: +2 dB 0.0, // 119 Hz: 0 dB (no change) -2.0, // 237 Hz: -2 dB 0.0, // 474 Hz 0.0, // 947 Hz 1.0, // 1889 Hz: +1 dB 2.0, // 3770 Hz: +2 dB 3.0, // 7523 Hz: +3 dB 4.0 // 15011 Hz: +4 dB }; var effect = new Equalizer10AudioEffect(levels); ``` --- ### EqualizerParametricAudioEffect **GStreamer Element**: `equalizer-nbands` **Purpose**: Parametric equalizer with configurable bands. **Parameters**: - `Bands` (ParametricEqualizerBand[]): Array of bands - Count: 1 to 64 bands - Each band: Frequency, Gain, Width (bandwidth in Hz) **Usage**: ``` var effect = new EqualizerParametricAudioEffect(3); effect.Bands[0].Frequency = 100; // Hz effect.Bands[0].Gain = -6; // dB effect.Bands[0].Width = 1.0f; // bandwidth // Configure other bands... effect.Update(); // Apply changes ``` --- ### TrebleEnhancerAudioEffect **Purpose**: Boost high frequencies. **Parameters**: - `Frequency` (int): Starting frequency in Hz - Typical: 4000-8000 Hz - Frequencies above this are boosted - `Volume` (ushort): Boost amount - Range: 0 to 10000 - 0 = no effect **Usage**: ``` var effect = new TrebleEnhancerAudioEffect(6000, 5000); ``` --- ### TrueBassAudioEffect **Purpose**: Boost low frequencies. **Parameters**: - `Frequency` (int): Upper frequency limit in Hz - Typical: 100-300 Hz - Frequencies below this are boosted - `Volume` (ushort): Boost amount - Range: 0 to 10000 - 0 = no effect **Usage**: ``` var effect = new TrueBassAudioEffect(150, 5000); ``` --- ## Filter Effects ### HighPassAudioEffect **Implementation**: Custom DSP (IIR high-pass filter) **Purpose**: Remove low frequencies. **Parameters**: - `CutOff` (uint): Cutoff frequency in Hz - Frequencies below are attenuated - Typical: 80-200 Hz for voice, 40 Hz for music **Common Frequencies**: - 20-40 Hz: Sub-sonic removal - 60-80 Hz: Rumble removal - 100-150 Hz: Clarity improvement **Usage**: ``` var effect = new HighPassAudioEffect(100); // Remove frequencies below 100 Hz ``` --- ### LowPassAudioEffect **Implementation**: Custom DSP (IIR low-pass filter) **Purpose**: Remove high frequencies. **Parameters**: - `CutOff` (uint): Cutoff frequency in Hz - Frequencies above are attenuated - Typical: 8000-12000 Hz for hiss removal **Common Frequencies**: - 15000-20000 Hz: Gentle air reduction - 8000-10000 Hz: Warmth - 3000-5000 Hz: Telephone effect **Usage**: ``` var effect = new LowPassAudioEffect(10000); // Remove frequencies above 10 kHz ``` --- ### BandPassAudioEffect **Implementation**: Custom DSP (state-variable filter) **Purpose**: Allow only specific frequency range. **Parameters**: - `CutOffHigh` (float): Upper frequency boundary in Hz - `CutOffLow` (float): Lower frequency boundary in Hz **Usage**: ``` // Constructor: BandPassAudioEffect(cutOffHigh, cutOffLow) var effect = new BandPassAudioEffect(5000, 300); // Allow 300-5000 Hz ``` --- ### NotchAudioEffect **Implementation**: Custom DSP (band-reject filter) **Purpose**: Remove specific frequency. **Parameters**: - `CutOff` (uint): Center frequency to remove in Hz - Typical: 50/60 Hz for hum removal **Usage**: ``` var effect = new NotchAudioEffect(60); // Remove 60 Hz hum ``` --- ### ChebyshevLimitAudioEffect **GStreamer Element**: `audiocheblimit` **Purpose**: Sharp low/high-pass filtering with ripple control. **Parameters**: - `CutOffFrequency` (float): Cutoff frequency in Hz - `Mode` (ChebyshevLimitAudioEffectMode): LowPass or HighPass - `Poles` (int): Filter order (2-8 typical) - Default: 4 - More poles = steeper rolloff - `Ripple` (float): Passband ripple in dB - Default: 0.25 - `Type` (int): Chebyshev type (1 or 2) - Default: 1 **Usage**: ``` var effect = new ChebyshevLimitAudioEffect(); effect.CutOffFrequency = 100; effect.Mode = ChebyshevLimitAudioEffectMode.HighPass; effect.Poles = 6; ``` --- ### ChebyshevBandPassRejectAudioEffect **GStreamer Element**: `audiochebband` **Purpose**: Sharp band-pass or band-reject filtering. **Parameters**: - `LowerFrequency` (float): Lower band boundary in Hz - `UpperFrequency` (float): Upper band boundary in Hz - `Mode` (ChebyshevBandPassRejectAudioEffectMode): BandPass or BandReject - `Poles` (int): Filter order (2-8 typical) - Default: 4 - `Ripple` (float): Passband ripple in dB - Default: 0.25 - `Type` (int): Chebyshev type (1 or 2) - Default: 1 **Usage**: ``` var effect = new ChebyshevBandPassRejectAudioEffect(); effect.LowerFrequency = 300; effect.UpperFrequency = 3000; effect.Mode = ChebyshevBandPassRejectAudioEffectMode.BandPass; ``` --- ## Spatial and Stereo Effects ### BalanceAudioEffect **GStreamer Element**: `audiopanorama` **Purpose**: Stereo balance (pan) control. **Parameters**: - `Level` (double): Balance position - Range: -1.0 to 1.0 - -1.0 = full left - 0.0 = center - 1.0 = full right - Default: 0.0 **Usage**: ``` var effect = new BalanceAudioEffect(-0.5); // Pan 50% left ``` --- ### WideStereoAudioEffect **GStreamer Element**: `stereo` **Purpose**: Enhance stereo width. **Parameters**: - `Level` (float): Widening intensity - Range: 0.0+ - Default: 0.01 - Typical: 0.01 to 1.0 - Higher values = wider stereo field **Usage**: ``` var effect = new WideStereoAudioEffect(); effect.Level = 0.5f; ``` --- ### Sound3DAudioEffect **Purpose**: 3D spatial audio simulation. **Parameters**: - `Value` (uint): Spatial amplification - Range: 1 to 20000 - 1000 = neutral (disabled) - < 1000 = narrower stereo - > 1000 = wider stereo - > 10000 may distort **Usage**: ``` var effect = new Sound3DAudioEffect(2000); // 2x spatial width ``` --- ### PhaseInvertAudioEffect **Purpose**: Invert audio phase by 180 degrees. **Parameters**: None. **Usage**: ``` var effect = new PhaseInvertAudioEffect(); ``` --- ### HRTFRenderAudioEffect **GStreamer Element**: `hrtfrender` (rsaudiofx) **Purpose**: HRTF-based 3D spatial audio. **Parameters**: - `HrirFile` (string): Path to an hrtfrender HRIR binary (not a SOFA file) - `InterpolationSteps` (ulong): Interpolation quality - Default: 8 - `BlockLength` (ulong): Processing block size - Default: 512 - `DistanceGain` (float): Distance attenuation factor - Default: 1.0 **Usage**: Download a compatible HRIR binary from [hrir\_sphere\_builder](https://github.com/mrDIMAS/hrir_sphere_builder/tree/master/hrtf_base/IRCAM). ``` var effect = new HRTFRenderAudioEffect("IRC_1002_C.bin"); effect.InterpolationSteps = 16; // Higher quality ``` --- ## Time-Based Effects ### EchoAudioEffect **GStreamer Element**: `audioecho` **Purpose**: Echo and delay effects. **Parameters**: - `Delay` (TimeSpan): Echo delay time - Must not exceed MaxDelay - `MaxDelay` (TimeSpan): Maximum delay buffer - Must be >= Delay - Set before starting playback - `Intensity` (float): Echo volume - Range: 0.0 to 1.0 - Default: 1.0 - `Feedback` (float): Echo repetition amount - Range: 0.0 to 1.0 - Default: 0.0 - Higher = more echoes **Usage**: ``` var delay = TimeSpan.FromMilliseconds(500); var effect = new EchoAudioEffect(delay); effect.Intensity = 0.7f; effect.Feedback = 0.4f; ``` --- ### RSAudioEchoAudioEffect **GStreamer Element**: `rsaudioecho` (rsaudiofx) **Purpose**: Enhanced echo with advanced controls. **Parameters**: - `Delay` (TimeSpan): Echo delay time - `MaxDelay` (TimeSpan): Maximum delay buffer - `Intensity` (double): Echo intensity - Range: 0.0 to 1.0 - `Feedback` (double): Feedback amount - Range: 0.0 to 1.0 **Usage**: ``` var effect = new RSAudioEchoAudioEffect(); effect.Delay = TimeSpan.FromMilliseconds(750); effect.Intensity = 0.6; effect.Feedback = 0.3; ``` --- ### ReverberationAudioEffect **GStreamer Element**: `freeverb` **Purpose**: Room reverberation simulation. **Parameters**: - `RoomSize` (float): Virtual room size - Range: 0.0 to 1.0 - Default: 0.5 - Larger = longer reverb tail - `Damping` (float): High-frequency absorption - Range: 0.0 to 1.0 - Default: 0.2 - Higher = darker reverb - `Level` (float): Wet/dry mix - Range: 0.0 to 1.0 - Default: 0.5 - 0 = dry, 1 = wet - `Width` (float): Stereo width - Range: 0.0 to 1.0 - Default: 1.0 - 0 = mono, 1 = full stereo **Usage**: ``` var effect = new ReverberationAudioEffect(); effect.RoomSize = 0.8f; // Large room effect.Damping = 0.3f; effect.Level = 0.4f; ``` --- ### FadeAudioEffect **Purpose**: Volume fade in/out automation. **Parameters**: - `StartVolume` (uint): Volume at start time - `StopVolume` (uint): Volume at stop time - `StartTime` (TimeSpan): When fade begins - `StopTime` (TimeSpan): When fade completes **Usage**: ``` // Fade out over 3 seconds starting at 10 seconds var effect = new FadeAudioEffect( 100, 0, TimeSpan.FromSeconds(10), TimeSpan.FromSeconds(13) ); ``` --- ## Modulation Effects ### PhaserAudioEffect **Purpose**: Phaser effect with LFO modulation. **Parameters**: - `Depth` (byte): Sweep depth - Range: 0 to 255 - `DryWetRatio` (byte): Mix ratio - Range: 0 to 255 - 0 = dry, 255 = wet - `Feedback` (byte): Resonance - Range: -100 to 100 - `Frequency` (float): LFO speed in Hz - Typical: 0.1 to 5 Hz - `Stages` (byte): Number of stages - Range: 2 to 24 recommended - More = stronger effect - `StartPhase` (float): LFO start phase in radians **Usage**: ``` var effect = new PhaserAudioEffect( 150, // depth 128, // 50% mix 50, // feedback 0.5f, // 0.5 Hz LFO 6, // 6 stages 0f // start phase ); ``` --- ### FlangerAudioEffect **Purpose**: Flanging effect with delay modulation. **Parameters**: - `Delay` (TimeSpan): Base delay time - Typical: 1-15 ms - `Frequency` (float): LFO speed in Hz - Typical: 0.1 to 5 Hz - `PhaseInvert` (bool): Invert delayed signal phase - Default: false **Usage**: ``` var effect = new FlangerAudioEffect( TimeSpan.FromMilliseconds(5), 1.0f, false ); ``` --- ## Pitch and Tempo Effects ### PitchShiftAudioEffect **Purpose**: Change pitch without changing speed. **Parameters**: - `Pitch` (float): Pitch shift ratio - 1.0 = no change - 2.0 = one octave up - 0.5 = one octave down - Typical range: 0.5 to 2.0 **Musical Intervals**: - 0.5 = -12 semitones - 1.059 = +1 semitone - 1.122 = +2 semitones - 2.0 = +12 semitones **Usage**: ``` var effect = new PitchShiftAudioEffect(1.5f); // Up by a fifth ``` --- ### ScaleTempoAudioEffect **GStreamer Element**: `scaletempo` **Purpose**: Change tempo without changing pitch (WSOLA algorithm). **Parameters**: - `Rate` (double): Playback speed - 1.0 = normal - 2.0 = double speed - 0.5 = half speed - Default: 1.0 - `Stride` (TimeSpan): Processing stride - Default: 30 ms - `Overlap` (double): Overlap percentage - Range: 0.0 to 1.0 - Default: 0.2 - `Search` (TimeSpan): Search window - Default: 14 ms **Usage**: ``` var effect = new ScaleTempoAudioEffect(1.5); // 1.5x speed ``` --- ## Special Effects ### KaraokeAudioEffect **GStreamer Element**: `audiokaraoke` **Purpose**: Remove center-panned vocals. **Parameters**: - `FilterBand` (float): Center frequency in Hz - Default: 220 Hz - Typical: 80-400 Hz - `FilterWidth` (float): Filter bandwidth in Hz - Default: 100 Hz - `Level` (float): Effect intensity - Range: 0.0 to 1.0 - Default: 1.0 - `MonoLevel` (float): Mono channel level - Range: 0.0 to 1.0 - Default: 1.0 **Usage**: ``` var effect = new KaraokeAudioEffect(); effect.FilterBand = 250f; effect.Level = 1.0f; ``` --- ### RemoveSilenceAudioEffect **Purpose**: Automatically remove silent sections. **Parameters**: - `Threshold` (double): Silence detection threshold, a linear amplitude - Range: 0.0 to 1.0, converted to the decibels the element uses (`20 * log10(value)`, clamped to -70..70 dB) - Default: 0.001 (-60 dB, the element's own default) - Lower = less audio is treated as silence. 1.0 is full scale and classifies everything as silence - `Squash` (bool): what happens to the timeline after silence is dropped - true = pull the surviving buffers back to close the gap - false = keep their original timestamps - Default: false (keeps the original timeline, so audio stays in sync with video) **Usage**: ``` var effect = new RemoveSilenceAudioEffect("silence-remover"); effect.Threshold = 0.001; effect.Squash = false; ``` --- ### CsoundAudioEffect **GStreamer Element**: `csoundfilter` **Purpose**: Csound-based audio programming. **Platforms**: Windows, macOS, Linux (requires Csound installation). **Parameters**: - `CsdText` (string): Csound CSD document as text - `Location` (string): Path to CSD file - `Loop` (bool): Loop score continuously - Default: false - `ScoreOffset` (double): Start time in seconds - Default: 0.0 **Usage**: ``` var csd = @" ; Your Csound code here ; Your score here "; var effect = new CsoundAudioEffect("my-csound", csd); effect.Loop = false; ``` --- ## Noise Reduction and Measurement ### AudioRNNoiseAudioEffect **GStreamer Element**: `audiornnoise` (rsaudiofx) **Purpose**: AI-based noise reduction. **Parameters**: - `VadThreshold` (float): Voice activity detection threshold - Range: 0.0 to 1.0 - Default: 0.0 - Higher = more sensitive to voice **Usage**: ``` var effect = new AudioRNNoiseAudioEffect(); effect.VadThreshold = 0.5f; ``` --- ### AudioLoudNormAudioEffect **GStreamer Element**: `audioloudnorm` (rsaudiofx) **Purpose**: EBU R128 loudness normalization. **Parameters**: - `LoudnessTarget` (double): Target loudness in LUFS - Range: -70.0 to -5.0 - Default: -24.0 - `LoudnessRangeTarget` (double): Target range in LU - Range: 1.0 to 20.0 - Default: 7.0 - `MaxTruePeak` (double): Max true peak in dbTP - Range: -9.0 to 0.0 - Default: -2.0 - `Offset` (double): Offset gain in LU - Range: -99.0 to 99.0 - Default: 0.0 **Usage**: ``` var effect = new AudioLoudNormAudioEffect(); effect.LoudnessTarget = -16.0; // Streaming standard effect.MaxTruePeak = -1.0; ``` --- ### EbuR128LevelAudioEffect **GStreamer Element**: `ebur128level` (rsaudiofx) **Purpose**: EBU R128 loudness measurement. **Parameters**: - `Mode` (EbuR128Mode): Measurement types to calculate - Options: Momentary, ShortTerm, Global, LoudnessRange, SamplePeak, TruePeak, All - Default: All - `PostMessages` (bool): Post measurement messages - Default: true - `Interval` (TimeSpan): Measurement update interval - Default: 1 second **Usage**: ``` var effect = new EbuR128LevelAudioEffect(); effect.Mode = EbuR128Mode.All; effect.Interval = TimeSpan.FromSeconds(0.5); ``` --- ## Channel Management ### ChannelOrderAudioEffect **Purpose**: Remap audio channels. **Parameters**: - `Orders` (byte[,]): 2D array of [target, source] pairs - Format: [[target0, source0], [target1, source1], ...] - Channels are zero-indexed **Usage**: ``` // Swap left and right channels var orders = new byte[2, 2] { { 0, 1 }, // Output channel 0 gets input channel 1 (right) { 1, 0 } // Output channel 1 gets input channel 0 (left) }; var effect = new ChannelOrderAudioEffect(orders); ``` --- ### DownMixAudioEffect **Implementation**: Custom DSP (channel averaging) **Purpose**: Reduce channel count (e.g., 5.1 to stereo). **Parameters**: None (automatic downmixing). **Usage**: ``` var effect = new DownMixAudioEffect(); ``` --- ## DirectSound Effects (Classic SDKs, Windows Only) The following effects are available only in Video Capture SDK (VideoCaptureCore), Media Player SDK (MediaPlayerCore), and Video Edit SDK (VideoEditCore) on Windows. They use DirectSound/DirectX technology. ### DS Chorus Creates a chorus effect with multiple delayed and modulated copies. **Properties**: - **WetDryMix** (float): Dry/wet mix (0-100) - **Depth** (float): Modulation depth (0-100) - **Feedback** (float): Feedback amount (0-100) - **Frequency** (float): LFO frequency (0-10 Hz) - **Waveform**: Sine or Triangle - **Delay** (float): Base delay (0-20 ms) - **Phase**: Phase relationship for stereo (-180 to 180 degrees) **Usage**: ``` // Signature: (int streamIndex, string name, float delay, float depth, // float feedback, float frequency, DSChorusPhase phase, // DSChorusWaveForm waveformTriangle, float wetDryMix) videoCaptureCore.Audio_Effects_DS_Chorus(0, "chorus", delay: 16, depth: 25, feedback: 25, frequency: 1.1f, phase: DSChorusPhase.Phase90, waveformTriangle: DSChorusWaveForm.Sine, wetDryMix: 50); ``` --- ### DS Distortion Adds distortion/overdrive to audio signal. **Properties**: - **Gain** (float): Pre-distortion gain (-60 to 0 dB) - **Edge** (float): Distortion amount (0-100%) - **PostEQCenterFrequency** (float): Post-EQ center (100-8000 Hz) - **PostEQBandwidth** (float): Post-EQ bandwidth (100-8000 Hz) - **PreLowpassCutoff** (float): Pre-distortion lowpass (100-8000 Hz) **Usage**: ``` // Signature: (int streamIndex, string name, float edge, float gain, // float postEQBandwidth, float postEQCenterFrequency, // float preLowpassCutOff) videoCaptureCore.Audio_Effects_DS_Distortion(0, "distortion", edge: 50, gain: -18, postEQBandwidth: 2400, postEQCenterFrequency: 2400, preLowpassCutOff: 8000); ``` --- ### DS Gargle Creates a gargling/tremolo modulation effect. **Properties**: - **RateHz** (int): Modulation rate (1-1000 Hz) - **WaveForm**: Triangle or Square wave **Usage**: ``` // Signature: (int streamIndex, string name, int rateHz, DSGargleWaveForm waveForm) videoCaptureCore.Audio_Effects_DS_Gargle(0, "gargle", rateHz: 20, waveForm: DSGargleWaveForm.Triangle); ``` --- ### DS Reverb (I3DL2) Professional reverb with environmental modeling. **Properties**: - **Room** (int): Room effect level (-10000 to 0 mB) - **RoomHF** (int): High-frequency room effect (-10000 to 0 mB) - **RoomRolloffFactor** (float): Rolloff factor (0 to 10) - **DecayTime** (float): Decay time (0.1 to 20 seconds) - **DecayHFRatio** (float): HF decay ratio (0.1 to 2.0) - **Reflections** (int): Early reflections (-10000 to 1000 mB) - **ReflectionsDelay** (float): Reflections delay (0 to 0.3 seconds) - **Reverb** (int): Late reverb level (-10000 to 2000 mB) - **ReverbDelay** (float): Reverb delay (0 to 0.1 seconds) - **Diffusion** (float): Diffusion (0 to 100%) - **Density** (float): Density (0 to 100%) - **HFReference** (float): Reference HF (20 to 20000 Hz) --- ### DS Waves Reverb Simplified reverb with basic parameters. **Properties**: - **InGain** (float): Input gain (0 to 96 dB) - **ReverbMix** (float): Reverb mix (0 to 96 dB) - **ReverbTime** (float): Reverb time (0.001 to 3000 ms) - **HighFreqRTRatio** (float): HF reverb time ratio (0.001 to 0.999) **Usage**: ``` // Signature: (int streamIndex, string name, float highFreqRTRatio, // float inGain, float reverbMix, float reverbTime) videoCaptureCore.Audio_Effects_DS_WavesReverb(0, "reverb", highFreqRTRatio: 0.001f, inGain: 0, reverbMix: -10, reverbTime: 1000); ``` --- ## Effects Availability Matrix | Effect | Cross-Platform SDKs | Classic SDKs | Platforms | | --- | --- | --- | --- | | **Volume/Level Control** | | | | | Volume | Yes | Yes | Cross-platform / Windows | | Amplify | Yes | Yes | Cross-platform / Windows | | **Stereo Processing** | | | | | Balance | Yes | No | Cross-platform | | Wide Stereo | Yes | No | Cross-platform | | Karaoke | Yes | No | Cross-platform | | **Delay and Modulation** | | | | | Echo | Yes | Yes | Cross-platform / Windows | | Reverberation (Freeverb) | Yes | No | Cross-platform | | Flanger | Yes | Yes | Cross-platform / Windows | | Phaser | Yes | Yes | Cross-platform / Windows | | **Pitch and Tempo** | | | | | Pitch Shift | Yes | Yes | Cross-platform / Windows | | Scale Tempo | Yes | No | Cross-platform | | Tempo | Yes | Yes | Cross-platform / Windows | | **Equalization** | | | | | Equalizer 10-band | Yes | No | Cross-platform | | Equalizer Parametric | Yes | Yes | Cross-platform / Windows | | **Filtering** | | | | | High-Pass | Yes | Yes | Cross-platform / Windows | | Low-Pass | Yes | Yes | Cross-platform / Windows | | Band-Pass | Yes | Yes | Cross-platform / Windows | | Notch | Yes | Yes | Cross-platform / Windows | | Chebyshev Band Pass/Reject | Yes | No | Cross-platform | | Chebyshev Limit | Yes | No | Cross-platform | | **Dynamic Processing** | | | | | Compressor/Expander | Yes | No | Cross-platform | | Dynamic Amplify | Yes | Yes | Cross-platform / Windows | | **Frequency Enhancement** | | | | | TrueBass | Yes | Yes | Cross-platform / Windows | | Treble Enhancer | Yes | Yes | Cross-platform / Windows | | **Advanced Effects** | | | | | Phase Invert | Yes | Yes | Cross-platform / Windows | | Sound 3D | Yes | Yes | Cross-platform / Windows | | Channel Order | Yes | Yes | Cross-platform / Windows | | Down Mix | Yes | Yes | Cross-platform / Windows | | Fade | Yes | Yes | Cross-platform / Windows | | **Noise Reduction** | | | | | Remove Silence | Yes | No | Cross-platform | | Audio RNNoise | Yes | No | Cross-platform (requires plugin) | | Audio Loud Norm | Yes | No | Cross-platform (requires plugin) | | **Analysis** | | | | | EBU R128 Level | Yes | No | Cross-platform (requires plugin) | | **Spatial Audio** | | | | | HRTF Render | Yes | No | Cross-platform (requires plugin) | | **Specialized** | | | | | RS Audio Echo | Yes | No | Cross-platform (requires plugin) | | Csound Filter | Yes | No | Windows/macOS/Linux (requires Csound) | | **DirectSound Effects (Windows Classic Only)** | | | | | DS Chorus | No | Yes | Windows only | | DS Distortion | No | Yes | Windows only | | DS Gargle | No | Yes | Windows only | | DS Reverb (I3DL2) | No | Yes | Windows only | | DS Waves Reverb | No | Yes | Windows only | **Legend**: - **Cross-platform SDKs** = Media Blocks SDK, Video Capture SDK (VideoCaptureCoreX), Media Player SDK (MediaPlayerCoreX) - **Classic SDKs** = Video Capture SDK (VideoCaptureCore), Media Player SDK (MediaPlayerCore), Video Edit SDK (VideoEditCore) — Windows only ## Audio Elements Reference | Effect | Audio Element | Plugin | | --- | --- | --- | | Volume | volume | coreelements | | Amplify | audioamplify | audiofx | | Balance | audiopanorama | audiofx | | Echo | audioecho | audiofx | | Karaoke | audiokaraoke | audiofx | | Wide Stereo | stereo | audiofx | | Reverberation | freeverb | freeverb | | Equalizer 10-band | equalizer-10bands | audiofx | | High-Pass | audiocheblimit | audiofx | | Low-Pass | audiocheblimit | audiofx | | Chebyshev Band | audiochebband | audiofx | | Chebyshev Limit | audiocheblimit | audiofx | | Compressor | audiodynamic | audiofx | | Scale Tempo | scaletempo | audiofx | | Pitch Shift | pitch | soundtouch | | Audio RNNoise | audiornnoise | rsaudiofx | | Audio Loud Norm | audioloudnorm | rsaudiofx | | EBU R128 Level | ebur128level | rsaudiofx | | RS Audio Echo | rsaudioecho | rsaudiofx | | HRTF Render | hrtfrender | rsaudiofx | | Csound Filter | csoundfilter | csound | ## Frequently Asked Questions What is the default value for audio effect parameters? Each effect has documented defaults that represent neutral/bypass behavior. For example, `VolumeAudioEffect` defaults to level 1.0 (100%), `Equalizer10AudioEffect` defaults all bands to 0 dB, and `ReverberationAudioEffect` defaults to a moderate room simulation. See each effect's parameter table above for specific defaults. How do I reset an audio effect to its default settings? Create a new instance of the effect with default constructor parameters and call `Audio_Effects_AddOrUpdate()` to replace the current settings. Each effect's default constructor initializes all parameters to their documented defaults. Can I use multiple instances of the same effect type? Yes. Effect **names** are used as unique identifiers, not effect types. To run multiple instances of the same type simultaneously, give each instance a distinct name. Calling `Audio_Effects_AddOrUpdate()` with an effect whose name matches an existing one replaces that instance; a new name adds a new instance to the chain. What sample rates and channel configurations are supported? All cross-platform audio effects support standard sample rates (8 kHz to 192 kHz) and channel configurations (mono, stereo, multi-channel). The effects automatically adapt to the audio format of the input stream. Some effects like `BalanceAudioEffect` and `WideStereoAudioEffect` require stereo input. How do I remove an audio effect during playback? Use the `Audio_Effects_Remove()` method with the effect type to remove it from the processing chain during playback. The change takes effect immediately without interrupting the audio stream. ## See Also - [Audio Effects Overview](../) - [Audio Sample Grabber](../audio-sample-grabber/) - [Audio Processing Blocks (Media Blocks SDK)](../../../mediablocks/AudioProcessing/) ---END OF PAGE--- ## AAC Audio Encoding with M4A Container Output in C# .NET **URL:** https://www.visioforge.com/help/docs/dotnet/general/audio-encoders/aac/ **Description:** Use avenc_aac, voaacenc, atenc, and Media Foundation backends with runtime detection. Bitrate 32-320 kbps, 5.1 surround, and M4A/MP4 containers. **Tags:** Video Capture SDK, Media Blocks SDK, Video Edit SDK, .NET, MediaBlocksPipeline, VideoCaptureCoreX, VideoEditCoreX, Windows, macOS, Linux, Android, iOS, Capture, Streaming, Recording, Encoding, Editing, MP4, TS, MPEG-2, AAC, C# **API:** M4AOutput, AACObject, AVENCAACEncoderSettings, VOAACEncoderSettings, AppleAACEncoderSettings, AACOutput # AAC encoder and M4A output [Video Capture SDK .Net](https://www.visioforge.com/video-capture-sdk-net) [Video Edit SDK .Net](https://www.visioforge.com/video-edit-sdk-net) [Media Blocks SDK .Net](https://www.visioforge.com/media-blocks-sdk-net) The VisioForge SDK provides several AAC encoder implementations, each with unique characteristics and use cases. ## What is M4A Output? M4A is a file format used for storing audio data encoded with the Advanced Audio Coding (AAC) codec. VisioForge .Net SDKs provide robust support for creating high-quality M4A audio files through their dedicated M4AOutput class. This format is widely used for digital audio distribution due to its excellent compression efficiency and sound quality. ## Cross-platform M4A (AAC) output [VideoCaptureCoreX](#) [VideoEditCoreX](#) [MediaBlocksPipeline](#) The cross-platform capable SDKs (VideoCaptureCoreX, VideoEditCoreX, MediaBlocksPipeline) allow you to utilize several AAC encoder implementations via `M4AOutput`. This guide focuses on three main approaches using dedicated settings objects: 1. [AVENC AAC Encoder](https://api.visioforge.org/dotnet/api/VisioForge.Core.Types.X.AudioEncoders.AVENCAACEncoderSettings.html) - A feature-rich, cross-platform encoder. 2. [VO-AAC Encoder](https://api.visioforge.org/dotnet/api/VisioForge.Core.Types.X.AudioEncoders.VOAACEncoderSettings.html) - A streamlined, cross-platform encoder. 3. Media Foundation AAC Encoder - A Windows-specific system encoder, accessible on Windows platforms via `MFAACEncoderSettings`. 4. Apple AAC Encoder - The AudioToolbox encoder built into macOS, accessible on macOS and Mac Catalyst via `AppleAACEncoderSettings`. ### AVENC AAC Encoder The AVENC AAC Encoder offers the most comprehensive configuration options for audio encoding. It provides advanced settings for stereo coding, prediction, and noise shaping. #### Key Features - Multiple coder strategies - Configurable stereo coding - Advanced noise and prediction techniques #### Coder Strategies The AVENC AAC Encoder supports three coder strategies: - `ANMR`: Advanced noise modeling and reduction method - `TwoLoop`: Two-loop searching method for optimization - `Fast`: Default fast search algorithm (recommended for most use cases) #### Sample Configuration ``` var aacSettings = new AVENCAACEncoderSettings { Coder = AVENCAACEncoderCoder.Fast, Bitrate = 192, IntensityStereo = true, ForceMS = AVENCAACTrilian.Auto, TNS = true }; ``` #### Supported Parameters - **Bitrates**: 0, 32, 64, 96, 128, 160, 192, 224, 256, 320 kbps - **Sample Rates**: 7350 to 96000 Hz - **Channels**: 1 to 6 channels ### VO-AAC Encoder Deprecated `VOAACEncoderSettings` is marked `[Obsolete]` in recent SDK releases — the underlying `voaacenc` element fails caps negotiation with `mpegtsmux` on iOS and is no longer recommended. Prefer `AVENCAACEncoderSettings` for new code; `MFAACEncoderSettings` remains a good choice on Windows. The VO-AAC Encoder is a more streamlined encoder with simpler configuration options. #### Key Features - Simplified configuration - Straightforward bitrate and sample rate controls - Limited to stereo audio #### Sample Configuration ``` var aacSettings = new VOAACEncoderSettings { Bitrate = 128 }; ``` #### Supported Parameters - **Bitrates**: 32, 64, 96, 128, 160, 192, 224, 256, 320 kbps - **Sample Rates**: 8000 to 96000 Hz - **Channels**: 1-2 channels ### Apple AAC Encoder (macOS and Mac Catalyst) `AppleAACEncoderSettings` wraps `atenc`, the AAC encoder built into the operating system through AudioToolbox — the same one the rest of macOS encodes AAC with. It is available on macOS and Mac Catalyst; the iOS runtime shipped with the SDK does not carry it yet, so always gate on `IsAvailable()` rather than on the platform. #### Key Features - Produced by the operating system's own encoder - Up to 8 channels, more than any other AAC backend in the SDK - Four rate control modes, including true VBR #### Rate Control `RateControl` selects how the encoder spends bits, and it decides whether `Bitrate` is read at all: - `Constant` (default): constant bitrate, driven by `Bitrate`. - `LongTermAverage`: the instantaneous rate varies, the long-term average follows `Bitrate`. - `VariableConstrained`: constrained VBR. **`Bitrate` is ignored.** - `Variable`: true VBR driven by `VBRQuality` (0-127, default 65). **`Bitrate` is ignored.** In the two variable modes the resulting file size is a function of the content and, for `Variable`, of `VBRQuality` alone — setting `Bitrate` there has no effect at all. #### Sample Configuration ``` var aacSettings = new AppleAACEncoderSettings { Bitrate = 192, RateControl = AppleAACRateControl.Constant }; ``` #### Supported Parameters - **Bitrates**: 0 (Auto), 32, 64, 96, 128, 160, 192, 224, 256, 320 kbps - **Sample Rates**: 8000 to 48000 Hz - **Channels**: 1 to 8 channels It is not the default `AVENCAACEncoderSettings` remains the default AAC encoder on macOS. Measured on Apple Silicon against a lossless source, the two encoders trade places depending on the bitrate - `atenc` is behind at 96 kbps, level at 128 kbps and ahead at 192 kbps - and their CPU cost is indistinguishable, since AAC encoding runs at well over a hundred times realtime either way. Select `AppleAACEncoderSettings` explicitly when you want the platform encoder, more than six channels, or true VBR. ### Media Foundation AAC Encoder (Windows Only) This encoder is specific to Windows platforms and offers a limited but performance-optimized encoding solution. #### Key Features - Windows-specific implementation - Predefined bitrate options - Limited sample rate support #### Supported Parameters - **Bitrates**: 0 (Auto), 96, 128, 160, 192, 576, 768, 960, 1152 kbps - **Sample Rates**: 44100, 48000 Hz - **Channels**: 1, 2, 6 channels ### Encoder Availability and Selection Each encoder provides a static `IsAvailable()` method to check if the encoder can be used in the current environment. This is useful for runtime compatibility checks. ``` #if __MACOS__ || __MACCATALYST__ if (AppleAACEncoderSettings.IsAvailable()) { // Use the operating system's own AAC encoder } #endif if (AVENCAACEncoderSettings.IsAvailable()) { // Use AVENC AAC Encoder } else if (VOAACEncoderSettings.IsAvailable()) { // Fallback to VO-AAC Encoder } ``` ### Getting Started with M4AOutput The cross-platform implementation uses the [M4AOutput](https://api.visioforge.org/dotnet/api/VisioForge.Core.Types.X.Output.M4AOutput.html) class as the foundation for M4A file creation. To begin using this feature, initialize the class with your desired output filename: ``` var output = new M4AOutput("output.m4a"); ``` ### Switching Between Encoders The default encoder selection is platform-dependent: - Windows environments: MF AAC - Other platforms: VO-AAC You can override this default selection by explicitly setting the `Audio` property: ``` // For VO-AAC encoder output.Audio = new VOAACEncoderSettings(); // For AVENC AAC encoder output.Audio = new AVENCAACEncoderSettings(); // For MF AAC encoder (Windows only) #if NET_WINDOWS output.Audio = new MFAACEncoderSettings(); #endif // For the Apple AAC encoder (macOS and Mac Catalyst) #if __MACOS__ || __MACCATALYST__ output.Audio = new AppleAACEncoderSettings(); #endif ``` ### Configuring MP4 Sink Settings Since M4A files are based on the MP4 container format, you can adjust various output parameters through the `Sink` property: ``` // Change the output filename output.Sink.Filename = "new_output.m4a"; ``` ### Advanced Audio Processing For workflows requiring specialized audio processing, the M4AOutput class supports custom audio processors: ``` // Implement your custom audio processing logic output.CustomAudioProcessor = new MyCustomAudioProcessor(); ``` ### Key Methods for File Management The M4AOutput class provides several methods for handling files and retrieving encoder information: ``` // Get current output filename string currentFile = output.GetFilename(); // Update the output filename output.SetFilename("updated_file.m4a"); // Retrieve available audio encoders var audioEncoders = output.GetAudioEncoders(); ``` ### Using M4A Output in Different SDKs Each VisioForge SDK has a slightly different approach to implementing M4A output: #### With Video Capture SDK ``` var core = new VideoCaptureCoreX(); core.Outputs_Add(output, true); ``` #### With Video Edit SDK ``` var core = new VideoEditCoreX(); core.Output_Format = output; ``` #### With Media Blocks SDK ``` var aac = new VOAACEncoderSettings(); var sinkSettings = new MP4SinkSettings("output.m4a"); var m4aOutput = new M4AOutputBlock(sinkSettings, aac); ``` ### Rate Control Considerations 1. **AVENC AAC Encoder**: 2. Most flexible rate control 3. Supports constant bitrate (CBR) 4. Multiple encoding strategies affect quality and performance 5. **VO-AAC Encoder**: 6. Simple constant bitrate control 7. Recommend for straightforward encoding needs 8. Limited advanced configuration 9. **Media Foundation Encoder**: 10. Limited to predefined bitrates 11. Good for quick Windows-based encoding 12. Auto bitrate option available ### Recommendations - For advanced audio encoding with maximum control, use AVENC AAC Encoder - For simple, cross-platform encoding, use VO-AAC Encoder - For Windows-specific, optimized encoding, use Media Foundation Encoder ### Performance and Quality Considerations - **Bitrate vs. Quality vs. File Size**: Higher bitrates generally result in better audio quality but also lead to larger file sizes. Experiment with different bitrates to find the optimal balance for your specific content and distribution needs. - **Sample Rate Matching**: Always try to choose sample rates that match your source audio. This avoids unnecessary resampling, which can potentially degrade audio quality. - **Encoder Characteristics**: - `AVENC AAC Encoder`: Offers the most extensive configuration options, allowing for fine-grained control over quality and performance. Ideal for advanced use cases. - `VO-AAC Encoder`: Provides a good balance of simplicity, cross-platform compatibility, and quality. A solid choice for many common scenarios. - `Media Foundation AAC Encoder`: Leverages built-in Windows audio processing capabilities. It can be efficient on Windows but offers less configuration flexibility than AVENC. - **Channel Configuration (Mono vs. Stereo)**: - For voice-only content, using mono encoding (1 channel) can significantly reduce file size without a noticeable loss in quality for speech. Check if your chosen encoder settings (e.g., `AVENCAACEncoderSettings.Channels`) allow explicit channel configuration. - For music and rich audio environments, stereo (2 channels) is generally preferred. - **Content-Specific Bitrate Ranges**: While higher is often better, the "best" bitrate depends on the audio content: - *Speech/Voice:* 64-96 kbps can be adequate. - *General Music:* 128-192 kbps is a common target for good quality. - *High-Fidelity Audio:* 256-320 kbps or higher might be used when pristine quality is critical. These are guidelines; always test with your specific audio. - **Target Audience and Platform**: Consider who will be listening and on what devices. For example, if the audio is primarily for web streaming to mobile devices, extremely high bitrates might lead to buffering issues or unnecessary data consumption. Tailor your encoder choice and settings accordingly. ### Sample Code - Check the [MP4 output](../../output-formats/mp4/) guide for sample code. - Check the [AAC encoder block](../../../mediablocks/AudioEncoders/) for sample code. ## Windows-only AAC output [VideoCaptureCore](#) [VideoEditCore](#) [M4AOutput](https://api.visioforge.org/dotnet/api/VisioForge.Core.Types.X.Output.M4AOutput.html) is the primary class for configuring M4A (AAC) output settings. It implements both `IVideoEditBaseOutput` and `IVideoCaptureBaseOutput` interfaces. ### Properties | Property | Type | Description | Default Value | | --- | --- | --- | --- | | Version | AACVersion | Specifies the AAC version (MPEG-2 or MPEG-4) | MPEG4 | | Object | AACObject | Defines the AAC object type | Low | | Output | AACOutput | Sets the AAC output mode | RAW | | Bitrate | int | Specifies the AAC bitrate in kbps | 128 | ### Methods #### `GetInternalTypeVC()` - Returns: `VideoCaptureOutputFormat.M4A` - Purpose: Gets the internal output format for video capture #### `GetInternalTypeVE()` - Returns: `VideoEditOutputFormat.M4A` - Purpose: Gets the internal output format for video editing #### `Save()` - Returns: JSON string representation of the M4AOutput object - Purpose: Serializes the current configuration to JSON #### `Load(string json)` - Parameters: JSON string containing M4AOutput configuration - Returns: New M4AOutput instance - Purpose: Creates a new M4AOutput instance from JSON configuration ### Supporting Enums #### AACVersion Defines the version of AAC to be used: | Value | Description | | --- | --- | | MPEG4 | MPEG-4 AAC (default) | | MPEG2 | MPEG-2 AAC | #### AACObject Specifies the AAC encoder stream object type: | Value | Description | | --- | --- | | Undefined | Not to be used | | Main | Main profile | | Low | Low Complexity profile (default) | | SSR | Scalable Sample Rate profile | | LTP | Long Term Prediction profile | #### AACOutput Determines the AAC encoder stream output type: | Value | Description | | --- | --- | | RAW | Raw AAC stream (default) | | ADTS | Audio Data Transport Stream format | ### Usage Example ``` // Create new M4A output configuration var core = new VideoCaptureCore(); core.Mode = VideoCaptureMode.VideoCapture; core.Output_Filename = "output.m4a"; var output = new M4AOutput { Bitrate = 192, Version = AACVersion.MPEG4, Object = AACObject.Low, Output = AACOutput.ADTS }; core.Output_Format = output; // core is an instance of VideoCaptureCore or VideoEditCore ``` ### Selecting the Right Bitrate The optimal bitrate depends on your content type and quality requirements: - **64-96 kbps**: Suitable for voice recordings and speech content - **128-192 kbps**: Recommended for general music and audio content - **256-320 kbps**: Ideal for high-fidelity music where quality is paramount ### Choosing the Appropriate Profile - Use `AACObject.Low` for most applications as it provides an excellent balance between quality and encoding efficiency - Reserve `AACObject.Main` for specialized use cases requiring maximum quality - Avoid `AACObject.Undefined` as it isn't a valid encoding option ### Container Format Selection - `AACOutput.ADTS` provides better compatibility with various players and devices - `AACOutput.RAW` is preferable when the AAC stream will be embedded within another container format ---END OF PAGE--- ## FLAC Lossless Audio Encoding and Recording in C# .NET **URL:** https://www.visioforge.com/help/docs/dotnet/general/audio-encoders/flac/ **Description:** Lossless recording with quality levels 0-9, sample rates up to 655 kHz, 8-channel surround, and LPC optimization. VisioForge SDK C# code examples. **Tags:** Video Capture SDK, Media Blocks SDK, Video Edit SDK, .NET, MediaBlocksPipeline, VideoCaptureCoreX, VideoEditCoreX, Windows, macOS, Linux, Android, iOS, Capture, Streaming, Encoding, Editing, FLAC, C# **API:** FLACOutput, FLACEncoderSettings, VideoCaptureCoreX, VideoEditCoreX, CustomAudioProcessor # FLAC encoder and output [Video Capture SDK .Net](https://www.visioforge.com/video-capture-sdk-net) [Video Edit SDK .Net](https://www.visioforge.com/video-edit-sdk-net) [Media Blocks SDK .Net](https://www.visioforge.com/media-blocks-sdk-net) The FLAC (Free Lossless Audio Codec) encoder provides high-quality lossless audio compression while preserving the original audio quality. ## Cross-platform FLAC output [VideoCaptureCoreX](#) [VideoEditCoreX](#) [MediaBlocksPipeline](#) ### Features The FLAC encoder supports a wide range of audio configurations: - Sample rates from 1 Hz to 655,350 Hz - Up to 8 audio channels (mono to 7.1 surround) - Lossless compression with adjustable quality settings - Streamable output support - Configurable block sizes and compression parameters ### Quality Settings The encoder provides a quality parameter ranging from 0 to 9: - 0: Fastest compression (lowest CPU usage) - 1-7: Balanced compression settings - 8: Highest compression (higher CPU usage) - 9: Insane compression (extremely CPU intensive) The default quality setting is 5, which offers a good balance between compression ratio and processing speed. ### Basic Settings The cross-platform [FLACEncoderSettings](https://api.visioforge.org/dotnet/api/VisioForge.Core.Types.X.AudioEncoders.FLACEncoderSettings.html) class offers advanced configuration options: ``` // Create FLAC encoder settings with default quality var flacSettings = new FLACEncoderSettings { // Default compression level Quality = 5, // Audio block size in samples BlockSize = 4608, // Enable streaming support StreamableSubset = true, // Enable stereo processing MidSideStereo = true }; ``` ### Advanced Compression Settings ``` // Create FLAC encoder settings with advanced configuration var advancedSettings = new FLACEncoderSettings { // Linear Prediction settings // Maximum LPC order for prediction MaxLPCOrder = 8, // Auto precision for coefficients QlpCoeffPrecision = 0, // Residual coding settings MinResidualPartitionOrder = 3, MaxResidualPartitionOrder = 3, // Search optimization settings // Disable expensive coefficient search ExhaustiveModelSearch = false, // Disable precision search QlpCoeffPrecSearch = false, // Disable escape code search EscapeCoding = false }; ``` ### Sample Code Add the FLAC output to the Video Capture SDK core instance: ``` // Create a Video Capture SDK core instance var core = new VideoCaptureCoreX(); // Create a FLAC output instance var flacOutput = new FLACOutput("output.flac"); // Set the quality of the FLAC encoder flacOutput.Audio.Quality = 5; // Add the FLAC output core.Outputs_Add(flacOutput, true); ``` Set the output format for the Video Edit SDK core instance: ``` // Create a Video Edit SDK core instance var core = new VideoEditCoreX(); // Create a FLAC output instance var flacOutput = new FLACOutput("output.flac"); // Set the quality flacOutput.Audio.Quality = 5; // Set the output format core.Output_Format = flacOutput; ``` Create a Media Blocks FLAC output instance: ``` // Create a FLAC encoder settings instance var flacSettings = new FLACEncoderSettings(); // Create a FLAC output instance var flacOutput = new FLACOutputBlock("output.flac", flacSettings); ``` ### FLACOutput class The `FLACOutput` class provides functionality for configuring FLAC (Free Lossless Audio Codec) output in the VisioForge SDKs. ``` // Create a new FLAC output instance var flacOutput = new FLACOutput("output.flac"); // Configure FLAC encoder settings (Quality: 0 fastest .. 8 highest, 9 insane) flacOutput.Audio.Quality = 5; ``` #### Filename - Set the output filename during initialization or via the `Filename` property - Or call `GetFilename()` / `SetFilename(string)` methods (equivalent — they back the `Filename` property) ``` // Set during initialization var flacOutput = new FLACOutput("audio_output.flac"); // Or via the property flacOutput.Filename = "new_output.flac"; // Or via the method accessors flacOutput.SetFilename("final.flac"); string currentPath = flacOutput.GetFilename(); // "final.flac" ``` #### Audio Settings The `Audio` property provides access to FLAC-specific encoding settings through the `FLACEncoderSettings` class: ``` flacOutput.Audio = new FLACEncoderSettings(); // Configure specific FLAC encoding parameters here ``` #### Custom Audio Processing You can set a custom audio processor using the `CustomAudioProcessor` property: ``` flacOutput.CustomAudioProcessor = new CustomMediaBlock(); ``` #### Implementation Notes - The class implements multiple interfaces: - `IVideoEditXBaseOutput` - `IVideoCaptureXBaseOutput` - `IOutputAudioProcessor` - Only FLAC audio encoding is supported (no video encoding capabilities) - Default FLAC encoder settings are automatically created during initialization Media Blocks SDK contains a dedicated [FLAC encoder block](../../../mediablocks/AudioEncoders/). ### Performance Considerations When configuring the FLAC encoder, consider these performance factors: 1. Higher quality settings (7-9) will significantly increase CPU usage 2. The `ExhaustiveModelSearch` option can greatly impact encoding speed 3. Larger block sizes may improve compression but increase memory usage 4. `StreamableSubset` should remain enabled unless you have specific requirements ### Compatibility The encoder supports the following configurations: - Audio channels: 1 to 8 channels - Sample rates: 1 Hz to 655,350 Hz - Bitrate: Variable (lossless compression) ### Error Handling Always check for encoder availability before use: ``` if (!FLACEncoderSettings.IsAvailable()) { // Handle unavailable encoder scenario Console.WriteLine("FLAC encoder is not available on this system"); return; } ``` ### Best Practices 1. Start with the default quality setting (5) and adjust based on your needs 2. Enable `MidSideStereo` for stereo content to improve compression 3. Use `SeekPoints` for longer audio files to enable quick seeking 4. Keep `StreamableSubset` enabled unless you have specific requirements 5. Avoid using `ExhaustiveModelSearch` unless compression ratio is critical ## Windows-only FLAC output [VideoCaptureCore](#) [VideoEditCore](#) The [FLACOutput](https://api.visioforge.org/dotnet/api/VisioForge.Core.Types.X.Output.FLACOutput.html) class provides Windows-only settings for the FLAC encoder. This class implements both `IVideoEditBaseOutput` and `IVideoCaptureBaseOutput` interfaces, making it suitable for both video editing and capture scenarios. ### Properties #### Compression Level - **Property**: `Level` - **Type**: `int` - **Range**: 0-8 - **Default**: 5 - **Description**: Controls the compression level, where 0 provides fastest compression and 8 provides highest compression. #### Block Size - **Property**: `BlockSize` - **Type**: `int` - **Default**: 4608 - **Valid Values**: For subset streams, must be one of: - 192, 256, 512, 576, 1024, 1152, 2048, 2304, 4096, 4608 - 8192, 16384 (only if sample rate > 48kHz) - **Description**: Specifies the block size in samples. The encoder uses the same block size for the entire stream. #### LPC Order - **Property**: `LPCOrder` - **Type**: `int` - **Default**: 8 - **Constraints**: - Must be ≤ 32 - For subset streams at ≤ 48kHz, must be ≤ 12 - **Description**: Specifies the maximum Linear Predictive Coding order. Setting to 0 disables generic linear prediction and uses only fixed predictors, which is faster but typically results in 5-10% larger files. #### Mid-Side Coding Options ##### Mid-Side Coding - **Property**: `MidSideCoding` - **Type**: `bool` - **Default**: `false` - **Description**: Enables mid-side coding for stereo streams. This typically increases compression by a few percent by encoding both stereo pair and mid-side versions of each block and selecting the smallest resulting frame. ##### Adaptive Mid-Side Coding - **Property**: `AdaptiveMidSideCoding` - **Type**: `bool` - **Default**: `false` - **Description**: Enables adaptive mid-side coding for stereo streams. This provides faster encoding than full mid-side coding but with slightly less compression by adaptively switching between independent and mid-side coding. #### Rice Parameters ##### Rice Minimum - **Property**: `RiceMin` - **Type**: `int` - **Default**: 3 - **Description**: Sets the minimum residual partition order. Works in conjunction with RiceMax to control how the residual signal is partitioned. ##### Rice Maximum - **Property**: `RiceMax` - **Type**: `int` - **Default**: 3 - **Description**: Sets the maximum residual partition order. The residual is partitioned into 2^min to 2^max pieces, each with its own Rice parameter. Optimal settings typically depend on block size, with best results when blocksize/(2^n)=128. #### Advanced Options ##### Exhaustive Model Search - **Property**: `ExhaustiveModelSearch` - **Type**: `bool` - **Default**: `false` - **Description**: Enables exhaustive model search for optimal encoding. When enabled, the encoder generates subframes for every order and uses the smallest, potentially improving compression by ~0.5% at the cost of significantly increased encoding time. ### Methods #### Constructor ``` public FLACOutput() ``` Initializes a new instance with default values: - Level = 5 - RiceMin = 3 - RiceMax = 3 - LPCOrder = 8 - BlockSize = 4608 ### Serialization #### Save() ``` public string Save() ``` Serializes the settings to a JSON string. #### Load(string json) ``` public static FLACOutput Load(string json) ``` Creates a new FLACOutput instance from a JSON string. ### Usage Example ``` var flacSettings = new FLACOutput { Level = 8, // Maximum compression BlockSize = 4608, // Default block size MidSideCoding = true, // Enable mid-side coding for better compression ExhaustiveModelSearch = true // Enable exhaustive search for best compression }; core.Output_Format = flacSettings; // Core is VideoCaptureCore or VideoEditCore ``` ### Best Practices #### Compression Level Selection - Use Level 0-3 for faster encoding with moderate compression - Use Level 4-6 for balanced compression/speed - Use Level 7-8 for maximum compression regardless of speed #### Block Size Considerations - Larger block sizes generally provide better compression - Stick to standard values (4608, 4096, etc.) for maximum compatibility - Consider memory constraints when selecting block size #### Mid-Side Coding - Enable for stereo content when compression is priority - Use adaptive mode when encoding speed is important - Disable for mono content as it has no effect #### Rice Parameters - Default values (3,3) are suitable for most use cases - Increase for potentially better compression at the cost of encoding speed - Values beyond 6 rarely provide significant benefits ---END OF PAGE--- ## Audio Encoders for .NET — AAC, FLAC, MP3, Opus Guide **URL:** https://www.visioforge.com/help/docs/dotnet/general/audio-encoders/ **Description:** Implement AAC, FLAC, MP3, Opus, and other audio encoders in .NET with optimal settings, performance tips, and best practices. **Tags:** Video Capture SDK, Media Blocks SDK, Video Edit SDK, .NET, Windows, macOS, Linux, Android, iOS, Streaming # Audio Encoders for .NET Development [Video Capture SDK .Net](https://www.visioforge.com/video-capture-sdk-net) [Video Edit SDK .Net](https://www.visioforge.com/video-edit-sdk-net) [Media Blocks SDK .Net](https://www.visioforge.com/media-blocks-sdk-net) ## Introduction to Audio Encoding in .NET Applications When developing media applications in .NET, choosing the right audio encoder is crucial for ensuring optimal performance, compatibility, and quality. VisioForge's suite of .NET SDKs provides developers with powerful tools for audio encoding across various formats, enabling the creation of professional-grade media applications. Audio encoders are essential components that convert raw audio data into compressed formats suitable for storage, streaming, or playback. Each encoder offers different advantages in terms of compression ratio, audio quality, processing requirements, and platform compatibility. This guide will help you navigate the various audio encoding options available in VisioForge's .NET SDKs. ## Quick Start — Pick an audio encoder Every encoder on the cross-platform engines is a settings class that you assign to the output's `Audio` property (or pass to a `*OutputBlock` in Media Blocks). The surrounding pipeline is the same — only the settings type changes. ``` using VisioForge.Core.Types.X.AudioEncoders; using VisioForge.Core.Types.X.Output; // MP4 container: encode audio with AAC. var mp4 = new MP4Output("output.mp4"); mp4.Audio = new VOAACEncoderSettings { Bitrate = 192 }; // 128/192/256 kbps typical // MKV container: swap in a different codec on the same Audio slot. var mkv = new MKVOutput("output.mkv"); mkv.Audio = new OPUSEncoderSettings { Bitrate = 128 }; // FLAC: lossless audio-only output. var flac = new FLACOutput("music.flac"); flac.Audio.Quality = 5; // 0 fastest .. 8 highest, 9 insane // Standalone formats (one encoder = one container): var mp3 = new MP3Output("song.mp3"); // MP3 var wav = new WAVOutput("raw.wav"); // uncompressed PCM var ogg = new OGGVorbisOutput("music.ogg"); // OGG + Vorbis // Attach to a VideoCaptureCoreX or VideoEditCoreX instance: // core.Outputs_Add(mp4, true); // VideoCaptureCoreX // core.Output_Format = mp4; // VideoEditCoreX ``` Pick the encoder that matches your target: **AAC** for broad compatibility (MP4, M4A, streaming), **Opus** for low-latency / low-bitrate voice or music, **MP3** for legacy distribution, **FLAC** for lossless archives, **Vorbis** for open-format WebM/OGG pipelines. Detailed per-encoder pages cover bitrate tables, sample-rate limits, and tuning parameters. ## Available Audio Encoders VisioForge's .NET SDKs include support for the following audio encoders, each designed for specific use cases: ### [AAC Encoder](aac/) Advanced Audio Coding (AAC) represents the industry standard for high-quality audio compression. It delivers excellent sound quality at lower bit rates compared to older formats like MP3. **Key features:** - Efficient compression with minimal quality loss - Wide device and platform compatibility - Variable bit rate support for optimized file sizes - Ideal for streaming applications and mobile devices - Support for multi-channel audio (up to 48 channels) AAC is particularly well-suited for applications where audio quality is paramount, such as music streaming services, video production tools, and professional media applications. ### [FLAC Encoder](flac/) Free Lossless Audio Codec (FLAC) provides lossless compression of audio data, preserving the original audio quality while reducing file size. **Key features:** - Lossless compression with no quality degradation - Open-source format with broad support - Typically reduces file sizes by 40-50% compared to uncompressed audio - Fast encoding and decoding performance - Supports metadata tags and seeking FLAC is ideal for archiving audio, professional audio editing applications, and audiophile-grade music playback systems where maintaining perfect audio fidelity is essential. ### [MP3 Encoder](mp3/) MPEG Audio Layer III (MP3) remains one of the most widely used audio formats due to its universal compatibility and acceptable quality-to-size ratio. **Key features:** - Nearly universal compatibility across devices and platforms - Configurable bit rates from 8 to 320 Kbps - Joint stereo mode for improved compression efficiency - Variable bit rate (VBR) encoding for optimized quality - Fast encoding and minimal processing requirements MP3 is best for applications where wide compatibility is more important than achieving the absolute highest audio quality, such as podcasts, basic music applications, and legacy system integration. ### [Opus Encoder](opus/) Opus is a highly versatile audio codec designed to handle both speech and music with excellent quality at low bit rates. **Key features:** - Superior performance at low bit rates (6-64 Kbps) - Low algorithmic delay for real-time applications - Seamless quality adjustment based on available bandwidth - Excellent for both speech and music content - Open standard with growing adoption Opus excels in real-time communication applications, VoIP systems, live streaming, and scenarios where bandwidth efficiency is critical. ### [Speex Encoder](speex/) Speex is an audio compression format specifically optimized for speech encoding, making it ideal for voice-centric applications. **Key features:** - Designed specifically for human voice compression - Variable bit rates from 2 to 44 Kbps - Voice activity detection and comfort noise generation - Low latency for real-time applications - Open source with minimal patent concerns Speex is particularly effective for voice chat applications, voice recording tools, and telephony systems where speech clarity is the priority. ### [Vorbis Encoder](vorbis/) Vorbis is an open-source, patent-free audio compression format that offers quality comparable to AAC at similar bit rates. **Key features:** - Free and open format without licensing restrictions - Excellent quality-to-size ratio for music - Variable and average bit rate encoding modes - Strong support in open-source software ecosystems - Multi-channel audio support Vorbis is well-suited for applications where licensing costs are a concern, such as open-source projects, indie game development, and web applications. ### [WavPack Encoder](wavpack/) WavPack offers a unique hybrid approach to audio compression, providing both lossless and high-quality lossy compression options. **Key features:** - Hybrid mode combining lossy and lossless techniques - Correction files to restore lossy files to lossless quality - Fast decoding with minimal CPU requirements - Support for high-resolution audio up to 32-bit/192kHz - Robust error correction capabilities WavPack is excellent for applications requiring flexible quality options, archival purposes, and systems where decoding performance is more critical than encoding speed. ### [Windows Media Audio Encoder](wma/) Windows Media Audio (WMA) provides a set of audio codecs developed by Microsoft, offering good integration with Windows platforms. **Key features:** - Native integration with Windows environments - Multiple codec variants (WMA Standard, Pro, Lossless) - Good performance on Windows devices and Xbox platforms - Professional variant supports multi-channel surround sound - Digital rights management capabilities WMA is particularly useful for Windows-centric applications, enterprise solutions, and scenarios where DRM protection is required. ## Choosing the Right Audio Encoder Selecting the appropriate audio encoder depends on several factors: 1. **Quality Requirements**: For archiving or professional applications, consider lossless options like FLAC or WavPack. For general-purpose use, AAC or Vorbis provide excellent quality at reasonable sizes. 2. **Platform Compatibility**: If your application needs to work across many devices, MP3 offers the widest compatibility, while AAC is well-supported on modern platforms. 3. **Content Type**: For speech-focused applications, Speex or Opus at lower bitrates excel. For music, AAC, Vorbis, or MP3 at higher bitrates are preferable. 4. **Bandwidth Considerations**: For streaming over limited connections, Opus provides excellent quality at very low bitrates. 5. **Licensing Requirements**: If your project requires open-source or patent-free solutions, focus on FLAC, Vorbis, or Opus. ## Implementation Considerations When implementing audio encoders in your .NET application: - **Threading**: Consider encoding audio on background threads to prevent UI freezing during processing. - **Buffer Management**: Properly manage audio buffers to prevent memory leaks during encoding operations. - **Error Handling**: Implement robust error handling for encoding failures or corrupt input data. - **Metadata**: Most formats support metadata tags—use them to enhance the user experience. - **Preprocessing**: Consider implementing audio normalization or other preprocessing before encoding for optimal results. ## Performance Optimization To achieve the best performance when using audio encoders: - Match encoding quality to your application's needs—higher quality settings require more processing power - Implement caching strategies for frequently accessed audio - Consider hardware acceleration when available, particularly for real-time encoding - Batch process audio files when possible rather than encoding on demand - Monitor memory usage, especially when processing long audio files ## Getting Started To begin implementing audio encoders in your .NET application using VisioForge SDKs, follow these steps: 1. Install the appropriate VisioForge SDK via NuGet or direct download 2. Reference the SDK in your project 3. Initialize the encoder with your desired configuration settings 4. Process audio through the encoder using the provided API methods 5. Handle the encoded output as needed for your application Each encoder has specific initialization parameters and optimal settings, which are detailed in their respective documentation pages. By understanding the strengths and appropriate use cases for each audio encoder, .NET developers can make informed decisions that optimize their media applications for quality, performance, and compatibility. ---END OF PAGE--- ## MP3 Audio Encoder in C# .NET — LAME Bitrate Settings **URL:** https://www.visioforge.com/help/docs/dotnet/general/audio-encoders/mp3/ **Description:** LAME encoder with CBR, ABR, and quality-based VBR modes. Joint stereo, voice optimization, bitrate 8-320 kbps. VisioForge SDK capture and editing examples. **Tags:** Video Capture SDK, Media Blocks SDK, Video Edit SDK, .NET, MediaBlocksPipeline, VideoCaptureCoreX, VideoEditCoreX, Windows, macOS, Linux, Android, iOS, Capture, Streaming, Encoding, Editing, MP3, C# **API:** MP3Output, MP3EncoderSettings, MP3EncoderRateControl, MP3ChannelsMode, MP3EncodingQuality # Mastering MP3 Audio: Record, Capture & Edit in C# and .NET [Video Capture SDK .Net](https://www.visioforge.com/video-capture-sdk-net) [Video Edit SDK .Net](https://www.visioforge.com/video-edit-sdk-net) [Media Blocks SDK .Net](https://www.visioforge.com/media-blocks-sdk-net) The VisioForge SDK empowers developers to seamlessly record, capture, and edit MP3 audio within C# applications. This guide explores how to leverage our robust .NET SDK for high-quality MP3 audio processing. Whether you need to capture media streams, record MP3 files, or edit audio waveforms, our C# media toolkit provides comprehensive tools using the LAME library. MP3, a widely adopted lossy audio compression format, is ideal for audio streaming and efficient storage. You can utilize the MP3 encoder to integrate audio capture and recording functionalities into various container formats such as MP4, AVI, and MKV, enhancing your audio capture projects. Our SDK works seamlessly with Visual Studio for a smooth development experience. SDK contains MP3 audio encoder that can be used to encode audio streams to MP3 format using the LAME library. MP3 is a lossy audio compression format that is widely used in audio streaming and storage. You can use MP3 encode to encode audio in MP4, AVI, MKV, and other containers. ## Cross-platform MP3 Audio Capture and Recording [VideoCaptureCoreX](#) [VideoEditCoreX](#) [MediaBlocksPipeline](#) The [MP3EncoderSettings](https://api.visioforge.org/dotnet/api/VisioForge.Core.Types.X.AudioEncoders.MP3EncoderSettings.html) class provides developers with a streamlined approach to configure MP3 encoding for C# audio capture projects. This cross-platform solution supports various rate controls and quality settings, making it ideal for record .NET MP3 applications across different operating systems. ### Supported Formats and Specifications for C# MP3 Recording - Input Format: S16LE (Signed 16-bit Little Endian) - Sample Rates: 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000 Hz - Channels: Mono (1) or Stereo (2) ### Rate Control Modes The encoder supports three rate control modes: 1. **CBR (Constant Bit Rate)** 2. Fixed bitrate throughout the entire encoding process 3. Supported bitrates: 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320 Kbit/s 4. Best for streaming MP3 and when consistent file size is important 5. **ABR (Average Bit Rate)** 6. Maintains an average bitrate while allowing some variation 7. More efficient than CBR while still maintaining predictable file sizes 8. Useful for streaming services that need approximate file size estimates 9. **Quality-based VBR** 10. Variable Bit Rate based on sound complexity 11. Quality setting ranges from 0 (best) to 10 12. Most efficient for storage and best quality-to-size ratio ### C# MP3 Encoding Examples Create basic MP3 encoder settings with CBR. ``` // Create basic MP3 encoder settings using Constant Bit Rate mode var mp3Settings = new MP3EncoderSettings { // Set to Constant Bit Rate - provides consistent file size and streaming reliability RateControl = MP3EncoderRateControl.CBR, // 192 kbps offers good quality for most music content while keeping file size reasonable Bitrate = 192, // Standard quality offers a good balance between encoding speed and output quality EncodingEngineQuality = MP3EncodingQuality.Standard, // Keep stereo channels (false) - set to true if you want to convert to mono ForceMono = false }; ``` Quality-based VBR configuration for high-quality .NET MP3 editing. ``` // Configure MP3 encoder with Variable Bit Rate for optimal quality-to-size ratio var vbrSettings = new MP3EncoderSettings { // Quality-based VBR adjusts bitrate dynamically based on audio complexity RateControl = MP3EncoderRateControl.Quality, // Quality scale: 0 (best) to 10 (worst) - 2.0 provides excellent quality with reasonable file size Quality = 2.0f, // High quality encoding uses more CPU but produces better results EncodingEngineQuality = MP3EncodingQuality.High }; ``` Add the MP3 output to capture C# MP3 audio with the Video Capture SDK: The [MP3Output](https://api.visioforge.org/dotnet/api/VisioForge.Core.Types.X.Output.MP3Output.html) class implements multiple interfaces: - IVideoEditXBaseOutput - IVideoCaptureXBaseOutput - IOutputAudioProcessor ``` // Create a Video Capture SDK core instance for recording var core = new VideoCaptureCoreX(); // Initialize MP3 output with target filename var mp3Output = new MP3Output("output.mp3"); // Configure audio encoding settings mp3Output.Audio.RateControl = MP3EncoderRateControl.CBR; // Use Constant Bit Rate for reliable streaming mp3Output.Audio.Bitrate = 128; // 128 kbps is suitable for general audio recording // Add the MP3 output to the capture pipeline core.Outputs_Add(mp3Output, true); ``` Set the output format for the Video Edit SDK core instance: ``` // Initialize Video Edit SDK for processing existing media var core = new VideoEditCoreX(); // Create MP3 output with target filename var mp3Output = new MP3Output("output.mp3"); // Configure Variable Bit Rate encoding for better quality-to-size ratio mp3Output.Audio.RateControl = MP3EncoderRateControl.Quality; mp3Output.Audio.Quality = 5.0f; // Middle quality setting (0-10 scale) - good balance of quality and size // Set as the primary output format for the editor core.Output_Format = mp3Output; ``` ### Initialization To create a new MP3Output instance, you need to provide the output filename: ``` // Initialize MP3 output with destination filename var mp3Output = new MP3Output("output.mp3"); ``` ### Audio Settings The `Audio` property provides access to MP3 encoder settings: ``` // Create default MP3 encoder settings object mp3Output.Audio = new MP3EncoderSettings(); // Additional configuration can be applied to mp3Output.Audio properties ``` ### Custom Audio Processing You can set a custom audio processor using the `CustomAudioProcessor` property to handle waveform manipulations: ``` // Attach a custom audio processor for advanced audio manipulation mp3Output.CustomAudioProcessor = new MediaBlock(); // The MediaBlock can be configured for effects, filtering, or other audio processing ``` ### Filename Operations There are multiple ways to work with the output filename: ``` // Retrieve the current output filename string currentFile = mp3Output.GetFilename(); // Change the output destination mp3Output.SetFilename("newoutput.mp3"); // Alternative way to set the filename via property mp3Output.Filename = "another.mp3"; ``` ### Audio Encoders The MP3Output class supports MP3 encoding exclusively. You can verify the available encoders: ``` // Get information about available audio encoders var audioEncoders = mp3Output.GetAudioEncoders(); // Returns a list of tuples containing encoder names and their setting types // For MP3Output, this will contain a single entry for MP3 ``` ### MP3OutputBlock class The [MP3OutputBlock](../../../mediablocks/AudioEncoders/) class provides a more flexible way to configure MP3 encoding. Create a Media Blocks MP3 output instance: ``` // Create MP3 encoder settings with desired configuration var mp3Settings = new MP3EncoderSettings(); // Initialize MP3 output block with destination file and settings var mp3Output = new MP3OutputBlock("output.mp3", mp3Settings); ``` Check if MP3 encoding is available. ``` // Check if MP3 encoding is available on the current system if (!MP3EncoderSettings.IsAvailable()) { // Handle case where MP3 encoding is not available // This might occur if LAME or other required libraries are missing } ``` ### Encoding Quality Levels The encoder supports three quality presets that affect the encoding speed and CPU usage: - `Fast`: Quickest encoding, lower CPU usage - `Standard`: Balanced speed and quality (default) - `High`: Best quality, higher CPU usage ### Common Scenarios #### High-Quality Music Capture in C ``` // Configure settings for high-quality music recording var highQualitySettings = new MP3EncoderSettings { // Use quality-based Variable Bit Rate for optimal audio fidelity RateControl = MP3EncoderRateControl.Quality, // Highest quality setting (0.0f) for maximum audio fidelity Quality = 0.0f, // Use high-quality encoding algorithm (more CPU intensive but better results) EncodingEngineQuality = MP3EncodingQuality.High }; ``` #### Streaming Audio ``` // Configure settings optimized for audio streaming applications var streamingSettings = new MP3EncoderSettings { // Use Constant Bit Rate for predictable streaming performance RateControl = MP3EncoderRateControl.CBR, // 128 kbps provides good quality for most content while being bandwidth-friendly Bitrate = 128, // Fast encoding reduces CPU usage, important for real-time streaming EncodingEngineQuality = MP3EncodingQuality.Fast }; ``` ## Windows-only MP3 output [VideoCaptureCore](#) [VideoEditCore](#) The [MP3 file output](https://api.visioforge.org/dotnet/api/VisioForge.Core.Types.X.Output.MP3Output.html) class provides advanced configuration options for MP3 encoding in C# audio video capture and editing scenarios. ### Key Features - Flexible channel mode selection - VBR and CBR encoding support for optimal .NET MP3 recording - Advanced encoding parameters for professional audio applications - Quality control settings for perfect C# MP3 editing results ### Basic Configuration #### CBR\_Bitrate Controls the Constant Bit Rate (CBR) setting for MP3 encoding. - For MPEG-1 (32, 44.1, 48 kHz): Valid values are 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320 kbps - For MPEG-2 (16, 22.05, 24 kHz): Valid values are 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160 kbps - Default values: 128 kbps (MPEG-1) or 64 kbps (MPEG-2) #### SampleRate Specifies the audio sampling frequency in Hz. Common values are: - 44100 Hz (CD quality, default) - 48000 Hz (professional audio) - 32000 Hz (broadcast) - 22050 Hz (lower quality) - 16000 Hz (voice) #### ChannelsMode Determines how audio channels are encoded. Options include: 1. StandardStereo: Independent channel encoding with dynamic bit allocation 2. JointStereo: Exploits correlation between channels using mid/side encoding 3. DualStereo: Independent encoding with fixed 50/50 bit allocation (ideal for dual language) 4. Mono: Single channel output (downmixes stereo input) ### Variable Bit Rate (VBR) Settings #### VBR\_Mode Enables Variable Bit Rate encoding when set to true (default). VBR allows the encoder to adjust bitrate based on audio complexity. #### VBR\_MinBitrate Sets the minimum allowed bitrate for VBR encoding (default: 96 kbps). #### VBR\_MaxBitrate Sets the maximum allowed bitrate for VBR encoding (default: 192 kbps). #### VBR\_Quality Controls VBR encoding quality (0-9): - Lower values (0-4): Higher quality, slower encoding - Middle values (5-6): Balanced quality and speed - Higher values (7-9): Lower quality, faster encoding ### Quality and Performance #### EncodingQuality Determines the algorithmic quality of encoding (0-9): - 0-1: Best quality, slowest encoding - 2: Recommended for high quality - 5: Default, good balance of speed and quality - 7: Fast encoding with acceptable quality - 9: Fastest encoding, lowest quality ### Special Features #### ForceMono When enabled, automatically downmixes multi-channel audio to mono. #### VoiceEncodingMode Experimental mode optimized for voice content. #### KeepAllFrequencies Disables automatic frequency filtering, preserving all frequencies at the cost of efficiency. #### DisableShortBlocks Forces use of long blocks only, which may improve quality at very low bitrates but can cause pre-echo artifacts. ### MP3 Frame Flags #### Copyright Sets the copyright bit in MP3 frames. #### Original Marks the stream as original content. #### CRCProtected Enables CRC error detection at the cost of 16 bits per frame. #### EnableXingVBRTag Adds VBR information headers for better player compatibility. #### StrictISOCompliance Enforces strict ISO MP3 standard compliance. ### Example MP3 Recording and Editing Configurations Basic settings for C# MP3 capture applications. ``` // Configure basic MP3 output with standard settings var mp3Output = new MP3Output { // 192 kbps provides good quality for most music content CBR_Bitrate = 192, // CD-quality sample rate SampleRate = 44100, // Joint stereo mode provides better compression for most stereo content ChannelsMode = MP3ChannelsMode.JointStereo, }; // Set as the output format for capture or editing core.Output_Format = mp3Output; // Core is VideoCaptureCore or VideoEditCore ``` VBR configuration. ``` // Configure MP3 output with Variable Bit Rate for better quality/size balance var mp3Output = new MP3Output { // Enable Variable Bit Rate encoding VBR_Mode = true, // Set minimum bitrate floor to ensure acceptable quality VBR_MinBitrate = 96, // Limit maximum bitrate to control file size VBR_MaxBitrate = 192, // Quality level 6 provides a good balance between quality and file size VBR_Quality = 6, }; // Set as the output format for capture or editing core.Output_Format = mp3Output; // Core is VideoCaptureCore or VideoEditCore ``` #### Basic Stereo MP3 Encoding ``` // Configure standard stereo MP3 encoding with fixed bitrate var mp3Output = new MP3Output { // 192 kbps provides good quality for most music while keeping file size reasonable CBR_Bitrate = 192, // Standard stereo mode encodes left and right channels independently ChannelsMode = MP3ChannelsMode.StandardStereo, // CD-quality sample rate SampleRate = 44100, // Disable Variable Bit Rate to ensure consistent file size and playback VBR_Mode = false }; ``` #### Voice-Optimized Encoding ``` // Configure MP3 settings optimized for voice recordings var voiceMP3 = new MP3Output { // Enable voice-optimized encoding algorithms VoiceEncodingMode = true, // Use mono for voice to reduce file size (most voice doesn't benefit from stereo) ChannelsMode = MP3ChannelsMode.Mono, // Lower sample rate is sufficient for voice content SampleRate = 22050, // Enable Variable Bit Rate for better quality/size ratio VBR_Mode = true, // Better quality setting for voice clarity while keeping file size reasonable VBR_Quality = 4 }; ``` #### High-Quality Music Encoding ``` // Configure high-quality MP3 settings for music archiving var highQualityMP3 = new MP3Output { // Enable Variable Bit Rate for optimal quality-to-size ratio VBR_Mode = true, // Set minimum bitrate to ensure good quality even in simple passages VBR_MinBitrate = 128, // Allow high bitrate for complex passages to preserve audio detail VBR_MaxBitrate = 320, // Use high quality setting (2) for excellent audio fidelity VBR_Quality = 2, // Set encoder algorithm to high quality mode EncodingQuality = 2, // Joint stereo provides better compression for most music content ChannelsMode = MP3ChannelsMode.JointStereo, // Professional audio sample rate captures full audible spectrum SampleRate = 48000, // Add VBR header for better player compatibility and seeking EnableXingVBRTag = true }; ``` ### Advanced Settings - **CRC Protection**: Adds error detection capability at the cost of 16 bits per frame - **Short Blocks**: Can be disabled to potentially increase quality at very low bitrates - **Frequency Range**: Option to keep all frequencies (disables automatic lowpass filtering) - **Voice Mode**: Experimental mode optimized for voice content ### Best Practices 1. **Choosing Rate Control for Different Applications** 2. Use CBR for streaming and real-time C# MP3 capturing 3. Use Quality-based VBR for archival and highest quality .NET MP3 recording 4. Use ABR when you need a balance between consistent size and quality 5. **Quality Settings for Different Use Cases** 6. For archival: Use VBR with quality 0-2 7. For general C# audio video capture: VBR with quality 3-5 or CBR 192-256kbps 8. For voice recording in .NET: Consider using voice encoding mode with lower bitrates 9. **Channel Mode Selection** 10. Use Joint Stereo for most music content 11. Use Standard Stereo for critical listening and complex stereo mixes 12. Use Mono for voice recordings or when bandwidth is critical 13. **Performance Optimization** 14. Use Fast encoding quality for real-time applications 15. Use Standard quality for general purpose encoding 16. Use High quality only for archival purposes where encoding time is not critical ### Notes on Default Values The class constructor sets these default values: - CBR\_Bitrate = 192 kbps - VBR\_MinBitrate = 96 kbps - VBR\_MaxBitrate = 192 kbps - VBR\_Quality = 6 - EncodingQuality = 6 - SampleRate = 44100 Hz - ChannelsMode = MP3ChannelsMode.StandardStereo - VBR\_Mode = true ---END OF PAGE--- ## Opus Audio Encoder in C# .NET — Bitrate, VBR, DTX Guide **URL:** https://www.visioforge.com/help/docs/dotnet/general/audio-encoders/opus/ **Description:** VBR, CBR, and CVBR rate control modes. Bitrate 6-510 kbps, 5 ms latency, complexity tuning, and DTX for speech. OGG/WebM output with C# examples. **Tags:** Video Capture SDK, Media Blocks SDK, Video Edit SDK, .NET, MediaBlocksPipeline, VideoCaptureCoreX, VideoEditCoreX, Windows, macOS, Linux, Android, iOS, Capture, Streaming, Encoding, Editing, WebM, OGG, Opus, C# **API:** OPUSEncoderSettings, VideoCaptureCoreX, VideoEditCoreX, OPUSOutput, OGGOpusOutputBlock # Mastering OPUS Audio Encoding in .NET Applications [Video Capture SDK .Net](https://www.visioforge.com/video-capture-sdk-net) [Video Edit SDK .Net](https://www.visioforge.com/video-edit-sdk-net) [Media Blocks SDK .Net](https://www.visioforge.com/media-blocks-sdk-net) ## Introduction to OPUS Audio Encoding OPUS stands as one of the most versatile and efficient audio codecs available for modern software development. VisioForge .NET SDKs include a royalty-free OPUS encoder that transforms audio into the highly adaptable Opus format. This encoded audio can be encapsulated in various containers including Ogg, Matroska, WebM, or RTP streams, making it ideal for both streaming applications and stored media. Developed by the Internet Engineering Task Force (IETF), OPUS combines the best elements of the SILK and CELT codecs to deliver exceptional performance across a wide range of audio requirements. The codec excels in both speech and music encoding at bitrates from as low as 6 kbps to as high as 510 kbps, offering developers remarkable flexibility in balancing quality against bandwidth constraints. ## Why Choose OPUS for Your .NET Applications OPUS has become the preferred choice for many audio applications for several compelling reasons: - **Low Latency**: With encoding delays as low as 5ms, OPUS is perfect for real-time communication applications - **Adaptive Bitrate**: Seamlessly switches between speech and music optimization - **Wide Bitrate Range**: Functions effectively from 6 kbps to 510 kbps - **Superior Compression**: Offers better quality than MP3, AAC, and other codecs at equivalent bitrates - **Open Standard**: Royalty-free and open-source, reducing licensing concerns - **Cross-Platform Support**: Works across all major platforms and browsers These advantages make OPUS particularly valuable for developers building applications that require efficient audio streaming, VoIP solutions, or any scenario where audio quality and bandwidth efficiency are crucial considerations. ## Implementing OPUS in Cross-Platform .NET Applications [VideoCaptureCoreX](#) [VideoEditCoreX](#) [MediaBlocksPipeline](#) When working with VisioForge's cross-platform X-engines, developers can leverage the [OPUSEncoderSettings](https://api.visioforge.org/dotnet/api/VisioForge.Core.Types.X.AudioEncoders.OPUSEncoderSettings.html) class to configure OPUS encoding parameters precisely for their application needs. ### Essential OPUS Encoder Configuration Properties To achieve optimal results with the OPUS encoder, understanding and configuring these key properties is essential: - **Bitrate**: Sets the target bitrate in Kbps, determining the balance between quality and file size - **Rate Control Mode**: Selects between Variable Bitrate (VBR), Constant Bitrate (CBR), or Constrained Variable Bitrate (CVBR) - **Complexity**: Controls encoding complexity on a scale from 0-10, where higher values produce better quality at the expense of increased CPU usage - **Frame Duration**: Configures the frame size (2.5, 5, 10, 20, 40, or 60ms), with shorter frames providing lower latency at the cost of encoding efficiency - **Application Type**: Optimizes for either voice or music content, allowing the encoder to apply specialized techniques - **Forward Error Correction**: Enables packet loss resilience for streaming applications - **DTX (Discontinuous Transmission)**: Reduces bandwidth during silence periods Each of these parameters can significantly impact audio quality, processing requirements, and bandwidth consumption, making them critical considerations for developers optimizing for specific application scenarios. ## Understanding Bitrate Control Modes in Depth One of the most important decisions when implementing OPUS encoding is selecting the appropriate bitrate control strategy. OPUS offers three primary modes, each with distinct advantages for different use cases. ### Variable Bitrate (VBR) VBR represents the most efficient approach for quality optimization, allowing the encoder to dynamically adjust bitrate based on audio complexity. This results in higher bitrates for complex passages and lower bitrates for simpler content. ``` // Create an instance of the OPUSEncoderSettings class. var opus = new OPUSEncoderSettings(); // Set rate control mode to VBR opus.RateControl = OPUSRateControl.VBR; // Set audio bitrate for the codec (in Kbps) opus.Bitrate = 128; ``` **Best for**: On-demand audio streaming, podcast distribution, music applications, and any scenario where consistent bandwidth isn't a primary concern. **Key advantage**: Provides the highest quality-to-size ratio by allocating more bits to complex audio sections. ### Constant Bitrate (CBR) CBR mode attempts to maintain a consistent bitrate throughout the encoding process. While OPUS is inherently a variable bitrate codec, its CBR implementation keeps fluctuations minimal, typically within 5% of the target. ``` // Create an instance of the OPUSEncoderSettings class. var opus = new OPUSEncoderSettings(); // Set rate control mode to CBR opus.RateControl = OPUSRateControl.CBR; // Set audio bitrate for the codec (in Kbps) opus.Bitrate = 128; ``` **Best for**: Live streaming applications, VoIP systems, videoconferencing, and scenarios where network bandwidth predictability is critical. **Key advantage**: Maintains consistent bandwidth utilization, making it easier to plan network capacity and ensure reliable transmission. ### Constrained Variable Bitrate (CVBR) CVBR offers a middle-ground approach, allowing bitrate variations based on content complexity while imposing constraints to prevent extreme fluctuations. This provides many of VBR's quality benefits while keeping bandwidth requirements more predictable. ``` // Create an instance of the OPUSEncoderSettings class. var opus = new OPUSEncoderSettings(); // Set rate control mode to Constrained VBR opus.RateControl = OPUSRateControl.ConstrainedVBR; // Set audio bitrate for the codec (in Kbps) opus.Bitrate = 128; ``` **Best for**: Adaptive streaming applications, mixed-content broadcasting, and scenarios where quality is important but bandwidth constraints still exist. **Key advantage**: Balances quality optimization with reasonable bandwidth predictability. ## Bitrate Selection Guidelines Setting an appropriate bitrate involves balancing quality requirements against bandwidth limitations. For OPUS encoding, consider these channel-specific recommendations: **For Mono Audio:** - 6-12 kbps: Acceptable for low-bitrate speech - 16-24 kbps: Good quality speech - 32-64 kbps: High-quality speech and acceptable music - 64-128 kbps: High-quality music **For Stereo Audio:** - 16-32 kbps: Low-quality stereo - 48-64 kbps: Good quality stereo speech - 64-128 kbps: Standard quality stereo music - 128-256 kbps: High-quality stereo music While OPUS can technically support bitrates up to 510 kbps, most applications achieve excellent results well below 192 kbps due to the codec's exceptional efficiency. ## Practical Implementation Examples ### Implementing OPUS in Video Capture Applications The following example demonstrates how to add OPUS output to a Video Capture SDK core instance: ``` // Create a Video Capture SDK core instance var core = new VideoCaptureCoreX(); // Create a OPUS output instance var opusOutput = new OPUSOutput("output.opus"); // Set the bitrate and rate control mode opusOutput.Audio.RateControl = OPUSRateControl.CBR; opusOutput.Audio.Bitrate = 128; // Add the OPUS output core.Outputs_Add(opusOutput, true); ``` ### Configuring OPUS for Video Editing Workflows When working with the Video Edit SDK, you can configure OPUS as your output format: ``` // Create a Video Edit SDK core instance var core = new VideoEditCoreX(); // Create a OPUS output instance var opusOutput = new OPUSOutput("output.opus"); // Set the bitrate for high-quality music encoding opusOutput.Audio.RateControl = OPUSRateControl.VBR; opusOutput.Audio.Bitrate = 192; // Set the output format core.Output_Format = opusOutput; ``` ### Creating OPUS Outputs with Media Blocks SDK The Media Blocks SDK offers flexible options for creating OPUS outputs in different container formats: ``` // Create a OPUS encoder settings instance with specific configuration var opusSettings = new OPUSEncoderSettings { Bitrate = 128, RateControl = OPUSRateControl.VBR, Complexity = 8 }; // Create an Ogg OPUS output instance (opus + ogg container) var oggOpusOutput = new OGGOpusOutputBlock("output.ogg", opusSettings); ``` ## Performance Optimization Tips To achieve the best results with OPUS encoding in your .NET applications: 1. **Match Complexity to Your Hardware**: For real-time applications on limited hardware, use lower complexity values (3-6). For offline encoding or on powerful systems, higher values (7-10) will yield better quality. 2. **Select Appropriate Frame Duration**: Shorter frames (2.5-10ms) minimize latency for real-time communication, while longer frames (20-60ms) improve compression efficiency for music and stored content. 3. **Consider Input Sample Rate**: OPUS performs optimally with 48kHz input. If your source is at a different sample rate, consider resampling to 48kHz before encoding. 4. **Optimize for Content Type**: Use the Application property to tell the encoder whether you're primarily encoding speech or music for content-specific optimizations. 5. **Enable DTX for Speech**: For voice communications with frequent silence, enabling DTX can significantly reduce bandwidth requirements without noticeable quality impact. ## Conclusion The OPUS codec offers .NET developers an exceptional tool for creating high-quality, bandwidth-efficient audio applications. With VisioForge's SDKs, implementing OPUS encoding becomes straightforward while still providing the flexibility to fine-tune every aspect of the encoding process. By understanding the bitrate control modes, selecting appropriate parameters, and following the implementation examples provided, you can leverage OPUS to deliver superior audio experiences in your .NET applications regardless of whether you're building real-time communication tools, media players, or content creation software. ---END OF PAGE--- ## Speex Speech Audio Encoder Integration for .NET SDK **URL:** https://www.visioforge.com/help/docs/dotnet/general/audio-encoders/speex/ **Description:** Implement Speex speech compression in .NET with optimized voice encoding settings, quality controls, and cross-platform audio capture. **Tags:** Video Capture SDK, Media Blocks SDK, Video Edit SDK, .NET, MediaBlocksPipeline, VideoCaptureCoreX, VideoEditCoreX, Windows, macOS, Linux, Android, iOS, Capture, Streaming, Encoding, Editing, Speex, C# **API:** SpeexEncoderSettings, VideoCaptureCoreX, VideoEditCoreX, MediaBlocksPipeline, SpeexOutput # Speex Audio Encoder for .NET [Video Capture SDK .Net](https://www.visioforge.com/video-capture-sdk-net) [Video Edit SDK .Net](https://www.visioforge.com/video-edit-sdk-net) [Media Blocks SDK .Net](https://www.visioforge.com/media-blocks-sdk-net) ## Introduction to Speex Speex is a patent-free audio codec specifically designed for speech encoding in .NET applications. Whether you need to capture, edit, or record audio in C#, Speex provides excellent compression while maintaining voice quality across various bitrates. VisioForge integrates this powerful encoder into its .NET SDKs, offering developers flexible configuration options for speech-based applications. The codec is particularly well-suited for C# developers looking to implement high-quality audio capture and recording features in their applications. ## Core Functionality The Speex encoder in VisioForge SDKs supports: - Multiple frequency bands for different quality levels - Variable and fixed bitrate encoding - Voice activity detection and silence compression - Adjustable complexity and quality settings - Cross-platform compatibility across Windows, macOS, and Linux - Seamless integration with dotnet applications ## Cross-platform Implementation [VideoCaptureCoreX](#) [VideoEditCoreX](#) [MediaBlocksPipeline](#) ### Encoder Modes Speex offers four operation modes optimized for different frequency ranges: | Mode | Value | Optimal Sample Rate | | --- | --- | --- | | Auto | 0 | Automatic selection based on input | | Ultra Wide Band | 1 | 32 kHz | | Wide Band | 2 | 16 kHz | | Narrow Band | 3 | 8 kHz | The encoder automatically adjusts internal parameters based on the selected mode. For most speech applications, Wide Band (mode 2) offers an excellent balance between quality and bandwidth usage. ## Technical Specifications ### Supported Sample Rates Speex works with three standard sampling frequencies: - 8,000 Hz - Best for telephone-quality audio (Narrow Band) - 16,000 Hz - Recommended for most voice applications (Wide Band) - 32,000 Hz - Highest quality speech encoding (Ultra Wide Band) ### Channel Configuration The encoder handles both: - Mono (1 channel) - Ideal for speech recordings - Stereo (2 channels) - For multi-speaker or immersive audio ## Rate Control Methods ### Quality-Based Encoding For consistent perceptual quality, use the `Quality` parameter: ``` var settings = new SpeexEncoderSettings { Quality = 8.0f, // Range from 0 (lowest) to 10 (highest) VBR = false // Fixed quality mode }; ``` Higher quality values produce better audio at the expense of increased file size. Most speech applications work well with quality values between 5-8. ### Variable Bit Rate (VBR) VBR dynamically adjusts the bitrate based on speech complexity: ``` var settings = new SpeexEncoderSettings { VBR = true, Quality = 8.0f // Target quality level }; ``` This approach typically saves bandwidth while maintaining consistent perceived quality, making it ideal for streaming applications. ### Average Bit Rate (ABR) ABR maintains a target bitrate over time while allowing quality fluctuations: ``` var settings = new SpeexEncoderSettings { ABR = 15.0f, // Target bitrate in kbps VBR = true // Required for ABR mode }; ``` This option works well when you need predictable file sizes or bandwidth usage. ### Fixed Bitrate Encoding For consistent data rates throughout the encoding process: ``` var settings = new SpeexEncoderSettings { Bitrate = 24.6f, // Fixed rate in kbps VBR = false }; ``` Supported bitrates range from 2.15 kbps to 24.6 kbps: - 2.15 kbps - Ultra-compressed speech (limited quality) - 3.95 kbps - Low bandwidth voice - 5.95 kbps - Basic speech clarity - 8.00 kbps - Standard voice quality - 11.0 kbps - Good speech reproduction - 15.0 kbps - Near-transparent speech - 18.2 kbps - High-quality voice - 24.6 kbps - Maximum quality speech ## Voice Optimization Features ### Voice Activity Detection (VAD) VAD identifies the presence of speech in audio signals: ``` var settings = new SpeexEncoderSettings { VAD = true, // Enable voice detection DTX = true // Recommended with VAD }; ``` This feature improves bandwidth efficiency by focusing encoding resources on actual speech segments. ### Discontinuous Transmission (DTX) DTX reduces data transmission during silence periods: ``` var settings = new SpeexEncoderSettings { DTX = true // Enable silence compression }; ``` For VoIP and real-time communications, enabling DTX can significantly reduce bandwidth requirements. ### Encoding Complexity Control CPU usage versus encoding quality: ``` var settings = new SpeexEncoderSettings { Complexity = 3 // Range: 1 (fastest) to 10 (highest quality) }; ``` Lower values prioritize speed and reduce CPU load, while higher values improve audio quality at the cost of performance. ## Implementation Examples ### Checking Encoder Availability Always verify encoder availability before implementing Speex in your C# application: ``` if (!SpeexEncoderSettings.IsAvailable()) { throw new InvalidOperationException("Speex encoder not available on this system."); } ``` ### Basic Configuration for Audio Capture Here's how to set up basic Speex encoding for audio capture in dotnet: ``` var encoderSettings = new SpeexEncoderSettings { Mode = SpeexEncoderMode.WideBand, SampleRate = 16000, Channels = 1, Quality = 7.0f }; ``` ### Optimized for Voice Recording For voice recording applications in .NET, use these optimized settings: ``` var voipSettings = new SpeexEncoderSettings { Mode = SpeexEncoderMode.WideBand, SampleRate = 16000, Channels = 1, VBR = true, VAD = true, DTX = true, Quality = 6.0f, Complexity = 4 }; ``` ### Highest Quality Audio Capture For maximum quality audio capture in dotnet: ``` var highQualitySettings = new SpeexEncoderSettings { Mode = SpeexEncoderMode.UltraWideBand, SampleRate = 32000, Channels = 2, Bitrate = 24.6f, Complexity = 8 }; ``` ## SDK Integration ### Video Capture SDK Integration Learn how to capture audio using Speex in your C# application: ``` using VisioForge.Core.Types.Events; using VisioForge.Core.Types.X.AudioEncoders; using VisioForge.Core.Types.X.Output; using VisioForge.Core.Types.X.Sources; // Create a Video Capture SDK core instance var core = new VideoCaptureCoreX(); // Set the audio input device, filter by API var api = AudioCaptureDeviceAPI.DirectSound; var audioInputDevice = (await DeviceEnumerator.Shared.AudioSourcesAsync()).FirstOrDefault(x => x.API == api); if (audioInputDevice == null) { MessageBox.Show("No audio input device found."); return; } var audioInput = new AudioCaptureDeviceSourceSettings(api, audioInputDevice, audioInputDevice.GetDefaultFormat()); core.Audio_Source = audioInput; // Configure Speex settings var speexSettings = new SpeexEncoderSettings { Mode = SpeexEncoderMode.WideBand, SampleRate = 16000, Channels = 1, VBR = true, Quality = 7.0f }; var speexOutput = new SpeexOutput("output.spx", speexSettings); // Add the Speex output core.Outputs_Add(speexOutput, true); // Set the audio record mode core.Audio_Record = true; core.Audio_Play = false; // Start the capture await core.StartAsync(); // Stop after 10 seconds await Task.Delay(10000); // Stop the capture await core.StopAsync(); ``` ### Video Edit SDK Integration Edit and process audio files using Speex in dotnet: ``` using VisioForge.Core.Types.Events; using VisioForge.Core.Types.X.AudioEncoders; using VisioForge.Core.Types.X.Output; using VisioForge.Core.Types.X.Sources; // Create a Video Edit SDK core instance var core = new VideoEditCoreX(); // Add the audio source file var audioFile = new AudioFileSource(@"c:\samples\!audio.mp3"); core.Input_AddAudioFile(audioFile, null); // Configure Speex settings var speexSettings = new SpeexEncoderSettings { Mode = SpeexEncoderMode.WideBand, SampleRate = 16000, Channels = 1, VBR = true, Quality = 7.0f }; var speexOutput = new SpeexOutput(@"output.spx", speexSettings); // Add the Speex output core.Output_Format = speexOutput; // Catch OnStop event core.OnStop += (s, e) => { // Handle the stop event here MessageBox.Show("Editing complete."); }; core.OnProgress += (s, e) => { // Handle progress updates here Debug.WriteLine($"Progress: {e.Progress}%"); }; core.OnError += (s, e) => { // Handle errors here Debug.WriteLine($"Error: {e.Message}"); }; // Start the editing core.Start(); ``` ### Media Blocks SDK Integration Process audio streams using Speex in your .NET application: ``` using VisioForge.Core; using VisioForge.Core.MediaBlocks; using VisioForge.Core.MediaBlocks.AudioEncoders; using VisioForge.Core.MediaBlocks.Sinks; using VisioForge.Core.MediaBlocks.Sources; using VisioForge.Core.Types.Events; using VisioForge.Core.Types.X.AudioEncoders; using VisioForge.Core.Types.X.Output; using VisioForge.Core.Types.X.Sources; // Create a new pipeline var pipeline = new MediaBlocksPipeline(); // Add universal source to read audio file var sourceSettings = await UniversalSourceSettings.CreateAsync(@"c:\samples\!audio.mp3", renderVideo: false, renderAudio: true); var source = new UniversalSourceBlock(sourceSettings); // Add Speex output var speexSettings = new SpeexEncoderSettings { Mode = SpeexEncoderMode.NarrowBand, SampleRate = 8000, DTX = true, VAD = true }; var speexOutput = new OGGSpeexOutputBlock("output.spx", speexSettings); // Connect pipeline.Connect(source.AudioOutput, speexOutput.Input); // Add OnStop event handler pipeline.OnStop += (sender, e) => { // Do something when the pipeline stops MessageBox.Show("Conversion complete"); }; // Start await pipeline.StartAsync(); ``` ## Performance Optimization When implementing Speex encoding, consider these optimization strategies: 1. **Match sample rate to content** - Use Narrow Band (8 kHz) for telephone audio, Wide Band (16 kHz) for most voice applications, and Ultra Wide Band (32 kHz) only when maximum quality is required 2. **Enable VBR with VAD/DTX** for speech content - This combination provides optimal bandwidth efficiency for typical voice recordings 3. **Adjust complexity based on platform** - Mobile applications may benefit from lower complexity values (2-4), while desktop applications can use higher values (5-8) 4. **Use ABR for streaming** - Average Bit Rate provides predictable bandwidth usage while maintaining quality flexibility 5. **Test different quality settings** - Often a quality setting of 5-7 provides excellent results without excessive file size ## Use Cases Speex encoding excels in these developer scenarios: - VoIP applications and internet telephony - Voice chat features in games and collaboration tools - Podcast creation and distribution - Speech recognition preprocessing - Voice note applications - Audio archiving of speech content ## Installation and Setup To get started with Speex in your dotnet application, check the main installation guide [here](../../../install/). ## Common Use Cases ### Audio Capture and Recording For streaming applications, use these optimized settings: ``` var streamingSettings = new SpeexEncoderSettings { Mode = SpeexEncoderMode.WideBand, SampleRate = 16000, Channels = 1, VBR = true, VAD = true, DTX = true, Quality = 6.0f, Complexity = 3 }; ``` ### Voice Over IP Applications For VoIP applications, prioritize low latency and bandwidth efficiency: ``` var voipSettings = new SpeexEncoderSettings { Mode = SpeexEncoderMode.NarrowBand, SampleRate = 8000, Channels = 1, VBR = true, VAD = true, DTX = true, Quality = 5.0f, Complexity = 2 }; ``` ## Licensing and Community Speex is released under the BSD license, making it free for both commercial and non-commercial use. The codec is actively maintained by the open-source community, with regular updates and improvements. ## Frequently Asked Questions ### What is the best bitrate for voice recording? For most voice applications, a bitrate between 8-15 kbps provides excellent quality while maintaining reasonable file sizes. Use VBR mode for optimal results. ### How does Speex compare to other codecs? Speex offers superior speech quality compared to many other codecs at similar bitrates, especially for voice content. It's particularly effective for low-bitrate applications. ### Can I use Speex for music encoding? While Speex can encode music, it's specifically optimized for speech. For music content, consider using other codecs like AAC or MP3. ## Conclusion The VisioForge implementation of Speex provides .NET developers with a powerful tool for capturing, editing, and recording audio in C# applications. Whether you're building a new voice capture application or enhancing an existing one, Speex delivers exceptional results with minimal resource usage. The codec's flexibility and performance make it an excellent choice for any .NET developer working with audio processing. ---END OF PAGE--- ## Vorbis Audio Encoding Guide for .NET SDK Development **URL:** https://www.visioforge.com/help/docs/dotnet/general/audio-encoders/vorbis/ **Description:** Implement Vorbis audio encoding in .NET with quality optimization, cross-platform support, and efficient compression for streaming. **Tags:** Video Capture SDK, Media Blocks SDK, Video Edit SDK, .NET, MediaBlocksPipeline, VideoCaptureCoreX, VideoEditCoreX, Windows, macOS, Linux, Android, iOS, Capture, Streaming, Encoding, Editing, WebM, OGG, Vorbis, C# **API:** OGGVorbisOutput, VorbisEncoderSettings, WebMOutput, VideoCaptureCore, VideoEditCore # Vorbis Audio Encoding for .NET Developers [Video Capture SDK .Net](https://www.visioforge.com/video-capture-sdk-net) [Video Edit SDK .Net](https://www.visioforge.com/video-edit-sdk-net) [Media Blocks SDK .Net](https://www.visioforge.com/media-blocks-sdk-net) ## Introduction to Vorbis in VisioForge SDK The VisioForge SDK suite offers powerful Vorbis audio encoding capabilities that enable developers to implement high-quality audio compression in their .NET applications. Vorbis, an open-source audio codec, delivers exceptional audio fidelity with efficient compression ratios, making it ideal for streaming applications, multimedia content, and web audio. This guide will help you navigate the various Vorbis implementation options available in the VisioForge SDK ecosystem, providing practical code examples and optimization strategies for different use cases. ## Vorbis Encoder Options The SDK exposes three distinct APIs for Vorbis encoding. Two are Windows-classic (`VideoCaptureCore` / `VideoEditCore`) and one is cross-platform (`VideoCaptureCoreX` / `VideoEditCoreX` / `MediaBlocksPipeline`). ### Implementation Options #### 1. WebM Container with Vorbis Audio (Windows classic) The [`WebMOutput`](https://api.visioforge.org/dotnet/api/VisioForge.Core.Types.X.Output.WebMOutput.html) class in namespace `VisioForge.Core.Types.X.Output` encapsulates Vorbis audio within the WebM container format. Runs on Windows only (DirectShow). #### 2. OGG Vorbis Dedicated Output (Windows classic) The [`OGGVorbisOutput`](https://api.visioforge.org/dotnet/api/VisioForge.Core.Types.X.Output.OGGVorbisOutput.html) class in namespace `VisioForge.Core.Types.X.Output` provides detailed control over VBR/bitrate modes for OGG-containerised Vorbis. Windows only. #### 3. Flexible VorbisEncoderSettings (cross-platform) The [`VorbisEncoderSettings`](https://api.visioforge.org/dotnet/api/VisioForge.Core.Types.X.AudioEncoders.VorbisEncoderSettings.html) class in namespace `VisioForge.Core.Types.X.AudioEncoders` drives Vorbis encoding on the X engines (`VideoCaptureCoreX`, `VideoEditCoreX`) and Media Blocks (`VorbisEncoderBlock`). This is the recommended path for cross-platform projects. ### Rate Control Strategies Choosing the appropriate rate control mode is crucial for balancing audio quality against file size requirements. Vorbis encoding in VisioForge supports two primary approaches: #### Quality-Based Variable Bit Rate (VBR) Quality-based VBR is the recommended approach for most applications, as it dynamically adjusts bitrate to maintain consistent perceptual quality throughout the audio stream. WebMOutputOGGVorbisOutputVorbisEncoderSettings WebMOutput implements a simplified quality-based approach with an easy-to-understand scale: ``` // Create and configure WebM output with high-quality Vorbis audio var webmOutput = new WebMOutput(); // Quality range: 20 (lowest) to 100 (highest) // Values 70-80 provide excellent quality for most content webmOutput.Audio_Quality = 80; // Higher values produce better audio quality with larger files // Lower values prioritize file size over audio fidelity ``` Key considerations: - Quality setting directly impacts perceived audio quality and file size - Values around 70-80 work well for most professional content - Lower settings (40-60) may be suitable for voice-only recordings OGGVorbisOutput offers more explicit quality mode selection: ``` // Initialize OGG Vorbis output for quality-focused encoding var oggOutput = new OGGVorbisOutput(); // Set the encoding mode to quality-based VBR oggOutput.Mode = VorbisMode.Quality; // Configure quality level (range: 20-100) // 80: High quality for music and complex audio // 60: Good quality for general purpose use // 40: Acceptable quality for voice recordings oggOutput.Quality = 80; ``` This implementation gives you direct control over the quality-to-size tradeoff, making it ideal for applications with varying content types. VorbisEncoderSettings uses the native Vorbis quality scale: ``` // Create Vorbis encoder with quality-based rate control var vorbisEncoder = new VorbisEncoderSettings(); // Set rate control mode to quality-based VBR vorbisEncoder.RateControl = VorbisEncoderRateControl.Quality; // Configure quality level using Vorbis scale (-1 to 10) // -1: Very low quality (~45 kbps) // 3: Good quality (~112 kbps) // 5: Very good quality (~160 kbps) // 8: Excellent quality (~224 kbps) // 10: Highest quality (~320 kbps) vorbisEncoder.Quality = 5; ``` The VorbisEncoderSettings implementation provides the most precise quality control, using the established Vorbis quality scale that audio engineers are familiar with. #### Bitrate-Constrained Encoding For scenarios with specific bandwidth limitations or target file sizes, bitrate-constrained encoding offers more predictable output sizes. WebMOutputOGGVorbisOutputVorbisEncoderSettings WebMOutput does not support explicit bitrate control for Vorbis audio. Developers should use the quality parameter instead and test to determine the resulting bitrates. OGGVorbisOutput provides comprehensive bitrate management tools: ``` // Set up OGG output with specific bitrate constraints var oggOutput = new OGGVorbisOutput(); // Enable bitrate-controlled encoding mode oggOutput.Mode = VorbisMode.Bitrate; // Configure bitrate parameters (all values in Kbps) oggOutput.MinBitRate = 96; // Minimum bitrate floor oggOutput.AvgBitRate = 160; // Target average bitrate oggOutput.MaxBitRate = 240; // Maximum bitrate ceiling // These settings create a controlled VBR encode that // averages 160 Kbps but can fluctuate between limits ``` This approach is ideal for streaming applications where bandwidth prediction is important. VorbisEncoderSettings offers the most detailed bitrate control options: ``` // Initialize Vorbis encoder with bitrate constraints var vorbisEncoder = new VorbisEncoderSettings(); // Set rate control mode to bitrate-based vorbisEncoder.RateControl = VorbisEncoderRateControl.Bitrate; // Configure bitrate parameters (all values in Kbps; valid range 16-240) vorbisEncoder.Bitrate = 192; // Target average bitrate vorbisEncoder.MinBitrate = 128; // Minimum allowed bitrate vorbisEncoder.MaxBitrate = 240; // Maximum allowed bitrate // These settings are ideal for applications requiring // predictable file sizes or streaming bandwidth ``` The flexible bitrate controls allow for precise audio encoding tailored to specific delivery requirements. Check the [VorbisEncoderBlock](../../../mediablocks/AudioEncoders/) and [OGGSinkBlock](../../../mediablocks/Sinks/) for more information. ### Best Practices for Developers To achieve optimal results with Vorbis encoding in your .NET applications, consider these developer-focused recommendations: #### Choosing the Right Encoding Mode 1. **Default choice: Quality-based VBR** 2. Produces consistent perceived quality across varying content 3. Automatically optimizes bitrate based on audio complexity 4. Simplifies configuration with a single quality parameter 5. **When to use Bitrate-constrained mode:** 6. Streaming applications with bandwidth limitations 7. Storage-constrained environments with fixed size allocations 8. Content delivery networks with predictable bandwidth requirements #### Recommended Settings for Common Use Cases | Content Type | Recommended Settings | | --- | --- | | Music (high quality) | WebM: Audio\_Quality = 80 OGG: Quality = 80 VorbisEncoder: Quality = 6 | | Voice recordings | WebM: Audio\_Quality = 60 OGG: Quality = 60 VorbisEncoder: Quality = 3 | | Mixed content | WebM: Audio\_Quality = 70 OGG: Quality = 70 VorbisEncoder: Quality = 4 | | Streaming audio | OGG: Mode = Bitrate, AvgBitRate = 128 VorbisEncoder: RateControl = Bitrate, Bitrate = 128 | ## Windows-only output [VideoCaptureCore](#) [VideoEditCore](#) The `OGGVorbisOutput` class provides configuration and functionality for encoding audio using the Vorbis codec. ### Class Details ``` public sealed class OGGVorbisOutput : IVideoEditBaseOutput, IVideoCaptureBaseOutput ``` The class implements two interfaces: - `IVideoEditBaseOutput`: Enables use in video editing scenarios - `IVideoCaptureBaseOutput`: Enables use in video capture scenarios ### Bitrate Controls When operating in Bitrate mode, these properties control the output bitrate constraints: #### AvgBitRate - Type: `int` - Default Value: 128 (Kbps) - Description: Specifies the target average bitrate for the encoded audio stream. This value represents the general quality level and file size trade-off. #### MaxBitRate - Type: `int` - Default Value: 192 (Kbps) - Description: Defines the maximum allowed bitrate during encoding. Useful for ensuring the encoded audio doesn't exceed bandwidth constraints. #### MinBitRate - Type: `int` - Default Value: 64 (Kbps) - Description: Sets the minimum allowed bitrate during encoding. Helps maintain a baseline quality level even during simple audio passages. ### Quality Controls #### Quality - Type: `int` - Default Value: 80 - Valid Range: 10-100 - Description: When operating in Quality mode, this value determines the encoding quality. Higher values result in better audio quality but larger file sizes. #### Mode - Type: `VorbisMode` (enum) - Default Value: `VorbisMode.Bitrate` - Options: - `VorbisMode.Quality`: Encoding focuses on maintaining a consistent quality level - `VorbisMode.Bitrate`: Encoding focuses on maintaining specified bitrate constraints ### Constructor ``` public OGGVorbisOutput() ``` Initializes a new instance with default values: - MinBitRate: 64 kbps - AvgBitRate: 128 kbps - MaxBitRate: 192 kbps - Quality: 80 - Mode: VorbisMode.Bitrate ### Serialization Methods #### Save() ``` public string Save() ``` Serializes the current configuration to a JSON string, allowing settings to be saved and restored later. #### Load(string json) ``` public static OGGVorbisOutput Load(string json) ``` Creates a new instance with settings deserialized from the provided JSON string. ### Usage Examples #### Basic Usage with Default Settings ``` var oggOutput = new OGGVorbisOutput(); // Ready to use with default settings (Bitrate mode, 128kbps average) ``` #### Quality-Based Encoding ``` var oggOutput = new OGGVorbisOutput { Mode = VorbisMode.Quality, Quality = 90 // High quality setting }; ``` #### Constrained Bitrate Encoding ``` var oggOutput = new OGGVorbisOutput { Mode = VorbisMode.Bitrate, MinBitRate = 96, // Minimum 96kbps AvgBitRate = 160, // Target 160kbps MaxBitRate = 240 // Maximum 240kbps }; ``` #### Saving and Loading Configuration ``` // Save configuration var oggOutput = new OGGVorbisOutput(); string savedConfig = oggOutput.Save(); ``` ``` // Load configuration var loadedOutput = OGGVorbisOutput.Load(savedConfig); ``` #### Apply settings to core instances ``` var core = new VideoCaptureCore(); core.Output_Filename = "output.ogg"; core.Output_Format = oggOutput; ``` ``` var core = new VideoEditCore(); core.Output_Filename = "output.ogg"; core.Output_Format = oggOutput; ``` ## Performance Considerations When implementing Vorbis encoding in production environments: - Encoding quality directly impacts CPU usage; higher quality settings require more processing power - The VorbisEncoderSettings implementation offers the best balance of flexibility and performance - Pre-configured profiles can help standardize output quality across different content types - Consider multi-threaded encoding for batch processing applications ## Conclusion Vorbis encoding provides an excellent open-source solution for high-quality audio compression in .NET applications. By understanding the different implementation options and configuration strategies available in the VisioForge SDK, developers can effectively balance audio quality, file size, and performance requirements for their specific use cases. Whether you're building a streaming application, a media processing tool, or integrating audio capabilities into a larger software ecosystem, the Vorbis encoders in VisioForge's .NET SDKs offer the flexibility and performance needed for professional audio processing. ---END OF PAGE--- ## WAV PCM Audio Encoder Settings and Code Examples for .NET **URL:** https://www.visioforge.com/help/docs/dotnet/general/audio-encoders/wav/ **Description:** Implement WAV audio processing in .NET with sample rates, channel configuration, PCM format selection, and cross-platform support. **Tags:** Video Capture SDK, Media Blocks SDK, Video Edit SDK, .NET, MediaBlocksPipeline, VideoCaptureCoreX, VideoEditCoreX, Windows, macOS, Linux, Android, iOS, Capture, Streaming, Encoding, Editing, WAV, C# **API:** WAVEncoderSettings, VideoCaptureCoreX, VideoEditCoreX, MediaBlocksPipeline, WAVOutput # Implementing WAV Audio in .NET Applications [Video Capture SDK .Net](https://www.visioforge.com/video-capture-sdk-net) [Video Edit SDK .Net](https://www.visioforge.com/video-edit-sdk-net) [Media Blocks SDK .Net](https://www.visioforge.com/media-blocks-sdk-net) ## What is WAV Format? WAV (Waveform Audio File Format) functions as an uncompressed audio container format rather than a codec. It stores raw PCM (Pulse-Code Modulation) audio data in its native form. When working with VisioForge SDKs, the WAV output functionality allows developers to create high-quality audio files with configurable PCM settings. Since WAV preserves audio without compression, it maintains original sound quality at the cost of larger file sizes compared to compressed formats like MP3 or AAC. ## How WAV Files Work The WAV format stores audio samples in their raw form. When your application outputs to WAV format, it performs three key operations: 1. Organizing raw PCM audio data into the WAV container structure 2. Defining interpretation parameters (sample rate, bit depth, and channel count) 3. Generating appropriate WAV headers and metadata This uncompressed nature means file sizes are predictable and directly calculated from the audio parameters: ``` File size (bytes) = Sample Rate × Bit Depth × Channels × Duration / 8 ``` For example, a one-minute stereo WAV file sampled at 44.1kHz with 16-bit samples consumes approximately 10.1 MB: ``` 44100 × 16 × 2 × 60 / 8 = 10,584,000 bytes ``` ## Cross-Platform WAV Implementation [VideoCaptureCoreX](#) [VideoEditCoreX](#) [MediaBlocksPipeline](#) ### Key Features - Flexible audio format configuration (default: S16LE) - Adjustable sample rates ranging from 8kHz to 192kHz - Support for both mono and stereo channel configurations - Consistent audio quality across different platforms ### Configuration Parameters #### Audio Format Options The WAV encoder supports multiple audio formats through the `AudioFormatX` enum, with S16LE (16-bit Little-Endian) serving as the default format for maximum compatibility. #### Sample Rate Selection - Available range: 8,000 Hz to 192,000 Hz - Default setting: 48,000 Hz - Increment values: 8,000 Hz steps #### Channel Configuration - Available options: 1 (mono) or 2 (stereo) - Default setting: 2 (stereo) ### Implementation Examples #### Basic Implementation ``` // Initialize WAV encoder with default settings var wavEncoder = new WAVEncoderSettings(); ``` ``` // Initialize with custom configuration var customWavEncoder = new WAVEncoderSettings( format: AudioFormatX.S16LE, sampleRate: 44100, channels: 2 ); ``` #### Integration with Video Capture SDK ``` // Initialize Video Capture SDK core var core = new VideoCaptureCoreX(); // Create WAV output with file path var wavOutput = new WAVOutput("output.wav"); // Add output to the capture pipeline core.Outputs_Add(wavOutput, true); ``` #### Integration with Video Edit SDK ``` // Initialize Video Edit SDK core var core = new VideoEditCoreX(); // Create WAV output instance var wavOutput = new WAVOutput("output.wav"); // Configure core to use WAV output core.Output_Format = wavOutput; ``` #### Media Blocks Pipeline Configuration ``` // Initialize WAV encoder settings var wavSettings = new WAVEncoderSettings(); // Create encoder block var wavOutput = new WAVEncoderBlock(wavSettings); // Add File Sink block for output var fileSink = new FileSinkBlock("output.wav"); // Connect encoder to file sink in pipeline pipeline.Connect(wavOutput.Output, fileSink.Input); // pipeline is MediaBlocksPipeline ``` #### Verifying Encoder Availability ``` if (WAVEncoderSettings.IsAvailable()) { // Encoder is available, proceed with encoding var encoder = new WAVEncoderSettings(); // Configure and use encoder } else { // Handle unavailability Console.WriteLine("WAV encoder is not available on this system"); } ``` #### Advanced Configuration ``` var wavEncoder = new WAVEncoderSettings { Format = AudioFormatX.S16LE, SampleRate = 96000, Channels = 1 // Configure for mono audio }; ``` #### Creating an Encoder Block ``` var settings = new WAVEncoderSettings(); MediaBlock encoderBlock = settings.CreateBlock(); // Integrate the encoder block into your media pipeline ``` #### Retrieving Supported Parameters ``` // Get list of supported audio formats IEnumerable formats = WAVEncoderSettings.GetFormatList(); // Get available sample rates var settings = new WAVEncoderSettings(); int[] sampleRates = settings.GetSupportedSampleRates(); // Returns array ranging from 8000 to 192000 in 8000 Hz increments // Get supported channel configurations int[] channels = settings.GetSupportedChannelCounts(); // Returns [1, 2] for mono and stereo options ``` ## Windows-Specific WAV Implementation [VideoCaptureCore](#) [VideoEditCore](#) ### Enumerating Available Audio Codecs ``` // core is an instance of VideoCaptureCore or VideoEditCore foreach (var codec in core.Audio_Codecs) { cbAudioCodecs.Items.Add(codec); } ``` ### Configuring Audio Settings ``` // Initialize ACM output for WAV var acmOutput = new ACMOutput(); // Configure audio parameters acmOutput.Channels = 2; acmOutput.BPS = 16; acmOutput.SampleRate = 44100; acmOutput.Name = "PCM"; // codec name // Set as output format core.Output_Format = acmOutput; ``` ### Specifying Output File ``` // Set output file path core.Output_Filename = "output.wav"; ``` ### Starting Processing ``` // Begin capture or conversion operation await core.StartAsync(); ``` ## Best Practices for WAV Implementation ### Sample Rate Selection Guidelines The sample rate significantly impacts audio quality and file size: - 8kHz: Suitable for basic voice recordings and telephony applications - 16kHz: Improved voice quality for speech recognition systems - 44.1kHz: Standard for CD-quality audio and music production - 48kHz: Professional audio standard used in video production - 96kHz+: High-resolution audio for professional sound engineering For most applications, 44.1kHz or 48kHz provides excellent quality without excessive file sizes. ### Channel Configuration Strategy Your channel selection should align with content requirements: - **Mono (1 channel)**: Ideal for voice recordings, podcasts, or when storage space is limited - **Stereo (2 channels)**: Essential for music, spatial audio, or any content where directional sound matters ### Format Selection Considerations When selecting audio formats: - S16LE (16-bit Little-Endian) offers the best compatibility across platforms - Higher bit depths (24-bit, 32-bit) provide greater dynamic range for professional audio work - Consider your target system's requirements and hardware capabilities ## Technical Limitations and Considerations ### File Size Implications WAV files grow linearly with recording duration, which can present challenges: - A 10-minute stereo recording at 44.1kHz/16-bit requires approximately 100MB - For mobile or web applications, consider implementing size limits or compression options - When streaming is required, compressed formats may be more appropriate ### Performance Factors WAV processing has specific performance characteristics: - Lower CPU usage during encoding compared to compressed formats - Higher disk I/O requirements due to larger data volumes - Memory buffer considerations for long recordings ## Conclusion The WAV format provides developers with a reliable, high-quality audio output option within VisioForge .NET SDKs. Its uncompressed nature ensures pristine audio quality, making it ideal for applications where audio fidelity is paramount. By leveraging the configuration options and implementation approaches outlined above, developers can effectively integrate WAV audio functionality into their .NET applications while maintaining optimal performance and quality. For most professional audio applications, WAV remains the format of choice during production and editing stages, even if compressed formats are used for final distribution. The flexibility and cross-platform compatibility of the VisioForge SDK's WAV implementation make it a valuable tool in any developer's audio processing toolkit. ---END OF PAGE--- ## WavPack Audio Encoder Settings and Configuration in .NET **URL:** https://www.visioforge.com/help/docs/dotnet/general/audio-encoders/wavpack/ **Description:** Implement WavPack lossless and hybrid lossy audio compression in .NET with quality settings, correction modes, and stereo encoding. **Tags:** Video Capture SDK, Media Blocks SDK, Video Edit SDK, .NET, MediaBlocksPipeline, VideoCaptureCoreX, VideoEditCoreX, Windows, macOS, Linux, Android, iOS, Capture, Streaming, Encoding, Editing, WavPack, C# **API:** WavPackEncoderSettings, VideoCaptureCoreX, VideoEditCoreX, MediaBlocksPipeline, WavPackOutput # WavPack Audio Encoder for .NET Applications [Video Capture SDK .Net](https://www.visioforge.com/video-capture-sdk-net) [Video Edit SDK .Net](https://www.visioforge.com/video-edit-sdk-net) [Media Blocks SDK .Net](https://www.visioforge.com/media-blocks-sdk-net) [VideoCaptureCoreX](#) [VideoEditCoreX](#) [MediaBlocksPipeline](#) ## Introduction to WavPack WavPack is a powerful audio codec that offers both lossless and hybrid lossy compression capabilities, making it highly versatile for different application requirements. The VisioForge.Core library provides a robust implementation of this codec for .NET developers seeking high-quality audio compression solutions. With support for various quality levels, correction modes, and stereo encoding options, the WavPack encoder can handle multiple channel configurations while delivering excellent compression across a wide range of bitrates and sample rates. ## Getting Started with WavPack ### Basic Configuration To begin using the WavPack encoder, you'll need to create an instance of the `WavPackEncoderSettings` class with your desired parameters: ``` var encoder = new WavPackEncoderSettings { Mode = WavPackEncoderMode.Normal, JointStereoMode = WavPackEncoderJSMode.Auto, CorrectionMode = WavPackEncoderCorrectionMode.Off, MD5 = false }; ``` This simple configuration uses balanced compression settings and automatic stereo encoding mode selection, suitable for most general use cases. ### Compression Modes Explained WavPack offers four distinct compression modes that balance processing speed against compression efficiency: ``` public enum WavPackEncoderMode { Fast = 1, // Prioritizes encoding speed Normal = 2, // Balanced compression (default) High = 3, // Higher compression ratio VeryHigh = 4 // Maximum compression } ``` For applications where file size is critical, you can implement higher compression settings: ``` var encoder = new WavPackEncoderSettings { Mode = WavPackEncoderMode.High, ExtraProcessing = 1 // Enables advanced filters for better compression }; ``` ## Quality Control Options ### Bitrate-Based Encoding The most straightforward method for controlling output quality is to specify a target bitrate: ``` var encoder = new WavPackEncoderSettings { Bitrate = 192000 // 192 kbps }; ``` Key specifications for bitrate control: - Valid range: 24,000 to 9,600,000 bits/second - Setting values below 24,000 disables lossy encoding - Enables the lossy encoding mode automatically ### Bits Per Sample Control For more precise quality control, especially when maintaining consistent quality across different sample rates is important: ``` var encoder = new WavPackEncoderSettings { BitsPerSample = 16.0 // Equivalent to 16-bit quality }; ``` Important notes: - Values below 2.0 disable lossy encoding - This approach maintains more consistent quality regardless of sample rate variations ## Advanced Encoding Features ### Stereo Encoding Options WavPack provides three methods for encoding stereo content, each with different characteristics: ``` var encoder = new WavPackEncoderSettings { JointStereoMode = WavPackEncoderJSMode.Auto }; ``` Available stereo encoding modes: - `Auto`: Intelligently selects the optimal encoding method based on content - `LeftRight`: Uses traditional left/right channel separation - `MidSide`: Implements mid/side encoding which often yields better compression for stereo material ### Hybrid Correction Mode One of WavPack's unique features is its hybrid mode, which generates a correction file alongside the main compressed file: ``` var encoder = new WavPackEncoderSettings { CorrectionMode = WavPackEncoderCorrectionMode.Optimized, Bitrate = 192000 // Required when using correction modes }; ``` The available correction options: - `Off`: Standard operation with no correction file - `On`: Generates a standard correction file - `Optimized`: Creates an optimization-focused correction file Note that correction modes only function when lossy encoding is active, making them ideal for applications where initial file size is important but future lossless restoration might be needed. ## Technical Specifications The WavPack encoder supports: - Sample rates from 6,000 Hz to 192,000 Hz - 1 to 8 audio channels - Optional MD5 hash storage of raw samples for verification - Additional processing options for quality enhancement Before implementation, you can verify encoder availability in your environment: ``` if (WavPackEncoderSettings.IsAvailable()) { // Configure and use the encoder var encoder = new WavPackEncoderSettings { Mode = WavPackEncoderMode.Normal, Bitrate = 192000, MD5 = true }; } ``` ## Implementation Examples ### Video Capture SDK Integration ``` // Initialize the Video Capture SDK core var core = new VideoCaptureCoreX(); // Create a WavPack output instance var wavPackOutput = new WavPackOutput("output.wv"); // Add the WavPack output to the capture pipeline core.Outputs_Add(wavPackOutput, true); ``` ### Video Edit SDK Integration ``` // Initialize the Video Edit SDK core var core = new VideoEditCoreX(); // Create a WavPack output instance var wavPackOutput = new WavPackOutput("output.wv"); // Set the output format core.Output_Format = wavPackOutput; ``` ### Media Blocks SDK Integration ``` // Configure WavPack encoder settings var wavPackSettings = new WavPackEncoderSettings(); // Create the encoder block var wavPackOutput = new WavPackEncoderBlock(wavPackSettings); // Create a file output destination var fileSink = new FileSinkBlock("output.wv"); // Connect the encoder to the file sink in the pipeline pipeline.Connect(wavPackOutput.Output, fileSink.Input); // pipeline is MediaBlocksPipeline ``` ## Optimization Strategies ### Performance vs. Quality For optimal encoder performance and quality balance: DefaultArchivalStreaming - Use `Normal` mode for everyday encoding tasks - Enable `ExtraProcessing` only when encoding time isn't critical - Maintain `JointStereoMode` as `Auto` for most content types - Implement `High` or `VeryHigh` mode for archival purposes - Enable MD5 hash generation for content verification - Consider lossless encoding for critical audio preservation - Use `Fast` mode for real-time encoding scenarios - Select an appropriate bitrate based on bandwidth constraints - Disable additional processing features to minimize latency ## Best Practices When implementing WavPack in your applications: 1. **Balance quality and performance** by selecting the appropriate compression mode based on your use case 2. **Leverage hybrid mode** when distributing lossy files that may need lossless restoration later 3. **Consider format compatibility** with your target platforms and playback environments 4. **Test thoroughly** across different audio content types to ensure optimal settings ## Conclusion The WavPack encoder provides a versatile solution for audio compression in .NET applications. Whether you need archival-grade lossless compression or efficient lossy compression with future upgrade potential, the implementation in VisioForge's SDKs offers the flexibility and performance required by professional audio applications. By understanding the various configuration options and implementation strategies outlined in this guide, you can effectively integrate WavPack encoding into your software development projects and deliver high-quality audio processing capabilities to your users. ---END OF PAGE--- ## Windows Media Audio (WMA) Encoder Integration Guide **URL:** https://www.visioforge.com/help/docs/dotnet/general/audio-encoders/wma/ **Description:** Implement WMA audio encoding in .NET with cross-platform and Windows-specific approaches, bitrate controls, and codec configuration. **Tags:** Video Capture SDK, Media Blocks SDK, Video Edit SDK, .NET, MediaBlocksPipeline, VideoCaptureCoreX, VideoEditCoreX, Windows, macOS, Linux, Android, iOS, Capture, Streaming, Encoding, Editing, MP3, WMA, C# **API:** WMAOutput, WMAEncoderSettings, VideoCaptureCore, VideoEditCore, VideoCaptureCoreX # Windows Media Audio encoder [Video Capture SDK .Net](https://www.visioforge.com/video-capture-sdk-net) [Video Edit SDK .Net](https://www.visioforge.com/video-edit-sdk-net) [Media Blocks SDK .Net](https://www.visioforge.com/media-blocks-sdk-net) Windows Media Audio (WMA) is a popular audio codec developed by Microsoft for efficient audio compression. This documentation covers the WMA encoder implementations available in the VisioForge .Net SDKs. ## Overview The VisioForge SDK provides two distinct approaches for WMA encoding: the platform-specific [WMAOutput](https://api.visioforge.org/dotnet/api/VisioForge.Core.Types.X.Output.WMAOutput.html) for Windows environments and the cross-platform [WMAEncoderSettings](https://api.visioforge.org/dotnet/api/VisioForge.Core.Types.X.AudioEncoders.WMAEncoderSettings.html). Let's explore both implementations in detail to understand their capabilities and use cases. ## Cross-platform WMA output [VideoCaptureCoreX](#) [VideoEditCoreX](#) [MediaBlocksPipeline](#) The `WMAEncoderSettings` provides a cross-platform solution for WMA encoding. This implementation is built on SDK and offers consistent behavior across different operating systems. ### Key Features The encoder supports the following audio configurations: - Sample rates: 44.1 kHz and 48 kHz - Bitrates: 128, 192, 256, and 320 Kbps - Channel configurations: Mono (1) and Stereo (2) ### Rate Control The WMA encoder implements constant bitrate (CBR) encoding, allowing you to specify a fixed bitrate from the supported values. This ensures consistent audio quality and predictable file sizes throughout the encoded content. ### Usage Example Add the WMA output to the Video Capture SDK core instance: ``` // Create a Video Capture SDK core instance var core = new VideoCaptureCoreX(); // Create a WMA output var wmaOutput = new WMAOutput("output.wma"); wmaOutput.Audio.SampleRate = 48000; wmaOutput.Audio.Channels = 2; wmaOutput.Audio.Bitrate = 320; // Add the WMA output core.Outputs_Add(wmaOutput, true); ``` Set the output format for the Video Edit SDK core instance: ``` // Create a Video Edit SDK core instance var core = new VideoEditCoreX(); // Create a WMA output var wmaOutput = new WMAOutput("output.wma"); wmaOutput.Audio.SampleRate = 48000; wmaOutput.Audio.Channels = 2; wmaOutput.Audio.Bitrate = 320; // Add the WMA output core.Output_Format = wmaOutput; ``` Create a Media Blocks WMA output instance: ``` // Create a WMA encoder settings instance var wmaSettings = new WMAEncoderSettings(); // Create a WMA output instance var wmaOutput = new WMAEncoderBlock(wmaSettings); // Create a ASF output instance var asfOutput = new ASFSinkBlock(new ASFSinkSettings("output.wma")); // Connect the WMA encoder to the ASF output pipeline.Connect(wmaOutput.Output, asfOutput.Input); // pipeline is MediaBlocksPipeline ``` Check if WMA encoding is available before you build the pipeline: ``` if (!WMAEncoderSettings.IsAvailable()) { // Handle error — the WMA encoder plugin is missing on this platform. } ``` ## Windows-only WMA output [VideoCaptureCore](#) [VideoEditCore](#) The `WMAOutput` class provides a comprehensive Windows-specific implementation with advanced features and configuration options. This implementation leverages the Windows Media Format SDK for optimal performance on Windows systems. ### Key Features The Windows-specific implementation offers: - Multiple profile support (internal, external, and custom) - Language and localization settings - Quality-based encoding - Advanced bitrate control with peak bitrate settings - Buffer size configuration ### Configuration Modes The classic Windows implementation selects its encoder source via the `WMVMode` enum on `WMAOutput.Mode`: - `WMVMode.InternalProfile` — pick a predefined Windows Media profile by name (simplest). - `WMVMode.ExternalProfile` — load a `.prx` profile file from disk. - `WMVMode.ExternalProfileFromText` — pass profile XML inline as a string. - `WMVMode.CustomSettings` — drive all encoder parameters manually (quality, peak bitrate, buffer, etc.) through the `Custom_Audio_*` properties. - `WMVMode.V8SystemProfile` — use a Windows Media Video 8 system profile for compatibility with older Windows Media systems (lower compression efficiency than WMV9; only when targeting legacy systems). Rate control (CBR / VBR / quality-based VBR) is expressed through those `Custom_Audio_*` properties or baked into the chosen profile — it is not a separate enum. ### Usage Example Here's how to set up the Windows-specific WMA encoder: Use an internal profile for simple configuration ``` var wmaOutput = new WMAOutput { // Use an internal profile for simple configuration Mode = WMVMode.InternalProfile, Internal_Profile_Name = "Windows Media Audio 9 High (192K)" }; core.Output_Format = wmaOutput; // Core is VideoCaptureCore or VideoEditCore ``` Or configure custom settings ``` var wmaOutput = new WMAOutput { Mode = WMVMode.CustomSettings, Custom_Audio_StreamPresent = true, Custom_Audio_Quality = 98, // High quality setting Custom_Audio_PeakBitrate = 320, // Maximum bitrate in Kbps Custom_Audio_PeakBufferSize = 3 // Buffer size for streaming }; core.Output_Format = wmaOutput; // Core is VideoCaptureCore or VideoEditCore ``` ### Profile Management The Windows implementation supports three profile modes: 1. Internal Profiles: 2. Pre-configured profiles for common use cases 3. Access through `Internal_Profile_Name` 4. External Profiles: 5. Load profiles from external files 6. Configure using `External_Profile_FileName` or `External_Profile_Text` 7. Custom Profiles: 8. Fine-grained control over encoding parameters 9. Configure through Custom\_\* properties ## Best Practices When implementing WMA encoding in your application: 1. For Windows applications requiring advanced features: 2. Use WMAOutput for access to Windows-specific optimizations 3. Consider saving configurations to JSON for reuse 4. Implement proper error handling for profile loading 5. For cross-platform applications: 6. Stick to WMAEncoderSettings for consistent behavior 7. Verify supported rates before setting configuration 8. Use the highest supported sample rate and bitrate for best quality This documentation provides a foundation for implementing WMA encoding in your applications. The choice between cross-platform and Windows-specific implementations should be based on your application's requirements for platform support, encoding features, and quality control. ---END OF PAGE--- ## Using Third-Party DirectShow Video Filters in .NET **URL:** https://www.visioforge.com/help/docs/dotnet/general/code-samples/3rd-party-video-effects/ **Description:** Implement third-party DirectShow video filters in .NET with code examples, best practices, and troubleshooting for Video SDK platforms. **Tags:** Video Capture SDK, Media Player SDK, Video Edit SDK, .NET, DirectShow, Windows, C# # Use Third-Party Video Filters in .NET [Video Capture SDK .Net](https://www.visioforge.com/video-capture-sdk-net) [Video Edit SDK .Net](https://www.visioforge.com/video-edit-sdk-net) [Media Player SDK .Net](https://www.visioforge.com/media-player-sdk-net) ## Introduction Third-party video processing filters provide powerful capabilities for manipulating video streams in .NET applications. These filters can be seamlessly integrated into various SDK platforms including Video Capture SDK .Net, Media Player SDK .Net, and Video Edit SDK .Net to enhance your applications with advanced video processing features. This guide explores how to implement, configure, and optimize third-party DirectShow filters within your .NET projects, providing you with the knowledge needed to create sophisticated video processing applications. ## Understanding DirectShow Filters DirectShow filters are COM-based components that process media data within the DirectShow framework. They can perform various operations including: - Video effects and transitions - Color correction and grading - Frame rate conversion - Resolution changes - Noise reduction - Special effects processing Before using third-party filters, it's important to understand how they operate within the DirectShow pipeline and how they interact with our SDK components. ## Prerequisites To successfully implement third-party video processing filters in your .NET applications, you'll need: 1. The appropriate SDK (.NET Video Capture, Media Player, or Video Edit) 2. Third-party DirectShow filters of your choice 3. Administrative access for filter registration 4. Basic understanding of DirectShow architecture ## Filter Registration Process DirectShow filters must be properly registered on the system before they can be used in your applications. This is typically done using the Windows registration utility: ``` regsvr32.exe path\to\your\filter.dll ``` Alternative COM registration methods can also be used, particularly in scenarios where: - You need to register filters during application installation - You're working in environments with limited user permissions - You require silent registration as part of a deployment process ### Registration Troubleshooting If filter registration fails, verify: 1. You have administrator privileges 2. The filter DLL is compatible with your system architecture (x86/x64) 3. All dependencies of the filter are available on the system 4. The filter is properly implemented as a COM object ## Implementation Guide ### Enumerating Available DirectShow Filters Before adding filters to your processing chain, you may want to discover what filters are available on the system: ``` // DirectShow_Filters() returns ObservableCollection — each entry is the filter name foreach (var filterName in VideoCapture1.DirectShow_Filters()) { Console.WriteLine($"Filter Name: {filterName}"); Console.WriteLine("----------------------------"); } ``` This code snippet allows you to inspect all registered DirectShow filters, helping you identify the correct filters to use in your application. ### Managing the Filter Chain Before adding new filters, you may want to clear any existing filters from the processing chain: ``` // Remove all currently applied filters VideoCapture1.Video_Filters_Clear(); ``` This ensures you're starting with a clean processing pipeline and prevents unexpected interactions between filters. ### Adding Filters to Your Application To add a third-party filter to your video processing pipeline: ``` // Ctor: CustomProcessingFilter(string name, Guid? clsid = null, bool beforeEffects = false) // Use the filter name as registered in DirectShow; the SDK resolves the CLSID automatically. var myFilter = new CustomProcessingFilter("My Effect Filter"); // Add the filter to the processing chain VideoCapture1.Video_Filters_Add(myFilter); ``` `CustomProcessingFilter` only exposes `Name`, `CLSID`, and `BeforeEffects` — filter-specific parameters are configured on the underlying COM filter (see the Filter Parameters section below). You can add multiple filters in sequence to create complex processing chains. The order of filters matters, as each filter processes the output of the previous one. ## Advanced Filter Configuration ### Filter Parameters Most third-party filters expose configurable parameters via their own COM interfaces (e.g. `IPropertyBag`, `ISpecifyPropertyPages`, or a vendor-specific `ISomethingFilter`). These interfaces are reached through the underlying `IBaseFilter` instance once the graph is built — not through `CustomProcessingFilter`, which only carries the registration identity (`Name` / `CLSID`). Consult the filter vendor's documentation for the concrete interface and property names. ### Filter Ordering The sequence of filters in your processing chain significantly impacts the final result: ``` // Example of a multi-filter processing chain VideoCapture1.Video_Filters_Add(new CustomProcessingFilter("Noise Reduction")); VideoCapture1.Video_Filters_Add(new CustomProcessingFilter("Color Enhancement")); VideoCapture1.Video_Filters_Add(new CustomProcessingFilter("Sharpening")); ``` Experiment with different filter arrangements to achieve the desired effect. For example, applying noise reduction before sharpening usually produces better results than the reverse order. ## Performance Considerations Third-party filters can impact application performance. Consider these optimization strategies: 1. Only enable filters when necessary 2. Use lower complexity filters for real-time processing 3. Consider the resolution and frame rate when applying multiple filters 4. Test performance with your target hardware configurations 5. Use profile-guided optimization when available ## Common Issues and Solutions ### Thread Safety When working with filters in multi-threaded applications, ensure proper synchronization: ``` private readonly object _filterLock = new object(); public void RebuildFilterChain(IEnumerable filters) { lock (_filterLock) { // VideoCaptureCore only exposes Add/Clear — rebuild the chain instead of removing a single filter. VideoCapture1.Video_Filters_Clear(); foreach (var filter in filters) { VideoCapture1.Video_Filters_Add(filter); } } } ``` ## Required Components To successfully deploy applications that use third-party video processing filters, ensure you include: - SDK redistributables for your chosen platform - Any dependencies required by the third-party filters - Proper installation and registration scripts for the filters ## Conclusion Third-party video processing filters offer powerful capabilities for enhancing your .NET video applications. By following the guidelines in this document, you can successfully integrate these filters into your projects, creating sophisticated video processing solutions. Remember to test thoroughly with your target environment configurations to ensure optimal performance and compatibility. --- For more code samples and implementation details, visit our [GitHub repository](https://github.com/visioforge/.Net-SDK-s-samples). ---END OF PAGE--- ## ASF and WMV File Indexing for .NET SDK Applications **URL:** https://www.visioforge.com/help/docs/dotnet/general/code-samples/asf-wmv-files-indexing/ **Description:** Learn why ASF, WMV, and WMA files need indexing for reliable seeking, and how to add indexes before opening them in VisioForge .NET apps. **Tags:** Video Capture SDK, Media Player SDK, Video Edit SDK, .NET, DirectShow, Windows, WinForms, Streaming, WMV, WMA, C# # ASF and WMV File Indexing in .NET [Video Capture SDK .Net](https://www.visioforge.com/video-capture-sdk-net) [Video Edit SDK .Net](https://www.visioforge.com/video-edit-sdk-net) [Media Player SDK .Net](https://www.visioforge.com/media-player-sdk-net) When working with Windows Media files in your .NET applications, you may encounter seeking problems with ASF, WMV, or WMA files that were produced without a proper index. This page explains the underlying issue and points to the right tool for building the index before VisioForge consumes the file. ## Understanding the indexing problem ASF (Advanced Systems Format) is Microsoft's container format designed for streaming media; WMV (Windows Media Video) and WMA (Windows Media Audio) are built on it. Files lacking an index exhibit: - Choppy or unpredictable seeking behaviour - Inability to jump to specific timestamps - Inconsistent playback when navigating through the file - High overhead during random access An ASF index is a lookup table that maps timestamps (or frame numbers) to byte offsets in the file. When present, players can jump directly to any point in the stream; when absent, they must fall back to sequential parsing. ## Building an ASF index VisioForge consumes ASF/WMV/WMA files once they are indexed, but it does not ship a public indexer on the managed surface. Build the index with one of the following external tools before handing the file to the SDK: - **Windows Media Format SDK** (`IWMWriterFileSink` / `IWMIndexer` COM interfaces, available via `Microsoft.Windows.WindowsMedia.Format`). This is the canonical Microsoft path for offline indexing; the `IWMIndexer::StartIndexing` method writes a `WM/Index` object into the file. - **Windows Media File Editor** (`WMFileEditor.exe`, part of the Windows Media Encoder 9 tools) for ad-hoc indexing during development. - **`ffmpeg -i input.wmv -c copy -map 0 -f asf output.wmv`** — muxing through ffmpeg will rewrite the ASF container with a fresh index in most cases, without re-encoding. Once the file carries a valid index, all VisioForge engines (`MediaPlayerCore`, `MediaPlayerCoreX`, `VideoEditCore`, `VideoEditCoreX`) will seek accurately and report consistent durations through the usual `Duration`/`Position_Get*` APIs. ## Best practices for ASF/WMV workflows 1. **Detect missing indexes up front.** If `Duration` is reported as zero or seeking returns the wrong frame, suspect a missing or corrupt ASF index. 2. **Index once per file.** Indexing rewrites the file on disk; do it as part of ingest, not at playback time. 3. **Cache indexed copies.** When a user loads an unindexed file, persist the indexed version to disk and point future sessions at it instead of re-indexing. 4. **Run indexing off the UI thread.** Large files can take several seconds to index; pipe the operation through `Task.Run` to keep your UI responsive. 5. **Prefer MP4 for new recordings.** If you control the capture pipeline, VisioForge's `MP4Output` produces seekable files without a separate indexing step. ## System requirements Indexing is a Windows-only workflow because the ASF container itself is Windows Media technology: - Windows Media Format SDK runtime (bundled with Windows 7 and later) - Write access to the target file - Enough free disk to rewrite the container (indexing appends metadata and, in some cases, re-serialises the stream) ## See also - [WMV encoding reference](../../output-formats/wmv/) — configure VisioForge's WMV output to produce indexed files on capture. - [Windows Media Format SDK — IWMIndexer](https://learn.microsoft.com/en-us/previous-versions/windows/desktop/api/wmsdkidl/nn-wmsdkidl-iwmindexer) - [MP4 output](../../output-formats/mp4/) — a seek-friendly alternative for new projects. --- For more code samples and advanced media processing techniques, check out our [GitHub repository](https://github.com/visioforge/.Net-SDK-s-samples). ---END OF PAGE--- ## Custom DirectShow Filter Interfaces Guide for .NET **URL:** https://www.visioforge.com/help/docs/dotnet/general/code-samples/custom-filter-interface/ **Description:** Implement custom DirectShow filter interfaces in .NET with IBaseFilter access and manipulation for multimedia applications. **Tags:** Video Capture SDK, Media Player SDK, Video Edit SDK, .NET, DirectShow, VideoCaptureCore, Windows, Capture, C#, NuGet **API:** IBaseFilter, FilterEventArgs, VideoCaptureCore # Use Custom DirectShow Filter Interfaces [Video Capture SDK .Net](https://www.visioforge.com/video-capture-sdk-net) [Video Edit SDK .Net](https://www.visioforge.com/video-edit-sdk-net) [Media Player SDK .Net](https://www.visioforge.com/media-player-sdk-net) *Note: The API shown in this guide is the same across all our SDK products, including Video Capture SDK .Net, Video Edit SDK .Net, and Media Player SDK .Net.* DirectShow is a powerful multimedia framework that allows developers to perform complex operations on media streams. One of its key strengths is the ability to work with custom filter interfaces, giving you precise control over media processing. This guide will walk you through implementing and utilizing custom DirectShow filter interfaces in your .NET applications. ## Understanding DirectShow Filters DirectShow uses a filter-based architecture where each filter performs a specific operation on the media stream. These filters are connected in a graph, creating a pipeline for media processing. ### Key DirectShow Components - **Filter**: A component that processes media data - **Pin**: Connection points between filters - **Filter Graph**: The complete pipeline of connected filters - **IBaseFilter**: The fundamental interface that all DirectShow filters implement ## Getting Started with Custom Filter Interfaces To work with DirectShow filters in .NET, you'll need to: 1. Add the proper references to your project 2. Access the filter through appropriate events 3. Cast the filter to the interface you need 4. Implement your custom logic ### Required Project References To access DirectShow functionality, include the appropriate package in your project: ``` ``` You can also add the `VisioForge.Core` assembly reference directly to your project. ## Implementing Custom Filter Interface Access Our SDK provides several events that give you access to filters as they're added to the filter graph. Here's how to use them effectively: ### Accessing Filters in Video Capture SDK The Video Capture SDK offers the `OnFilterAdded` event that fires whenever a filter is added to the graph. This event provides access to each filter through its event arguments. ``` // Subscribe to the OnFilterAdded event videoCaptureCore.OnFilterAdded += VideoCaptureCore_OnFilterAdded; // Event handler implementation private void VideoCaptureCore_OnFilterAdded(object sender, FilterEventArgs eventArgs) { // Access the DirectShow filter interface IBaseFilter baseFilter = eventArgs.Filter as IBaseFilter; // Now you can work with the filter through the IBaseFilter interface if (baseFilter != null) { // Custom filter manipulation code goes here } } ``` ## Working with IBaseFilter Interface The `IBaseFilter` interface is the foundation of DirectShow filters. Here's what you can do with it: ### Retrieving Filter Information ``` private void GetFilterInfo(IBaseFilter filter) { FilterInfo filterInfo = new FilterInfo(); int hr = filter.QueryFilterInfo(out filterInfo); if (hr >= 0) { Console.WriteLine($"Filter Name: {filterInfo.achName}"); // Don't forget to release the reference to the filter graph if (filterInfo.pGraph != null) { Marshal.ReleaseComObject(filterInfo.pGraph); } } } ``` ### Enumerating Filter Pins ``` private void EnumerateFilterPins(IBaseFilter filter) { IEnumPins enumPins; int hr = filter.EnumPins(out enumPins); if (hr >= 0 && enumPins != null) { IPin[] pins = new IPin[1]; int fetched; while (enumPins.Next(1, pins, out fetched) == 0 && fetched > 0) { PinInfo pinInfo = new PinInfo(); pins[0].QueryPinInfo(out pinInfo); Console.WriteLine($"Pin Name: {pinInfo.name}, Direction: {pinInfo.dir}"); // Release pin and info if (pinInfo.filter != null) Marshal.ReleaseComObject(pinInfo.filter); Marshal.ReleaseComObject(pins[0]); } Marshal.ReleaseComObject(enumPins); } } ``` ## Identifying the Right Filter When working with the `OnFilterAdded` event, remember that it can be called multiple times as various filters are added to the graph. To work with a specific filter, you'll need to identify it correctly: ``` private void VideoCaptureCore_OnFilterAdded(object sender, FilterEventArgs eventArgs) { IBaseFilter baseFilter = eventArgs.Filter as IBaseFilter; if (baseFilter != null) { FilterInfo filterInfo = new FilterInfo(); baseFilter.QueryFilterInfo(out filterInfo); // Check if this is the filter we're looking for if (filterInfo.achName == "Video Capture Device") { // This is our target filter, perform specific operations ConfigureVideoCaptureFilter(baseFilter); } // Release the filter graph reference if (filterInfo.pGraph != null) { Marshal.ReleaseComObject(filterInfo.pGraph); } } } ``` ## Advanced Filter Configuration Once you have access to the filter interface, you can perform advanced configurations: ### Setting Filter Properties ``` private void SetFilterProperty(IBaseFilter filter, Guid propertySet, int propertyId, object propertyValue) { IKsPropertySet propertySetInterface = filter as IKsPropertySet; if (propertySetInterface != null) { // Convert property value to byte array byte[] propertyData = ConvertToByteArray(propertyValue); // Set the property int hr = propertySetInterface.Set( propertySet, propertyId, IntPtr.Zero, 0, propertyData, propertyData.Length ); Marshal.ReleaseComObject(propertySetInterface); } } ``` ### Retrieving Filter Properties ``` private object GetFilterProperty(IBaseFilter filter, Guid propertySet, int propertyId, Type propertyType) { IKsPropertySet propertySetInterface = filter as IKsPropertySet; object result = null; if (propertySetInterface != null) { int dataSize = Marshal.SizeOf(propertyType); byte[] propertyData = new byte[dataSize]; int returnedDataSize; // Get the property int hr = propertySetInterface.Get( propertySet, propertyId, IntPtr.Zero, 0, propertyData, propertyData.Length, out returnedDataSize ); if (hr >= 0) { result = ConvertFromByteArray(propertyData, propertyType); } Marshal.ReleaseComObject(propertySetInterface); } return result; } ``` ## Common Use Cases for Custom Filter Interfaces ### Video Processing Filters When working with video, you might need to access specific properties of camera devices: ``` private void ConfigureVideoCaptureFilter(IBaseFilter captureFilter) { // Access and set camera properties IAMCameraControl cameraControl = captureFilter as IAMCameraControl; if (cameraControl != null) { // Set exposure cameraControl.Set(CameraControlProperty.Exposure, 0, CameraControlFlags.Manual); // Set focus cameraControl.Set(CameraControlProperty.Focus, 0, CameraControlFlags.Manual); Marshal.ReleaseComObject(cameraControl); } } ``` ### Audio Processing Filters For audio processing, you might want to adjust volume or audio quality settings: ``` private void ConfigureAudioFilter(IBaseFilter audioFilter) { // Access volume interface IBasicAudio basicAudio = audioFilter as IBasicAudio; if (basicAudio != null) { // Set volume (0 to -10000, where 0 is max and -10000 is min) basicAudio.put_Volume(-2000); // 80% volume Marshal.ReleaseComObject(basicAudio); } } ``` ## Handling Resources Properly When working with DirectShow interfaces, it's crucial to properly release COM objects to prevent memory leaks: ``` private void ReleaseComObject(object comObject) { if (comObject != null) { Marshal.ReleaseComObject(comObject); } } ``` ## Complete Example Here's a more complete example that demonstrates finding and configuring a video capture filter: ``` using System; using System.Runtime.InteropServices; using VisioForge.Libs.DirectShowLib; // Public namespace — IBaseFilter, FilterInfo, IPin, etc. public class CustomFilterExample { private VideoCaptureCore captureCore; public void Initialize() { captureCore = new VideoCaptureCore(); captureCore.OnFilterAdded += CaptureCore_OnFilterAdded; // Configure source // ... // Start capture captureCore.Start(); } private void CaptureCore_OnFilterAdded(object sender, FilterEventArgs eventArgs) { IBaseFilter baseFilter = eventArgs.Filter as IBaseFilter; if (baseFilter != null) { // Get filter information FilterInfo filterInfo = new FilterInfo(); baseFilter.QueryFilterInfo(out filterInfo); Console.WriteLine($"Filter added: {filterInfo.achName}"); // Check if this is the video capture filter if (filterInfo.achName.Contains("Video Capture")) { ConfigureVideoCaptureFilter(baseFilter); } // Release filter graph reference if (filterInfo.pGraph != null) { Marshal.ReleaseComObject(filterInfo.pGraph); } } } private void ConfigureVideoCaptureFilter(IBaseFilter captureFilter) { // Your filter configuration code here } public void Cleanup() { if (captureCore != null) { captureCore.Stop(); captureCore.OnFilterAdded -= CaptureCore_OnFilterAdded; captureCore.Dispose(); captureCore = null; } } } ``` ## Required System Components To use DirectShow functionality in your application, ensure your end-users have the following components installed: - DirectX Runtime (included with Windows) - SDK redistributable components ## Conclusion Working with custom DirectShow filter interfaces gives you powerful capabilities for media processing in your .NET applications. By following the patterns described in this guide, you can access and manipulate the underlying DirectShow components to achieve precise control over your multimedia applications. For additional assistance with implementing these techniques, please contact our support team. Visit our GitHub repository for more code samples and implementation examples. ---END OF PAGE--- ## Creating Custom Real-Time Video Effects in C# .NET **URL:** https://www.visioforge.com/help/docs/dotnet/general/code-samples/custom-video-effects/ **Description:** Implement custom video effects in C# with OnVideoFrameBitmap and OnVideoFrameBuffer events for real-time video processing and overlays. **Tags:** Video Capture SDK, Media Player SDK, Video Edit SDK, .NET, Windows, C# **API:** VideoFrameBitmapEventArgs, VideoFrameBufferEventArgs # Creating Custom Real-time Video Effects in C# Applications [Video Capture SDK .Net](https://www.visioforge.com/video-capture-sdk-net) [Video Edit SDK .Net](https://www.visioforge.com/video-edit-sdk-net) [Media Player SDK .Net](https://www.visioforge.com/media-player-sdk-net) ## Introduction to Video Frame Processing When developing video applications, you often need to apply custom effects or overlays to video streams in real-time. The .NET SDK provides two powerful events for this purpose: `OnVideoFrameBitmap` and `OnVideoFrameBuffer`. These events give you direct access to each video frame, allowing you to modify pixels before they're rendered or encoded. ## Implementation Methods There are two primary approaches to implementing custom video effects: 1. **Using OnVideoFrameBitmap**: Process frames as Bitmap objects with GDI+ - easier to use but with moderate performance 2. **Using OnVideoFrameBuffer**: Manipulate raw RGB24 image buffer directly - offers better performance but requires more low-level code ## Code Examples for Custom Video Effects ### Text Overlay Implementation Adding text overlays to video is useful for watermarking, displaying information, or creating captions. This example demonstrates how to add simple text to your video frames: ``` private void VideoCapture1_OnVideoFrameBitmap(object sender, VideoFrameBitmapEventArgs e) { Graphics grf = Graphics.FromImage(e.Frame); grf.DrawString("Hello!", new Font(FontFamily.GenericSansSerif, 20), new SolidBrush(Color.White), 20, 20); grf.Dispose(); e.UpdateData = true; } ``` ### Grayscale Effect Implementation Converting video to grayscale is a fundamental image processing technique. This example shows how to access and modify individual pixel values: ``` private void VideoCapture1_OnVideoFrameBitmap(object sender, VideoFrameBitmapEventArgs e) { Bitmap bmp = e.Frame; Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height); System.Drawing.Imaging.BitmapData bmpData = bmp.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadWrite, bmp.PixelFormat); IntPtr ptr = bmpData.Scan0; int bytes = Math.Abs(bmpData.Stride) * bmp.Height; byte[] rgbValues = new byte[bytes]; System.Runtime.InteropServices.Marshal.Copy(ptr, rgbValues, 0, bytes); // Apply standard luminance formula (0.3R + 0.59G + 0.11B) for accurate grayscale conversion for (int i = 0; i < rgbValues.Length; i += 3) { int gray = (int)(rgbValues[i] * 0.3 + rgbValues[i + 1] * 0.59 + rgbValues[i + 2] * 0.11); rgbValues[i] = (byte)gray; rgbValues[i + 1] = (byte)gray; rgbValues[i + 2] = (byte)gray; } System.Runtime.InteropServices.Marshal.Copy(rgbValues, 0, ptr, bytes); bmp.UnlockBits(bmpData); e.UpdateData = true; } ``` ### Brightness Adjustment Implementation This example demonstrates how to adjust the brightness of video frames - a common requirement in video processing applications: ``` private void VideoCapture1_OnVideoFrameBitmap(object sender, VideoFrameBitmapEventArgs e) { float brightness = 1.2f; // Values > 1 increase brightness, < 1 decrease it Bitmap bmp = e.Frame; Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height); System.Drawing.Imaging.BitmapData bmpData = bmp.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadWrite, bmp.PixelFormat); IntPtr ptr = bmpData.Scan0; int bytes = Math.Abs(bmpData.Stride) * bmp.Height; byte[] rgbValues = new byte[bytes]; System.Runtime.InteropServices.Marshal.Copy(ptr, rgbValues, 0, bytes); // Apply brightness adjustment to each color channel for (int i = 0; i < rgbValues.Length; i++) { int newValue = (int)(rgbValues[i] * brightness); rgbValues[i] = (byte)Math.Min(255, Math.Max(0, newValue)); } System.Runtime.InteropServices.Marshal.Copy(rgbValues, 0, ptr, bytes); bmp.UnlockBits(bmpData); e.UpdateData = true; } ``` ### Timestamp Overlay Implementation Adding timestamps to video frames is essential for surveillance and logging applications. This example shows how to create a professional-looking timestamp with a semi-transparent background: ``` private void VideoCapture1_OnVideoFrameBitmap(object sender, VideoFrameBitmapEventArgs e) { Graphics grf = Graphics.FromImage(e.Frame); // Create a semi-transparent background for better readability Rectangle textBackground = new Rectangle(10, e.Frame.Height - 50, 250, 40); grf.FillRectangle(new SolidBrush(Color.FromArgb(128, 0, 0, 0)), textBackground); // Display current date and time string dateTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"); grf.DrawString(dateTime, new Font(FontFamily.GenericSansSerif, 16), new SolidBrush(Color.White), 15, e.Frame.Height - 45); grf.Dispose(); e.UpdateData = true; } ``` ## Performance Optimization Tips ### Working with Raw Buffer Data For high-performance applications, processing raw buffer data offers significant speed advantages: ``` // OnVideoFrameBuffer event example (pseudo-code) private void VideoCapture1_OnVideoFrameBuffer(object sender, VideoFrameBufferEventArgs e) { // e.Frame.Data is an IntPtr to the native buffer (length = e.Frame.DataSize). // Dimensions and stride live in e.Frame.Info; actual pixel layout is in // e.Frame.Info.Colorspace (RGB24/RGB32/YUY2/NV12/...). Don't assume RGB24. int width = e.Frame.Info.Width; int height = e.Frame.Info.Height; int stride = e.Frame.Info.Stride; var colorspace = e.Frame.Info.Colorspace; // Process e.Frame.Data in place for maximum performance, then set // e.UpdateData = true so the modified buffer flows downstream. } ``` ### Best Practices for Frame Processing - **Memory Management**: Always dispose Graphics objects and unlock bitmapped data - **Performance Considerations**: For real-time processing, keep operations lightweight - **Buffer Processing**: We strongly recommend processing RAW data in the OnVideoFrameBuffer event for optimal performance - **External Libraries**: Consider using Intel IPP or other optimized image-processing libraries for complex operations --- ## Additional Resources Visit our [GitHub](https://github.com/visioforge/.Net-SDK-s-samples) page to access more code samples and complete project examples. ---END OF PAGE--- ## Implementing Dynamic Text Overlays on Video Frames **URL:** https://www.visioforge.com/help/docs/dotnet/general/code-samples/draw-multitext-onvideoframebuffer/ **Description:** Create multiple text overlays on video frames with OnVideoFrameBuffer event for customizable text properties and dynamic updates in .NET. **Tags:** Video Capture SDK, Media Player SDK, Video Edit SDK, .NET, Windows, C# **API:** VideoFrameBufferEventArgs # Implementing Dynamic Text Overlays on Video Frames in .NET [Video Capture SDK .Net](https://www.visioforge.com/video-capture-sdk-net) [Video Edit SDK .Net](https://www.visioforge.com/video-edit-sdk-net) [Media Player SDK .Net](https://www.visioforge.com/media-player-sdk-net) ## Introduction Adding text overlays to video content has become essential for various applications, from adding watermarks and timestamps to creating informative annotations and captions. While many SDKs offer built-in text overlay capabilities, these functions might not always provide the level of customization or flexibility required for advanced projects. This guide demonstrates how to implement custom text overlays using the `OnVideoFrameBuffer` event. This approach gives you full control over the text appearance, position, and behavior, allowing for more sophisticated overlay implementations than what's possible with standard API methods. ## Why Use Custom Text Overlays? Standard text overlay APIs often have limitations in areas such as: - Number of concurrent text elements - Font customization options - Dynamic text updates - Animation capabilities - Precise positioning control - Alpha channel management By leveraging the `OnVideoFrameBuffer` event and working directly with bitmap data, you can overcome these limitations and implement exactly what your application needs. ## Understanding the Approach The technique demonstrated in this article involves: 1. Creating a transparent bitmap with the same dimensions as the video frame 2. Drawing text elements onto this bitmap using GDI+ (System.Drawing) 3. Converting the bitmap to a memory buffer 4. Overlaying this buffer onto the video frame data 5. Optionally updating text elements dynamically This provides a powerful method for text overlay creation while maintaining good performance. ## Basic Implementation The following code sample shows a straightforward implementation for drawing multiple text overlays on video frames: ``` // Image private Bitmap logoImage = null; // Image RGB32 buffer private IntPtr logoImageBuffer = IntPtr.Zero; private int logoImageBufferSize = 0; private string text1 = "Hello World"; private string text2 = "Hey-hey"; private string text3 = "Ocean of pancakes"; private void SDK_OnVideoFrameBuffer(Object sender, VideoFrameBufferEventArgs e) { // draw text to image if (logoImage == null) { logoImage = new Bitmap(e.Frame.Info.Width, e.Frame.Info.Height, PixelFormat.Format32bppArgb); using (var grf = Graphics.FromImage(logoImage)) { // antialiasing mode grf.TextRenderingHint = TextRenderingHint.AntiAlias; // drawing mode grf.InterpolationMode = InterpolationMode.HighQualityBicubic; // smoothing mode grf.SmoothingMode = SmoothingMode.HighQuality; // text 1 var brush1 = new SolidBrush(Color.Blue); var font1 = new Font("Arial", 30, FontStyle.Regular); grf.DrawString(text1, font1, brush1, 100, 100); // text 2 var brush2 = new SolidBrush(Color.Red); var font2 = new Font("Times New Roman", 35, FontStyle.Strikeout); grf.DrawString(text2, font2, brush2, e.Frame.Info.Width / 2, e.Frame.Info.Height / 2); // text 3 var brush3 = new SolidBrush(Color.Green); var font3 = new Font("Verdana", 40, FontStyle.Italic); grf.DrawString(text3, font3, brush3, 200, 200); } } // create image buffer if not allocated or have zero size if (logoImageBuffer == IntPtr.Zero || logoImageBufferSize == 0) { if (logoImageBuffer == IntPtr.Zero) { logoImageBufferSize = ImageHelper.GetStrideRGB32(logoImage.Width) * logoImage.Height; logoImageBuffer = Marshal.AllocCoTaskMem(logoImageBufferSize); } else { logoImageBufferSize = ImageHelper.GetStrideRGB32(logoImage.Width) * logoImage.Height; Marshal.FreeCoTaskMem(logoImageBuffer); logoImageBuffer = Marshal.AllocCoTaskMem(logoImageBufferSize); } BitmapHelper.BitmapToIntPtr(logoImage, logoImageBuffer, logoImage.Width, logoImage.Height, PixelFormat.Format32bppArgb); } // Draw image FastImageProcessing.Draw_RGB32OnRGB24(logoImageBuffer, logoImage.Width, logoImage.Height, e.Frame.Data, e.Frame.Info.Width, e.Frame.Info.Height, 0, 0); e.UpdateData = true; } ``` ### Key Components Explained 1. **Bitmap Creation**: We create a 32-bit bitmap (with alpha channel) matching the video frame dimensions 2. **Graphics Settings**: We configure anti-aliasing, interpolation, and smoothing for high-quality text rendering 3. **Text Configuration**: Each text element gets its own font, color, and position 4. **Memory Management**: We allocate unmanaged memory for the bitmap buffer 5. **Bitmap to Buffer Conversion**: We convert the bitmap to a memory buffer using `BitmapHelper.BitmapToIntPtr` 6. **Buffer Overlay**: We draw the RGBA buffer onto the video frame using `FastImageProcessing.Draw_RGB32OnRGB24` 7. **Frame Update Flag**: We set `e.UpdateData = true` to inform the SDK that the frame data has been modified ## Advanced Implementation with Dynamic Updates For more interactive applications, you might need to update text overlays dynamically. The following implementation supports on-the-fly updates of text content, fonts, and colors: ``` // Image Bitmap logoImage = null; // Image RGB32 buffer IntPtr logoImageBuffer = IntPtr.Zero; int logoImageBufferSize = 0; // text settings string text1 = "Hello World"; Font font1 = new Font("Arial", 30, FontStyle.Regular); SolidBrush brush1 = new SolidBrush(Color.Blue); string text2 = "Hey-hey"; Font font2 = new Font("Times New Roman", 35, FontStyle.Strikeout); SolidBrush brush2 = new SolidBrush(Color.Red); string text3 = "Ocean of pancakes"; Font font3 = new Font("Verdana", 40, FontStyle.Italic); SolidBrush brush3 = new SolidBrush(Color.Green); // update flag bool textUpdate = false; object textLock = new object(); // Update text overlay, index is [1..3] void UpdateText(int index, string text, Font font, SolidBrush brush) { lock (textLock) { textUpdate = true; } switch (index) { case 1: text1 = text; font1 = font; brush1 = brush; break; case 2: text2 = text; font2 = font; brush2 = brush; break; case 3: text3 = text; font3 = font; brush3 = brush; break; default: return; } } private void SDK_OnVideoFrameBuffer(Object sender, VideoFrameBufferEventArgs e) { lock (textLock) { if (textUpdate) { logoImage.Dispose(); logoImage = null; } // draw text to image if (logoImage == null) { logoImage = new Bitmap(e.Frame.Info.Width, e.Frame.Info.Height, PixelFormat.Format32bppArgb); using (var grf = Graphics.FromImage(logoImage)) { // antialiasing mode grf.TextRenderingHint = TextRenderingHint.AntiAlias; // drawing mode grf.InterpolationMode = InterpolationMode.HighQualityBicubic; // smoothing mode grf.SmoothingMode = SmoothingMode.HighQuality; // text 1 grf.DrawString(text1, font1, brush1, 100, 100); // text 2 grf.DrawString(text2, font2, brush2, e.Frame.Info.Width / 2, e.Frame.Info.Height / 2); // text 3 grf.DrawString(text3, font3, brush3, 200, 200); } } // create image buffer if not allocated or have zero size if (logoImageBuffer == IntPtr.Zero || logoImageBufferSize == 0) { if (logoImageBuffer == IntPtr.Zero) { logoImageBufferSize = ImageHelper.GetStrideRGB32(e.Frame.Info.Width) * e.Frame.Info.Height; logoImageBuffer = Marshal.AllocCoTaskMem(logoImageBufferSize); } else { logoImageBufferSize = ImageHelper.GetStrideRGB32(e.Frame.Info.Width) * e.Frame.Info.Height; Marshal.FreeCoTaskMem(logoImageBuffer); logoImageBuffer = Marshal.AllocCoTaskMem(logoImageBufferSize); } BitmapHelper.BitmapToIntPtr(logoImage, logoImageBuffer, logoImage.Width, logoImage.Height, PixelFormat.Format32bppArgb); } if (textUpdate) { textUpdate = false; BitmapHelper.BitmapToIntPtr(logoImage, logoImageBuffer, logoImage.Width, logoImage.Height, PixelFormat.Format32bppArgb); } // Draw image FastImageProcessing.Draw_RGB32OnRGB24(logoImageBuffer, logoImage.Width, logoImage.Height, e.Frame.Data, e.Frame.Info.Width, e.Frame.Info.Height, 0, 0); e.UpdateData = true; } } private void btUpdateText1_Click(object sender, EventArgs e) { UpdateText(1, "Hello world", new Font("Arial", 48, FontStyle.Underline), new SolidBrush(Color.Aquamarine)); } ``` ### New Features in the Advanced Implementation 1. **Thread Safety**: We use a lock object to prevent concurrent access to shared resources 2. **Update Mechanism**: The `UpdateText` method provides a clean interface for changing text properties 3. **Text Property Storage**: Each text element has its own variables for content, font, and color 4. **Change Detection**: We use a flag (`textUpdate`) to indicate when text properties have changed 5. **Resource Management**: We dispose of the old bitmap when text properties change 6. **Buffer Update**: We update the memory buffer when text properties change 7. **UI Integration**: A sample button click handler demonstrates how to trigger text updates ## Performance Optimization Tips When implementing text overlays with this method, consider these performance optimizations: 1. **Minimize Bitmap Recreations**: Only recreate the bitmap when necessary (text changes, resolution changes) 2. **Cache Font Objects**: Font creation is expensive; create fonts once and reuse them 3. **Use Memory Efficiently**: Free unmanaged memory when it's no longer needed 4. **Optimize Drawing Operations**: Use hardware acceleration when available 5. **Consider Update Frequency**: For frequent updates, consider double-buffering techniques 6. **Profile Your Code**: Use performance profiling tools to identify bottlenecks ## Advanced Features to Consider This basic implementation can be extended with additional features: 1. **Text Animation**: Implement text movement, fading, or other animations 2. **Text Formatting**: Add support for rich text formatting (bold, italic, etc.) 3. **Text Effects**: Implement shadows, outlines, or glow effects 4. **Text Alignment**: Add support for different text alignment options 5. **Multi-Line Text**: Implement proper handling of multi-line text with wrapping 6. **Localization**: Add support for different languages and text directions 7. **Performance Monitoring**: Add diagnostics to monitor rendering performance ## Memory Management Considerations When working with unmanaged memory, it's crucial to handle resource cleanup properly: 1. Implement the `IDisposable` pattern in your class 2. Free unmanaged memory in the `Dispose` method 3. Consider using `SafeHandle` or similar constructs for safer resource management 4. Set buffer pointers to `IntPtr.Zero` after freeing them 5. Use structured exception handling around memory operations ## Cleanup Example ``` protected override void Dispose(bool disposing) { if (disposing) { // Dispose managed resources if (logoImage != null) { logoImage.Dispose(); logoImage = null; } } // Free unmanaged resources if (logoImageBuffer != IntPtr.Zero) { Marshal.FreeCoTaskMem(logoImageBuffer); logoImageBuffer = IntPtr.Zero; logoImageBufferSize = 0; } base.Dispose(disposing); } ``` ## Required Dependencies - SDK redistributable components ## Conclusion Implementing custom text overlays using the `OnVideoFrameBuffer` event provides a powerful and flexible solution for applications that require advanced text display capabilities. While it requires more code than using built-in API methods, the additional flexibility and control make it worthwhile for sophisticated video applications. By following the patterns demonstrated in this guide, you can create dynamic, high-quality text overlays that can be updated in real-time, providing a rich user experience in your video applications. --- Visit our [GitHub](https://github.com/visioforge/.Net-SDK-s-samples) page to get more code samples. ---END OF PAGE--- ## Render Live Video in WinForms PictureBox — C# .NET Guide **URL:** https://www.visioforge.com/help/docs/dotnet/general/code-samples/draw-video-picturebox/ **Description:** Thread-safe frame updates, bitmap disposal, and double buffering to prevent flicker. Frame skipping for high-FPS sources. VisioForge SDK zoom and size modes. **Tags:** Video Capture SDK, Media Player SDK, Video Edit SDK, .NET, Windows, C# **API:** VideoFrameBitmapEventArgs # Drawing Video on PictureBox in .NET Applications [Video Capture SDK .Net](https://www.visioforge.com/video-capture-sdk-net) [Video Edit SDK .Net](https://www.visioforge.com/video-edit-sdk-net) [Media Player SDK .Net](https://www.visioforge.com/media-player-sdk-net) ## Introduction to Video Rendering in WinForms Displaying video content in desktop applications is a common requirement for many software developers working with multimedia. Whether you're building applications for video surveillance, media players, video editing tools, or any software that processes video streams, understanding how to effectively render video is crucial. The PictureBox control is one of the most straightforward ways to display video frames in Windows Forms applications. While it wasn't specifically designed for video playback, with proper implementation, it can provide smooth video rendering with minimal resource consumption. This guide focuses on implementing video rendering on PictureBox controls in .NET WinForms applications. We'll cover the entire process from setup to implementation, addressing common pitfalls and optimization techniques. ## Why Use PictureBox for Video Display? Before diving into implementation details, let's examine the advantages of using PictureBox for video display: - **Simplicity**: PictureBox is a straightforward control that most .NET developers are already familiar with. - **Flexibility**: It allows customization of how images are displayed through its SizeMode property. - **Integration**: It integrates seamlessly with other WinForms controls. - **Low overhead**: For many applications, it provides sufficient performance without requiring more complex DirectX or OpenGL implementations. However, it's important to note that PictureBox wasn't designed specifically for high-performance video playback. For applications requiring professional-grade video performance or hardware acceleration, more specialized rendering approaches might be necessary. ## Prerequisites To implement video rendering on a PictureBox, you'll need: - Basic knowledge of C# and .NET WinForms development - Visual Studio or another IDE for .NET development - A video source (from Video Capture SDK, Video Edit SDK, or Media Player SDK) - Understanding of event-driven programming ## Setting Up Your Environment ### Configuring the PictureBox Control 1. Add a PictureBox control to your form through the designer or programmatically. 2. Configure the basic properties for optimal video display: ``` // Configure PictureBox for video display pictureBox1.BackColor = Color.Black; pictureBox1.SizeMode = PictureBoxSizeMode.StretchImage; ``` The `BackColor` property set to `Black` provides a clean background for video display, especially during initialization or when the video has black borders. The `SizeMode` property determines how the video frame fits within the control: - `StretchImage`: Stretches the image to fill the PictureBox (may distort aspect ratio) - `Zoom`: Maintains aspect ratio while filling the control - `CenterImage`: Centers the image without scaling - `Normal`: Displays the image at its original size For most video applications, `StretchImage` or `Zoom` work best, depending on whether maintaining aspect ratio is important. ## Implementation Steps ### Step 1: Prepare Your Class with Required Variables Add a boolean class member to track when an image is being applied to the PictureBox. This prevents race conditions when multiple frames arrive in quick succession: ``` private bool applyingPictureBoxImage = false; ``` ### Step 2: Initialize Video Settings in the Start Handler When starting your video capture or playback, ensure the flag is properly initialized: ``` private async void btnStart_Click(object sender, EventArgs e) { // Reset the flag before starting capture/playback. applyingPictureBoxImage = false; // Subscribe to OnVideoFrameBitmap before starting so the first frame is not missed. // The event is EventHandler, fired from a worker thread. videoCapture1.OnVideoFrameBitmap += VideoCapture1_OnVideoFrameBitmap; // Video Capture SDK example — swap for MediaPlayer1 / VideoEdit1 if you are using those engines. videoCapture1.Video_CaptureDevice = new VideoCaptureSource("USB Camera"); videoCapture1.Mode = VideoCaptureMode.VideoPreview; videoCapture1.Audio_RecordAudio = false; await videoCapture1.StartAsync(); } ``` The same `OnVideoFrameBitmap` event exists on all three engines — `VideoCaptureCore`, `MediaPlayerCore`, and `VideoEditCore` — so the handler below works unchanged no matter which SDK raised it. ### Step 3: Implement the Frame Handler The core of video rendering is the frame handler. This event fires each time a new video frame is available. Here's how to implement it efficiently: ``` private void VideoCapture1_OnVideoFrameBitmap(object sender, VideoFrameBitmapEventArgs e) { // Prevent concurrent updates that could cause threading issues if (applyingPictureBoxImage) { return; } applyingPictureBoxImage = true; try { // Store current image for proper disposal var currentImage = pictureBox1.Image; // Create a new bitmap from the frame pictureBox1.Image = new Bitmap(e.Frame); // Properly dispose of the previous image to prevent memory leaks currentImage?.Dispose(); } catch (Exception ex) { // Consider logging the exception Console.WriteLine($"Error updating frame: {ex.Message}"); } finally { // Ensure flag is reset even if an exception occurs applyingPictureBoxImage = false; } } ``` This implementation includes several important concepts: 1. **Thread safety**: Using the `applyingPictureBoxImage` flag prevents concurrent updates. 2. **Memory management**: Properly disposing of the previous image prevents memory leaks. 3. **Exception handling**: Catching exceptions prevents application crashes during rendering. ### Step 4: Implement Cleanup When Stopping Video When stopping video capture or playback, you need to clean up resources properly: ``` private void btnStop_Click(object sender, EventArgs e) { // Your video stop code here // videoCapture1.Stop(); or similar SDK call // Wait until any in-progress frame updates complete while (applyingPictureBoxImage) { Thread.Sleep(50); } // Clean up resources if (pictureBox1.Image != null) { pictureBox1.Image.Dispose(); pictureBox1.Image = null; } } ``` This cleanup process: 1. Waits for any in-progress frame updates to complete 2. Properly disposes of the image 3. Sets the PictureBox image to null for visual cleanup ## Advanced Implementation Considerations ### Handling High Frame Rates For high-frame-rate video sources, you might want to implement frame skipping to maintain application responsiveness: ``` private DateTime lastFrameTime = DateTime.MinValue; private TimeSpan frameInterval = TimeSpan.FromMilliseconds(33); // About 30fps private void VideoCapture1_OnVideoFrameBitmap(object sender, VideoFrameBitmapEventArgs e) { // Skip frames if they're coming too quickly if (DateTime.Now - lastFrameTime < frameInterval) { return; } if (applyingPictureBoxImage) { return; } applyingPictureBoxImage = true; lastFrameTime = DateTime.Now; // Frame processing code as before... } ``` ### Cross-Thread Invocation When handling video frames from background threads, you'll need to use cross-thread invocation: ``` private void VideoCapture1_OnVideoFrameBitmap(object sender, VideoFrameBitmapEventArgs e) { if (applyingPictureBoxImage) { return; } applyingPictureBoxImage = true; if (pictureBox1.InvokeRequired) { pictureBox1.BeginInvoke(new Action(() => { var currentImage = pictureBox1.Image; pictureBox1.Image = new Bitmap(e.Frame); currentImage?.Dispose(); applyingPictureBoxImage = false; })); } else { // Direct update code as before... } } ``` ## Performance Optimization Tips ### Reduce Bitmap Creation Overhead Creating a new Bitmap for each frame can be expensive. Consider reusing Bitmap objects: ``` private Bitmap displayBitmap; private void VideoCapture1_OnVideoFrameBitmap(object sender, VideoFrameBitmapEventArgs e) { if (applyingPictureBoxImage) { return; } applyingPictureBoxImage = true; try { // Initialize bitmap if needed if (displayBitmap == null || displayBitmap.Width != e.Frame.Width || displayBitmap.Height != e.Frame.Height) { displayBitmap?.Dispose(); displayBitmap = new Bitmap(e.Frame.Width, e.Frame.Height); } // Copy frame to display bitmap using (Graphics g = Graphics.FromImage(displayBitmap)) { g.DrawImage(e.Frame, 0, 0, e.Frame.Width, e.Frame.Height); } // Update display var oldImage = pictureBox1.Image; pictureBox1.Image = displayBitmap; oldImage?.Dispose(); } finally { applyingPictureBoxImage = false; } } ``` ### Consider Using Double Buffering For smoother display, enable double buffering on your form: ``` // In your form constructor this.DoubleBuffered = true; ``` ## Troubleshooting Common Issues ### Memory Leaks If your application experiences increasing memory usage, check: - Proper disposal of old Bitmap objects - References to frames that might prevent garbage collection - Whether frames are being skipped when necessary ### Flickering Display If video display flickers: - Ensure double buffering is enabled - Check if multiple threads are updating the PictureBox simultaneously - Consider implementing a more sophisticated frame synchronization mechanism ### High CPU Usage If rendering causes high CPU usage: - Implement frame skipping as shown above - Consider reducing the frame rate of the source if possible - Optimize bitmap handling to reduce GC pressure ## Required Dependencies To implement this solution, you'll need: - .NET Framework or .NET Core/5+ - SDK redist files for the specific video SDK you're using ## Conclusion Implementing video rendering on a PictureBox control provides a straightforward way to display video in Windows Forms applications. By following the patterns outlined in this guide, you can achieve smooth video display while avoiding common pitfalls like memory leaks, thread safety issues, and performance bottlenecks. Remember that while PictureBox is suitable for many applications, high-performance video applications might benefit from more specialized rendering approaches using DirectX or OpenGL. --- For more code samples, visit our [GitHub](https://github.com/visioforge/.Net-SDK-s-samples) repository. ---END OF PAGE--- ## How to Exclude DirectShow Filters in .NET Applications **URL:** https://www.visioforge.com/help/docs/dotnet/general/code-samples/exclude-filters/ **Description:** Identify and exclude problematic DirectShow filters from multimedia pipelines in .NET video capture, editing, and playback applications. **Tags:** Video Capture SDK, Media Player SDK, Video Edit SDK, .NET, DirectShow, VideoCaptureCore, Windows, Capture, Playback, Streaming, Encoding, Decoding, Mixing, Conversion, C# **API:** VideoCaptureCore # Excluding DirectShow Filters in .NET Applications [Video Capture SDK .Net](https://www.visioforge.com/video-capture-sdk-net) [Video Edit SDK .Net](https://www.visioforge.com/video-edit-sdk-net) [Media Player SDK .Net](https://www.visioforge.com/media-player-sdk-net) ## Introduction When developing multimedia applications in .NET, you'll frequently interact with DirectShow — Microsoft's framework for multimedia streaming. DirectShow uses a filter-based architecture where individual components (filters) process media data. However, not all filters are created equal. Some can cause performance issues, compatibility problems, or simply don't meet your application's specific needs. This guide explores how to effectively identify and exclude problematic DirectShow filters from your application's processing pipeline. ## Understanding DirectShow Filters DirectShow filters are COM objects that perform specific operations on media data, such as: - **Source filters**: Read media from files, capture devices, or network streams - **Transform filters**: Process or convert media data (decoders, encoders, effects) - **Renderer filters**: Display video or play audio When DirectShow builds a filter graph, it automatically selects filters based on merit (priority) and compatibility. This automatic selection sometimes includes third-party filters that may: - Reduce performance - Cause stability issues - Introduce compatibility problems - Override preferred processing methods ## Common Issues with DirectShow Filters ### Decoder Conflicts Multiple decoders installed on a system can compete to handle the same media formats. For example: - NVIDIA's video decoder might conflict with Intel's hardware decoder - Third-party codec packs might introduce low-quality decoders - Legacy decoders might be selected over newer, more efficient ones ### Performance Bottlenecks Some filters can significantly impact performance: - Non-optimized video processing filters - Filters without hardware acceleration support - Debugging filters that add logging overhead ### Compatibility Problems Not all filters work well together: - Version mismatches between filters - Filters with different pixel format expectations - Non-standard implementation of interfaces ## When to Exclude DirectShow Filters Consider excluding DirectShow filters when: 1. You notice unexplained performance issues during media playback or processing 2. Your application crashes when handling specific media formats 3. Media quality is unexpectedly poor 4. You want to enforce consistent behavior across different user systems 5. You're implementing a custom processing pipeline with specific requirements ## Implementing Filter Exclusion Our .NET SDKs provide a straightforward API for managing DirectShow filter exclusions. ### Clearing the Blacklist Before setting up your exclusion list, you may want to clear any previously blacklisted filters: ``` // Clear any existing blacklisted filters videoProcessor.DirectShow_Filters_Blacklist_Clear(); ``` This ensures you're starting with a clean slate and your exclusion list contains only the filters you explicitly specify. ### Adding Filters to the Blacklist To exclude specific filters, you'll use the `DirectShow_Filters_Blacklist_Add` method with the exact filter name: ``` // Exclude specific filters by name videoProcessor.DirectShow_Filters_Blacklist_Add("NVIDIA NVENC Encoder"); videoProcessor.DirectShow_Filters_Blacklist_Add("Intel® Hardware H.264 Encoder"); videoProcessor.DirectShow_Filters_Blacklist_Add("Fraunhofer IIS MPEG Audio Layer 3 Decoder"); ``` ### Complete Code Example Here's a more complete example demonstrating filter exclusion in a video processing application: ``` using System; using VisioForge.Core.VideoCapture; using VisioForge.Core.VideoEdit; using VisioForge.Core.MediaPlayer; public class FilterExclusionExample { private VideoCaptureCore captureCore; public void SetupFilterExclusions() { captureCore = new VideoCaptureCore(); // Clear any existing blacklisted filters captureCore.DirectShow_Filters_Blacklist_Clear(); // Add problematic filters to the blacklist captureCore.DirectShow_Filters_Blacklist_Add("SampleGrabber"); captureCore.DirectShow_Filters_Blacklist_Add("Overlay Mixer"); captureCore.DirectShow_Filters_Blacklist_Add("VirtualDub H.264 Decoder"); Console.WriteLine("DirectShow filters successfully excluded."); } // Additional application logic... } ``` ## Best Practices for Filter Exclusion ### Identify Before Excluding Before blacklisting filters, identify which ones are causing issues: 1. Use DirectShow diagnostic tools like GraphEdit or GraphStudio 2. Enable logging in your application to track which filters are being used 3. Test with different filter configurations to isolate problematic components ### Be Specific with Filter Names Use exact, case-sensitive filter names when excluding: ``` // Correct - uses exact filter name videoProcessor.DirectShow_Filters_Blacklist_Add("ffdshow Video Decoder"); // Incorrect - may exclude unintended filters or none at all videoProcessor.DirectShow_Filters_Blacklist_Add("ffdshow"); ``` ### Consider Alternative Approaches Filter exclusion is not always the best solution: - **Merit adjustment**: SDK allows adjusting filter merit instead of complete exclusion - **Explicit graph building**: Build the filter graph manually with preferred filters - **Alternative frameworks**: Consider MediaFoundation for newer applications ## Troubleshooting ### Filter Still Being Used Despite Blacklisting If a filter continues to be used despite being blacklisted: 1. Verify you're using the exact filter name (case-sensitive) 2. Ensure the blacklist is set before building the filter graph 3. Check if the filter is being inserted through an alternative method ### Performance Issues After Blacklisting If performance degrades after blacklisting certain filters: 1. The blacklisted filter might have been providing hardware acceleration 2. The replacement filter might be less efficient 3. The filter graph might be more complex without the excluded filter ### Application Crashes After Filter Exclusion If your application becomes unstable after filter exclusion: 1. Some filters might be required for proper operation 2. The alternative filter path might have compatibility issues 3. The filter graph might be incomplete without certain filters ## Conclusion Excluding problematic DirectShow filters provides a powerful tool for optimizing and stabilizing your multimedia applications. By carefully identifying and blacklisting problematic filters, you can ensure consistent behavior, better performance, and higher quality media processing across different user systems. Remember to test thoroughly after implementing filter exclusions, as the DirectShow filter graph may behave differently when certain components are unavailable. --- Visit our [GitHub](https://github.com/visioforge/.Net-SDK-s-samples) page to get more code samples and implementation examples. ---END OF PAGE--- ## Process Video Frames in C# .NET — OnVideoFrameBuffer Event **URL:** https://www.visioforge.com/help/docs/dotnet/general/code-samples/image-onvideoframebuffer/ **Description:** Access the raw video frame buffer in C# / .NET via the OnVideoFrameBuffer event. Modify pixels, draw images, apply custom blends — full frame control. **Tags:** Video Capture SDK, Media Player SDK, Video Edit SDK, .NET, DirectShow, MediaPlayerCoreX, VideoCaptureCoreX, Windows, macOS, Linux, Android, iOS, GStreamer, Capture, Playback, Encoding, C# **API:** VideoFrameXBufferEventArgs, VideoCaptureCoreX, MediaPlayerCoreX, VideoCaptureCore, VideoFrameBufferEventArgs # Drawing Images with OnVideoFrameBuffer in .NET [Video Capture SDK .Net](https://www.visioforge.com/video-capture-sdk-net) [Video Edit SDK .Net](https://www.visioforge.com/video-edit-sdk-net) [Media Player SDK .Net](https://www.visioforge.com/media-player-sdk-net) ## Introduction The `OnVideoFrameBuffer` event gives direct, pixel-level access to every video frame as it passes through the pipeline. Event handlers receive a raw buffer and can inspect, modify, or overwrite pixels before the frame continues to the next stage (preview, encoder, file output). Drawing an image onto the frame — for a watermark, logo, debug overlay, or computer-vision annotation — is the most common use case and the one this guide walks through. Looking for the high-level overlay feature? If you just need to drop a static or animated image on the video (PNG / JPG / GIF / BMP), use the dedicated [image overlay effect](../../video-effects/image-overlay/) — one line of code via `Video_Effects_Add(new VideoEffectImageLogo(...))`. Use `OnVideoFrameBuffer` (this page) when you need **pixel-level control**: custom blend modes, per-frame logic, CV annotations, or integration with third-party imaging libraries. ### Supported engines The `OnVideoFrameBuffer` event is exposed on both engine families: | Engine | Event args type | Frame pixel format | | --- | --- | --- | | `VideoCaptureCore` (DirectShow, Windows) | `VideoFrameBufferEventArgs` | RGB24 / RGB32 | | `VideoCaptureCoreX` (GStreamer, cross-platform) | `VideoFrameXBufferEventArgs` | BGRA (most common) | | `MediaPlayerCoreX` (GStreamer, cross-platform) | `VideoFrameXBufferEventArgs` | BGRA (most common) | Both engines follow the same pattern — subscribe to the event, read `e.Frame.Data` (an `IntPtr`) along with `Width` / `Height` / `Stride`, optionally modify the buffer in place, and set `e.UpdateData = true` to have the changes propagated downstream. ## Understanding the process When working with video frames you need to: 1. Load your image (logo, watermark, etc.) into memory. 2. Convert the image to a compatible buffer format (RGB24/RGB32 for the legacy engine, BGRA for the X engines). 3. Subscribe to the `OnVideoFrameBuffer` event. 4. Draw the image onto each video frame as it is processed. 5. Set `e.UpdateData = true` so the modified frame replaces the original downstream. ## VideoCaptureCore (DirectShow) example Let's walk through the implementation step by step: ### Step 1: Load Your Image First, load the image file you want to overlay on the video: ``` // Bitmap loading from file private Bitmap logoImage = new Bitmap(@"logo24.jpg"); // You can also use PNG with alpha channel for transparency //private Bitmap logoImage = new Bitmap(@"logo32.png"); ``` ### Step 2: Prepare Memory Buffers Initialize pointers for the image buffer: ``` // Logo RGB24/RGB32 buffer private IntPtr logoImageBuffer = IntPtr.Zero; private int logoImageBufferSize = 0; ``` ### Step 3: Implement the OnVideoFrameBuffer Event Handler The full event handler implementation: ``` private void VideoCapture1_OnVideoFrameBuffer(Object sender, VideoFrameBufferEventArgs e) { // Create logo buffer if not allocated or have zero size if (logoImageBuffer == IntPtr.Zero || logoImageBufferSize == 0) { if (logoImageBuffer == IntPtr.Zero) { if (logoImage.PixelFormat == PixelFormat.Format32bppArgb) { logoImageBufferSize = ImageHelper.GetStrideRGB32(logoImage.Width) * logoImage.Height; logoImageBuffer = Marshal.AllocCoTaskMem(logoImageBufferSize); } else { logoImageBufferSize = ImageHelper.GetStrideRGB24(logoImage.Width) * logoImage.Height; logoImageBuffer = Marshal.AllocCoTaskMem(logoImageBufferSize); } } else { if (logoImage.PixelFormat == PixelFormat.Format32bppArgb) { logoImageBufferSize = ImageHelper.GetStrideRGB32(logoImage.Width) * logoImage.Height; Marshal.FreeCoTaskMem(logoImageBuffer); logoImageBuffer = Marshal.AllocCoTaskMem(logoImageBufferSize); } else { logoImageBufferSize = ImageHelper.GetStrideRGB24(logoImage.Width) * logoImage.Height; Marshal.FreeCoTaskMem(logoImageBuffer); logoImageBuffer = Marshal.AllocCoTaskMem(logoImageBufferSize); } } if (logoImage.PixelFormat == PixelFormat.Format32bppArgb) { BitmapHelper.BitmapToIntPtr(logoImage, logoImageBuffer, logoImage.Width, logoImage.Height, PixelFormat.Format32bppArgb); } else { BitmapHelper.BitmapToIntPtr(logoImage, logoImageBuffer, logoImage.Width, logoImage.Height, PixelFormat.Format24bppRgb); } } // Draw image — the classic VideoFrame struct keeps Width/Height/Stride inside Frame.Info if (logoImage.PixelFormat == PixelFormat.Format32bppArgb) { FastImageProcessing.Draw_RGB32OnRGB24(logoImageBuffer, logoImage.Width, logoImage.Height, e.Frame.Data, e.Frame.Info.Width, e.Frame.Info.Height, 0, 0); } else { FastImageProcessing.Draw_RGB24OnRGB24Old(logoImageBuffer, logoImage.Width, logoImage.Height, e.Frame.Data, e.Frame.Info.Width, e.Frame.Info.Height, 0, 0); } e.UpdateData = true; } ``` ## Detailed Explanation ### Memory Management The code handles both 24-bit and 32-bit image formats. Here's what happens: 1. **Buffer Initialization Check**: The code first checks if the logo buffer needs to be created or recreated. 2. **Format Detection**: It determines whether to use RGB24 or RGB32 format based on the loaded image: 3. RGB24: Standard 24-bit color (8 bits each for R, G, B) 4. RGB32: 32-bit color with alpha channel for transparency (8 bits each for R, G, B, A) 5. **Memory Allocation**: Allocates unmanaged memory using `Marshal.AllocCoTaskMem()` to store the image data. 6. **Image Conversion**: Converts the Bitmap to raw pixel data in the allocated buffer using `BitmapHelper.BitmapToIntPtr()`. ### Drawing Process Once the buffer is prepared, drawing takes place: 1. **Format-Specific Drawing**: The code selects the appropriate drawing method based on the image format: 2. `FastImageProcessing.Draw_RGB32OnRGB24()` for 32-bit images with transparency 3. `FastImageProcessing.Draw_RGB24OnRGB24Old()` for standard 24-bit images (8-arg form) or `Draw_RGB24OnRGB24S()` when source/destination strides are known 4. **Position Parameters**: The `0, 0` parameters specify where to draw the image (top-left corner in this example). 5. **Frame Update**: Setting `e.UpdateData = true` ensures the modified frame data is used for display or further processing. ## VideoCaptureCoreX / MediaPlayerCoreX (X engines) example On the cross-platform X engines the event signature changes to `VideoFrameXBufferEventArgs` and the frame buffer typically arrives in **BGRA** format (4 bytes per pixel). The same pattern applies — subscribe, inspect, modify, flag updates. The example below uses SkiaSharp to wrap the raw buffer and draw a PNG logo on top; SkiaSharp is already a transitive dependency of the X engines, so no extra NuGet package is needed. ``` using SkiaSharp; // Load logo once (PNG with alpha works well for watermarks) private SKBitmap _logo = SKBitmap.Decode(@"logo.png"); // Subscribe after constructing VideoCaptureCoreX / MediaPlayerCoreX _videoCapture.OnVideoFrameBuffer += VideoCapture_OnVideoFrameBuffer; private void VideoCapture_OnVideoFrameBuffer(object sender, VideoFrameXBufferEventArgs e) { if (e.Frame == null || e.Frame.Data == IntPtr.Zero) { return; } // Wrap the raw BGRA buffer in a SkiaSharp canvas (no extra allocation) var info = new SKImageInfo(e.Frame.Width, e.Frame.Height, SKColorType.Bgra8888, SKAlphaType.Premul); using (var pixmap = new SKPixmap(info, e.Frame.Data, e.Frame.Stride)) using (var surface = SKSurface.Create(pixmap)) { var canvas = surface.Canvas; // Draw the logo at bottom-right with 16px padding var x = e.Frame.Width - _logo.Width - 16; var y = e.Frame.Height - _logo.Height - 16; canvas.DrawBitmap(_logo, x, y); canvas.Flush(); } // Propagate the modified frame downstream e.UpdateData = true; } ``` **Why BGRA matters.** The X engines request BGRA by default for frame callbacks because it maps 1:1 to SkiaSharp, System.Drawing, and most GPU-friendly interop paths. If you need a different format (I420, NV12, RGB24), request a format conversion block upstream of your handler rather than converting on every frame. **Alternative imaging stacks.** You can also use `System.Drawing.Bitmap` via `new Bitmap(width, height, stride, PixelFormat.Format32bppArgb, data)` on Windows, or manual byte writes via `Marshal.Copy` / `Span` for maximum control. SkiaSharp is the recommended option on macOS / Linux / iOS / Android. **Engine-level parity.** Everything documented in the [Memory Management](#memory-management), [Error Handling](#error-handling), and [Performance Optimization](#performance-optimization) sections below applies equally to the X engines — the event fires on a processing thread, `UpdateData` toggles whether the buffer is re-used downstream, and heavy work should be offloaded to avoid dropping frames. ## Best Practices for Image Overlay For optimal performance when overlaying images on video frames: 1. **Memory Management**: Always free allocated memory when it's no longer needed to prevent memory leaks. 2. **Buffer Reuse**: Create the buffer once and reuse it for subsequent frames rather than recreating it for each frame. 3. **Image Size Considerations**: Use appropriately sized images; overlaying large images can impact performance. 4. **Format Selection**: 5. Use PNG (RGB32) when you need transparency 6. Use JPG (RGB24) when transparency isn't required (more efficient) 7. **Position Calculation**: For dynamic positioning, calculate coordinates based on frame dimensions. On the classic engine (`VideoFrameBufferEventArgs`) Width/Height live on `e.Frame.Info`; on the X engines (`VideoFrameXBufferEventArgs`) they're flat on `e.Frame`. ``` // Classic engine — Width/Height live on e.Frame.Info int xPos = e.Frame.Info.Width - logoImage.Width - 10; int yPos = e.Frame.Info.Height - logoImage.Height - 10; ``` ## Error Handling When implementing this functionality, consider adding error handling: ``` try { // Your existing implementation } catch (OutOfMemoryException ex) { // Handle memory allocation failures Console.WriteLine("Failed to allocate memory: " + ex.Message); } catch (Exception ex) { // Handle other exceptions Console.WriteLine("Error during frame processing: " + ex.Message); } finally { // Optional cleanup code } ``` ## Performance Optimization For high-performance applications, consider these optimizations: 1. **Buffer Pre-allocation**: Initialize buffers during application startup rather than during video processing. 2. **Conditional Processing**: Only process frames that need the overlay (e.g., skip processing for certain frames). 3. **Parallel Processing**: For complex operations, consider using parallel processing techniques. ## Conclusion The `OnVideoFrameBuffer` event gives direct access to every raw frame on both the legacy `VideoCaptureCore` engine (RGB24/RGB32 via `VideoFrameBufferEventArgs`) and the cross-platform X engines (`VideoCaptureCoreX` / `MediaPlayerCoreX`, BGRA via `VideoFrameXBufferEventArgs`). This is the right tool when you need pixel-level control — custom blend modes, per-frame CV annotations, or integration with third-party imaging libraries. For static or animated image overlays without writing a per-frame handler, the one-line [image overlay effect](../../video-effects/image-overlay/) is usually the better choice. ## Related documentation - [Image overlay effect](../../video-effects/image-overlay/) — high-level, declarative watermark / logo overlay without writing a callback. - [Text overlay via OnVideoFrameBuffer](../text-onvideoframebuffer/) — same technique applied to text instead of images. - [Drawing video in a PictureBox](../draw-video-picturebox/) — WinForms rendering pattern that often pairs with pixel-level frame work. --- Looking for more code samples? Visit our [GitHub repository](https://github.com/visioforge/.Net-SDK-s-samples) for additional examples and resources. ---END OF PAGE--- ## Essential .NET SDK Code Samples for Media Developers **URL:** https://www.visioforge.com/help/docs/dotnet/general/code-samples/ **Description:** Implementation examples for DirectShow filters, audio/video processing, rendering, and media manipulation in .NET SDK applications. **Tags:** .NET, DirectShow, Editing # .NET SDK Code Samples: Practical Implementation Guide In this guide, you'll find a collection of practical code samples and implementation techniques for working with our .NET SDKs. These examples address common development scenarios and demonstrate how to leverage our libraries effectively for media processing applications. ## DirectShow Filter Implementation DirectShow provides a powerful framework for handling multimedia streams. Our SDKs simplify working with these components through well-designed interfaces and helper methods. ### Media Indexing and Format Handling - [ASF and WMV Files Indexing](asf-wmv-files-indexing/) - Learn techniques for properly indexing Windows Media formats to enable seeking and efficient playback position control. This sample demonstrates how to establish accurate navigation points within media files and handle large ASF/WMV content effectively. ### Custom Filter Integration - [Custom DirectShow Filter Interface Usage](custom-filter-interface/) - This tutorial walks through the process of implementing and connecting custom DirectShow filters within your application. You'll learn how to create filter interfaces that integrate seamlessly with the existing DirectShow architecture while adding your own specialized functionality. ### Third-Party Integration - [Integrating Third-Party Video Processing Filters](3rd-party-video-effects/) - Discover how to incorporate external video processing components into your DirectShow filter graph. This example demonstrates proper filter registration, connection methods, and parameter configuration for third-party video effects and transformations. ### Filter Management - [Manual DirectShow Filter Uninstallation](uninstall-directshow-filter/) - This guide explains the registry entries, COM object registration, and system directories involved in completely removing DirectShow filters when standard uninstallation isn't sufficient or available. - [Excluding Specific DirectShow Filters](exclude-filters/) - Learn techniques for selectively bypassing certain DirectShow filters in your filter graph construction. This sample shows how to exclude specific decoders, encoders, or processing filters while maintaining proper media handling. ## Audio and Video Processing Techniques Manipulating audio and video streams is a core requirement for many media applications. These samples demonstrate different approaches to accessing and modifying media data. ### Real-time Video Effects - [Custom Video Effects Using Frame Events](custom-video-effects/) - Learn two powerful approaches for implementing real-time video effects through the OnVideoFrameBitmap and OnVideoFrameBuffer events. This comprehensive sample demonstrates how to access video frames, apply effects, and optimize performance. ### Advanced Overlay Techniques - [Multi-text Overlay Drawing](draw-multitext-onvideoframebuffer/) - This sample demonstrates techniques for rendering multiple text elements on video frames with precise positioning and style control. You'll learn how to handle text formatting, alpha blending, and performance optimization. - [Text Overlay Implementation](text-onvideoframebuffer/) - A focused tutorial on adding dynamic text annotations to video content. This example covers font selection, positioning, and real-time updates of overlay text. - [Image Overlay Integration](image-onvideoframebuffer/) - Learn how to composite images onto video frames with proper scaling, alpha blending, and positioning. This example shows techniques for watermarking, logo placement, and dynamic image overlays. ### Video Transformation - [Manual Zoom Effect Implementation](zoom-onvideoframebuffer/) - This detailed example demonstrates how to implement a custom zoom functionality by directly manipulating video frame buffers. You'll learn techniques for region selection, scaling algorithms, and smooth transitions between zoom levels. ### Bitmap-Based Frame Processing - [OnVideoFrameBitmap Event Usage](onvideoframebitmap-usage/) - This guide explores the bitmap-based approach to video frame processing, which offers simplified access to frame data through GDI+ compatible objects. Learn how this differs from buffer-based processing and when to choose each approach. ## Video Rendering Solutions Displaying video content with flexibility and performance requires understanding various rendering techniques. These samples demonstrate different approaches for visual presentation. ### Windows Forms Integration - [PictureBox Video Rendering](draw-video-picturebox/) - This sample demonstrates how to properly render video content within a standard Windows Forms PictureBox control. You'll learn about frame timing, aspect ratio preservation, and performance considerations. ### Multi-Display Functionality - [Multiple Renderer Zoom Configuration](zoom-video-multiple-renderer/) - Learn techniques for independently controlling zoom levels across multiple video renderers. This sample is essential for applications requiring synchronized but visually distinct video outputs. - [WPF Multi-screen Video Output](multiple-screens-wpf/) - This example shows how to implement multiple independent video display surfaces within a WPF application. You'll learn proper control initialization, resource management, and synchronization techniques. ### Renderer Selection and Customization - [Video Renderer Selection (WinForms)](select-video-renderer-winforms/) - This tutorial explains how to choose and configure the most appropriate video renderer for your Windows Forms application. You'll understand the tradeoffs between EVR, VMR9, and other renderer types. - [Overlaying WPF Controls on Video](wpf-controls-over-video/) - Learn how to place WPF buttons, banners and transport controls on top of the video preview. This guide covers the D3D11 composable renderer, the software `WriteableBitmap` mode, the WPF airspace limitation, and migrating from `WPF_WinUI_Callback` to the X engines. ### User Interaction - [Mouse Wheel Event Integration](mouse-wheel-usage/) - Learn how to handle mouse wheel events for interactive video displays. This sample demonstrates zoom control, timeline scrubbing, and other wheel-based interactions. - [Custom Image Video View](video-view-set-custom-image/) - This guide shows how to replace the standard video frame with a custom image for scenarios like connection loss, buffering states, or application-specific messaging. ## Media Information and Visualization These samples demonstrate how to extract information from media files and create useful visualizations. ### File Analysis - [Media File Information Extraction](read-file-info/) - Learn techniques for reading detailed metadata, stream properties, and format information from media files. This example shows how to access duration, bitrate, codec information, and other essential media properties. ### Audio Visualization - [VU Meter and Waveform Visualization](vu-meters/) - This comprehensive sample demonstrates how to create real-time audio visualizations including volume unit meters and waveform displays. You'll learn about audio level analysis, drawing techniques, and synchronization with playback. ## Performance Optimization Each sample in this collection is designed with performance considerations in mind. You'll find techniques for efficient buffer handling, memory management, and processing optimizations that help you build responsive media applications, even when working with high-resolution content or applying complex effects. ## Cross-Platform Considerations While focusing on .NET implementations, many of the concepts demonstrated in these samples apply to other platforms as well. Where appropriate, we've noted platform-specific considerations and alternative approaches for cross-platform development scenarios. ## Getting Started To use these examples effectively, we recommend reviewing the appropriate SDK documentation for your specific product version. Each sample includes the necessary references and initialization code, but may require configuration based on your development environment and target platform. These code samples serve as building blocks for your media applications, providing proven implementation patterns that you can adapt and extend for your specific requirements. ---END OF PAGE--- ## Mouse Wheel Event Handling in .NET Video Applications **URL:** https://www.visioforge.com/help/docs/dotnet/general/code-samples/mouse-wheel-usage/ **Description:** Handle mouse wheel events in .NET video apps for zooming, scrolling, and timeline navigation with best practices and optimization techniques. **Tags:** Video Capture SDK, Media Player SDK, Video Edit SDK, .NET, Windows, Editing, C# # Implementing Mouse Wheel Events in .NET SDKs [Video Capture SDK .Net](https://www.visioforge.com/video-capture-sdk-net) [Video Edit SDK .Net](https://www.visioforge.com/video-edit-sdk-net) [Media Player SDK .Net](https://www.visioforge.com/media-player-sdk-net) ## Introduction to Mouse Wheel Events Mouse wheel events provide an intuitive way for users to interact with video content in multimedia applications. Whether you're developing a video player, editor, or capture application, implementing proper mouse wheel event handling enhances user experience by allowing smooth zooming, scrolling, or timeline navigation. In .NET applications, the `MouseWheel` event is triggered when the user rotates the mouse wheel. This event provides crucial information about the direction and intensity of the wheel movement through the `MouseEventArgs` parameter. ## Why Implement Mouse Wheel Events? Mouse wheel functionality offers several benefits to your video applications: - **Improved User Experience**: Enables intuitive zoom functionality in video viewers - **Enhanced Navigation**: Allows quick timeline scrubbing in video editors - **Volume Control**: Provides convenient volume adjustment in media players - **Efficient UI Interaction**: Reduces reliance on on-screen controls ## Basic Implementation ### Setting Up Event Handlers To implement mouse wheel functionality in your .NET application, you need to set up three key event handlers: 1. `MouseEnter`: Ensures the control gains focus when the mouse enters 2. `MouseLeave`: Releases focus when the mouse leaves 3. `MouseWheel`: Handles the actual wheel rotation event Here's a basic implementation: ``` private void VideoView1_MouseEnter(object sender, EventArgs e) { if (!VideoView1.Focused) { VideoView1.Focus(); } } private void VideoView1_MouseLeave(object sender, EventArgs e) { if (VideoView1.Focused) { VideoView1.Parent.Focus(); } } private void VideoView1_MouseWheel(object sender, MouseEventArgs e) { mmLog.Text += "Delta: " + e.Delta + Environment.NewLine; } ``` The `MouseWheel` event handler receives a `MouseEventArgs` parameter that includes the `Delta` property. This value indicates the direction and distance the wheel has rotated: - **Positive Delta**: The wheel rotated forward (away from the user) - **Negative Delta**: The wheel rotated backward (toward the user) - **Delta Magnitude**: Indicates the intensity of the rotation ## Advanced Implementation Techniques ### Implementing Zoom Functionality One common use of the mouse wheel in video applications is to zoom in and out. Here's how you might implement zoom functionality: ``` private void VideoView1_MouseWheel(object sender, MouseEventArgs e) { // Determine zoom direction based on delta if (e.Delta > 0) { // Zoom in code ZoomIn(0.1); // Increase zoom by 10% } else { // Zoom out code ZoomOut(0.1); // Decrease zoom by 10% } } private double _zoomRatio = 1.0; private void ZoomIn(double factor) { // Zoom is exposed on the renderer (classic engine) or via a ZoomEffect on the X engine, // not on VideoView. The classic engine uses `videoCapture1.Video_Renderer.Zoom_Ratio` // (and Zoom_ShiftX / Zoom_ShiftY for the centre offset). _zoomRatio = Math.Min(_zoomRatio + factor, 3.0); // Max zoom of 300% videoCapture1.Video_Renderer.Zoom_Ratio = _zoomRatio; videoCapture1.Video_Renderer_Update(); } private void ZoomOut(double factor) { _zoomRatio = Math.Max(_zoomRatio - factor, 0.5); // Min zoom of 50% videoCapture1.Video_Renderer.Zoom_Ratio = _zoomRatio; videoCapture1.Video_Renderer_Update(); } ``` ### Timeline Navigation For video editing applications, the mouse wheel can be used to navigate through the timeline: ``` private void TimelineControl_MouseWheel(object sender, MouseEventArgs e) { // Calculate how much to move based on delta and timeline length double moveFactor = e.Delta / 120.0; // Normalize to increments of 1.0 double moveAmount = moveFactor * 5.0; // 5 seconds per wheel "click" // Move position double newPosition = TimelineControl.CurrentPosition + moveAmount; // Ensure we stay within bounds newPosition = Math.Max(0, Math.Min(newPosition, TimelineControl.Duration)); // Apply the new position TimelineControl.CurrentPosition = newPosition; } ``` ### Volume Control Another common use case is controlling volume in media player applications: ``` private void VideoView1_MouseWheel(object sender, MouseEventArgs e) { // Volume is engine-level (not on VideoView). The classic engine exposes // Audio_OutputDevice_Volume in 0–100 percent range; the X engine exposes // Audio_OutputDevice_Volume in 0.0–1.0 range. Sample below targets the // classic VideoCaptureCore / MediaPlayerCore — adjust the percent math // to a 0–1 ratio if you are on the X engine. int volumeChangePercent = (int)Math.Round(e.Delta / 120.0 * 5.0); // 5 percentage points per wheel "click" int newVolume = videoCapture1.Audio_OutputDevice_Volume + volumeChangePercent; newVolume = Math.Max(0, Math.Min(newVolume, 100)); videoCapture1.Audio_OutputDevice_Volume = newVolume; // Optional: Display volume indicator (0–1 ratio for the indicator UI) ShowVolumeIndicator(newVolume / 100f); } ``` ## Handling Focus Management Proper focus management is crucial for mouse wheel events to work correctly. The example code shows a basic implementation, but in more complex applications, you may need a more sophisticated approach: ``` private void VideoView1_MouseEnter(object sender, EventArgs e) { // Store the previously focused control _previouslyFocused = Form.ActiveControl; // Focus our control VideoView1.Focus(); // Optional: Visual indication that the control has focus VideoView1.BorderStyle = BorderStyle.FixedSingle; } private void VideoView1_MouseLeave(object sender, EventArgs e) { // Return focus to previous control if appropriate if (_previouslyFocused != null && _previouslyFocused.CanFocus) { _previouslyFocused.Focus(); } else { // If no previous control, focus the parent VideoView1.Parent.Focus(); } // Reset visual indication VideoView1.BorderStyle = BorderStyle.None; } ``` ## Performance Considerations When implementing mouse wheel events, consider these performance tips: 1. **Debounce Wheel Events**: Mouse wheels can generate many events in quick succession 2. **Optimize Calculations**: Avoid complex calculations in the wheel event handler 3. **Use Animation**: For smooth zooming, consider using animation rather than abrupt changes Here's an example of debouncing wheel events: ``` private DateTime _lastWheelEvent = DateTime.MinValue; private const int DebounceMs = 50; private void VideoView1_MouseWheel(object sender, MouseEventArgs e) { // Check if enough time has passed since the last event TimeSpan elapsed = DateTime.Now - _lastWheelEvent; if (elapsed.TotalMilliseconds < DebounceMs) { return; // Ignore event if it's too soon } // Process the wheel event ProcessWheelEvent(e.Delta); // Update the last event time _lastWheelEvent = DateTime.Now; } ``` ## Cross-Platform Considerations If you're developing cross-platform .NET applications, be aware that mouse wheel behavior can vary: - **Windows**: Typically 120 units per "click" - **macOS**: May have different sensitivity settings - **Linux**: Can vary based on distribution and configuration Your code should account for these differences: ``` private void VideoView1_MouseWheel(object sender, MouseEventArgs e) { // Normalize delta based on platform double normalizedDelta; if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { normalizedDelta = e.Delta / 120.0; } else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) { normalizedDelta = e.Delta / 100.0; } else { normalizedDelta = e.Delta / 120.0; // Default for Linux and others } // Use normalized delta for calculations ApplyZoom(normalizedDelta); } ``` ## Troubleshooting Common Issues ### Mouse Wheel Events Not Firing If your mouse wheel events aren't firing, check: 1. **Focus Issues**: Ensure the control has focus when the mouse is over it 2. **Event Registration**: Verify the event handler is properly registered 3. **Control Properties**: Some controls need specific properties set to receive wheel events ### Inconsistent Behavior If wheel events behave inconsistently: 1. **Delta Normalization**: Ensure you're properly normalizing delta values 2. **User Settings**: Account for user-specific mouse settings 3. **Hardware Variations**: Different mouse hardware can produce different delta values ## Conclusion Mouse wheel event handling is an essential aspect of creating intuitive and user-friendly video applications. By implementing the techniques outlined in this guide, you can enhance your .NET video applications with smooth, intuitive controls that improve the overall user experience. The implementation can vary depending on your specific requirements, but the core principles remain the same: handle focus properly, normalize wheel delta values, and apply appropriate changes based on user input. --- Visit our [GitHub](https://github.com/visioforge/.Net-SDK-s-samples) page to get more code samples. ---END OF PAGE--- ## Multiple Video Screens in WPF — C# .NET Multi-Display Guide **URL:** https://www.visioforge.com/help/docs/dotnet/general/code-samples/multiple-screens-wpf/ **Description:** Create multi-display video applications in WPF with Image controls, event handling, memory management, and performance optimization techniques. **Tags:** Video Capture SDK, Media Player SDK, Video Edit SDK, .NET, Windows, WPF, C# **API:** VideoCaptureCore, VideoCaptureSource, VideoFrameBufferEventArgs, MultiscreenVideoView, VideoView # Implementing Multiple Video Output Screens in WPF Applications [Video Capture SDK .Net](https://www.visioforge.com/video-capture-sdk-net) [Video Edit SDK .Net](https://www.visioforge.com/video-edit-sdk-net) [Media Player SDK .Net](https://www.visioforge.com/media-player-sdk-net) When developing WPF applications that require handling multiple video feeds simultaneously, developers often face challenges with performance, synchronization, and resource management. This guide provides a comprehensive approach to implementing multiple video output screens in your WPF applications using C# and the Image control. ## Getting Started with Multiple Video Screens Check the installation guide for WPF [here](../../../install/). To begin implementing multiple video outputs in your WPF application, you'll need to: 1. Add the appropriate Video View control to your application 2. Set up event handling for video frame processing 3. Configure your rendering pipeline for optimal performance ### Two supported patterns To show the same video feed on multiple views in WPF, pick one of these two real patterns: 1. **`MultiscreenVideoView` + `OnVideoFrameBuffer`** — one SDK engine pushes each frame into as many `MultiscreenVideoView` controls as you like. Use this when a single capture/playback engine drives several on-screen copies. 2. **One engine per `VideoView`** — each display gets its own `VideoCaptureCore` / `MediaPlayerCore` / `VideoEditCore` instance bound to its own regular `VideoView`. Use this when the displays show **different** sources (e.g. a four-camera security grid). See the [Four-Camera Security System](#practical-example-four-camera-security-system) example below. Regular `VisioForge.Core.UI.WPF.VideoView` does not expose a `RenderFrame` method — it is driven automatically by the engine it's bound to via `CreateAsync(IVideoView)`. Frame fan-out requires `MultiscreenVideoView`. ### Setting Up Your WPF Project for Frame Fan-out Drop one or more `VisioForge.Core.UI.WPF.MultiscreenVideoView` controls on your WPF window. Give them descriptive names (e.g. `multiView1`, `multiView2`). These are the controls that accept pushed frames. ### Handling Video Frames Subscribe to the SDK engine's `OnVideoFrameBuffer` event. The event args carry a `VideoFrameBufferEventArgs` that each `MultiscreenVideoView` can render. ## Implementing the Video Frame Handler ``` private void VideoCapture1_OnVideoFrameBuffer(object sender, VideoFrameBufferEventArgs e) { multiView1.RenderFrame(e); } ``` `MultiscreenVideoView.RenderFrame(VideoFrameBufferEventArgs)` copies the frame into its own internal surface, so the engine's buffer can be released when the handler returns. ## Advanced Implementation Techniques ### Creating Dynamic MultiscreenVideoViews For applications requiring a variable number of video outputs, dynamically create `MultiscreenVideoView` controls: ``` private List multiViews = new List(); private void CreateMultiView(Grid container, int row, int column) { var view = new VisioForge.Core.UI.WPF.MultiscreenVideoView(); Grid.SetRow(view, row); Grid.SetColumn(view, column); container.Children.Add(view); multiViews.Add(view); } // Usage example: // CreateMultiView(mainGrid, 0, 0); // CreateMultiView(mainGrid, 0, 1); ``` ### Distributing Video Frames to Multiple Views Fan out incoming frames to every registered `MultiscreenVideoView`: ``` private void VideoCapture1_OnVideoFrameBuffer(object sender, VideoFrameBufferEventArgs e) { // Render to all MultiscreenVideoView instances foreach (var view in multiViews) { view.RenderFrame(e); } } ``` ## Performance Optimization Strategies ### Reducing Render Load For multiple video views, consider these optimization techniques: 1. **Frame skipping**: Not every view needs to update at full frame rate 2. **Hide off-screen views**: WPF culls rendering for collapsed controls — use `Visibility.Collapsed` on views that aren't visible ``` private int frameCounter; private void VideoCapture1_OnVideoFrameBuffer(object sender, VideoFrameBufferEventArgs e) { // Primary view gets every frame primaryMultiView.RenderFrame(e); // Secondary views get every second frame if (frameCounter % 2 == 0) { foreach (var view in secondaryMultiViews) { view.RenderFrame(e); } } frameCounter++; } ``` ## Practical Example: Four-Camera Security System Here's a more complete example of implementing a four-camera security system using the Video Capture SDK's `VideoCaptureCore` engine. Each camera gets its own engine instance bound to a dedicated `VideoView`. ``` using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using VisioForge.Core.Types; using VisioForge.Core.Types.VideoCapture; using VisioForge.Core.UI.WPF; using VisioForge.Core.VideoCapture; public partial class SecurityMonitorWindow : Window { private readonly List _cameraViews = new List(); private readonly List _cameras = new List(); public SecurityMonitorWindow() { InitializeComponent(); } public async Task InitializeCamerasAsync(IEnumerable deviceNames) { // Enumerate the first four capture devices if names aren't provided. var names = deviceNames?.Take(4).ToList(); // Build a 2x2 grid of VideoView controls paired with VideoCaptureCore engines. int i = 0; for (int row = 0; row < 2; row++) { for (int col = 0; col < 2; col++, i++) { var view = new VideoView(); Grid.SetRow(view, row); Grid.SetColumn(view, col); mainGrid.Children.Add(view); _cameraViews.Add(view); // The classic engine uses a constructor; CreateAsync is the X-engine pattern. // For VideoCaptureCoreX use `await VideoCaptureCoreX.CreateAsync(view)` instead. var camera = new VideoCaptureCore(view); _cameras.Add(camera); if (names != null && i < names.Count) { camera.Video_CaptureDevice = new VideoCaptureSource(names[i]); camera.Video_CaptureDevice.Format_UseBest = true; camera.Mode = VideoCaptureMode.VideoPreview; camera.Audio_PlayAudio = false; camera.Audio_RecordAudio = false; } } } } public async Task StartCamerasAsync() { foreach (var camera in _cameras) { await camera.StartAsync(); } } public async Task StopCamerasAsync() { foreach (var camera in _cameras) { await camera.StopAsync(); } foreach (var camera in _cameras) { camera.Dispose(); } } } ``` Enumerate available devices with `camera.Video_CaptureDevices()` (or its async variant) to populate the `deviceNames` argument at runtime — see [the device enumeration guide](../../../videocapture/video-sources/video-capture-devices/enumerate-and-select/). ## Troubleshooting Common Issues ### Handling Frame Synchronization If you experience frame timing issues across multiple displays: ``` private readonly object syncLock = new object(); private void VideoCapture1_OnVideoFrameBuffer(object sender, VideoFrameBufferEventArgs e) { lock (syncLock) { foreach (var view in multiViews) { view.RenderFrame(e); } } } ``` --- For more code samples and advanced implementation techniques, visit our [GitHub repository](https://github.com/visioforge/.Net-SDK-s-samples). ---END OF PAGE--- ## OnVideoFrameBitmap — Real-Time Video Frame Access in .NET **URL:** https://www.visioforge.com/help/docs/dotnet/general/code-samples/onvideoframebitmap-usage/ **Description:** Access and modify video frames in real-time with OnVideoFrameBitmap events for advanced video manipulation in C# applications. **Tags:** Video Capture SDK, Media Player SDK, Video Edit SDK, .NET, Windows, C# **API:** VideoFrameBitmapEventArgs # OnVideoFrameBitmap Real-Time Frame Guide [Video Capture SDK .Net](https://www.visioforge.com/video-capture-sdk-net) [Video Edit SDK .Net](https://www.visioforge.com/video-edit-sdk-net) [Media Player SDK .Net](https://www.visioforge.com/media-player-sdk-net) The `OnVideoFrameBitmap` event is a powerful feature in .NET video processing libraries that allows developers to access and modify video frames in real-time. This guide explores the practical applications, implementation techniques, and performance considerations when working with bitmap frame manipulation in C# applications. ## Understanding OnVideoFrameBitmap Events The `OnVideoFrameBitmap` event provides a direct interface to access video frames as they're processed by the SDK. This capability is essential for applications that require: - Real-time video analysis - Frame-by-frame manipulation - Dynamic overlay implementation - Custom video effects - Computer vision integration When the event fires, it delivers a bitmap representation of the current video frame, allowing for pixel-level access and manipulation before the frame continues through the processing pipeline. ## Basic Implementation `OnVideoFrameBitmap` exists on the Windows-only engines: `VideoCaptureCore`, `MediaPlayerCore`, and `VideoEditCore`. In the snippets below, `VideoCapture1` is a `VideoCaptureCore` instance — swap in `MediaPlayer1` or `VideoEdit1` if you are using a different engine. Subscribe before starting the pipeline so the first frame is not missed: ``` // Event type: EventHandler. Fires on a worker thread. VideoCapture1.OnVideoFrameBitmap += VideoCapture1_OnVideoFrameBitmap; // Implement the event handler private void VideoCapture1_OnVideoFrameBitmap(object sender, VideoFrameBitmapEventArgs e) { // e.Frame — the current frame as a System.Drawing.Bitmap (owned by the SDK; do not dispose). // Set e.UpdateData = true if you mutate the bitmap in place. } ``` ## Manipulating Video Frames ### Simple Bitmap Overlay Example The following example demonstrates how to overlay an image on each video frame: ``` Bitmap bmp = new Bitmap(@"c:\samples\pics\1.jpg"); using (Graphics g = Graphics.FromImage(e.Frame)) { g.DrawImage(bmp, 0, 0, bmp.Width, bmp.Height); e.UpdateData = true; } bmp.Dispose(); ``` In this code: 1. We create a `Bitmap` object from an image file 2. We use the `Graphics` class to draw onto the frame bitmap 3. We set `e.UpdateData = true` to inform the SDK that we've modified the frame 4. We dispose of our resources properly to prevent memory leaks > **Important:** Always set `e.UpdateData = true` when you modify the frame bitmap. This signals the SDK to use your modified frame instead of the original. ### Adding Text Overlays Text overlays are commonly used for timestamps, captions, or informational displays: ``` using (Graphics g = Graphics.FromImage(e.Frame)) { // Create a semi-transparent background for text using (SolidBrush brush = new SolidBrush(Color.FromArgb(150, 0, 0, 0))) { g.FillRectangle(brush, 10, 10, 200, 30); } // Add text overlay using (Font font = new Font("Arial", 12)) using (SolidBrush textBrush = new SolidBrush(Color.White)) { g.DrawString(DateTime.Now.ToString(), font, textBrush, new PointF(15, 15)); } e.UpdateData = true; } ``` ## Performance Considerations When working with `OnVideoFrameBitmap`, it's crucial to optimize your code for performance. Each frame processing operation must complete quickly to maintain smooth video playback. ### Resource Management Proper resource management is essential: ``` // Poor performance approach private void VideoCapture1_OnVideoFrameBitmap(object sender, VideoFrameBitmapEventArgs e) { Bitmap overlay = new Bitmap(@"c:\logo.png"); Graphics g = Graphics.FromImage(e.Frame); g.DrawImage(overlay, 0, 0); e.UpdateData = true; // Memory leak! Graphics and Bitmap not disposed } // Optimized approach private Bitmap _cachedOverlay; private void InitializeResources() { _cachedOverlay = new Bitmap(@"c:\logo.png"); } private void VideoCapture1_OnVideoFrameBitmap(object sender, VideoFrameBitmapEventArgs e) { using (Graphics g = Graphics.FromImage(e.Frame)) { g.DrawImage(_cachedOverlay, 0, 0); e.UpdateData = true; } } private void CleanupResources() { _cachedOverlay?.Dispose(); } ``` ### Optimizing Processing Time To maintain smooth video playback: 1. **Pre-compute where possible**: Prepare resources before processing begins 2. **Cache frequently used objects**: Avoid creating new objects for each frame 3. **Process only when necessary**: Add conditional logic to skip frames or perform less intensive operations when needed 4. **Use efficient drawing operations**: Choose appropriate GDI+ methods based on your needs ``` private void VideoCapture1_OnVideoFrameBitmap(object sender, VideoFrameBitmapEventArgs e) { // Only process every second frame if (_frameCounter % 2 == 0) { using (Graphics g = Graphics.FromImage(e.Frame)) { // Your frame processing code e.UpdateData = true; } } _frameCounter++; } ``` ## Advanced Frame Manipulation Techniques ### Applying Filters and Effects You can implement custom image processing filters: ``` private void ApplyGrayscaleFilter(Bitmap bitmap) { Rectangle rect = new Rectangle(0, 0, bitmap.Width, bitmap.Height); BitmapData bmpData = bitmap.LockBits(rect, ImageLockMode.ReadWrite, bitmap.PixelFormat); IntPtr ptr = bmpData.Scan0; int bytes = Math.Abs(bmpData.Stride) * bitmap.Height; byte[] rgbValues = new byte[bytes]; Marshal.Copy(ptr, rgbValues, 0, bytes); // Process pixel data for (int i = 0; i < rgbValues.Length; i += 4) { byte gray = (byte)(0.299 * rgbValues[i + 2] + 0.587 * rgbValues[i + 1] + 0.114 * rgbValues[i]); rgbValues[i] = gray; // Blue rgbValues[i + 1] = gray; // Green rgbValues[i + 2] = gray; // Red } Marshal.Copy(rgbValues, 0, ptr, bytes); bitmap.UnlockBits(bmpData); } ``` ## Integration with Computer Vision Libraries The `OnVideoFrameBitmap` event can be combined with popular computer vision libraries: ``` // Example using a hypothetical computer vision library private void VideoCapture1_OnVideoFrameBitmap(object sender, VideoFrameBitmapEventArgs e) { // Convert bitmap to format needed by CV library byte[] imageData = ConvertBitmapToByteArray(e.Frame); // Process with CV library var results = _computerVisionProcessor.DetectFaces(imageData, e.Frame.Width, e.Frame.Height); // Draw results back onto frame using (Graphics g = Graphics.FromImage(e.Frame)) { foreach (var face in results) { g.DrawRectangle(new Pen(Color.Yellow, 2), face.X, face.Y, face.Width, face.Height); } e.UpdateData = true; } } ``` ## Troubleshooting Common Issues ### Memory Leaks If you experience memory growth during prolonged video processing: 1. Ensure all `Graphics` objects are disposed 2. Properly dispose of any temporary `Bitmap` objects 3. Avoid capturing large objects in lambda expressions ### Performance Degradation If frame processing becomes sluggish: 1. Profile your event handler to identify bottlenecks 2. Consider reducing processing frequency 3. Optimize GDI+ operations or consider DirectX for performance-critical applications ## SDK Integration The `OnVideoFrameBitmap` event is available in the following SDKs: ## Required Dependencies To use the functionality described in this guide, you'll need: - SDK redistribution package - System.Drawing (included in .NET Framework) - Windows GDI+ support --- Visit our [GitHub](https://github.com/visioforge/.Net-SDK-s-samples) page to get more code samples and projects demonstrating these techniques in action. ---END OF PAGE--- ## Read Video File Info in C# .NET — Duration, Codec, Streams **URL:** https://www.visioforge.com/help/docs/dotnet/general/code-samples/read-file-info/ **Description:** MediaInfoReader API returns video/audio stream details, subtitle tracks, FOURCC codes, and ID3 tags. Cross-platform file analysis with VisioForge SDK. **Tags:** Video Capture SDK, Media Player SDK, Video Edit SDK, .NET, Windows, Metadata, MP4, C# **API:** MediaInfoReader # Reading Media File Information in C [Video Capture SDK .Net](https://www.visioforge.com/video-capture-sdk-net) [Video Edit SDK .Net](https://www.visioforge.com/video-edit-sdk-net) [Media Player SDK .Net](https://www.visioforge.com/media-player-sdk-net) ## Introduction Accessing detailed information embedded within media files is essential for developing sophisticated applications like media players, video editors, content management systems, and file analysis tools. Understanding properties such as codecs, resolution, frame rate, bitrate, duration, and embedded tags allows developers to build more intelligent and user-friendly software. This guide demonstrates how to read comprehensive information from video and audio files using C# and the `MediaInfoReader` class. The techniques shown are applicable across various .NET projects and provide a foundation for handling media files programmatically. ## Why Extract Media File Information? Media file information serves multiple purposes in application development: - **User Experience**: Display technical details to users in media players - **Compatibility Checks**: Verify if files meet required specifications - **Automated Processing**: Configure encoding parameters based on source properties - **Content Organization**: Catalog media libraries with accurate metadata - **Quality Assessment**: Evaluate media files for potential issues ## Implementation Guide Let's explore the process of extracting media file information in a step-by-step approach. The examples assume a WinForms application with a `TextBox` control named `mmInfo` for displaying the extracted information. ### Step 1: Initialize the Media Information Reader The first step involves creating an instance of the `MediaInfoReader` class: ``` // Import the necessary namespace using VisioForge.Core.MediaInfo; // Namespace for MediaInfoReader using VisioForge.Core.Helpers; // Namespace for TagLibHelper (optional) // Create an instance of MediaInfoReader var infoReader = new MediaInfoReader(); ``` This initialization prepares the reader to process media files. ### Step 2: Verify File Playability (Optional) Before diving into detailed analysis, it's often useful to check if the file is supported: ``` // Define variables to hold potential error information FilePlaybackError errorCode; string errorText; // Specify the path to the media file string filename = @"C:\path\to\your\mediafile.mp4"; // Replace with your actual file path // Check if the file is playable if (MediaInfoReader.IsFilePlayable(filename, out errorCode, out errorText)) { // Display success message mmInfo.Text += "Status: This file appears to be playable." + Environment.NewLine; } else { // Display error message including the error code and description mmInfo.Text += $"Status: This file might not be playable. Error: {errorCode} - {errorText}" + Environment.NewLine; } mmInfo.Text += "------------------------------------" + Environment.NewLine; ``` This verification provides early feedback on file integrity and compatibility. ### Step 3: Extract Detailed Stream Information Now we can extract the rich metadata from the file: ``` try { // Assign the filename to the reader infoReader.Filename = filename; // Read the file information (true for full analysis) infoReader.ReadFileInfo(true); // Process Video Streams mmInfo.Text += $"Found {infoReader.VideoStreams.Count} video stream(s)." + Environment.NewLine; for (int i = 0; i < infoReader.VideoStreams.Count; i++) { var stream = infoReader.VideoStreams[i]; mmInfo.Text += Environment.NewLine; mmInfo.Text += $"--- Video Stream #{i + 1} ---" + Environment.NewLine; mmInfo.Text += $" Codec: {stream.Codec}" + Environment.NewLine; mmInfo.Text += $" Duration: {stream.Duration}" + Environment.NewLine; mmInfo.Text += $" Dimensions: {stream.Width}x{stream.Height}" + Environment.NewLine; mmInfo.Text += $" FOURCC: {stream.FourCC}" + Environment.NewLine; if (stream.AspectRatio != null && stream.AspectRatio.Item1 > 0 && stream.AspectRatio.Item2 > 0) { mmInfo.Text += $" Aspect Ratio: {stream.AspectRatio.Item1}:{stream.AspectRatio.Item2}" + Environment.NewLine; } // VideoFrameRate is a struct (numerator/denominator) and not IFormattable — format via .Value (double). mmInfo.Text += $" Frame Rate: {stream.FrameRate.Value:F2} fps" + Environment.NewLine; mmInfo.Text += $" Bitrate: {stream.Bitrate / 1000.0:F0} kbps" + Environment.NewLine; mmInfo.Text += $" Frames Count: {stream.FramesCount}" + Environment.NewLine; } // Process Audio Streams mmInfo.Text += Environment.NewLine; mmInfo.Text += $"Found {infoReader.AudioStreams.Count} audio stream(s)." + Environment.NewLine; for (int i = 0; i < infoReader.AudioStreams.Count; i++) { var stream = infoReader.AudioStreams[i]; mmInfo.Text += Environment.NewLine; mmInfo.Text += $"--- Audio Stream #{i + 1} ---" + Environment.NewLine; mmInfo.Text += $" Codec: {stream.Codec}" + Environment.NewLine; mmInfo.Text += $" Codec Info: {stream.CodecInfo}" + Environment.NewLine; mmInfo.Text += $" Duration: {stream.Duration}" + Environment.NewLine; mmInfo.Text += $" Bitrate: {stream.Bitrate / 1000.0:F0} kbps" + Environment.NewLine; mmInfo.Text += $" Channels: {stream.Channels}" + Environment.NewLine; mmInfo.Text += $" Sample Rate: {stream.SampleRate} Hz" + Environment.NewLine; mmInfo.Text += $" Bits Per Sample (BPS): {stream.BPS}" + Environment.NewLine; mmInfo.Text += $" Language: {stream.Language}" + Environment.NewLine; } // Process Subtitle Streams mmInfo.Text += Environment.NewLine; mmInfo.Text += $"Found {infoReader.Subtitles.Count} subtitle stream(s)." + Environment.NewLine; for (int i = 0; i < infoReader.Subtitles.Count; i++) { var stream = infoReader.Subtitles[i]; mmInfo.Text += Environment.NewLine; mmInfo.Text += $"--- Subtitle Stream #{i + 1} ---" + Environment.NewLine; mmInfo.Text += $" Codec/Format: {stream.Codec}" + Environment.NewLine; mmInfo.Text += $" Name: {stream.Name}" + Environment.NewLine; mmInfo.Text += $" Language: {stream.Language}" + Environment.NewLine; } } catch (Exception ex) { // Handle potential errors during file reading mmInfo.Text += $"{Environment.NewLine}Error reading file info: {ex.Message}{Environment.NewLine}"; } finally { // Important: Dispose the reader to release file handles and resources infoReader.Dispose(); } ``` The code iterates through each collection (`VideoStreams`, `AudioStreams`, and `Subtitles`), extracting and displaying relevant information for every stream found. ### Step 4: Extract Metadata Tags Beyond technical stream information, media files often contain metadata tags: ``` // Read Metadata Tags mmInfo.Text += Environment.NewLine + "--- Metadata Tags ---" + Environment.NewLine; try { // Use TagLibHelper to read tags from the file var tags = TagLibHelper.ReadTags(filename); // Check if tags were successfully read if (tags != null) { mmInfo.Text += $"Title: {tags.Title}" + Environment.NewLine; mmInfo.Text += $"Artist(s): {string.Join(", ", tags.Performers ?? new string[0])}" + Environment.NewLine; mmInfo.Text += $"Album: {tags.Album}" + Environment.NewLine; mmInfo.Text += $"Year: {tags.Year}" + Environment.NewLine; mmInfo.Text += $"Genre: {string.Join(", ", tags.Genres ?? new string[0])}" + Environment.NewLine; mmInfo.Text += $"Comment: {tags.Comment}" + Environment.NewLine; } else { mmInfo.Text += "No standard metadata tags found or readable." + Environment.NewLine; } } catch (Exception ex) { // Handle errors during tag reading mmInfo.Text += $"Error reading tags: {ex.Message}" + Environment.NewLine; } ``` ## Best Practices for Media File Analysis When implementing media file analysis in your applications, consider these best practices: ### Error Handling Always wrap file operations in appropriate try-catch blocks. Media files can be corrupted, inaccessible, or in unexpected formats, which might cause exceptions. ``` try { // Media file operations } catch (Exception ex) { // Log error and provide user feedback } ``` ### Resource Management Properly dispose of objects that access file resources to prevent file locking issues: ``` using (var infoReader = new MediaInfoReader()) { // Use the reader } // Or manually in a finally block try { // Operations } finally { infoReader.Dispose(); } ``` ### Performance Considerations For large media libraries, consider: 1. Implementing caching mechanisms for repeated analysis 2. Using background threads for processing to keep UI responsive 3. Limiting the depth of analysis for initial quick scans ## Required Components For successful implementation, ensure your project includes the necessary dependencies as specified in the SDK documentation. ## Conclusion Extracting information from media files is a powerful capability for developers building applications that work with audio and video content. With the techniques outlined in this guide, you can access detailed technical properties and metadata tags to enhance your application's functionality. The `MediaInfoReader` class provides a convenient and efficient way to extract the necessary metadata, allowing you to build more sophisticated media handling features in your C# applications. For more advanced scenarios, explore the full capabilities of the SDK and consult the detailed documentation. You can find additional code samples and examples on GitHub to further expand your media file processing capabilities. ---END OF PAGE--- ## Video Renderer in C# .NET — EVR, Direct2D, WPF, MadVR **URL:** https://www.visioforge.com/help/docs/dotnet/general/code-samples/select-video-renderer-winforms/ **Description:** Configure video rendering in C# / .NET across WinForms, WPF, and WinUI 3. EVR, Direct2D, madVR, native HWND, callback modes — setup and hardware acceleration. **Tags:** Video Capture SDK, Media Player SDK, Video Edit SDK, .NET, DirectShow, MediaPlayerCoreX, VideoCaptureCoreX, VideoEditCore, Windows, macOS, Linux, Android, iOS, GStreamer, Capture, Playback, Streaming, Encoding, Editing, Conversion, C# **API:** VideoRenderer, VideoRendererMode, VideoView, VideoRendererStretchMode, VideoCaptureCoreX # Video Renderer Options in C# .NET [Video Capture SDK .Net](https://www.visioforge.com/video-capture-sdk-net) [Video Edit SDK .Net](https://www.visioforge.com/video-edit-sdk-net) [Media Player SDK .Net](https://www.visioforge.com/media-player-sdk-net) ## Introduction The classic engines (`VideoCaptureCore`, `VideoEditCore`, `MediaPlayerCore`) expose **10 video renderer modes** through the `VideoRendererMode` enum. Choosing the right one controls how frames reach the screen: raw DirectShow filters, Direct2D GPU surfaces, native HWND embedded in WPF, frame callbacks for custom rendering, WinUI 3 controls, or the third-party madVR renderer. This guide walks through each mode with minimal enable code, platform availability, and a decision guide at the top so you can skip straight to the mode your app needs. Classic engines only This page covers the DirectShow-based classic engines. The cross-platform `VideoCaptureCoreX` / `MediaPlayerCoreX` engines use a `VideoView` control with GStreamer sinks and do not expose a `VideoRendererMode` enum on the engine — the render mode is selected on the `VideoView` control itself. See [Overlaying WPF Controls on Video](../wpf-controls-over-video/) for the WPF render modes of both engine families. ## Quick pick — which renderer for which app? | Mode | UI framework | Best for | | --- | --- | --- | | `VideoRenderer` (legacy GDI) | WinForms | Maximum compatibility on very old hardware | | `VMR9` | WinForms | Windows XP / Vista, software + light HW accel | | `EVR` | WinForms | Default pick on modern Windows (Vista+) | | `Direct2D` | WinForms, WPF | GPU-accelerated 2D, 4K+ content, modern apps | | `Direct2DManaged` | WPF | Managed Direct2D with WPF-aware pause on minimize | | `WPF_NativeHWND` | WPF | Native HWND embedded in WPF for higher perf than pure WPF | | `WPF_WinUI_Callback` (`FrameCallback`) | WPF, WinUI, custom | Per-frame callbacks for CV, AI, custom rendering | | `WinUI` | WinUI 3 | Native WinUI 3 apps (Windows 10/11) | | `MadVR` | WinForms | Reference-grade scaling + color, needs external madVR install | | `None` | any | Headless / audio-only / file conversion without preview | ## Understanding Available Video Renderer Options The detailed sections below describe each mode, starting with the three classic DirectShow renderers. ### Legacy Video Renderer (GDI-based) The Video Renderer is the oldest option in the DirectShow ecosystem. It relies on GDI (Graphics Device Interface) for drawing operations. **Key characteristics:** - Software-based rendering without hardware acceleration - Compatible with older systems and configurations - Lower performance ceiling compared to modern alternatives - Simple implementation with minimal configuration options **Implementation example:** ``` VideoCapture1.Video_Renderer.VideoRenderer = VideoRendererMode.VideoRenderer; ``` **When to use:** - Compatibility is the primary concern - Application targets older hardware or operating systems - Minimal video processing requirements - Troubleshooting issues with newer renderers ### Video Mixing Renderer 9 (VMR9) VMR9 represents a significant improvement over the legacy renderer, introducing support for hardware acceleration and advanced features. **Key characteristics:** - Hardware-accelerated rendering through DirectX 9 - Support for multiple video streams mixing - Advanced deinterlacing options - Alpha blending and compositing capabilities - Custom video effects processing **Implementation example:** ``` VideoCapture1.Video_Renderer.VideoRenderer = VideoRendererMode.VMR9; ``` **When to use:** - Modern applications requiring good performance - Video editing or composition features are needed - Multiple video stream scenarios - Applications that need to balance performance and compatibility ### Enhanced Video Renderer (EVR) EVR is the most advanced option, available in Windows Vista and later operating systems. It leverages the Media Foundation framework rather than pure DirectShow. **Key characteristics:** - Latest hardware acceleration technologies - Superior video quality and performance - Enhanced color space processing - Better multi-monitor support - More efficient CPU usage - Improved synchronization mechanisms **Implementation example:** ``` VideoCapture1.Video_Renderer.VideoRenderer = VideoRendererMode.EVR; ``` **When to use:** - Modern applications targeting Windows Vista or later - Maximum performance and quality are required - Applications handling HD or 4K content - When advanced synchronization is important - Multiple display environments ### Direct2D Renderer Direct2D provides high-performance 2D rendering with GPU acceleration. It is available on both WinForms and WPF hosts and is the recommended modern choice when you need hardware-accelerated rendering with simple rotation, flip, and stretch controls. **Key characteristics:** - Hardware-accelerated via Direct2D / Direct3D 11 - Works on both WinForms and WPF - Supports rotation (0 / 90 / 180 / 270), horizontal and vertical flip - Clean stretch mode integration (`Stretch` / `Letterbox`) - Low CPU overhead, scales well to 4K / 8K content **Implementation example:** ``` VideoCapture1.Video_Renderer.VideoRenderer = VideoRendererMode.Direct2D; VideoCapture1.Video_Renderer.RotationAngle = 0; VideoCapture1.Video_Renderer.StretchMode = VideoRendererStretchMode.Letterbox; VideoCapture1.Video_Renderer.Flip_Horizontal = false; VideoCapture1.Video_Renderer.Flip_Vertical = false; await VideoCapture1.Video_Renderer_UpdateAsync(); ``` **When to use:** - Modern WinForms or WPF apps that want GPU-accelerated rendering - 4K / 8K sources where CPU-based paths would bottleneck - Apps that need run-time rotation or flip controls ### Direct2DManaged Renderer (WPF) A WPF-specific managed variant of Direct2D. Integrates more cleanly with the WPF object model and automatically pauses rendering when the window is minimized — useful for long-running playback apps where you don't want GPU work on hidden windows. **Implementation example:** ``` VideoCapture1.Video_Renderer.VideoRenderer = VideoRendererMode.Direct2DManaged; VideoCapture1.Video_Renderer.StretchMode = VideoRendererStretchMode.Letterbox; await VideoCapture1.Video_Renderer_UpdateAsync(); ``` Rotation, flip, and stretch options are shared with the regular `Direct2D` mode. Pause-on-minimize is handled automatically by the WPF `VideoView` control. **When to use:** - WPF apps where you want Direct2D performance with WPF-friendly lifecycle - Multi-window dashboards where inactive windows should not consume GPU cycles ### WPF Native HWND Renderer Hosts a native Win32 HWND inside the WPF `VideoView` control. Gives you raw DirectShow renderer performance in a WPF layout at the cost of standard WPF-render-chain quirks (airspace issues with overlapping controls). **Implementation example:** ``` VideoCapture1.Video_Renderer.VideoRenderer = VideoRendererMode.WPF_NativeHWND; await VideoCapture1.Video_Renderer_UpdateAsync(); ``` **When to use:** - WPF apps that need maximum DirectShow rendering performance - Apps embedding legacy filters that expect a HWND target - You don't need to overlay WPF controls on top of the video surface ### FrameCallback Renderer (WPF\_WinUI\_Callback) A callback-based rendering mode. Instead of drawing frames directly, the engine delivers each frame to your code via events, letting you render with any library (SkiaSharp, `System.Drawing`, custom OpenGL/DirectX, WriteableBitmap) or feed a non-visual pipeline (computer vision, AI inference, streaming to a remote endpoint). `FrameCallback` is an alias for `WPF_WinUI_Callback` — the same mode with a more self-descriptive name. **Implementation example:** ``` VideoCapture1.Video_Renderer.VideoRenderer = VideoRendererMode.FrameCallback; await VideoCapture1.Video_Renderer_UpdateAsync(); // Subscribe to frame events VideoCapture1.OnVideoFrameBitmap += (sender, e) => { // e.Frame is a System.Drawing.Bitmap — render to a PictureBox, WriteableBitmap, etc. }; VideoCapture1.OnVideoFrameBuffer += (sender, e) => { // e.Frame.Data is IntPtr — wrap with SkiaSharp / Marshal.Copy for pixel-level work }; ``` See [Image drawing via OnVideoFrameBuffer](../image-onvideoframebuffer/) and [Text drawing via OnVideoFrameBuffer](../text-onvideoframebuffer/) for detailed per-frame processing examples. **When to use:** - Computer-vision / ML pipelines that consume raw frames - Custom rendering with SkiaSharp, DirectX, or OpenGL - WPF / WinUI / MAUI apps that render into a `WriteableBitmap` manually - Apps with no preview surface at all (frames shipped to a server, encoder, etc.) ### WinUI 3 Renderer Native rendering for WinUI 3 apps on Windows 10/11. Use this mode when your shell is `Microsoft.UI.Xaml` and you host a `VisioForge.Core.UI.WinUI.VideoView` control. **Implementation example:** ``` VideoCapture1.Video_Renderer.VideoRenderer = VideoRendererMode.WinUI; await VideoCapture1.Video_Renderer_UpdateAsync(); ``` **When to use:** - WinUI 3 apps (Windows App SDK, not the old WinUI 2 / UWP) - You want native look-and-feel consistency with other WinUI content ### madVR Renderer (third-party) [madVR](https://madvr.com/) is a reference-quality external video renderer popular with home-theatre PCs and high-end video software. It delivers superior scaling algorithms, color management, and deinterlacing at the cost of higher GPU load. Supported only on WinForms hosts; requires a separate madVR installation on the target machine (the CLSID-registered DirectShow filter must be present). **Implementation example:** ``` VideoCapture1.Video_Renderer.VideoRenderer = VideoRendererMode.MadVR; await VideoCapture1.Video_Renderer_UpdateAsync(); ``` **Runtime requirement:** ensure madVR is installed on the target system. If the filter is missing, `Video_Renderer_UpdateAsync` will fail — use the fallback pattern shown in [Renderer Compatibility Problems](#renderer-compatibility-problems) below to degrade gracefully to EVR. **When to use:** - Reference-grade video quality for mastering, HTPC, or media server UIs - Audiences with GPUs that can absorb the extra rendering cost - You can ship / document a separate madVR install step ### None (headless) Disables rendering entirely. The capture / edit / playback graph still runs — frames flow to encoders, file outputs, streaming endpoints, or callbacks — but no preview surface is allocated. **Implementation example:** ``` VideoCapture1.Video_Renderer.VideoRenderer = VideoRendererMode.None; await VideoCapture1.Video_Renderer_UpdateAsync(); ``` **When to use:** - Audio-only capture (microphone-to-file) when the SDK has both audio and video branches - File conversion / transcoding without a preview window - Server-side rendering pipelines - Unit tests and headless CI runs ## Advanced Configuration Options Beyond just selecting a renderer, the SDK provides various configuration options to fine-tune video presentation. ### Working with Deinterlacing Modes When displaying interlaced video content (common in broadcast sources), proper deinterlacing improves visual quality significantly. The SDK supports various deinterlacing algorithms depending on the renderer chosen. First, retrieve the available deinterlacing modes. `Video_Renderer_Deinterlace_Modes()` returns the VMR-9 mode names auto-discovered from the current driver: ``` // Populate a dropdown with the available VMR-9 modes foreach (string deinterlaceMode in VideoCapture1.Video_Renderer_Deinterlace_Modes()) { cbDeinterlaceModes.Items.Add(deinterlaceMode); } ``` Deinterlacing is configured on the two renderers separately. VMR-9 takes a mode-name string; EVR takes a `VideoRendererEVRDeinterlaceMode` enum value: ``` // VMR-9 — set the mode string selected by the user VideoCapture1.Video_Renderer.Deinterlace_VMR9_Mode = cbDeinterlaceModes.SelectedItem.ToString(); VideoCapture1.Video_Renderer.Deinterlace_VMR9_UseDefault = false; // EVR — use the enum instead // VideoCapture1.Video_Renderer.Deinterlace_EVR_Mode = VideoRendererEVRDeinterlaceMode.Auto; VideoCapture1.Video_Renderer_Update(); ``` VMR9 and EVR support various deinterlacing algorithms including: - Bob (simple line doubling) - Weave (field interleaving) - Motion adaptive - Motion compensated (highest quality) The availability of specific algorithms depends on the video card capabilities and driver implementation. ### Managing Aspect Ratio and Stretch Modes When displaying video in a window or control that doesn't match the source's native aspect ratio, you need to decide how to handle this discrepancy. The SDK provides multiple stretch modes to address different scenarios. #### Stretch Mode This mode stretches the video to fill the entire display area, potentially distorting the image: ``` VideoCapture1.Video_Renderer.StretchMode = VideoRendererStretchMode.Stretch; VideoCapture1.Video_Renderer_Update(); ``` **Use cases:** - When aspect ratio is not critical - Filling the entire display area is more important than proportions - Source and display have similar aspect ratios - User interface constraints require full-area usage #### Letterbox Mode This mode preserves the original aspect ratio by adding black borders as needed: ``` VideoCapture1.Video_Renderer.StretchMode = VideoRendererStretchMode.Letterbox; VideoCapture1.Video_Renderer_Update(); ``` **Use cases:** - Maintaining correct proportions is essential - Professional video applications - Content where distortion would be noticeable or problematic - Cinema or broadcast content viewing #### LetterboxToFill Mode This mode fills the display area while preserving aspect ratio, cropping any overflow on one axis: ``` VideoCapture1.Video_Renderer.StretchMode = VideoRendererStretchMode.LetterboxToFill; VideoCapture1.Video_Renderer_Update(); ``` **Use cases:** - Consumer video applications where filling the screen is preferred - Content where edges are less important than center - Social media-style video display - When trying to eliminate letterboxing in already letterboxed content ### Aspect-Ratio Override To force a specific display aspect ratio (e.g. show 4:3 content letterboxed inside a 16:9 container), enable the override and set the ratio components: ``` VideoCapture1.Video_Renderer.Aspect_Ratio_Override = true; VideoCapture1.Video_Renderer.Aspect_Ratio_X = 4; VideoCapture1.Video_Renderer.Aspect_Ratio_Y = 3; VideoCapture1.Video_Renderer_Update(); ``` ### Zoom and Pan `VideoRendererSettings` exposes zoom/shift properties useful for digital PTZ on a preview: ``` VideoCapture1.Video_Renderer.Zoom_Ratio = 150; // 150% VideoCapture1.Video_Renderer.Zoom_ShiftX = 0; VideoCapture1.Video_Renderer.Zoom_ShiftY = 0; VideoCapture1.Video_Renderer_Update(); ``` ### Flip and Rotation ``` VideoCapture1.Video_Renderer.Flip_Horizontal = true; VideoCapture1.Video_Renderer.Flip_Vertical = false; // RotationAngle is only respected by the Direct2D renderer and accepts 0, 90, 180, or 270. VideoCapture1.Video_Renderer.RotationAngle = 90; VideoCapture1.Video_Renderer_Update(); ``` ## Troubleshooting Common Issues ### Renderer Compatibility Problems If you encounter issues with a specific renderer, try falling back to a more compatible option: ``` try { // Try using EVR first VideoCapture1.Video_Renderer.VideoRenderer = VideoRendererMode.EVR; VideoCapture1.Video_Renderer_Update(); } catch { try { // Fall back to VMR9 VideoCapture1.Video_Renderer.VideoRenderer = VideoRendererMode.VMR9; VideoCapture1.Video_Renderer_Update(); } catch { // Last resort - legacy renderer VideoCapture1.Video_Renderer.VideoRenderer = VideoRendererMode.VideoRenderer; VideoCapture1.Video_Renderer_Update(); } } ``` ## Best Practices and Recommendations 1. **Choose the right renderer for your target environment**: 2. For modern Windows: EVR 3. For broad compatibility: VMR9 4. For legacy systems: Video Renderer 5. **Test on various hardware configurations**: Video rendering can behave differently across GPU vendors and driver versions. 6. **Implement renderer fallback logic**: Always have a backup plan if the preferred renderer fails. 7. **Consider your video content**: Higher resolution or interlaced content will benefit more from advanced renderers. 8. **Balance quality vs. performance**: The highest quality settings might not always deliver the best user experience if they impact performance. ## Required Dependencies To ensure proper functionality of these renderers, make sure to include: - SDK redistributable packages - DirectX End-User Runtime (latest version recommended) - .NET Framework runtime appropriate for your application ## Conclusion The classic engines offer 10 renderer modes covering WinForms, WPF, and WinUI 3. **EVR** is the safe default for WinForms, **Direct2D** for modern GPU-accelerated rendering on either WinForms or WPF, **FrameCallback** for custom pipelines (CV / AI / bespoke rendering), **WinUI** for WinUI 3 shells, and **madVR** for reference-quality scenarios that can accommodate the external install. `None` is the right mode when there is no preview at all. For applications built on the cross-platform `VideoCaptureCoreX` / `MediaPlayerCoreX` engines, renderer choice is handled by the `VideoView` control and does not use this enum. ## Related documentation - [Image drawing via OnVideoFrameBuffer](../image-onvideoframebuffer/) — pixel-level frame processing, the canonical use case for `FrameCallback`. - [Text drawing via OnVideoFrameBuffer](../text-onvideoframebuffer/) — text overlays with `FrameCallback`. - [Rendering video in a PictureBox](../draw-video-picturebox/) — WinForms rendering pattern that pairs well with `FrameCallback`. --- Visit our [GitHub](https://github.com/visioforge/.Net-SDK-s-samples) page to get more code samples. ---END OF PAGE--- ## Draw Text on Video Frames in C# .NET — OnVideoFrameBuffer **URL:** https://www.visioforge.com/help/docs/dotnet/general/code-samples/text-onvideoframebuffer/ **Description:** Draw dynamic text on video frames in C# / .NET using the OnVideoFrameBuffer event. Timestamps, sensor data, custom fonts — pixel-level rendering. **Tags:** Video Capture SDK, Media Player SDK, Video Edit SDK, .NET, DirectShow, MediaPlayerCoreX, VideoCaptureCoreX, Windows, macOS, Linux, Android, iOS, GStreamer, Capture, Playback, C# **API:** VideoEffectTextLogo, VideoFrameBufferEventArgs, VideoFrameXBufferEventArgs, VideoCaptureCoreX, MediaPlayerCoreX # Creating Custom Text Overlays with OnVideoFrameBuffer in .NET [Video Capture SDK .Net](https://www.visioforge.com/video-capture-sdk-net) [Video Edit SDK .Net](https://www.visioforge.com/video-edit-sdk-net) [Media Player SDK .Net](https://www.visioforge.com/media-player-sdk-net) ## Introduction The `OnVideoFrameBuffer` event gives direct, pixel-level access to every video frame as it passes through the pipeline. Drawing text onto the frame — timestamps, sensor readings, debug telemetry, or custom branding — is one of the most common uses. This guide shows how to render text on raw frames with full control over font, color, position, and per-frame logic. Looking for the high-level text overlay feature? If you just need a static, animated, or clock-driven text overlay with standard positioning, use the dedicated [text overlay effect](../../video-effects/text-overlay/) — one line of code via `Video_Effects_Add(new VideoEffectTextLogo(...))`. Use `OnVideoFrameBuffer` (this page) when you need **pixel-level control**: custom fonts, advanced layout, per-frame dynamic content, or integration with third-party text/graphics libraries. ### Supported engines The `OnVideoFrameBuffer` event is exposed on both engine families: | Engine | Event args type | Frame pixel format | | --- | --- | --- | | `VideoCaptureCore` (DirectShow, Windows) | `VideoFrameBufferEventArgs` | RGB24 / RGB32 | | `VideoCaptureCoreX` (GStreamer, cross-platform) | `VideoFrameXBufferEventArgs` | BGRA (most common) | | `MediaPlayerCoreX` (GStreamer, cross-platform) | `VideoFrameXBufferEventArgs` | BGRA (most common) | Both engines follow the same pattern — subscribe to the event, read `e.Frame.Data` (an `IntPtr`) with `Width` / `Height` / `Stride`, render into the buffer in place, and set `e.UpdateData = true` to propagate changes downstream. ## Understanding the OnVideoFrameBuffer Event The OnVideoFrameBuffer event is a powerful hook that gives developers direct access to the video frame buffer during processing. This event fires for each frame of video, providing an opportunity to modify the frame data before it's displayed or encoded. Key benefits of using OnVideoFrameBuffer for text overlays include: - **Frame-level access**: Modify individual frames with pixel-perfect precision - **Dynamic content**: Update text based on real-time data or timestamps - **Custom styling**: Apply custom fonts, colors, and effects beyond what built-in APIs offer - **Performance optimizations**: Implement efficient rendering techniques for high-performance applications ## Implementation Overview The technique presented here uses the following components: 1. An event handler for OnVideoFrameBuffer that processes each video frame 2. A VideoEffectTextLogo object to define text properties 3. The FastImageProcessing API to render text onto the frame buffer This approach is particularly useful when you need to: - Display dynamic data like timestamps, metadata, or sensor readings - Create animated text effects - Position text with pixel-perfect accuracy - Apply custom styling not available through standard APIs ## Sample Code Implementation The following C# example demonstrates how to implement a basic text overlay system using the OnVideoFrameBuffer event: ``` private void SDK_OnVideoFrameBuffer(object sender, VideoFrameBufferEventArgs e) { if (!logoInitiated) { logoInitiated = true; InitTextLogo(); } // AddTextLogo(context, pixels, pixels32bit, pixels32tmp, frameWidth, frameHeight, // ref textLogo, timeStamp, frameNumber) // Pass pixels32bit: false + pixels32tmp: IntPtr.Zero for RGB24 frames. FastImageProcessing.AddTextLogo( context: null, pixels: e.Frame.Data, pixels32bit: false, pixels32tmp: IntPtr.Zero, frameWidth: e.Frame.Info.Width, frameHeight: e.Frame.Info.Height, textLogo: ref textLogo, timeStamp: e.Frame.Timestamp, frameNumber: 0); } private bool logoInitiated = false; private VideoEffectTextLogo textLogo = null; private void InitTextLogo() { textLogo = new VideoEffectTextLogo(true); textLogo.Text = "Hello world!"; textLogo.Left = 50; textLogo.Top = 50; } ``` ## Detailed Code Explanation Let's break down the key components of this implementation: ### The Event Handler ``` private void SDK_OnVideoFrameBuffer(object sender, VideoFrameBufferEventArgs e) ``` This method is triggered for each video frame. The VideoFrameBufferEventArgs provides access to: - Frame data (pixel buffer) - Frame dimensions (width and height) - Timestamp information ### Initialization Logic ``` if (!logoInitiated) { logoInitiated = true; InitTextLogo(); } ``` This code ensures the text logo is only initialized once, preventing unnecessary object creation for each frame. This pattern is important for performance when processing video at high frame rates. ### Text Logo Setup ``` private void InitTextLogo() { textLogo = new VideoEffectTextLogo(true); textLogo.Text = "Hello world!"; textLogo.Left = 50; textLogo.Top = 50; } ``` The VideoEffectTextLogo class is used to define the properties of the text overlay: - The text content ("Hello world!") - Position coordinates (50 pixels from both left and top) ### Rendering the Text Overlay ``` FastImageProcessing.AddTextLogo( context: null, pixels: e.Frame.Data, pixels32bit: false, // true when the engine delivers RGB32 pixels32tmp: IntPtr.Zero, // optional scratch buffer; IntPtr.Zero lets the helper allocate on demand frameWidth: e.Frame.Info.Width, frameHeight: e.Frame.Info.Height, textLogo: ref textLogo, timeStamp: e.Frame.Timestamp, frameNumber: 0); ``` The 9-arg signature mirrors `FastImageProcessing.AddTextLogo` exactly. Width/height live inside `e.Frame.Info` on the classic `VideoFrame` struct; the timestamp lives on `e.Frame.Timestamp`. Pass `pixels32bit: true` when your source is RGB32. ## Advanced Customization Options While the basic example demonstrates a simple static text overlay, the VideoEffectTextLogo class supports numerous customization options: ### Text Formatting ``` // Font is a full System.Drawing.Font — any typeface + style combo works. textLogo.Font = new System.Drawing.Font("Arial", 24, System.Drawing.FontStyle.Bold); textLogo.FontColor = System.Drawing.Color.White; textLogo.TransparencyLevel = 200; // 0 (fully transparent) - 255 (opaque) ``` ### Background and Borders ``` textLogo.BackgroundTransparent = false; textLogo.BackgroundColor = System.Drawing.Color.Black; // Border ring is configured via BorderMode + per-ring colors and sizes (inner/outer). // TextEffectMode values: None, Inner, Outer, InnerAndOuter, Embossed, Outline, FilledOutline, Halo. textLogo.BorderMode = TextEffectMode.InnerAndOuter; textLogo.BorderInnerColor = System.Drawing.Color.Yellow; textLogo.BorderInnerSize = 2; textLogo.BorderOuterColor = System.Drawing.Color.Black; textLogo.BorderOuterSize = 1; ``` ### Animation and Dynamic Content For dynamic content that changes per frame: ``` private void SDK_OnVideoFrameBuffer(object sender, VideoFrameBufferEventArgs e) { if (!logoInitiated) { logoInitiated = true; InitTextLogo(); } // Timestamp lives on e.Frame.Timestamp (TimeSpan) textLogo.Text = $"Timestamp: {e.Frame.Timestamp:hh\\:mm\\:ss\\.fff}"; // Animate position textLogo.Left = 50 + (int)(Math.Sin(e.Frame.Timestamp.TotalSeconds) * 50); FastImageProcessing.AddTextLogo( context: null, pixels: e.Frame.Data, pixels32bit: false, pixels32tmp: IntPtr.Zero, frameWidth: e.Frame.Info.Width, frameHeight: e.Frame.Info.Height, textLogo: ref textLogo, timeStamp: e.Frame.Timestamp, frameNumber: 0); } ``` ## Performance Considerations When implementing custom text overlays, consider these performance best practices: 1. **Initialize objects once**: Create the VideoEffectTextLogo object only once, not per frame 2. **Minimize text changes**: Update text content only when necessary 3. **Use efficient fonts**: Simple fonts render faster than complex ones 4. **Consider resolution**: Higher resolution videos require more processing power 5. **Test on target hardware**: Ensure your implementation performs well on production systems ## Multiple Text Elements To display multiple text elements on the same frame: ``` private VideoEffectTextLogo titleLogo = null; private VideoEffectTextLogo timestampLogo = null; private void InitTextLogos() { titleLogo = new VideoEffectTextLogo(true); titleLogo.Text = "Camera Feed"; titleLogo.Left = 50; titleLogo.Top = 50; timestampLogo = new VideoEffectTextLogo(true); timestampLogo.Left = 50; timestampLogo.Top = 100; } private void SDK_OnVideoFrameBuffer(object sender, VideoFrameBufferEventArgs e) { if (!logosInitiated) { logosInitiated = true; InitTextLogos(); } // Update dynamic content timestampLogo.Text = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff"); // Render both text elements FastImageProcessing.AddTextLogo(null, e.Frame.Data, false, IntPtr.Zero, e.Frame.Info.Width, e.Frame.Info.Height, ref titleLogo, e.Frame.Timestamp, 0); FastImageProcessing.AddTextLogo(null, e.Frame.Data, false, IntPtr.Zero, e.Frame.Info.Width, e.Frame.Info.Height, ref timestampLogo, e.Frame.Timestamp, 0); } ``` ## VideoCaptureCoreX / MediaPlayerCoreX (X engines) example On the cross-platform X engines the event signature is `VideoFrameXBufferEventArgs` and the frame buffer typically arrives in **BGRA** format (4 bytes per pixel). The example below uses SkiaSharp to wrap the raw buffer and draw text on top; SkiaSharp is a transitive dependency of the X engines, so no extra NuGet package is needed. ``` using SkiaSharp; // Create paints once, reuse across frames private SKPaint _textPaint = new SKPaint { Color = SKColors.White, TextSize = 32, IsAntialias = true, Typeface = SKTypeface.FromFamilyName("Arial", SKFontStyle.Bold) }; private SKPaint _shadowPaint = new SKPaint { Color = SKColors.Black.WithAlpha(160), TextSize = 32, IsAntialias = true, Typeface = SKTypeface.FromFamilyName("Arial", SKFontStyle.Bold) }; // Subscribe after constructing VideoCaptureCoreX / MediaPlayerCoreX _videoCapture.OnVideoFrameBuffer += VideoCapture_OnVideoFrameBuffer; private void VideoCapture_OnVideoFrameBuffer(object sender, VideoFrameXBufferEventArgs e) { if (e.Frame == null || e.Frame.Data == IntPtr.Zero) { return; } // Wrap the raw BGRA buffer in a SkiaSharp surface (no extra allocation) var info = new SKImageInfo(e.Frame.Width, e.Frame.Height, SKColorType.Bgra8888, SKAlphaType.Premul); using (var pixmap = new SKPixmap(info, e.Frame.Data, e.Frame.Stride)) using (var surface = SKSurface.Create(pixmap)) { var canvas = surface.Canvas; // Dynamic content built per frame var timestamp = e.Frame.Timestamp.ToString(@"hh\:mm\:ss\.fff"); var line = $"REC {timestamp}"; // Draw shadow first, then main text for legibility on any background canvas.DrawText(line, 18, 42, _shadowPaint); canvas.DrawText(line, 16, 40, _textPaint); canvas.Flush(); } // Propagate the modified frame downstream e.UpdateData = true; } ``` **Why BGRA matters.** The X engines request BGRA by default for frame callbacks because it maps 1:1 to SkiaSharp, System.Drawing, and most GPU-friendly interop paths. If you need a different format, request a format conversion block upstream rather than converting on every frame. **Measuring and positioning text.** Use `_textPaint.MeasureText(line)` to compute width for right- or center-alignment. SkiaSharp also exposes `SKFontMetrics` via `_textPaint.FontMetrics` for baseline / ascent / descent to position text precisely against frame edges. **Alternative imaging stacks.** You can also use `System.Drawing.Graphics` wrapping a `Bitmap` constructed over the raw buffer on Windows, or direct byte writes with `Marshal.Copy` / `Span` for full control. SkiaSharp is the recommended option on macOS / Linux / iOS / Android. **Engine-level parity.** Everything in [Performance Considerations](#performance-considerations) and [Multiple Text Elements](#multiple-text-elements) applies equally to the X engines — the event fires on a processing thread, `UpdateData` propagates changes, and heavy work should be offloaded to avoid dropping frames. ## Required Components To implement this solution, you'll need: - SDK redist package installed in your application (NuGet on the X engines, installer on `VideoCaptureCore`). - Reference to the appropriate SDK (Video Capture SDK, Video Edit SDK, or Media Player SDK — X or classic). - For the X-engine sample: a transitive SkiaSharp reference (already pulled in by the SDK) or your own text-rendering library. ## Conclusion The `OnVideoFrameBuffer` event gives direct access to every raw frame on both the classic `VideoCaptureCore` engine (RGB24/RGB32 via `VideoFrameBufferEventArgs` + `FastImageProcessing`) and the cross-platform X engines (`VideoCaptureCoreX` / `MediaPlayerCoreX`, BGRA via `VideoFrameXBufferEventArgs` + SkiaSharp). This is the right tool when you need pixel-level text rendering — custom fonts, per-frame dynamic content, anti-aliasing you control, or integration with third-party text/graphics libraries. For static or clock-driven text overlays without writing a per-frame handler, the one-line [text overlay effect](../../video-effects/text-overlay/) is usually the better choice. ## Related documentation - [Text overlay effect](../../video-effects/text-overlay/) — high-level, declarative text overlay without writing a callback. - [Image drawing via OnVideoFrameBuffer](../image-onvideoframebuffer/) — same technique applied to images instead of text. - [Drawing video in a PictureBox](../draw-video-picturebox/) — WinForms rendering pattern that often pairs with pixel-level frame work. --- Visit our [GitHub](https://github.com/visioforge/.Net-SDK-s-samples) page to get more code samples. ---END OF PAGE--- ## Uninstall DirectShow Filters in Windows Using regsvr32 **URL:** https://www.visioforge.com/help/docs/dotnet/general/code-samples/uninstall-directshow-filter/ **Description:** Properly uninstall DirectShow filters with manual techniques, troubleshooting steps, and best practices for .NET multimedia applications. **Tags:** Video Capture SDK, Media Player SDK, Video Edit SDK, .NET, DirectShow, Windows, Playback # Remove DirectShow Filters in Windows [Video Capture SDK .Net](https://www.visioforge.com/video-capture-sdk-net) [Video Edit SDK .Net](https://www.visioforge.com/video-edit-sdk-net) [Media Player SDK .Net](https://www.visioforge.com/media-player-sdk-net) DirectShow filters are essential components for multimedia applications in Windows environments. They enable software to process audio and video data efficiently. However, there may be situations where you need to uninstall these filters, such as when upgrading your application, resolving conflicts, or completely removing a software package. This guide provides detailed instructions on how to properly uninstall DirectShow filters from your system. ## Understanding DirectShow Filters DirectShow is a multimedia framework and API designed by Microsoft for software developers to perform various operations with media files. It's built on the Component Object Model (COM) architecture and uses a modular approach where each processing step is handled by a separate component called a filter. Filters are categorized into three main types: - **Source filters**: Read data from files, capture devices, or network streams - **Transform filters**: Process or modify the data (compression, decompression, effects) - **Rendering filters**: Display video or play audio When SDK components are installed, they register DirectShow filters in the Windows Registry, making them available to any application that uses the DirectShow framework. ## Why Uninstall DirectShow Filters? There are several reasons why you might need to uninstall DirectShow filters: 1. **Version conflicts**: Newer versions of the SDK might require removing older filters 2. **System cleanup**: Removing unused components to maintain system efficiency 3. **Troubleshooting**: Resolving issues with multimedia applications 4. **Complete software removal**: Ensuring no components remain after uninstalling the main application 5. **Re-registration**: Sometimes uninstalling and reinstalling filters can resolve registration issues ## Methods for Uninstalling DirectShow Filters ### Method 1: Using the SDK Installer (Recommended) The most straightforward way to uninstall DirectShow filters is through the SDK (or redist) installer itself. SDK packages include uninstallation routines that properly remove all components, including DirectShow filters. ### Method 2: Manual Unregistration with regsvr32 If automatic uninstallation isn't possible or you need to unregister specific filters, you can use the `regsvr32` command-line tool: 1. Open Command Prompt as Administrator (right-click on Command Prompt and select "Run as administrator") 2. Use the following command syntax to unregister a filter: ``` regsvr32 /u "C:\path\to\filter.dll" ``` 1. Replace `C:\path\to\filter.dll` with the actual path to the DirectShow filter file 2. Press Enter to execute the command For example, to unregister a filter located at `C:\Program Files\Common Files\FilterFolder\example_filter.dll`, you would use: ``` regsvr32 /u "C:\Program Files\Common Files\FilterFolder\example_filter.dll" ``` You should see a confirmation dialog indicating successful unregistration. ## Finding DirectShow Filter Locations Before you can manually unregister filters, you need to know their locations. Here are several methods to find installed DirectShow filters: ### Using GraphStudio [GraphStudio](https://github.com/cplussharp/graph-studio-next) is a powerful open-source tool for working with DirectShow filters. To find filter locations: 1. Download and install GraphStudio 2. Launch the application with administrator privileges 3. Go to "Graph > Insert Filters" 4. Browse through the list of installed filters 5. Right-click on a filter and select "Properties" 6. Note the "File:" path shown in the properties dialog This method provides the exact file path needed for manual unregistration. ### Using System Registry You can also find DirectShow filters through the Windows Registry: 1. Press `Win + R` to open the Run dialog 2. Type `regedit` and press Enter to open Registry Editor 3. Navigate to `HKEY_CLASSES_ROOT\CLSID` 4. Use the Search function (Ctrl+F) to find filter names 5. Look for the "InprocServer32" key under the filter's CLSID, which contains the file path ## Platform Considerations (x86 vs x64) DirectShow filters are platform-specific, meaning 32-bit (x86) and 64-bit (x64) versions are separate components. If you've installed both versions, you need to unregister each one separately. For x64 systems: - 64-bit filters are typically installed in `C:\Windows\System32` - 32-bit filters are typically installed in `C:\Windows\SysWOW64` Use the appropriate version of `regsvr32` for each platform: - For 64-bit filters: `C:\Windows\System32\regsvr32.exe` - For 32-bit filters: `C:\Windows\SysWOW64\regsvr32.exe` ## Troubleshooting Filter Uninstallation If you encounter issues during filter uninstallation, try these troubleshooting steps: ### Unable to Unregister Filter If you receive an error like "DllUnregisterServer failed with error code 0x80004005": 1. Ensure you're running Command Prompt as Administrator 2. Verify that the path to the filter is correct 3. Check if the filter file exists and isn't in use by any application 4. Close any applications that might be using DirectShow filters 5. In some cases, a system restart may be necessary before unregistration ### Filter Still Present After Unregistration If a filter appears to be still registered after attempting to unregister it: 1. Use GraphStudio to check if the filter is still listed 2. Look for multiple instances of the filter in different locations 3. Check both 32-bit and 64-bit registry locations 4. Try using the Microsoft-provided tool "OleView" to inspect COM registrations ## Verifying Successful Uninstallation After uninstalling DirectShow filters, verify the removal was successful: 1. Use GraphStudio to check if the filters no longer appear in the available filters list 2. Check the registry for any remaining entries related to the filters 3. Test any applications that previously used the filters to ensure they handle the absence gracefully --- Visit our [GitHub](https://github.com/visioforge/.Net-SDK-s-samples) page to get more code samples and implementation examples for working with DirectShow and multimedia applications in .NET. ---END OF PAGE--- ## Setting Custom Placeholder Images for VideoView .NET **URL:** https://www.visioforge.com/help/docs/dotnet/general/code-samples/video-view-set-custom-image/ **Description:** Display custom placeholder images in VideoView controls when no video is playing for professional branding and enhanced user experience in .NET. **Tags:** Video Capture SDK, Media Player SDK, Video Edit SDK, .NET, Windows, Playback, C# **API:** VideoView, VideoPlayerForm # Setting Custom Images for VideoView Controls in .NET Applications [Video Capture SDK .Net](https://www.visioforge.com/video-capture-sdk-net) [Video Edit SDK .Net](https://www.visioforge.com/video-edit-sdk-net) [Media Player SDK .Net](https://www.visioforge.com/media-player-sdk-net) ## Introduction When developing media applications in .NET, it's often necessary to display a custom image within your VideoView control when no video content is playing. This capability is essential for creating professional-looking applications that maintain visual appeal during inactive states. Custom images can serve as placeholders, branding opportunities, or informational displays to enhance the user experience. This guide explores the implementation of custom image functionality for VideoView controls across various .NET SDK applications. ## Understanding VideoView Custom Images The VideoView control is a versatile component that displays video content in your application. However, when the control is not actively playing video, it typically shows a blank or default display. By implementing custom images, you can: - Display your application or company logo - Show preview thumbnails of available content - Present instructional information to users - Maintain visual consistency across your application - Indicate the video's status (paused, stopped, loading, etc.) It's important to note that the custom image is only visible when the control is not playing any video content. Once playback begins, the video stream automatically replaces the custom image. ## Implementation Process The process of setting a custom image for a VideoView control involves three primary operations: 1. Creating a picture box with appropriate dimensions 2. Setting the desired image 3. Cleaning up resources when no longer needed Let's explore each of these steps in detail. ## Step 1: Creating the Picture Box The first step is to initialize a picture box within your VideoView control with the appropriate dimensions. This operation should be performed once during the setup phase: ``` VideoView1.PictureBoxCreate(VideoView1.Width, VideoView1.Height); ``` This method call creates an internal picture box component that will host your custom image. The parameters specify the width and height of the picture box, which should typically match the dimensions of your VideoView control to ensure proper display without stretching or distortion. ### Best Practices for Picture Box Creation - **Timing Considerations**: Create the picture box during form initialization or after the control has been sized appropriately - **Dynamic Sizing**: If your application supports resizing, consider recreating the picture box when the control size changes - **Error Handling**: Implement try-catch blocks to handle potential exceptions during creation ## Step 2: Setting the Custom Image After creating the picture box, you can set your custom image. Note that there appears to be a duplication in the original documentation - the correct code for setting the image should use the `PictureBoxSetImage` method: `PictureBoxSetImage` takes a `System.Drawing.Bitmap`, so load the file as `Bitmap` (or cast) rather than `Image`: ``` // Load an image from a file as Bitmap Bitmap customImage = new Bitmap("path/to/your/image.jpg"); VideoView1.PictureBoxSetImage(customImage); ``` Alternatively, you can use built-in resources or dynamically generated images: ``` // Using a Bitmap resource (the resource must be declared as Bitmap, not Image) VideoView1.PictureBoxSetImage(Properties.Resources.MyCustomImage); // Or creating a dynamic image using (Bitmap dynamicImage = new Bitmap(VideoView1.Width, VideoView1.Height)) { using (Graphics g = Graphics.FromImage(dynamicImage)) { // Draw on the image g.Clear(Color.DarkBlue); g.DrawString("Ready to Play", new Font("Arial", 24), Brushes.White, new PointF(50, 50)); } VideoView1.PictureBoxSetImage((Bitmap)dynamicImage.Clone()); } ``` ### Image Format Considerations The image format you choose can impact performance and visual quality: - **PNG**: Best for images with transparency - **JPEG**: Suitable for photographic content - **BMP**: Uncompressed format with higher memory usage - **GIF**: Supports simple animations but with limited color depth ### Image Size Optimization For optimal performance, consider these factors when preparing your custom images: 1. **Match Dimensions**: Resize your image to match the VideoView dimensions to avoid scaling operations 2. **Resolution Awareness**: Consider display DPI for crisp images on high-resolution displays 3. **Memory Consumption**: Large images consume more memory, which may impact application performance ## Step 3: Cleaning Up Resources When the custom image is no longer required, it's important to clean up the resources to prevent memory leaks: ``` VideoView1.PictureBoxDestroy(); ``` This method should be called when: - The application is closing - The control is being disposed - You're switching to video playback mode and won't need the custom image anymore ### Resource Management Best Practices Proper resource management is crucial for maintaining application stability: - **Explicit Cleanup**: Always call `PictureBoxDestroy()` when you're done with the custom image - **Disposal Timing**: Include the cleanup call in your form's `Dispose` or `Closing` events - **State Tracking**: Keep track of whether a picture box has been created to avoid destroying a non-existent resource ## Advanced Scenarios ### Dynamic Image Updates In some applications, you may need to update the custom image dynamically: ``` private void UpdateCustomImage(string imagePath) { // Ensure picture box exists if (VideoView1.PictureBoxExists()) { // Update image Bitmap newImage = new Bitmap(imagePath); VideoView1.PictureBoxSetImage(newImage); } else { // Create picture box first VideoView1.PictureBoxCreate(VideoView1.Width, VideoView1.Height); Bitmap newImage = new Bitmap(imagePath); VideoView1.PictureBoxSetImage(newImage); } } ``` ### Handling Control Resizing If your application allows resizing of the VideoView control, you'll need to handle image scaling: ``` private void VideoView1_SizeChanged(object sender, EventArgs e) { // Recreate picture box with new dimensions if (VideoView1.PictureBoxExists()) { VideoView1.PictureBoxDestroy(); } VideoView1.PictureBoxCreate(VideoView1.Width, VideoView1.Height); // Set image again with appropriate scaling SetScaledCustomImage(); } ``` ### Multiple VideoView Controls When working with multiple VideoView controls, ensure proper management for each: ``` private void InitializeAllVideoViews() { // Initialize each VideoView with appropriate custom images VideoView1.PictureBoxCreate(VideoView1.Width, VideoView1.Height); VideoView1.PictureBoxSetImage(Properties.Resources.Camera1Placeholder); VideoView2.PictureBoxCreate(VideoView2.Width, VideoView2.Height); VideoView2.PictureBoxSetImage(Properties.Resources.Camera2Placeholder); // Additional VideoView controls... } ``` ## Troubleshooting Common Issues ### Image Not Displaying If your custom image isn't appearing: 1. **Check Timing**: Ensure you're setting the image after the picture box is created 2. **Verify Video State**: Confirm the control isn't currently playing video 3. **Image Loading**: Verify the image path is correct and accessible 4. **Control Visibility**: Ensure the VideoView control is visible in the UI ### Memory Leaks To prevent memory leaks: 1. **Dispose Images**: Always dispose Image objects after they're no longer needed 2. **Destroy Picture Box**: Call `PictureBoxDestroy()` when appropriate 3. **Resource Tracking**: Implement proper tracking of created resources ## Complete Implementation Example Here's a complete implementation example that demonstrates the proper lifecycle management: ``` public partial class VideoPlayerForm : Form { private bool isPictureBoxCreated = false; public VideoPlayerForm() { InitializeComponent(); this.Load += VideoPlayerForm_Load; this.FormClosing += VideoPlayerForm_FormClosing; } private void VideoPlayerForm_Load(object sender, EventArgs e) { InitializeCustomImage(); } private void InitializeCustomImage() { try { VideoView1.PictureBoxCreate(VideoView1.Width, VideoView1.Height); isPictureBoxCreated = true; // PictureBoxSetImage expects System.Drawing.Bitmap — declare the resource as Bitmap (or cast from Image). using (Bitmap customImage = (Bitmap)Properties.Resources.VideoPlaceholder) { VideoView1.PictureBoxSetImage(customImage); } } catch (Exception ex) { // Handle exceptions MessageBox.Show($"Error setting custom image: {ex.Message}"); } } private void btnPlay_Click(object sender, EventArgs e) { // Play video logic here // The custom image will automatically be replaced during playback } private void VideoPlayerForm_FormClosing(object sender, FormClosingEventArgs e) { CleanupResources(); } private void CleanupResources() { if (isPictureBoxCreated) { VideoView1.PictureBoxDestroy(); isPictureBoxCreated = false; } } } ``` ## Conclusion Implementing custom images for VideoView controls enhances the user experience and professional appearance of your .NET media applications. By following the steps outlined in this guide, you can effectively display branded or informative content when videos aren't playing. Remember the key points: 1. Create the picture box with the appropriate dimensions 2. Set your custom image with proper resource management 3. Clean up resources when they're no longer needed 4. Handle resizing and other special scenarios as required With these techniques, you can create more polished and user-friendly video applications in .NET. --- Visit our [GitHub](https://github.com/visioforge/.Net-SDK-s-samples) page to get more code samples and implementation examples. ---END OF PAGE--- ## Implementing Audio VU Meters & Waveform Visualizers **URL:** https://www.visioforge.com/help/docs/dotnet/general/code-samples/vu-meters/ **Description:** Build VU meters and waveform visualizers in WinForms and WPF for real-time audio level monitoring with mono and stereo channel support in .NET. **Tags:** Video Capture SDK, Media Player SDK, Video Edit SDK, .NET, Windows, WinForms, WPF, C# **API:** AudioLevelEventArgs, VUMeterMaxSampleEventArgs # Audio Visualization: Implementing VU Meters and Waveform Displays in .NET [Video Capture SDK .Net](https://www.visioforge.com/video-capture-sdk-net) [Video Edit SDK .Net](https://www.visioforge.com/video-edit-sdk-net) [Media Player SDK .Net](https://www.visioforge.com/media-player-sdk-net) Audio visualization is a crucial component of modern media applications, providing users with visual feedback about audio levels and waveform patterns. This guide demonstrates how to implement VU (Volume Unit) meters and waveform visualizers in both WinForms and WPF applications. ## Understanding Audio Visualization Components Before diving into implementation, it's important to understand the two main visualization tools we'll be working with: ### VU Meters VU meters display the instantaneous audio level of a signal, typically showing how loud the audio is at any given moment. They provide real-time feedback about audio levels, helping users monitor signal strength and prevent distortion or clipping. ### Waveform Painters Waveform visualizers display the audio signal as a continuous line that represents amplitude changes over time. They provide a more detailed representation of the audio content, showing patterns and characteristics that might not be apparent from listening alone. ## Implementation in WinForms Applications WinForms provides a straightforward way to implement audio visualization components with minimal code. Let's explore the implementation of both VU meters and waveform painters. ### WinForms VU Meter Implementation Implementing a VU meter in WinForms requires just a few steps: 1. **Add the VU Meter Control**: First, add the VU meter control to your form. For stereo audio, you'll typically add two controls—one for each channel. ``` // Add this to your form design VisioForge.Core.UI.WinForms.VolumeMeterPro.VolumeMeter volumeMeter1; VisioForge.Core.UI.WinForms.VolumeMeterPro.VolumeMeter volumeMeter2; // For stereo ``` 1. **Enable VU Meter in Your Media Control**: Before starting playback or capture, enable the VU meter functionality in your media control. ``` // Enable VU meter before starting playback/capture mediaPlayer.Audio_VUMeter_Pro_Enabled = true; ``` 1. **Implement the Event Handler**: Add an event handler to process the audio level data and update the VU meter display. ``` private void VideoCapture1_OnAudioVUMeterProVolume(object sender, AudioLevelEventArgs e) { volumeMeter1.Amplitude = e.ChannelLevelsDb[0]; if (e.ChannelLevelsDb.Length > 1) { volumeMeter2.Amplitude = e.ChannelLevelsDb[1]; } } ``` With these steps, your VU meter will dynamically update based on the audio levels of your media playback or capture. ### WinForms Waveform Painter Implementation The waveform painter implementation follows a similar pattern: 1. **Add the Waveform Painter Control**: Add the waveform painter control to your form. For stereo audio, add two controls. ``` // Add this to your form design VisioForge.Core.UI.WinForms.VolumeMeterPro.WaveformPainter waveformPainter1; VisioForge.Core.UI.WinForms.VolumeMeterPro.WaveformPainter waveformPainter2; // For stereo ``` 1. **Enable VU Meter Processing**: Enable the VU meter functionality to provide data for the waveform painter. ``` // Enable VU meter before starting playback/capture mediaPlayer.Audio_VUMeter_Pro_Enabled = true; ``` 1. **Implement the Event Handler**: Add an event handler to process the audio data and update the waveform display. ``` private void VideoCapture1_OnAudioVUMeterProVolume(object sender, AudioLevelEventArgs e) { waveformPainter1.AddMax(e.ChannelLevelsDb[0]); if (e.ChannelLevelsDb.Length > 1) { waveformPainter2.AddMax(e.ChannelLevelsDb[1]); } } ``` ## Implementation in WPF Applications WPF requires a slightly different approach due to its threading model and UI framework. Let's look at how to implement both visualization types in WPF. ### WPF VU Meter Implementation 1. **Add the VU Meter Control**: Add the VU meter control to your XAML layout. For stereo audio, add two controls. ``` ``` 1. **Enable VU Meter Processing and Start the Meters**: ``` VideoCapture1.Audio_VUMeter_Pro_Enabled = true; volumeMeter1.Start(); volumeMeter2.Start(); ``` 1. **Implement the Event Handler with Dispatcher**: In WPF, you need to use the Dispatcher to update UI elements from non-UI threads. ``` private delegate void AudioVUMeterProVolumeDelegate(AudioLevelEventArgs e); private void AudioVUMeterProVolumeDelegateMethod(AudioLevelEventArgs e) { volumeMeter1.Amplitude = e.ChannelLevelsDb[0]; volumeMeter1.Update(); if (e.ChannelLevelsDb.Length > 1) { volumeMeter2.Amplitude = e.ChannelLevelsDb[1]; volumeMeter2.Update(); } } private void VideoCapture1_OnAudioVUMeterProVolume(object sender, AudioLevelEventArgs e) { Dispatcher.BeginInvoke(new AudioVUMeterProVolumeDelegate(AudioVUMeterProVolumeDelegateMethod), e); } ``` 1. **Clean Up After Playback**: When playback stops, clean up the VU meters to release resources. ``` volumeMeter1.Stop(); volumeMeter1.Clear(); volumeMeter2.Stop(); volumeMeter2.Clear(); ``` ### WPF Waveform Painter Implementation 1. **Add the Waveform Painter Control**: Add the waveform painter control to your XAML layout. ``` ``` 1. **Enable VU Meter Processing and Start the Waveform Painter**: ``` VideoCapture1.Audio_VUMeter_Pro_Enabled = true; waveformPainter.Start(); ``` 1. **Implement the Maximum Calculated Event Handler**: For waveform painters in WPF, we use a different event. ``` private delegate void AudioVUMeterProMaximumCalculatedDelegate(VUMeterMaxSampleEventArgs e); private void AudioVUMeterProMaximumCalculatedelegateMethod(VUMeterMaxSampleEventArgs e) { waveformPainter.AddValue(e.MaxSample, e.MinSample); } private void VideoCapture1_OnAudioVUMeterProMaximumCalculated(object sender, VUMeterMaxSampleEventArgs e) { Dispatcher.BeginInvoke(new AudioVUMeterProMaximumCalculatedDelegate(AudioVUMeterProMaximumCalculatedelegateMethod), e); } ``` 1. **Clean Up After Playback**: When playback stops, clean up the waveform painter. ``` waveformPainter.Stop(); waveformPainter.Clear(); ``` ## Advanced Customization Options Both the VU meter and waveform painter controls offer extensive customization options to match your application's design and user experience requirements. ### Customizing VU Meters The `VolumeMeter` control exposes the following real properties: - **`MinDb` / `MaxDb`**: decibel range displayed by the meter - **`Boost`**: gain multiplier applied before rendering - **`Orientation`**: horizontal or vertical bar direction - **`ForeColor`**: bar color (inherited from `Control`) - **`MinimalUpdateInterval`** (WPF only): throttles redraws Example of customizing a VU meter: ``` volumeMeter1.MinDb = -60; volumeMeter1.MaxDb = 6; volumeMeter1.Boost = 1.0f; volumeMeter1.ForeColor = System.Drawing.Color.Green; // WinForms volumeMeter1.Orientation = System.Windows.Forms.Orientation.Vertical; ``` ### Customizing Waveform Painters The `WaveformPainter` control has a small real surface: - **`Boost`** (WinForms): pre-render gain multiplier - **`ForeColor` / `BackColor`**: line and background colors (inherited from `Control`) - **`Clear()`**: resets the painted history - **`AddMax(float)`** (WinForms) / **`AddValue(float, float)`** (WPF): append a new sample Example of customizing a waveform painter: ``` waveformPainter.ForeColor = System.Drawing.Color.SkyBlue; waveformPainter.BackColor = System.Drawing.Color.Black; waveformPainter.Boost = 1.5f; ``` ## Performance Considerations When implementing audio visualization, consider these performance tips: 1. **Update Frequency**: Balance visual responsiveness with CPU usage by adjusting how frequently you update the visuals 2. **UI Thread Management**: Always update UI elements on the appropriate thread (especially important in WPF) 3. **Resource Cleanup**: Properly stop and clear visualization controls when not in use 4. **Buffering**: Consider implementing buffering for smoother visualization during high CPU usage ## Conclusion Implementing VU meters and waveform painters adds valuable visual feedback to media applications. Whether you're developing in WinForms or WPF, these audio visualization components help users monitor and understand audio levels and patterns more intuitively. By following the implementation steps outlined in this guide, you can enhance your .NET media applications with professional-quality audio visualization features that improve the overall user experience. --- For more code examples and related SDKs, visit our [GitHub repository](https://github.com/visioforge/.Net-SDK-s-samples). ---END OF PAGE--- ## Overlay WPF Controls on Video in C# .NET Applications **URL:** https://www.visioforge.com/help/docs/dotnet/general/code-samples/wpf-controls-over-video/ **Description:** Place WPF buttons, text and panels on top of VideoView. D3D11 composable renderer, WriteableBitmap mode, airspace issues, and the WPF_WinUI_Callback migration. **Tags:** Video Capture SDK, Media Player SDK, Video Edit SDK, Media Blocks SDK, .NET, WPF, MediaPlayerCoreX, VideoCaptureCoreX, MediaPlayerCore, VideoCaptureCore, Windows, Playback, Capture, C# **API:** VideoView, VideoRendererMode, IVideoSurfaceProvider, MediaPlayerCoreX, VideoCaptureCore # Overlaying WPF Controls on Video [Video Capture SDK .Net](https://www.visioforge.com/video-capture-sdk-net) [Media Player SDK .Net](https://www.visioforge.com/media-player-sdk-net) [Video Edit SDK .Net](https://www.visioforge.com/video-edit-sdk-net) ## Introduction Placing WPF elements — buttons, overlays, status banners, transport controls — on top of the video preview only works when the video is drawn *inside* the WPF visual tree. If the frames go to a native child window (HWND), WPF cannot paint anything over them: that is the classic WPF **airspace** limitation, and no amount of `Panel.ZIndex` fixes it. The WPF `VisioForge.Core.UI.WPF.VideoView` control supports three ways to draw a frame. Two of them compose with WPF, one does not: | Render mode | How to enable | WPF controls on top | Notes | | --- | --- | --- | --- | | `D3D11Composable` | `VideoView1.UseD3D11ComposableRenderer()` | Yes | Frames stay on the GPU, presented to WPF as a `D3DImage`. Recommended. | | Software (`WriteableBitmap`) | X engines: `VideoView1.SetNativeRendering(false)`; classic engines: `VideoRendererMode.FrameCallback` on the engine | Yes | CPU upload per frame. The classic `WPF_WinUI_Callback` mode. | | Native HWND | default (`VideoView1.SetNativeRendering(true)`) | No | Fastest path, but airspace blocks every overlay. | Coming from `VideoRendererMode.WPF_WinUI_Callback`? In the classic engines the mode was set on the engine: `VideoCapture1.Video_Renderer.VideoRenderer`. The cross-platform X engines (`VideoCaptureCoreX`, `MediaPlayerCoreX`, `VideoEditCoreX`) have no `Video_Renderer` object — the render mode moved onto the `VideoView` control itself, so a single view works with any engine. See [Migrating from WPF\_WinUI\_Callback](#migrating-from-wpf_winui_callback) below. ## D3D11 composable renderer (recommended) `D3D11Composable` uploads each frame into a shared Direct3D 11 texture, opens it on a hidden Direct3D 9Ex device and exposes it to WPF as a `D3DImage`. The video becomes an ordinary element of the visual tree: render transforms, opacity, z-order and rounded clipping all apply to it, and there is no HWND to fight with. **Requirements:** Windows Vista or later (Direct3D 9Ex) and a Direct3D 10/11-class GPU. ### Enabling it with the X engines Call `UseD3D11ComposableRenderer()` before you start playback or capture — the call is idempotent, so it is safe to repeat it after an engine restart: ``` // Before creating / starting the engine. VideoView1.UseD3D11ComposableRenderer(); _player = new MediaPlayerCoreX(VideoView1); var source = await UniversalSourceSettingsV2.CreateAsync(new Uri(filename)); await _player.OpenAsync(source); await _player.PlayAsync(); ``` The same call works for `VideoCaptureCoreX` and `VideoEditCoreX`, and for a `VideoRendererBlock` built on the same view in Media Blocks SDK .NET. ### Enabling it with the classic engines `VideoCaptureCore`, `MediaPlayerCore` and `VideoEditCore` use exactly the same call on the view: ``` VideoView1.UseD3D11ComposableRenderer(); ``` The engine is switched to the frame-callback channel behind the scenes and its frames are uploaded into the shared texture. Prefer this call over selecting `VideoRendererMode.D3D11Composable` on the engine's `Video_Renderer` settings: the view starts in native rendering mode, and while it stays there it overrides the engine's choice with a native HWND. `UseD3D11ComposableRenderer()` takes care of that for you. ### XAML layout Put the view and the overlay into the same `Grid` cell. Later children are drawn on top: ```