OutputMeta enables usage-based pricing by reporting what your app processes and generates.
Basic Structure
1from inferencesh import BaseAppOutput, OutputMeta, TextMeta, ImageMeta, VideoMeta, AudioMeta23class AppOutput(BaseAppOutput):4 result: File = Field(description="Generated output")5 # output_meta is inherited from BaseAppOutputMetaItem Types
| Type | Class | Key Fields |
|---|---|---|
| Text | TextMeta | tokens |
| Image | ImageMeta | width, height, resolution_mp, steps, count |
| Video | VideoMeta | width, height, resolution, resolution_mp, seconds, fps |
| Audio | AudioMeta | seconds |
Examples
LLM/Text Generation
Track both input (prompt) and output (completion) tokens:
1from inferencesh.models.usage import OutputMeta, TextMeta23# In your run method, after getting the response:4return AppOutput(5 response=generated_text,6 output_meta=OutputMeta(7 inputs=[TextMeta(tokens=prompt_tokens)],8 outputs=[TextMeta(tokens=completion_tokens)]9 )10)For streaming responses, update token counts from the final chunk:
1# Track usage from stream chunks2if hasattr(chunk, "usage") and chunk.usage:3 input_tokens = chunk.usage.prompt_tokens4 output_tokens = chunk.usage.completion_tokens56# Build output with token tracking7output_meta = OutputMeta(8 inputs=[TextMeta(tokens=input_tokens)] if input_tokens else [],9 outputs=[TextMeta(tokens=output_tokens)] if output_tokens else []10)Image Generation
1return AppOutput(2 image=File(path=output_path),3 output_meta=OutputMeta(4 outputs=[ImageMeta(5 width=1024,6 height=1024,7 resolution_mp=1.05,8 steps=20,9 count=110 )]11 )12)Video Generation
Prefer probing the output file instead of hardcoding dimensions and duration:
1from inferencesh import VideoMeta, OutputMeta23return AppOutput(4 video=File(path=output_path),5 output_meta=OutputMeta(6 outputs=[7 VideoMeta.from_file(8 output_path,9 resolution="720p",10 resolution_mp=0.92,11 )12 ]13 )14)VideoMeta.from_file() and probe_video() ship in inferencesh ≥ v0.7.10. They call ffprobe (from the ffmpeg apt package — add ffmpeg to packages.txt).
Audio Generation
1return AppOutput(2 audio=File(path=output_path),3 output_meta=OutputMeta(4 outputs=[AudioMeta(seconds=30.0)]5 )6)Probing video files (Python)
When your app writes a video to disk, use the SDK helpers to populate VideoMeta from the actual file:
1from inferencesh import probe_video, VideoMeta23# Low-level: returns a dict (empty on failure)4info = probe_video("/path/to/output.mp4")5# keys: width, height, fps, nb_frames, seconds67# High-level: builds VideoMeta with probed fields8meta = VideoMeta.from_file(9 "/path/to/output.mp4",10 resolution="1080p", # optional kwargs pass through11 extra={"model": "kling"},12)Duration calculation: seconds is nb_frames / fps (frame-accurate), not container metadata. This matches how upstream video APIs (e.g. BytePlus) bill on frame count.
Failure behavior: If ffprobe is missing, times out (10s), or cannot read a video stream, probe_video() returns {} and VideoMeta.from_file() falls back to zero values for probed fields. Pass explicit resolution or other kwargs when you need non-zero metadata on probe failure.
Both helpers are exported from inferencesh and inferencesh.models.output_meta.
Custom Data
Use extra for app-specific pricing factors:
1output_meta=OutputMeta(2 outputs=[ImageMeta(3 width=1024,4 height=1024,5 extra={6 "model": "sdxl-turbo",7 "lora_count": 28 }9 )]10)Public API visibility
output_meta is pricing metadata for the platform. App authors should always set it on task output, but it is not returned on public surfaces:
| Surface | What you see |
|---|---|
Task output (REST, WebSocket, SDK) | output_meta is extracted at write time; only your app's user-facing fields remain in output |
App output_schema (version DTO, app store, Grid) | output_meta is stripped from schemas at deploy and on read |
Your app code still returns output_meta in AppOutput / run results — the backend stores it for usage-based billing and CEL pricing formulas. Do not rely on clients reading output_meta from completed tasks or published schemas.
Best Practices
- Always populate
output_metaif usage varies per request - Use accurate token counts from the actual tokenizer
- Report actual dimensions — for video, use
VideoMeta.from_file()instead of hardcoding width, height, fps, or seconds - Include relevant
extradata for pricing flexibility
Next
→ Usage-based pricing — CEL formulas that read output_meta
→ Secrets — API keys and sensitive values