use std::time::Duration;
use clap::{ArgGroup, Args, Parser, Subcommand};
use crate::publish::PublishFormat;
use crate::subscribe::{CatalogFormatArg, SubscribeFormat};
#[derive(Parser, Clone)]
#[command(name = "moq", version = env!("VERSION"))]
pub struct Cli {
#[command(flatten)]
pub log: moq_native::Log,
#[command(flatten)]
pub moq: MoqSide,
#[command(subcommand)]
pub direction: Direction,
}
#[derive(Args, Clone)]
#[command(group = ArgGroup::new("moq").required(true).multiple(true).args(["client-connect", "server-bind"]))]
pub struct MoqSide {
#[arg(long, alias = "name", help_heading = "MoQ")]
pub broadcast: Option<String>,
#[command(flatten)]
pub client: moq_native::ClientConfig,
#[command(flatten)]
pub server: moq_native::ServerConfig,
#[cfg(feature = "iroh")]
#[command(flatten)]
pub iroh: moq_native::iroh::EndpointConfig,
}
#[derive(Subcommand, Clone)]
pub enum Direction {
Import(Import),
Export(Export),
}
#[derive(Args, Clone)]
pub struct Import {
#[command(subcommand)]
pub source: ImportSource,
}
#[derive(Subcommand, Clone)]
pub enum ImportSource {
Avc3,
Fmp4,
Ts,
Flv,
Hls(crate::hls::ImportArgs),
Rtmp(crate::rtmp::Args),
Srt(crate::srt::Args),
Rtc(crate::rtc::Args),
}
impl ImportSource {
pub fn stdin_format(&self) -> Option<PublishFormat> {
Some(match self {
Self::Avc3 => PublishFormat::Avc3,
Self::Fmp4 => PublishFormat::Fmp4,
Self::Ts => PublishFormat::Ts,
Self::Flv => PublishFormat::Flv,
_ => return None,
})
}
}
#[derive(Args, Clone)]
pub struct Export {
#[arg(long = "catalog-format")]
pub catalog_format: Option<CatalogFormatArg>,
#[command(subcommand)]
pub sink: ExportSink,
}
#[derive(Subcommand, Clone)]
pub enum ExportSink {
Fmp4(Fragmented),
Mkv(Fragmented),
Ts(Container),
Flv(Container),
Hls(crate::hls::ExportArgs),
Rtmp(crate::rtmp::ExportArgs),
Srt(crate::srt::Args),
Rtc(crate::rtc::Args),
}
impl ExportSink {
pub fn stdout(&self) -> Option<(SubscribeFormat, Duration, Option<Duration>)> {
Some(match self {
Self::Fmp4(args) => (
SubscribeFormat::Fmp4,
args.container.latency_max,
args.fragment_duration,
),
Self::Mkv(args) => (SubscribeFormat::Mkv, args.container.latency_max, args.fragment_duration),
Self::Ts(args) => (SubscribeFormat::Ts, args.latency_max, None),
Self::Flv(args) => (SubscribeFormat::Flv, args.latency_max, None),
_ => return None,
})
}
}
#[derive(Args, Clone)]
pub struct Container {
#[arg(long = "latency-max", default_value = "500ms", value_parser = humantime::parse_duration)]
pub latency_max: Duration,
}
#[derive(Args, Clone)]
pub struct Fragmented {
#[command(flatten)]
pub container: Container,
#[arg(long, value_parser = humantime::parse_duration)]
pub fragment_duration: Option<Duration>,
}