Transcribe from URL
Transcribe audio from a URL using the SubQ API
With URL transcription, you transcribe audio hosted remotely on cloud storage, a CDN, or any publicly accessible URL without downloading it to your machine first. You download the audio, send the bytes to the API, and get the transcript back.
This approach is useful when your audio files are stored in services like Amazon S3, Google Cloud Storage, or any web server.
Prerequisites
- Python 3.8 or later
httpxinstalled. If you haven't already, follow the set up and installation guide.- A publicly accessible URL pointing to an audio file in a supported format
Transcribe audio from a URL
In this example, you download audio from a public URL and send it to the SubQ API for transcription:
import os
import httpx
SUBQ_API_KEY = os.environ["SUBQ_API_KEY"]
AUDIO_URL = "https://speech.subq.ai/subq_sample.wav"
# Download the audio file
print("Downloading audio...")
audio_response = httpx.get(AUDIO_URL, timeout=30.0, follow_redirects=True)
audio_data = audio_response.content
print(f"Downloaded {len(audio_data)} bytes")
# Send the audio to the SubQ API
print("Transcribing...")
response = httpx.post(
"https://stt-api.subq.ai/v1/listen",
headers={"Authorization": f"Bearer {SUBQ_API_KEY}"},
content=audio_data,
timeout=60.0
)
result = response.json()
if response.status_code == 200:
transcript = (
result.get("results", {})
.get("channels", [{}])[0]
.get("alternatives", [{}])[0]
.get("transcript", "")
)
print(f"Transcript: {transcript}")
else:
print(f"Error {response.status_code}: {result}")Run it:
python transcribe_url.pyHow it works
To transcribe from a URL, you download the audio, send it to the API, and extract the transcript from the response:
-
Download the audio:
httpx.get()fetches the audio file from the URL. Thefollow_redirects=Trueparameter handles HTTP redirects automatically. This is important for URLs from storage services that often redirect to a CDN. Thetimeout=30.0prevents the request from hanging on slow connections. -
POST to
/v1/listen: You send the downloaded audio bytes to the SubQ API in the request body. This is the same endpoint and format used in Transcribe a file. The only difference is where the audio comes from. -
Parse the response: The response structure is the same as file transcription. For full field descriptions, see the response structure in Transcribe a file.
The approach is the same as Transcribe a file: you're sending audio bytes to POST /v1/listen. The difference is just where the bytes come from:
| Approach | Source | When to use |
|---|---|---|
| File | open("audio.wav", "rb").read() | Audio is on your local disk |
| URL | httpx.get(url).content | Audio is hosted remotely |
Prerequisites
- Node.js 18 or later
- A publicly accessible URL pointing to an audio file in a supported format
Transcribe audio from a URL
In this example, you download audio from a public URL and send it to the SubQ API for transcription:
const SUBQ_API_KEY = process.env.SUBQ_API_KEY;
const AUDIO_URL = "https://speech.subq.ai/subq_sample.wav";
// Download the audio file
console.log("Downloading audio...");
const audioResponse = await fetch(AUDIO_URL);
const audioData = await audioResponse.arrayBuffer();
console.log(`Downloaded ${audioData.byteLength} bytes`);
// Send the audio to the SubQ API
console.log("Transcribing...");
const response = await fetch("https://stt-api.subq.ai/v1/listen", {
method: "POST",
headers: { "Authorization": `Bearer ${SUBQ_API_KEY}` },
body: audioData,
});
const result = await response.json();
if (response.ok) {
const transcript = result?.results?.channels?.[0]?.alternatives?.[0]?.transcript ?? "";
console.log(`Transcript: ${transcript}`);
} else {
console.error(`Error ${response.status}:`, result);
}Run it:
node transcribe_url.jsHow it works
To transcribe from a URL, you download the audio, send it to the API, and extract the transcript from the response:
-
Download the audio:
fetch()retrieves the audio file from the URL. The response is read as anArrayBufferwith.arrayBuffer(), which gives you the raw binary data.fetchfollows redirects automatically, which is important for URLs from storage services that often redirect to a CDN. -
POST to
/v1/listen: You send the downloaded audio bytes to the SubQ API in the request body. This is the same endpoint and format used in Transcribe a file. The only difference is where the audio comes from. -
Parse the response: The response structure is the same as file transcription. For full field descriptions, see the response structure in Transcribe a file.
The approach is the same as Transcribe a file: you're sending audio bytes to POST /v1/listen. The difference is just where the bytes come from:
| Approach | Source | When to use |
|---|---|---|
| File | readFileSync("audio.wav") | Audio is on your local disk |
| URL | fetch(url).arrayBuffer() | Audio is hosted remotely |
Prerequisites
- Go 1.21 or later
- A publicly accessible URL pointing to an audio file in a supported format
Transcribe audio from a URL
In this example, you download audio from a public URL and send it to the SubQ API for transcription:
package main
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
"os"
)
func main() {
apiKey := os.Getenv("SUBQ_API_KEY")
audioURL := "https://speech.subq.ai/subq_sample.wav"
// Download the audio file
fmt.Println("Downloading audio...")
audioResp, err := http.Get(audioURL)
if err != nil {
fmt.Println("Error downloading:", err)
return
}
defer audioResp.Body.Close()
audioData, _ := io.ReadAll(audioResp.Body)
fmt.Printf("Downloaded %d bytes\n", len(audioData))
// Send the audio to the SubQ API
fmt.Println("Transcribing...")
req, _ := http.NewRequest("POST", "https://stt-api.subq.ai/v1/listen", bytes.NewReader(audioData))
req.Header.Set("Authorization", "Bearer "+apiKey)
resp, err := http.DefaultClient.Do(req)
if err != nil {
fmt.Println("Error:", err)
return
}
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
if resp.StatusCode != 200 {
fmt.Printf("Error %d: %s\n", resp.StatusCode, string(body))
return
}
var result struct {
Results struct {
Channels []struct {
Alternatives []struct {
Transcript string `json:"transcript"`
} `json:"alternatives"`
} `json:"channels"`
} `json:"results"`
}
json.Unmarshal(body, &result)
fmt.Printf("Transcript: %s\n", result.Results.Channels[0].Alternatives[0].Transcript)
}Run it:
go run transcribe_url.goHow it works
To transcribe from a URL, you download the audio, send it to the API, and extract the transcript from the response:
-
Download the audio:
http.Get()fetches the audio file from the URL. Go's HTTP client follows redirects automatically, which is important for URLs from storage services that often redirect to a CDN. -
POST to
/v1/listen: You send the downloaded audio bytes to the SubQ API in the request body. This is the same endpoint and format used in Transcribe a file. The only difference is where the audio comes from. -
Parse the response: The response structure is the same as file transcription. For full field descriptions, see the response structure in Transcribe a file.
The approach is the same as Transcribe a file: you're sending audio bytes to POST /v1/listen. The difference is just where the bytes come from:
| Approach | Source | When to use |
|---|---|---|
| File | os.ReadFile("audio.wav") | Audio is on your local disk |
| URL | http.Get(url) + io.ReadAll | Audio is hosted remotely |
Prerequisites
- Rust 1.70 or later with
reqwest,tokio, andserde_jsonin yourCargo.toml, If you haven't already, follow the set up and installation guide. - A publicly accessible URL pointing to an audio file in a supported format
Transcribe audio from a URL
In this example, you download audio from a public URL and send it to the SubQ API for transcription:
use serde_json::Value;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let api_key = std::env::var("SUBQ_API_KEY").expect("SUBQ_API_KEY not set");
let audio_url = "https://speech.subq.ai/subq_sample.wav";
// Download the audio file
println!("Downloading audio...");
let audio_data = reqwest::get(audio_url).await?.bytes().await?;
println!("Downloaded {} bytes", audio_data.len());
// Send the audio to the SubQ API
println!("Transcribing...");
let client = reqwest::Client::new();
let response = client
.post("https://stt-api.subq.ai/v1/listen")
.header("Authorization", format!("Bearer {}", api_key))
.body(audio_data)
.send()
.await?;
let status = response.status();
let text = response.text().await?;
if !status.is_success() {
eprintln!("Error {}: {}", status, text);
return Ok(());
}
let json: Value = serde_json::from_str(&text)?;
let transcript = json["results"]["channels"][0]["alternatives"][0]["transcript"]
.as_str()
.unwrap_or("");
println!("Transcript: {}", transcript);
Ok(())
}Run it:
cargo run --bin transcribe_urlHow it works
To transcribe from a URL, you download the audio, send it to the API, and extract the transcript from the response:
-
Download the audio:
reqwest::get(url).await?.bytes().await?fetches the audio file into memory.reqwestfollows redirects automatically, which is important for URLs from storage services that often redirect to a CDN. -
POST to
/v1/listen: You send the downloaded audio bytes to the SubQ API in the request body. This is the same endpoint and format used in Transcribe a file. The only difference is where the audio comes from. -
Parse the response: The response structure is the same as file transcription. For full field descriptions, see the response structure in Transcribe a file.
The approach is the same as Transcribe a file: you're sending audio bytes to POST /v1/listen. The difference is just where the bytes come from:
| Approach | Source | When to use |
|---|---|---|
| File | tokio::fs::read("audio.wav") | Audio is on your local disk |
| URL | reqwest::get(url).await?.bytes() | Audio is hosted remotely |
The URL must be publicly accessible. If your audio is behind authentication (for example, a private S3 bucket), generate a pre-signed URL first. A pre-signed URL is a time-limited public URL that grants temporary access to a private resource.
You can customize transcriptions with query parameters for smart formatting, speaker diarization, language detection, and more.
Next steps
- Transcribe a file - transcribe audio from your local filesystem
- Real-time streaming - transcribe audio as it's being recorded or received
- Migrate from Deepgram - already using the Deepgram SDK? Switch to SubQ with a 2-line change