pub struct RtmpClient { /* private fields */ }Implementations§
Source§impl RtmpClient
impl RtmpClient
Sourcepub fn connect(url: &str) -> Result<Self>
pub fn connect(url: &str) -> Result<Self>
Dial the given rtmp://host[:port]/app/stream_name URL,
perform the full handshake + connect + createStream + publish
sequence, and return a ready-to-send client.
Sourcepub fn connect_with_type(url: &str, publish_type: &str) -> Result<Self>
pub fn connect_with_type(url: &str, publish_type: &str) -> Result<Self>
Same as connect but lets the caller pick the
RTMP publish type (typically "live", "record", or
"append").
Sourcepub fn connect_with_capabilities(
url: &str,
publish_type: &str,
caps: &ConnectCapabilities,
) -> Result<Self>
pub fn connect_with_capabilities( url: &str, publish_type: &str, caps: &ConnectCapabilities, ) -> Result<Self>
Connect and advertise the supplied Enhanced RTMP v1+v2
capability block in the NetConnection connect command
(enhanced-rtmp-v2.pdf §“Enhancing NetConnection connect
Command”). The block is appended to the legacy Command Object
in the documented order — peers that don’t speak E-RTMP keep
parsing the message correctly because the extras are tacked on
after the historical videoFunction field.
The server’s _result properties object is parsed for the same
set of keys and stashed on the client; retrieve it via
server_capabilities to learn
which v1+v2 features the peer agreed to support.
Sourcepub fn server_capabilities(&self) -> &ConnectCapabilities
pub fn server_capabilities(&self) -> &ConnectCapabilities
Capability block advertised by the server in _result(connect).
Empty when the peer is pre-2023 / unaware of E-RTMP — callers can
detect that with ConnectCapabilities::is_empty. Otherwise
describes which FourCC codecs the server reports it can decode /
encode / forward, plus the v2 capsEx bitfield (Reconnect,
Multitrack, ModEx, TimestampNanoOffset).
Sourcepub fn tc_url(&self) -> &str
pub fn tc_url(&self) -> &str
The tcUrl this client dialled (e.g.
rtmp://host:1935/app) — the base every Enhanced RTMP v2
reconnect target resolves against.
Sourcepub fn resolve_reconnect_url(&self, tc_url: Option<&str>) -> String
pub fn resolve_reconnect_url(&self, tc_url: Option<&str>) -> String
Resolve the tcUrl carried by an Enhanced RTMP v2
ClientEvent::ReconnectRequest into the absolute URL to
re-dial, per enhanced-rtmp-v2.pdf §“Reconnect Request”:
None→ “use the tcUrl for the current connection”.Some(reference)→ “absolute or relative URI reference of the server to which to reconnect. A relative URI reference should be resolved relative to the tcUrl for the current connection.” All four spec example shapes are honoured:rtmp://foo.mydomain.com:1935/realtimeapp(absolute),//192.0.2.0/realtimeapp(network-path: keep our scheme),/realtimeapp(absolute-path: keep scheme + authority), andrealtimeapp(relative-path: merge onto our tcUrl’s path).
Append the stream key (/{stream_name}) and feed the result to
RtmpClient::connect to complete the spec’s reconnect flow.
Sourcepub fn send_video_sequence_header(&mut self, avc_c: &[u8]) -> Result<()>
pub fn send_video_sequence_header(&mut self, avc_c: &[u8]) -> Result<()>
Send the AVC sequence header (AVCDecoderConfigurationRecord
aka avcC). Must be called once before any NALU-carrying
send_video.
Sourcepub fn send_video(
&mut self,
timestamp_ms: u32,
is_keyframe: bool,
body: &[u8],
) -> Result<()>
pub fn send_video( &mut self, timestamp_ms: u32, is_keyframe: bool, body: &[u8], ) -> Result<()>
Send one video access unit. body is the AVCC-formatted
content (one or more [u32 length BE][NALU bytes] pairs).
is_keyframe drives the FLV frame_type bits.
Sourcepub fn send_audio_sequence_header(&mut self, asc: &[u8]) -> Result<()>
pub fn send_audio_sequence_header(&mut self, asc: &[u8]) -> Result<()>
Send the AAC AudioSpecificConfig (2 bytes for LC-AAC 44.1k
stereo: 0x12 0x10). Must be called once before any
raw-frame send_audio.
Sourcepub fn send_audio(&mut self, timestamp_ms: u32, aac_frame: &[u8]) -> Result<()>
pub fn send_audio(&mut self, timestamp_ms: u32, aac_frame: &[u8]) -> Result<()>
Send one raw AAC frame.
Sourcepub fn send_metadata(&mut self, metadata: Amf0Value) -> Result<()>
pub fn send_metadata(&mut self, metadata: Amf0Value) -> Result<()>
Send @setDataFrame("onMetaData", metadata). Metadata is an
AMF0 value, typically an ECMA array or object populated with
width, height, duration, videodatarate, framerate,
videocodecid, audiodatarate, audiocodecid, etc.
Sourcepub fn send_metadata_amf3(&mut self, metadata: Amf3Value) -> Result<()>
pub fn send_metadata_amf3(&mut self, metadata: Amf3Value) -> Result<()>
Send onMetaData as an AMF3-encoded data message (RTMP message
type 15) instead of the AMF0 default.
The body is framed per AMF 3 spec §4.1 / AMF 0 spec §3.1: the
outer NetConnection message structure is AMF0, and each value
switches to AMF3 by prefixing it with the avmplus-object-marker
(0x11). Most ingest endpoints stay on AMF0, so prefer
send_metadata; this exists for peers that
negotiated an AMF3 channel.
Sourcepub fn send_aggregate(&mut self, subs: &[Message]) -> Result<()>
pub fn send_aggregate(&mut self, subs: &[Message]) -> Result<()>
Send a batch of audio / video / data sub-messages as one Aggregate Message (RTMP 1.0 §7.1.6, message type id 22).
An aggregate trades one extra 11-byte sub-header per sub-message (plus a 4-byte back-pointer) for the chunk-header overhead the chunk writer would emit on each sub if it sent them individually. For an active publish with several A/V messages queued at the same timestamp this can cut the chunk-header surface in half.
subs carries pre-built FLV-shaped messages — typically AVC
video (type 9) and AAC audio (type 8) bodies the caller has
already framed via flv::build_video / flv::build_audio.
Caller-supplied msg_stream_id fields are overridden to this
client’s publish stream id per §7.1.6 (“the message stream ID
of the aggregate message overrides the message stream IDs of
the sub-messages”). The aggregate’s own wire timestamp is set
to the first sub’s timestamp so the §7.1.6 re-normalisation
offset is zero on the wire.
Returns the same errors as
build_aggregate plus any
I/O error from the underlying chunk writer. An empty subs
slice is a no-op.
Sourcepub fn send_ping_request(&mut self, timestamp_ms: u32) -> Result<()>
pub fn send_ping_request(&mut self, timestamp_ms: u32) -> Result<()>
Send a UserControl PingRequest (RTMP 1.0 §3.7, UCM type 6)
carrying the supplied 4-byte timestamp.
The peer is expected to echo the value back as a PingResponse
(UCM type 7), which surfaces from
poll_event as
ClientEvent::PingResponse. Typical use is round-trip-time
measurement: stamp the local monotonic clock into the request,
then subtract from the response timestamp once the matching
PingResponse arrives. The publish direction normally never
needs this — but a publisher pumping a low-bandwidth feed over
a flaky link may want to probe liveness explicitly rather than
wait for TCP keepalive.
Sourcepub fn poll_event(&mut self) -> Result<Option<ClientEvent>>
pub fn poll_event(&mut self) -> Result<Option<ClientEvent>>
Poll for one server-originated event.
Reads up to one inbound RTMP message from the server, applies
protocol-level housekeeping internally (set-chunk-size,
window-ack-size, set-peer-bandwidth, ping-request/response,
acks), and surfaces externally-visible notifications as a
ClientEvent:
UserControl StreamBegin(sid)→ClientEvent::StreamBeginUserControl StreamEOF(sid)→ClientEvent::StreamEof(mirror ofRtmpSession::close’s server-side teardown; RTMP 1.0 §7.1.7)onStatus(...)→ClientEvent::OnStatus_result(tx_id, ...)→ClientEvent::Result_error(tx_id, ...)→ClientEvent::ErrorReply- everything else →
ClientEvent::Other
Returns Ok(None) once the server has signalled a clean stream
end (StreamEOF) or once the TCP read half observes EOF /
connection-reset. After Ok(None) is returned the caller
should stop writing and finish the session with
close.
This is a blocking call. Set a finite read timeout on
inner_mut ahead of time if you want
poll_event to return periodically with an Err(Error::Io)
kind WouldBlock / TimedOut so an outer event loop can do
other work between polls — the underlying TCP read deadline is
the timeout granularity, not a poll interval.
pub fn inner_mut(&mut self) -> &mut TcpStream
Sourcepub fn set_read_timeout(&mut self, d: Option<Duration>) -> Result<()>
pub fn set_read_timeout(&mut self, d: Option<Duration>) -> Result<()>
Apply a recv timeout to the chunk reader’s actual socket
clone (the one poll_event blocks on)
rather than the session’s bookkeeping clone.
On Linux a sockopt set through one try_clone descriptor
carries to its sibling clones because they share one file
description; on Windows each clone has its own kernel handle
with independent socket options, so the timeout has to be
installed on the exact socket the recv call will issue
against. Use this rather than
inner_mut.set_read_timeout(...) when the
goal is to bound poll_event’s block time.