dub

package
v1.4.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 24, 2026 License: MIT Imports: 26 Imported by: 0

Documentation

Overview

Package dub implements the OrcaDub MCP server internals: the HTTP client and the MCP tool layer. ALL submit/query requests go through the OrcaRouter gateway (https://api.orcarouter.ai) — the officially documented integration surface (see /api-docs): the gateway routes requests to the orca/dub model by the `model` field, wraps billing, and scopes task ids. Direct dub-server routes (native /api/v1/dub/*, GET /v1/videos list, DELETE, cancel) are NOT exposed by the gateway and therefore not offered here. Wire shapes reuse internal/quality/openai

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func RegisterTools

func RegisterTools(s *mcp.Server, c *Client)

RegisterTools wires every tool onto the server. The surface is exactly the OrcaRouter gateway's documented dub lifecycle (upload → create → poll → download); list/cancel/delete/native-detail are not exposed by the gateway. Annotations follow the MCP spec so hosts can pick approval policies: health/get are read-only; upload/create/download are additive (non-destructive) and non-idempotent; everything talks to an external service (open world).

func RunCLI added in v1.1.0

func RunCLI(args []string) int

RunCLI executes one CLI subcommand. args is os.Args[1:] (args[0] is the subcommand). Success prints result JSON to stdout and returns 0; failures print to stderr and return 1; an unknown subcommand returns 2.

Types

type Client

type Client struct {
	// contains filtered or unexported fields
}

Client issues authenticated HTTP calls to the OrcaRouter gateway.

func NewClient

func NewClient(cfg Config) *Client

NewClient builds a Client. Timeout is generous because uploads and downloads stream video bytes through this process.

func (*Client) CreateVideo

func (c *Client) CreateVideo(ctx context.Context, req *CreateVideoRequest) (Video, error)

CreateVideo calls POST /v1/videos through the gateway, forcing the model=orca/dub routing field.

func (*Client) DownloadContent

func (c *Client) DownloadContent(ctx context.Context, id, dest string) (int64, error)

DownloadContent streams the finished mp4 into dest and returns the byte count. It resolves the gateway task id to the underlying job first (the origin content route is the reliable delivery path), then streams from the URL GetVideo derived. Refuses to overwrite an existing file.

func (*Client) GetVideo

func (c *Client) GetVideo(ctx context.Context, id string) (GatewayVideo, error)

GetVideo calls GET /v1/videos/{id} on the gateway. The id must come from a job submitted through the gateway (gateway task ids are its own scope). On completed jobs the response gains content_url pointing at the origin's content route for the underlying job.

func (*Client) Health

func (c *Client) Health(ctx context.Context) (HealthResult, error)

Health probes the gateway → orca/dub route end to end without creating a job: POST /v1/videos with only the model field must come back as the dub service's own "source_lang is required" validation error. Any other reply (gateway "Model name not specified", auth failure, network error) means the chain is broken and is surfaced verbatim.

func (*Client) UploadFile

func (c *Client) UploadFile(ctx context.Context, path, purpose string) (FileObject, error)

UploadFile pushes a local file through the gateway and returns the resulting FileObject whose ID feeds dub_create's file_id. Files at or under directUploadLimit go through single-request POST /v1/files; larger files walk the OpenAI Uploads chain (create → parts → complete).

type CompleteUploadRequest

type CompleteUploadRequest struct {
	PartIDs []string `json:"part_ids"`
	MD5     string   `json:"md5,omitempty"`
}

CompleteUploadRequest is the JSON body of POST /v1/uploads/{id}/complete.

type Config

type Config struct {
	BaseURL string // OrcaRouter gateway origin; gatewayBaseURL outside tests
	APIKey  string // REQUIRED Authorization: Bearer credential (OrcaRouter sk-orca key)
}

Config carries the MCP server's runtime configuration. The gateway origin is fixed in code (gatewayBaseURL); the ONLY environment input is the ORCADUB_API_KEY credential. BaseURL stays a struct field solely so tests can point the client at an httptest server.

func LoadConfig

func LoadConfig() Config

LoadConfig reads ORCADUB_API_KEY. A missing key does NOT fail startup — the server comes up and every tool call returns errNotAuthorized instead, so the calling agent can redirect the user to the OrcaRouter console to register; once the key is set (and the session restarted) authentication passes automatically.

type CreateInput

type CreateInput struct {
	SourceLang string `` /* 180-byte string literal not displayed */
	TargetLang string `json:"target_lang" jsonschema:"REQUIRED — ask the user if not stated. Target language code; auto is not allowed"`
	FileID     string `` /* 154-byte string literal not displayed */
	URL        string `` /* 137-byte string literal not displayed */
	VideoName  string `` /* 127-byte string literal not displayed */
	// Content / translation knobs.
	Profile          string            `` /* 138-byte string literal not displayed */
	TranslationStyle string            `` /* 135-byte string literal not displayed */
	Glossary         map[string]string `json:"glossary,omitempty" jsonschema:"pinned source→target term renderings, max 64 entries"`
	AdaptIdioms      *bool             `json:"adapt_idioms,omitempty" jsonschema:"render idioms as natural target-language equivalents; empty = deploy default"`
	CometEnabled     *bool             `json:"comet_enabled,omitempty" jsonschema:"COMET translation-quality gate; empty = deploy default"`
	// Voice / TTS knobs.
	TTSBackend         string            `json:"tts_backend,omitempty" jsonschema:"TTS backend id (qwen3 | higgs); empty = deploy default"`
	SongTranslation    *bool             `json:"song_translation,omitempty" jsonschema:"dub sung segments instead of passing original audio through; empty = false"`
	ProjectID          string            `json:"project_id,omitempty" jsonschema:"dubbing project id for cross-job character voice memory"`
	SpeakerAssignments map[string]string `json:"speaker_assignments,omitempty" jsonschema:"ASR diarization label → character id map; requires project_id"`
	VoiceCloneConsent  bool              `json:"voice_clone_consent,omitempty" jsonschema:"attest the caller holds rights/consent to clone voices in the source"`
	// Audio bed / mix knobs.
	PreserveBGM     *bool   `json:"preserve_bgm,omitempty" jsonschema:"keep background music via source separation; empty = deploy default"`
	BedLevelMatch   *bool   `json:"bed_level_match,omitempty" jsonschema:"match bed loudness to broadcast level; empty = deploy default"`
	BedDuck         *bool   `json:"bed_duck,omitempty" jsonschema:"duck the bed under dialog; empty = deploy default"`
	BedReverbPreset *string `json:"bed_reverb_preset,omitempty" jsonschema:"bed reverb: none | small_room | hall | outdoor; empty = deploy default"`
	LoudnessEnabled *bool   `json:"loudness_enabled,omitempty" jsonschema:"EBU R128 loudness-match gate on the final mux; empty = deploy default"`
	// Alignment / video output knobs.
	AlignPerWord         *bool  `json:"align_per_word,omitempty" jsonschema:"per-word forced-alignment atempo; empty = deploy default"`
	Lipsync              *bool  `json:"lipsync,omitempty" jsonschema:"enable lipsync; empty = deploy default"`
	LipsyncVisemes       *bool  `json:"lipsync_visemes,omitempty" jsonschema:"viseme-aware lipsync plan; empty = deploy default"`
	LipsyncIdentityGuard *bool  `json:"lipsync_identity_guard,omitempty" jsonschema:"post-lipsync face-identity guard; empty = deploy default"`
	Watermark            *bool  `json:"watermark,omitempty" jsonschema:"burn watermark; empty = deploy default"`
	RemoveWatermark      *bool  `` /* 147-byte string literal not displayed */
	Resolution           string `json:"resolution,omitempty" jsonschema:"output height: source | 720p | 1080p | 2k; empty = 720p"`
	Ratio                string `json:"ratio,omitempty" jsonschema:"output canvas: source | 16:9 | 9:16 | 1:1; empty = source"`
	CompactOutput        *bool  `json:"compact_output,omitempty" jsonschema:"re-encode final mp4 smaller (720p cap, crf 28); empty = false"`
}

CreateInput is the dub_create tool surface — the FULL per-job parameter set of POST /v1/videos. The model=orca/dub gateway routing field is attached automatically. Required fields (source_lang, target_lang, the file_id/url source, video_name with file_id) must come from the USER — the calling agent is instructed (skill + schema descriptions) to ask rather than guess. Only multi-request orchestration fields (batch_id/ batch_total/group_id) and the admin-only bench_run_id stay unexposed.

type CreateVideoRequest

type CreateVideoRequest struct {
	Prompt                 string            `json:"prompt,omitempty"`
	VideoPath              *VideoPath        `json:"video_path,omitempty"`
	Model                  string            `json:"model,omitempty"`
	Seconds                string            `json:"seconds,omitempty"`
	Size                   string            `json:"size,omitempty"`
	SourceLang             string            `json:"source_lang,omitempty"`
	TargetLang             string            `json:"target_lang,omitempty"`
	Profile                string            `json:"profile,omitempty"`
	Lipsync                *string           `json:"lipsync,omitempty"`
	LipsyncVisemes         *string           `json:"lipsync_visemes,omitempty"`
	LipsyncIdentityGuard   *string           `json:"lipsync_identity_guard,omitempty"`
	PreserveBGM            *string           `json:"preserve_bgm,omitempty"`
	Watermark              *string           `json:"watermark,omitempty"`
	RemoveWatermark        *string           `json:"remove_watermark,omitempty"`
	BedLevelMatch          *string           `json:"bed_level_match,omitempty"`
	BedDuck                *string           `json:"bed_duck,omitempty"`
	BedReverbPreset        *string           `json:"bed_reverb_preset,omitempty"`
	AlignPerWord           *string           `json:"align_per_word,omitempty"`
	CometEnabled           *string           `json:"comet_enabled,omitempty"`
	LoudnessEnabled        *string           `json:"loudness_enabled,omitempty"`
	AdaptIdiomsEnabled     *string           `json:"adapt_idioms_enabled,omitempty"`
	SongTranslationEnabled *string           `json:"song_translation_enabled,omitempty"`
	CompactOutput          *string           `json:"compact_output,omitempty"`
	Resolution             string            `json:"resolution,omitempty"`
	Ratio                  string            `json:"ratio,omitempty"`
	ProjectID              string            `json:"project_id,omitempty"`
	SpeakerAssignments     map[string]string `json:"speaker_assignments,omitempty"`
	Glossary               map[string]string `json:"glossary,omitempty"`
	VoiceCloneConsent      bool              `json:"voice_clone_consent,omitempty"`
	TTSBackend             string            `json:"tts_backend,omitempty"`
	TranslationStyle       string            `json:"translation_style,omitempty"`
	VideoName              string            `json:"video_name,omitempty"`
}

CreateVideoRequest is the JSON body of POST /videos. Dub-specific knobs ride along as extra_body fields; boolean knobs are *string "true"/"false" on the wire (the server treats nil/empty as "use deploy default").

type DownloadInput

type DownloadInput struct {
	VideoID string `json:"video_id" jsonschema:"the completed job/video id"`
	Dest    string `json:"dest" jsonschema:"absolute local path to write the MP4 (must not already exist)"`
}

DownloadInput saves a completed job's MP4 locally.

type FileObject

type FileObject struct {
	ID        string `json:"id"`
	Bytes     int64  `json:"bytes"`
	CreatedAt int64  `json:"created_at"`
	Filename  string `json:"filename"`
	Object    string `json:"object"`
	Purpose   string `json:"purpose"`
	Status    string `json:"status"`
	ExpiresAt *int64 `json:"expires_at,omitempty"`
}

FileObject mirrors OpenAI's FileObject (POST /files).

type GatewayVideo

type GatewayVideo struct {
	Video
	JobID string `json:"job_id,omitempty"`
	// ContentURL is the delivery address of the finished video. It requires
	// the same Authorization: Bearer header as every other call
	// (curl -H "Authorization: Bearer sk-orca-..." <content_url>), or use
	// dub_download which sends it automatically.
	ContentURL string `json:"content_url,omitempty"`
}

GatewayVideo is Video plus gateway-specific fields: job_id (the underlying dub job uuid the gateway maps the task to) and content_url (the delivery address of the finished mp4 — the gateway retrieve strips output_url by design, so the client derives the origin content route from job_id; the origin re-signs the object freshly on every request).

type GetInput

type GetInput struct {
	VideoID string `json:"video_id" jsonschema:"the job id returned by dub_create (gateway task ids are gateway-scoped)"`
}

GetInput identifies one gateway-submitted job.

type HealthInput

type HealthInput struct{}

HealthInput has no fields (empty object schema).

type HealthResult

type HealthResult struct {
	Status  string `json:"status"` // ok | degraded
	Gateway string `json:"gateway"`
	Detail  string `json:"detail"`
}

HealthResult is dub_health's report.

type Upload

type Upload struct {
	ID        string      `json:"id"`
	Object    string      `json:"object"`
	Bytes     int64       `json:"bytes"`
	CreatedAt int64       `json:"created_at"`
	ExpiresAt int64       `json:"expires_at"`
	Filename  string      `json:"filename"`
	Purpose   string      `json:"purpose"`
	Status    string      `json:"status"`
	File      *FileObject `json:"file,omitempty"`
}

Upload mirrors OpenAI's Upload object (POST /v1/uploads chain). Once status="completed", File carries the materialised FileObject whose id feeds video_path.file_id.

type UploadInput

type UploadInput struct {
	Path    string `json:"path" jsonschema:"absolute path of the local video file to upload"`
	Purpose string `json:"purpose,omitempty" jsonschema:"OpenAI file purpose; default user_data"`
}

UploadInput selects a local file to push through the gateway.

type UploadPart

type UploadPart struct {
	ID        string `json:"id"`
	Object    string `json:"object"`
	UploadID  string `json:"upload_id"`
	CreatedAt int64  `json:"created_at"`
}

UploadPart mirrors OpenAI's UploadPart object (POST /v1/uploads/{id}/parts).

type Video

type Video struct {
	ID              string      `json:"id"`
	Name            string      `json:"name,omitempty"`
	Object          string      `json:"object"`
	Status          string      `json:"status"` // queued|in_progress|completed|failed
	Progress        int         `json:"progress"`
	CreatedAt       int64       `json:"created_at"`
	CompletedAt     *int64      `json:"completed_at,omitempty"`
	StartedAt       *int64      `json:"started_at,omitempty"`
	EndedAt         *int64      `json:"ended_at,omitempty"`
	ExpiresAt       *int64      `json:"expires_at,omitempty"`
	Model           string      `json:"model"`
	Prompt          string      `json:"prompt"`
	Seconds         string      `json:"seconds"`
	Size            string      `json:"size"`
	SourceLang      string      `json:"source_lang,omitempty"`
	TargetLang      string      `json:"target_lang,omitempty"`
	DurationSeconds *int32      `json:"duration_seconds,omitempty"`
	OutputURL       string      `json:"output_url,omitempty"`
	Error           *VideoError `json:"error,omitempty"`
}

Video mirrors OpenAI's Video object (POST /videos / GET /videos/{id}) with the OrcaDub extension fields the gateway serves.

type VideoError

type VideoError struct {
	Code    string `json:"code"`
	Message string `json:"message"`
}

VideoError matches OpenAI's VideoCreateError envelope.

type VideoPath

type VideoPath struct {
	URL    string `json:"url,omitempty"`
	FileID string `json:"file_id,omitempty"`
}

VideoPath carries the source video reference: exactly one of file_id (a previously uploaded file) or url (http(s) remote video, fetched server-side).

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL