Pre-recorded transcription
Transcribe audio files and URLs from your iOS or Android app
Pre-recorded transcription sends a complete audio file or URL to the SubQ API in a single request and returns the full transcript in the response. Use it for voicemails, uploaded recordings, podcast episodes, or any audio that is already available before transcription starts.
For background on how pre-recorded and streaming transcription differ, see Transcription modes.
Prerequisites
- A SubQ API key (Get your API key)
- The
SubQSTTClientclass added to your project (Setup)
Transcribe audio from a URL
To transcribe audio hosted at a public URL, call transcribeURL(_:). The client sends a POST request to /v1/listen with a JSON body {"url": "..."}. The API downloads the audio and returns the transcript.
let client = SubQSTTClient(token: "org_YOUR_API_KEY")
do {
let transcript = try await client.transcribeURL(
"https://platform.subquadratic.ai/subq_sample.wav"
)
print("Transcript: \(transcript)")
} catch {
print("Error: \(error.localizedDescription)")
}Transcribe audio data
To transcribe audio loaded into memory, call transcribeFile(data:contentType:). This sends the raw audio bytes in the request body. The API auto-detects the format from binary headers, but you can specify the MIME type explicitly.
let client = SubQSTTClient(token: "org_YOUR_API_KEY")
// Load audio data from the app bundle or filesystem
let audioData: Data = // ... load your audio file
do {
let transcript = try await client.transcribeFile(
data: audioData,
contentType: "audio/wav"
)
print("Transcript: \(transcript)")
} catch {
print("Error: \(error.localizedDescription)")
}Error handling
Both methods throw Swift errors on failure. HTTP errors include the status code and response body in the error message. Wrap calls in a do/catch block to handle errors:
do {
let transcript = try await client.transcribeURL("https://example.com/audio.wav")
// Use the transcript
} catch let error as NSError where error.code == 401 {
print("Invalid API key. Verify that your key starts with org_.")
} catch let error as NSError where error.code == 413 {
print("Audio file is too large.")
} catch {
print("Transcription failed: \(error.localizedDescription)")
}Transcribe audio from a URL
To transcribe audio hosted at a public URL, call transcribeUrl(). The client sends a POST request to /v1/listen with a JSON body {"url": "..."}. The API downloads the audio and returns the transcript.
The method returns a Kotlin Result<String>, so you handle success and failure separately:
val client = SubQSTTClient(token = "org_YOUR_API_KEY")
scope.launch {
client.transcribeUrl("https://platform.subquadratic.ai/subq_sample.wav")
.onSuccess { transcript ->
Log.d("SubQSTT", "Transcript: $transcript")
}
.onFailure { error ->
Log.e("SubQSTT", "Error: ${error.message}")
}
}Transcribe audio data
To transcribe audio loaded into memory, call transcribeFile(). This sends the raw audio bytes in the request body. The API auto-detects the format from binary headers, but you can specify the MIME type explicitly.
val client = SubQSTTClient(token = "org_YOUR_API_KEY")
// Load audio data from a file, content resolver, or asset
val audioData: ByteArray = // ... load your audio file
scope.launch {
client.transcribeFile(audioData, "audio/wav")
.onSuccess { transcript ->
Log.d("SubQSTT", "Transcript: $transcript")
}
.onFailure { error ->
Log.e("SubQSTT", "Error: ${error.message}")
}
}Error handling
Both methods return Result<String>. Failed HTTP responses are wrapped as exceptions with the status code and response body. Use onFailure or getOrElse to handle errors:
scope.launch {
val transcript = client.transcribeUrl("https://example.com/audio.wav")
.getOrElse { error ->
when {
error.message?.contains("401") == true ->
Log.e("SubQSTT", "Invalid API key. Verify that your key starts with org_.")
error.message?.contains("413") == true ->
Log.e("SubQSTT", "Audio file is too large.")
else ->
Log.e("SubQSTT", "Transcription failed: ${error.message}")
}
return@launch
}
// Use the transcript
Log.d("SubQSTT", transcript)
}How it works
- The client sends a POST request to
https://api.subquadratic.ai/v1/listen. - For URL transcription, the request body contains JSON:
{"url": "https://..."}. For file transcription, the request body contains raw audio bytes. - The API auto-detects the audio format from binary headers. Supported formats include MP3, WAV, AAC, FLAC, OGG, Opus, WebM, and M4A.
- The API returns a JSON response. The client extracts the transcript from
results.channels[0].alternatives[0].transcript.
Add query parameters
You can customize transcription by appending query parameters to the /v1/listen URL. For example, to enable smart formatting and set the language to Spanish, modify the URL in the SubQSTTClient class:
// Modify the URL to include query parameters
guard let url = URL(
string: "\(host)/v1/listen?smart_format=true&language=es"
) else {
throw URLError(.badURL)
}// Modify the URL to include query parameters
val request = Request.Builder()
.url("$host/v1/listen?smart_format=true&language=es")
.header("Authorization", "Token $token")
.post(data.toRequestBody(contentType.toMediaType()))
.build()For the full list of available parameters, see Parameters.
Next steps
- Real-time streaming - stream live audio from the microphone
- SDK reference - complete class and method reference
- Smart formatting - automatic punctuation, capitalization, and number formatting