pub trait FrameProcessor: Send + 'static {
// Required method
fn name(&self) -> &str;
// Provided methods
fn start<'life0, 'life1, 'life2, 'async_trait>(
&'life0 mut self,
_setup: &'life1 ProcessorSetup,
_params: &'life2 StartParams,
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait { ... }
fn process_frame<'life0, 'life1, 'async_trait>(
&'life0 mut self,
env: Envelope,
link: &'life1 Link,
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait { ... }
fn stop<'life0, 'async_trait>(
&'life0 mut self,
_reason: StopReason,
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait { ... }
fn can_generate_metrics(&self) -> bool { ... }
}Expand description
The building block (PROCESSOR-DESIGN §2.1). Each processor runs in its own
tokio task fed by a bounded mpsc channel; the framework owns the task loop, an
impl writes only process_frame (and optional start/stop).
§Lifecycle frames bypass process_frame (read this before writing a processor)
The framework — not the processor — owns the lifecycle. The per-processor task
loop (run_processor) intercepts lifecycle frames and routes them to the hooks
instead of process_frame:
Frame::Start→ callsstart, then forwards.- A downstream
Frame::End/Frame::Stop/Frame::Cancel→ callsstop, forwards, and (End/Cancel) ends the task. Frame::Interruption→ drains the interruptible backlog, then forwards.
So your process_frame never sees these frames — observe lifecycle via the
start/stop hooks (this is why the internal Sink taps from the hooks). An
upstream End/Stop/Cancel is the exception: it is a “request to end” and DOES
reach process_frame (the default forwards it upstream so the Source can
convert it to a downstream drain — pipecat’s EndTaskFrame vs EndFrame). Keep
process_frame about data; do not try to handle Start/terminal frames there.
Mirrors pipecat FrameProcessor (frame_processor.py:175).
Required Methods§
Provided Methods§
Sourcefn start<'life0, 'life1, 'life2, 'async_trait>(
&'life0 mut self,
_setup: &'life1 ProcessorSetup,
_params: &'life2 StartParams,
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn start<'life0, 'life1, 'life2, 'async_trait>(
&'life0 mut self,
_setup: &'life1 ProcessorSetup,
_params: &'life2 StartParams,
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Called once when the Frame::Start frame reaches this processor, before
any data frame. Open sockets / spawn provider readers here. Default: no-op.
Sourcefn process_frame<'life0, 'life1, 'async_trait>(
&'life0 mut self,
env: Envelope,
link: &'life1 Link,
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn process_frame<'life0, 'life1, 'async_trait>(
&'life0 mut self,
env: Envelope,
link: &'life1 Link,
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Handle one frame. Push results via link. Must not block: long work
(a provider round-trip) is driven by an internally-spawned task that feeds
results back as frames. The default impl forwards the frame unchanged in
its direction — so a pure observer/no-op processor is process_frame =
default.
Sourcefn stop<'life0, 'async_trait>(
&'life0 mut self,
_reason: StopReason,
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn stop<'life0, 'async_trait>(
&'life0 mut self,
_reason: StopReason,
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Called on End/Stop/Cancel after the terminal frame is forwarded.
Flush + close. Default: no-op.
Sourcefn can_generate_metrics(&self) -> bool
fn can_generate_metrics(&self) -> bool
Whether this processor produces metrics (pipecat can_generate_metrics,
:395). Services override to true.
Dyn Compatibility§
This trait is dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety".