OpenAILLMService or CartesiaTTSService, utilities, like UserIdleProcessor, and other things. Largely, you can build most of your application with these built-in FrameProcessors, but commonly, your application code may require custom frame processing logic. For example, you may want to perform an action as a result of a frame that’s pushed in the pipeline.
Example: MetricsFrame logger
This custom FrameProcessor format and logs MetricsFrames:MetricsFrames. When it sees one, it formats the data and logs it.
It uses this format_metrics function:
See this working
example
using the
MetricsFrameLogger FrameProcessorAdd to a Pipeline
Critical Responsibility: Frame Forwarding
FrameProcessors receive all frames that are pushed through the pipeline. This gives them a lot of power, but also a great responsibility. Critically, they must push all frames through the pipeline; if they don’t, they block frames from moving through the Pipeline, which will cause issues in how your application functions. As well as formatting and logging MetricsFrames,MetricsFrameLogger also has an await self.push_frame(frame, direction) which pushes the frame through to the next processor in the pipeline.
Frame Direction
When pushing frames, you can specify the direction:Best Practices
- Always call the parent methods: Use
super().__init__()andawait super().process_frame() - Forward all frames: Make sure every frame is pushed through with
await self.push_frame(frame, direction) - Handle frames conditionally: Use
isinstance()checks to handle specific frame types - Use proper error handling: Wrap risky operations in try/catch blocks
- Position carefully in pipeline: Consider where in the pipeline your processor needs to be to receive the right frames