Architecture Overview
EZInfiniteYTLive follows a simple two-layer architecture typical of small WinForms utilities: a UI layer (Form1) and a worker layer (VideoStreamer) that does the actual work on a background thread, keeping the UI responsive.
High-level flow
Components
Program (entry point)
Starts the WinForms message loop and shows Form1. See API Reference → Program.
Form1 (UI / controller)
- Owns the UI state: selected folder, shuffle flag, FFmpeg path.
- Validates user input (folder exists, RTMP URL/stream key present, and FFmpeg is resolvable).
- Builds the full RTMP destination string.
- Creates, starts, stops, and disposes a single
VideoStreamerinstance per stream session. - Never touches FFmpeg directly — it delegates all of that to
VideoStreamer.
VideoStreamer (streaming engine)
- Pure logic class (no UI dependencies), implementing
IDisposable. - Recursively scans a folder for files with recognized video extensions, taking a fresh snapshot after every playlist pass.
- Runs a dedicated background
Threadthat loops forever over an alphabetically sorted or shuffled file list. - For each file, spawns an
ffmpegprocess (Process+ProcessStartInfo) that stream-copies (-c copy) the file to the destination RTMP URL using the FLV container (-f flv), as required by the RTMP protocol. - Waits for each FFmpeg process to exit before moving to the next file (
process.WaitForExit()), which gives the "continuous playback" illusion as videos play back-to-back. - Reports scan, startup, and FFmpeg exit errors through
ErrorOccurred. - Exposes
StartStreaming()/StopStreaming()/Dispose()to control the lifecycle from the UI thread.
See API Reference → VideoStreamer.
Concurrency model
StartStreaming()spawns a single backgroundThread(IsBackground = true, so it won't prevent app exit).- That thread owns the loop; it is the only thread that starts FFmpeg processes.
StopStreaming()(called from the UI thread) sets a_stopRequestedflag and force-kills the currently running FFmpeg process viaProcess.Kill(), which unblocks the background thread'sWaitForExit()call so the loop can observe_stopRequestedand exit promptly.- Because only one
_ffmpegProcessfield is tracked at a time, only one FFmpeg process is ever running perVideoStreamerinstance.
Design characteristics & trade-offs
- Simplicity over configurability: no playlist persistence, no re-encoding options, no bitrate/resolution controls exposed in the UI — this keeps the tool approachable, but also limits flexibility.
- Stream copy (
-c copy): avoids CPU-intensive re-encoding, so the app can run24/7 on modest hardware, but requires your source files to already be in an RTMP/FLV-compatible codec. - Recursive, extension-filtered folder scan: nested folders are included, and each pass reflects files added or removed while streaming.
- Thread + Process, not
async/await: the codebase favors a classic dedicated-thread + blocking-process model, which is simple to reason about for a single always-on worker loop.