Public Interface
The recorder SDK exposes two public layers:
- A native C++ DLL interface in
TSRecorder/ITSRecorder.h - A managed .NET-facing wrapper in
TSRecorderWr/ITSRecorderWr.h
This page documents the API surface that is actually implemented by the recorder code, including the lifecycle, configuration types, callbacks, and the segment filename convention.
Interface Layers
Native Recorder Interface
The native entry point is the exported factory function:
ITSRecorder* recorder = CreateTSRecorder("Recorder-1");
The created object implements ITSRecorder and is configured with plain C++ types:
NetSourcePropsFileTargetPropsNetRecasterProps
Managed Wrapper Interface
The managed interface is TSRecorderWr::ITSRecorderWr. The concrete implementation used by .NET callers is TSRecorderWr::CTSRecorderWr.
using TSRecorderWr;
var recorder = new CTSRecorderWr(0, "Recorder-1");
The wrapper maps directly to the native recorder API and adds activation plus a small set of convenience properties.
Recorder Lifecycle
Use the recorder in this order:
- Create the recorder instance.
- Register recorder and error callbacks.
- Configure the source and target properties.
- Call
Init(...). - Optionally call
SetRecaster(...)beforeStart(). - Call
Start(). - Observe events and query statistics while recording.
- Call
Stop(). - Call
Close()before releasing the object.
Native Example
ITSRecorder* recorder = CreateTSRecorder("Recorder-1");
recorder->SetEventListener(OnRecorderEvent, OnRecorderError, context);
NetSourceProps source;
source.IP = "227.1.1.1";
source.Port = 1234;
FileTargetProps target;
target.Dir = "C:/Recordings";
target.BaseName = "capture.ts";
target.SegmentationType = SegmentationType_Seconds;
target.SegmentDuration = 10000;
if (recorder->Init(source, target))
{
recorder->Start();
}
// ...
recorder->Stop();
recorder->Close();
Native C++ Types
NetSourceProps
| Field | Type | Meaning |
|---|---|---|
Nic | string | Network interface identifier. Defaults to localhost. |
IP | string | Source IP address or multicast address. |
Port | int | UDP port. |
Timeout | int | Idle timeout in milliseconds. When it expires, the recorder raises WaitingForData. |
MaxDetectionTime | int | Maximum PID detection time in milliseconds for GOP-aligned mode. |
Url | string | Optional full input URL. The implementation also inspects it for /shmem=... shared-memory input. |
NetRecasterProps
| Field | Type | Meaning |
|---|---|---|
Nic | string | Outgoing network interface used for recasting. |
IP | string | Recast destination IP address. |
Port | int | Recast destination UDP port. |
Ttl | unsigned int | Multicast TTL. |
Url | string | Optional full recast URL. |
FileTargetProps
| Field | Type | Meaning |
|---|---|---|
BaseName | string | Output filename template. The recorder uses its stem and extension when generating the actual segment filenames. |
Dir | string | Output directory. It is created during Init(...) if it does not exist. |
SegmentationType | FileSegmentationType | SegmentationType_None, SegmentationType_KBytes, or SegmentationType_Seconds. |
SegmentDuration | unsigned int | Segment duration in milliseconds when splitting by time. |
SegmentLength | __int64 | Segment size in bytes when splitting by size. Must be non-zero for size-based segmentation. |
StartIndex | unsigned int | Initial segment index used in generated filenames and event parameters. |
GopAlignedSegmentation | bool | When true, segment cuts are delayed to H.264 GOP boundaries. |
OldSegmentDeletionMode | OldSegmentDeleteMode | None, delete by count, or delete by quota. |
LastSegmentsToKeep | unsigned int | Retention count used with OldSegmentDelete_OnCount. |
DiskSpaceQuota | unsigned long | Retention quota used with OldSegmentDelete_OnQuota. The native code treats this as megabytes. |
MinFlushInterval | int | Minimum flush interval in milliseconds. -1 disables explicit flushing. |
MinWriteSize | unsigned int | Buffered write threshold in bytes. |
Enumerations
The public header also exports these enums:
Recorder_EventError_TypeITSRecorderState::TSRecorderStateFileSegmentationTypeOldSegmentDeleteMode
See the separate Recorder Events page for the event list.
Native C++ Methods
| Method | Description |
|---|---|
Init(const NetSourceProps&, const FileTargetProps&) | Stores configuration, validates segmentation settings, creates the target directory when needed, and raises Initialized on success. |
SetRecaster(const NetRecasterProps&) | Enables optional UDP recasting before or during recording setup. |
Start() | Starts the UDP client and processing thread. Returns false if called in the wrong state. |
Stop() | Stops input, finalizes the current segment, and raises Stopped. |
Close() | Releases the recorder resources. Call this before deleting the object. |
SetEventListener(...) | Registers the recorder and error callbacks plus a caller-provided context pointer. |
GetCurrentSegmentPath() | Returns the full path of the current output file. |
GetTotalReceivedSize() | Returns the total received byte count for the current session. |
GetTotalRecordedSize() | Returns the total recorded byte count for the current session. |
GetCurrentSegmentReceivedSize() | Returns bytes received for the current segment. |
GetCurrentSegmentRecordedSize() | Returns bytes written for the current segment. |
GetCurrentSegmentIndex() | Returns the current segment index. |
GetRecordingBitrate() | Returns the average bitrate since the previous bitrate query. |
GetProgress() | Returns segment progress as a percentage. In segmented mode it is based on the current duration or size threshold and capped at 100. |
Callback Contracts
Native Callbacks
typedef void (__stdcall *TSRECORDER_EVENT_CALLBACK)(
Recorder_Event ev,
LPCSTR description,
__int64 param,
void* context);
typedef void (__stdcall *TSRECORDER_ERROR_CALLBACK)(
Error_Type e,
LPCSTR description,
void* context);
The description and param values are event-specific. For the segment lifecycle events, the implementation uses the following values:
SegmentStarted:descriptionis the full segment path,paramis the segment indexSegmentCompleted:descriptionis the full segment path,paramis the segment indexWaitingForData:paramis the configured timeout in millisecondsDetectionCompleted:paramcarries the detected video PID when one is found
Managed Delegates
public delegate void NotifyRecorderEvent(
Recorder_Event ev,
string info,
long param,
object context);
public delegate void NotifyError(
Error_Type e,
string err,
object context);
The wrapper passes the recorder Id object as the managed context argument.
Managed Wrapper Surface
The managed wrapper mirrors the native recording functions and adds activation support.
Main Members of ITSRecorderWr
| Member | Description |
|---|---|
Activate(appName, licPath, key) | Activates the licensed feature set. |
GetNodeInfo() | Returns host information used for licensing and support. |
Init(NetSourcePropsWr, FileTargetPropsWr) | Managed equivalent of the native Init(...). |
SetRecaster(NetRecasterPropsWr) | Managed equivalent of the native SetRecaster(...). |
Start(), Stop(), Close() | Recorder lifecycle methods. |
GetTotalReceivedSize(), GetTotalRecordedSize() | Session totals. |
GetCurrentSegmentReceivedSize(), GetCurrentSegmentRecordedSize() | Current-segment totals. |
GetCurrentSegmentIndex() | Current segment index. |
GetCurrentSegmentPath() | Current segment full path. |
GetRecordingBitrate() | Bitrate since the previous query. |
GetProgress() | Progress percentage for the current segment. |
RecorderEvent | Recorder event notification. |
ErrorEvent | Error notification. |
Id, Name | Caller-supplied identity values from CTSRecorderWr. |
RecorderState | Wrapper-side state that is updated from core events. |
SessionDuration | Elapsed time since the session start. |
LastError | Last error text observed by the wrapper. |
SourceProps, TargetProps | Last source and target objects passed to Init(...). |
Wrapper Property Types
NetSourcePropsWr, NetRecasterPropsWr, and FileTargetPropsWr map directly to the native structures, with two notable differences:
FileTargetPropsWr.SegmentDurationis aTimeSpanFileTargetPropsWr.DiskSpaceQuotais documented and passed as megabytes
Managed Wrapper Notes
CTSRecorderWris constructed asCTSRecorderWr(Object^ id, String^ name).- The wrapper rejects
Init(...)if the source IP is missing. - The wrapper rejects
SetRecaster(...)if the recast IP is missing. - The current implementation stores only one handler for
RecorderEventand one handler forErrorEvent.
Recorder Segment Naming Convention
The recorder has two naming layers:
- The native recorder generates the actual transport-stream file paths.
- The HLS wrapper reuses those
.tsfiles and adds playlist-specific naming rules.
Native TS Segment Files
The native recorder does not write directly to BaseName.
Instead, it splits BaseName into a stem and an extension, then generates the actual filename in the following format:
<stem>_<index>_<YYYY>_<MM>_<DD>_<HH>_<MM>_<SS><extension>
Example:
BaseName: capture.ts
StartIndex: 42
Generated file: capture_42_2026_03_25_14_07_11.ts
Native naming rules:
- The timestamp uses local system time.
- The timestamp has one-second resolution.
- The numeric index starts from
StartIndex. - The segment index is incremented after each completed segment.
- If
BaseNamehas no extension, the generated files are also extensionless. - Even when segmentation is disabled, the recorder still creates the output path through the same naming function, so the single output file also receives the index and timestamp suffix.
HLS Media Segments And Playlists
When you initialize HLS recording with InitHls(srcUrl, trgtManifest, ...), the wrapper derives segment names from the target manifest path:
- The video playlist path is exactly
trgtManifest. - The native segment
BaseNamebecomesPath.ChangeExtension(trgtManifest, ".ts"). - Because of that, the underlying HLS media files still use the native filename pattern.
Example:
Target manifest: C:/Recordings/live.m3u8
Derived BaseName: C:/Recordings/live.ts
First segment file: C:/Recordings/live_0_2026_03_25_14_07_11.ts
The HLS manifest stores only the file name portion of each segment path, not the full absolute path. In the example above, the playlist entry is:
live_0_2026_03_25_14_07_11.ts
If CreateMasterManifest is enabled, the wrapper creates the master playlist as:
Master-<video-manifest-stem>.m3u8
Example:
Target manifest: live.m3u8
Master manifest: Master-live.m3u8
HLS Discontinuity Split Names
If SplitSegmentOnHlsDiscontinuity is enabled and the wrapper detects a PTS discontinuity inside one recorded .ts file, it physically cuts that file into sub-segments.
The first sub-segment is named:
<generated-segment-stem>-1.ts
Additional sub-segments continue the same suffix sequence:
<generated-segment-stem>-2.ts
<generated-segment-stem>-3.ts
Example:
Original recorded segment: live_0_2026_03_25_14_07_11.ts
Split sub-segments:
live_0_2026_03_25_14_07_11-1.ts
live_0_2026_03_25_14_07_11-2.ts
After the split files are created, the original unsplit file is scheduled for deletion and the manifest is updated to reference the split files.
Internal Temporary Files
During finalized-manifest generation and duration collection, the wrapper may create a temporary copy of the currently open segment using this pattern:
<generated-segment-stem>_last.ts
Example:
live_12_2026_03_25_14_20_00_last.ts
This _last file is an internal helper for analysis and finalization. It is not the steady-state segment naming convention used for normal recording output.
Retention And Naming Interaction
OldSegmentDelete_OnCounttracks only segments created during the current session.OldSegmentDelete_OnQuotascans the target directory for existing files that share the same extension asBaseName, sorts them by last write time, and deletes the oldest ones first.- Because quota deletion is extension-based, using a dedicated directory for each recorder output is the safest way to avoid unrelated files being treated as recorder segments.
Practical Guidance
- Always provide
BaseNamewith the extension you want on the final files. - Use a dedicated output directory when retention-by-quota is enabled.
- Treat
GetRecordingBitrate()as a delta measurement, not a lifetime average. - Call
Close()even afterStop()so that internal resources are released deterministically.