libopx 1.3.0
dotnet add package libopx --version 1.3.0
NuGet\Install-Package libopx -Version 1.3.0
<PackageReference Include="libopx" Version="1.3.0" />
<PackageVersion Include="libopx" Version="1.3.0" />
<PackageReference Include="libopx" />
paket add libopx --version 1.3.0
#r "nuget: libopx, 1.3.0"
#:package libopx@1.3.0
#addin nuget:?package=libopx&version=1.3.0
#tool nuget:?package=libopx&version=1.3.0
libopx - an MXF and Teletext caption processing library
A .NET 9 C# library for parsing and extracting data from MXF (Material Exchange Format), BIN (MXF caption data stream), VBI (Vertical Blanking Interval), and T42 (Teletext packet stream) files, with SMPTE timecode and Teletext caption support (OP-42 & OP-47 in particular).
Key Features
Format conversions: Convert between HD and SD T42 and VBI formats or vice versa. You can even pipe that data to other applications like ffmpeg
or mpv
.
Example:
opx convert -of vbi "NOVA-BOMB-XDCAM.mxf" | mpv --window-scale=2 --demuxer=rawvideo --demuxer-rawvideo-mp-format=gray --demuxer-rawvideo-w=720 --demuxer-rawvideo-h=2 --lavfi-complex="[vid1]pad=720:32:0:28,format=yuv422p[v1];movie='NOVA-BOMB-XDCAM.mxf',scale=720:576:flags=lanczos[v2];[v1][v2]vstack,setsar=608:405,setdar=1.7777[vo];amovie='NOVA-BOMB-XDCAM.mxf'[ao]" -
ANSI Escaped Teletext: Supports parsing and filtering of teletext data with ANSI escape sequences:
Table of Contents
- libopx - an MXF and Teletext caption processing library
Features
- Multi-format support: BIN, VBI, T42, and MXF file parsing
- Format conversion: Automatic VBI ↔ T42 conversion
- Teletext filtering: Magazine and row-based filtering with Unicode mapping
- SMPTE timecode: Full timecode calculations with various frame rates
- MXF processing: Stream extraction and demuxing capabilities
- CLI tool: Unified
opx
command-line interface utilizing various library features
Installation
# Clone the repository
git clone https://github.com/nathanpbutler/libopx
cd libopx
# Build the solution
dotnet build
# Run tests (to be implemented)
dotnet test
Quick Start
Using the CLI Tool
# Filter teletext data by magazine and rows
opx filter -m 8 -r 20 -r 22 <input>
# Convert from one format to another
opx convert <input> <output>
# Extract specific streams from MXF files
opx extract -k d,v input.mxf
# Restripe MXF with new timecode
opx restripe -t 10:00:00:00 input.mxf
Using the Library
Filtering teletext Data
using nathanbutlerDEV.libopx;
using nathanbutlerDEV.libopx.Formats;
// Parse MXF file with filtering
using var mxf = new MXF("input.mxf");
foreach (var line in mxf.Parse(magazine: null, rows: Constants.CAPTION_ROWS))
{
Console.WriteLine(line);
}
// Parse VBI file with filtering
using var vbi = new VBI("input.vbi");
foreach (var line in vbi.Parse(magazine: null, rows: Constants.CAPTION_ROWS))
{
Console.WriteLine(line);
}
// Parse T42 file
using var t42 = new T42("input.t42");
foreach (var line in t42.Parse(magazine: null))
{
Console.WriteLine(line);
}
Converting Between Formats
using nathanbutlerDEV.libopx;
using nathanbutlerDEV.libopx.Formats;
using nathanbutlerDEV.libopx.Enums;
// Format conversion pattern - works for VBI, T42, BIN, and MXF
using var parser = new VBI("input.vbi") // or T42, BIN, MXF
{
OutputFormat = Format.T42 // or Format.VBI, Format.VBI_DOUBLE
};
parser.SetOutput("output.t42");
// For VBI/T42 (returns IEnumerable<Line>)
foreach (var line in parser.Parse(magazine: null, rows: Constants.DEFAULT_ROWS))
{
parser.Output.Write(line.Data);
}
// For BIN/MXF (returns IEnumerable<Packet>)
foreach (var packet in parser.Parse(magazine: null, rows: Constants.DEFAULT_ROWS))
{
foreach (var line in packet.Lines.Where(l => l.Type != Format.Unknown))
{
parser.Output.Write(line.Data);
}
}
parser.Dispose(); // Ensure output is flushed
CLI Commands
filter - Filter teletext data
opx filter [options] <input-file?>
Options:
-m, --magazine <int>
: Filter by magazine number (default: all magazines)-r, --rows <string>
: Filter by rows (comma-separated or hyphen ranges, e.g., 1,2,5-8,15)-f, --format <bin|vbi|vbid|t42>
: Input format override-c, --caps
: Use caption rows (1-24) instead of default rows (0-24)-l, --line-count <int>
: Lines per frame for timecode (default: 2)-V, --verbose
: Enable verbose output
Examples:
# Filter VBI data for magazine 8, rows 20 and 22
opx filter -m 8 -r 20,22 input.vbi
# Filter T42 data for all magazines, caption rows only
opx filter -c input.t42
# Filter MXF data for magazine 8, rows 5-8 and 15
opx filter -m 8 -r 5-8,15 input.mxf
# Pipe a D10 MXF from FFmpeg to opx and filter teletext data
ffmpeg -v error -i input.mxf -vf crop=720:2:0:28 -f rawvideo -pix_fmt gray - | opx filter -c -i -
convert - Convert between MXF data and teletext formats
opx convert [options] <input-file?>
Options:
-i, --input-format <bin|vbi|vbid|t42|mxf>
: Input format (auto-detected if not specified)-o, --output-format <vbi|vbid|t42>
: Output format [required]-f, --output-file <file>
: Output file path (writes to stdout if not specified)-m, --magazine <int>
: Filter by magazine number (default: all magazines)-r, --rows <string>
: Filter by rows (comma-separated or hyphen ranges, e.g., 1,2,5-8,15)-c, --caps
: Use caption rows (1-24) instead of default rows (0-24)-k, --keep
: Write blank bytes if rows or magazine doesn't match-l, --line-count <int>
: Lines per frame for timecode (default: 2)-V, --verbose
: Enable verbose output
Examples:
# Convert VBI to T42 format (auto-detect input)
opx convert -o t42 input.vbi
# Convert MXF data stream to T42 with file output
opx convert -i mxf -o t42 -f output.t42 input.mxf
# Convert T42 to VBI with magazine/row filtering
opx convert -i t42 -o vbi -m 8 -r 20-22 input.t42
# Convert VBI to T42 with caption rows only
opx convert -o t42 -c input.vbi
# Convert MXF to VBI preserving structure with blank bytes
opx convert -i mxf -o vbi -k input.mxf
# Pipe a D10 MXF from FFmpeg to opx and convert to T42
ffmpeg -v error -i input.mxf -vf crop=720:2:0:28 -f rawvideo -pix_fmt gray - | ./opx convert -o t42 -f output.t42 -
extract - Extract/demux streams from MXF
opx extract [options] <input.mxf>
Options:
-o, --output <string>
: Output base path-k, --key <d|v|s|t|a>
: Extract specific keys-d, --demux
: Extract all keys found--klv
: Include key and length bytes-V, --verbose
: Enable verbose output
Examples:
# Extract all streams from MXF file
opx extract input.mxf
# Extract only data and video streams
opx extract -k d,v input.mxf
restripe - Restripe MXF with new timecode
opx restripe [options] <input-file>
Options:
-t, --timecode <string>
: New start timecode (HH:MM:SS:FF) [required]-V, --verbose
: Enable verbose output
Project Structure
libopx/
apps/
opx/ # Unified CLI tool
lib/ # Main library
Formats/ # Format parsers (MXF, BIN, VBI, T42)
SMPTE/ # SMPTE metadata system
Enums/ # Enumeration definitions
samples/ # Sample files for testing
scripts/ # Various scripts
tests/ # xUnit test suite
Building
# Build entire solution
dotnet build
# Release build
dotnet build -c Release
# Publish CLI tool as single-file executable
dotnet publish apps/opx -c Release -r win-x64 --self-contained
dotnet publish apps/opx -c Release -r linux-x64 --self-contained
dotnet publish apps/opx -c Release -r osx-x64 --self-contained
Testing
# Run all tests
dotnet test
# Run with coverage
dotnet test --collect:"XPlat Code Coverage"
# Run specific test
dotnet test --filter "TestMethodName"
Requirements
- .NET 9 or later
- Supported platforms: Windows, Linux, macOS
Dependencies
- System.CommandLine (v2.0.0-beta6)
- xUnit (testing)
- coverlet (code coverage)
Contributing
- Fork the repository
- Create a feature branch
- Make your changes
- Add tests for new functionality
- Ensure all tests pass
- Submit a pull request
License
MIT - see the LICENSE file for details.
Acknowledgments
- vhs-teletext - Software to recover teletext data from VHS recordings (inspiration for
filter
command) - MXFInspect - Tool for displaying the internal structure of MXF files (was super helpful for understanding MXF parsing and the intricacies of SMPTE timecodes)
- bmxtranswrap - BBC's MXF processing library and utilities (inspiration for
extract
command) - SubtitleEdit - An incredibly useful C# library and software for subtitle editing and processing
- CCExtractor - Closed caption and subtitle extraction and processing
- ffmpeg - The swiss army knife of multimedia processing
Support
For questions and support, please open an issue.
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net9.0 is compatible. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net9.0
- No dependencies.
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
v1.3.0: Enhanced T42.GetText parsing to handle header rows and improve SMPTE XML documentation to reduce warnings.