Use this file to discover all available pages before exploring further.
The official Go SDK for Camb.ai provides convenient access to text-to-speech, dubbing, translation, transcription, voice cloning, and audio generation. It uses functional options for configuration and returns io.Reader streams for audio output.
The module currently declares Go 1.13 as its minimum version in go.mod. Newer Go releases work with the module; use the version your team standardizes on for builds and CI.
Get your API key from Camb.ai Studio and pass it with option.WithAPIKey. Reading CAMB_API_KEY from the environment keeps secrets out of source control.
The root module is package cambai, so the default import name is cambai when you import github.com/camb-ai/cambai-go-sdk. You may also use an explicit alias (import cambai "github.com/camb-ai/cambai-go-sdk") for clarity in larger codebases. The snippets below assume the default name cambai.
Camb.ai offers MARS models tuned for different quality and latency needs. Set SpeechModel on CreateStreamTtsRequestPayload using the generated constants (for example CreateStreamTtsRequestPayloadSpeechModelMarsFlash). If you omit it, the API applies its default model.
Model
Sample Rate
Best For
mars-8.1-flash-beta
48 kHz
Faster MARS 8.1 generation; same quality improvements as mars-8.1-pro-beta
mars-8.1-pro-beta
48 kHz
Improved pronunciation, expressiveness, and prosody over mars-pro
mars-flash
22.05 kHz
Low-latency real-time applications and conversational AI
mars-pro
48 kHz
High-fidelity audio production and long-form content
mars-instruct
22.05 kHz
Fine-grained tone and style control via text instructions
MARS Flash
MARS Pro
MARS Instruct
stream, err := c.TextToSpeech.Tts(ctx, &cambai.CreateStreamTtsRequestPayload{ Text: "Hey, I can respond much faster.", Language: cambai.CreateStreamTtsRequestPayloadLanguageEnUs, VoiceID: 147320, SpeechModel: cambai.CreateStreamTtsRequestPayloadSpeechModelMarsFlash.Ptr(), OutputConfiguration: &cambai.StreamTtsOutputConfiguration{ Format: cambai.OutputFormatWav.Ptr(), },})if err != nil { panic(err)}_ = stream
Best for: Voice agents and real-time applications.Sample rate: 22.05 kHz.
VoiceCloning.ListVoices returns the voices available to your account.
voices, err := c.VoiceCloning.ListVoices(ctx, &cambai.ListVoicesListVoicesGetRequest{})if err != nil { panic(err)}for _, item := range voices { // item is a discriminated union; visit to get the typed Voice value. if v := item.Voice; v != nil { fmt.Println(v.ID, v.VoiceName) }}
VoiceCloning.CreateCustomVoice accepts BodyCreateCustomVoiceCreateCustomVoicePost (voice name, Gender, optional description, and other metadata). Map Gender to the integer values described in the Create custom voice reference. The generated request type in this module does not include a sample audio field; if your workflow requires uploading a clip, use the REST multipart contract or confirm the latest SDK types match your needs.
TTS requests use typed language constants on CreateStreamTtsRequestPayload (for example CreateStreamTtsRequestPayloadLanguageEnUs). Dubbing, translation, transcription, and related payloads use the shared cambai.Languages type (for example cambai.LanguagesEnUs).Languages.GetSourceLanguages and Languages.GetTargetLanguages return the language lists exposed by the API for products that distinguish source and target sets.
Dubbing takes a public video URL, translates the audio into your target language, and synthesizes speech. The flow is asynchronous: submit with Dub.EndToEndDubbing, poll with Dub.GetEndToEndDubbingStatus, then read the output with Dub.GetDubbedRunInfo. Go uses EndToEndDubbing (same naming as the TypeScript SDK, unlike Python create_dub).
Poll Dub.GetEndToEndDubbingStatus with that task id until Status is cambai.TaskStatusSuccess or cambai.TaskStatusError, then call Dub.GetDubbedRunInfo with the RunID from the status object. See examples/dubbing in the cambai-go-sdk repository for a full loop.For multiple targets in one job, set TargetLanguages instead of TargetLanguage.
Submit strings with Translation.CreateTranslation, poll GetTranslationTaskStatus, then fetch strings with GetTranslationResult. CreateTranslation is typed as interface{} in this client; round-trip through JSON is a reliable way to read task_id into OrchestratorPipelineCallResult.
raw, err := c.Translation.CreateTranslation(ctx, &cambai.CreateTranslationRequestPayload{ Texts: []string{"Hello, how are you?", "Welcome to Camb.ai."}, SourceLanguage: cambai.LanguagesEnUs, TargetLanguage: cambai.LanguagesFrFr,})if err != nil { panic(err)}// CreateTranslation returns interface{}; round-trip through JSON to read task_id.b, _ := json.Marshal(raw)var started cambai.OrchestratorPipelineCallResultjson.Unmarshal(b, &started)taskID := *started.TaskIDfor { time.Sleep(2 * time.Second) status, err := c.Translation.GetTranslationTaskStatus( ctx, taskID, &cambai.GetTranslationTaskStatusTranslateTaskIDGetRequest{}, ) if err != nil { panic(err) } if status.Status == cambai.TaskStatusSuccess && status.RunID != nil { result, err := c.Translation.GetTranslationResult( ctx, status.RunID, &cambai.GetTranslationResultTranslationResultRunIDGetRequest{}, ) if err != nil { panic(err) } fmt.Println(result.Texts) return } if status.Status == cambai.TaskStatusError { panic("translation failed") }}
Pass a remote URL with MediaURL on BodyCreateTranscriptionTranscribePost. Poll GetTranscriptionTaskStatus, then call GetTranscriptionResult with optional word-level timestamps.
The generated transcription request type in this module exposes MediaURL (and deprecated AudioURL). If you need to upload a local file from Go, confirm the latest SDK supports the multipart fields your server expects, or use the REST API directly.
The client exposes AudioSeparation.CreateAudioSeparation, GetAudioSeparationStatus, GetAudioSeparationRunInfo, and batch helpers. The generated BodyCreateAudioSeparationAudioSeparationPost type in this repository currently carries metadata fields only. For production uploads, validate the request type against Audio separation in your SDK version or call the REST endpoints until the generator includes the media parts you rely on.
Text-to-voice creates candidate voices from a description. Submit with TextToVoice.CreateTextToVoice, poll GetTextToVoiceStatus, then read previews from GetTextToVoiceResult.
resp, err := c.TextToVoice.CreateTextToVoice(ctx, &cambai.CreateTextToVoiceRequestPayload{ Text: "A confident narrator introducing a documentary.", VoiceDescription: "Deep, measured baritone with a slight gravel. Calm and authoritative.",})if err != nil { panic(err)}taskID := *resp.TaskIDfor { time.Sleep(2 * time.Second) status, err := c.TextToVoice.GetTextToVoiceStatus( ctx, taskID, &cambai.GetTextToVoiceStatusTextToVoiceTaskIDGetRequest{}, ) if err != nil { panic(err) } if status.Status == cambai.TaskStatusSuccess && status.RunID != nil { runID := *status.RunID out, err := c.TextToVoice.GetTextToVoiceResult( ctx, &runID, &cambai.GetTextToVoiceResultTextToVoiceResultRunIDGetRequest{}, ) if err != nil { panic(err) } fmt.Println(out.Previews) return } if status.Status == cambai.TaskStatusError { panic("text-to-voice failed") }}
The GetTextToVoiceResultOut value includes Previews (URLs) you can audition before choosing a voice_id for TTS.
Text-to-audio generates sound from a prompt. The pattern matches other async jobs: CreateTextToAudio, GetTextToAudioStatus, then GetTextToAudioResult as an io.Reader.
resp, err := c.TextToAudio.CreateTextToAudio(ctx, &cambai.CreateTextToAudioRequestPayload{ Prompt: "Heavy rain on a tin roof at night with distant thunder.", Duration: cambai.Float64(15), AudioType: cambai.TextToAudioTypeSound.Ptr(),})if err != nil { panic(err)}taskID := *resp.TaskIDfor { time.Sleep(3 * time.Second) status, err := c.TextToAudio.GetTextToAudioStatus( ctx, taskID, &cambai.GetTextToAudioStatusTextToSoundTaskIDGetRequest{}, ) if err != nil { panic(err) } if status.Status == cambai.TaskStatusSuccess && status.RunID != nil { runID := *status.RunID stream, err := c.TextToAudio.GetTextToAudioResult( ctx, &runID, &cambai.GetTextToAudioResultTextToSoundResultRunIDGetRequest{}, ) if err != nil { panic(err) } out, _ := os.Create("soundscape.wav") defer out.Close() io.Copy(out, stream) return } if status.Status == cambai.TaskStatusError { panic("text-to-audio failed") }}
Story.CreateStory returns *CreateStoryStoryPostResponse, a discriminated union over OrchestratorPipelineCallResult (async task_id) and GetSetupStoryResultResponse (immediate setup payload). Use Accept with CreateStoryStoryPostResponseVisitor to read whichever branch the API returned, then poll GetStoryStatus when you received a task id.The generated BodyCreateStoryStoryPost struct lists the fields this client sends. If you rely on uploading a source document, compare that struct to the REST story endpoint for your SDK revision.
TranslatedTts.CreateTranslatedTts returns CreateTranslatedTtsOut with a string TaskID. Poll with GetTranslatedTtsTaskStatus until Status is success or error.
DeleteDictionaryTerm and DeleteDictionary take integer IDs and optional RunID query parameters on their request structs. The CreateDictionaryFromFile helper in this module builds multipart metadata only; for CSV-based creation, prefer the REST contract in the API reference until the client matches it.
Folders.ListFolders and Folders.CreateFolder organize runs in Studio-compatible projects. Pass the generated request structs from the cambai package for optional filters.
API failures surface as error values. Validation responses decode to *cambai.UnprocessableEntityError, which embeds *core.APIError. Use errors.As to inspect status codes and optional Body details.
The Go SDK does not mirror the TypeScript ttsProvider constructor flag on the main client. Instead, implement provider.TtsProvider from github.com/camb-ai/cambai-go-sdk/provider and call Tts yourself (or inject the implementation into your own stack). See the baseten-provider example in the Go SDK repository for a complete BasetenProvider struct, HTTP wiring, and streaming output to disk.
package mainimport ( "bytes" "context" "encoding/json" "fmt" "io" "net/http" "strings" cambai "github.com/camb-ai/cambai-go-sdk" "github.com/camb-ai/cambai-go-sdk/provider")// BasetenProvider implements provider.TtsProvider for the Baseten Mars8-Flash model.// API reference: https://www.baseten.co/library/mars8-flash/type BasetenProvider struct { APIKey string URL string ReferenceAudio string ReferenceLanguage string}// CreateTts is a stub because Baseten does not support async TTS.func (b *BasetenProvider) CreateTts(ctx context.Context, request *cambai.CreateTtsRequestPayload) (*cambai.CreateTtsOut, error) { return nil, fmt.Errorf("Baseten custom hosting provider does not support async CreateTts; use Tts (streaming) instead")}// Tts calls the Baseten Mars8-Flash endpoint and returns the audio as an io.Reader.func (b *BasetenProvider) Tts(ctx context.Context, request *cambai.CreateStreamTtsRequestPayload) (io.Reader, error) { langStr := strings.ToLower(strings.ReplaceAll(string(request.Language), "_", "-")) payload := map[string]interface{}{ "text": request.Text, "language": langStr, "output_duration": nil, "reference_audio": b.ReferenceAudio, "reference_language": b.ReferenceLanguage, "output_format": "flac", "apply_ner_nlp": false, } payloadBytes, err := json.Marshal(payload) if err != nil { return nil, fmt.Errorf("failed to marshal payload: %w", err) } req, err := http.NewRequestWithContext(ctx, "POST", b.URL, bytes.NewBuffer(payloadBytes)) if err != nil { return nil, fmt.Errorf("failed to create request: %w", err) } req.Header.Set("Authorization", "Api-Key "+b.APIKey) req.Header.Set("Content-Type", "application/json") httpClient := &http.Client{} resp, err := httpClient.Do(req) if err != nil { return nil, fmt.Errorf("request failed: %w", err) } defer resp.Body.Close() if resp.StatusCode != http.StatusOK { body, _ := io.ReadAll(resp.Body) return nil, fmt.Errorf("baseten error (%d): %s", resp.StatusCode, string(body)) } var buf bytes.Buffer if _, err = io.Copy(&buf, resp.Body); err != nil { return nil, fmt.Errorf("failed to read response body: %w", err) } return &buf, nil}var _ provider.TtsProvider = (*BasetenProvider)(nil)