ChartQuery

Extraire l'audio d'une vidéo

Téléchargez uniquement la piste audio de n'importe quelle URL vidéo en fichier MP3 avec HuntAPI — idéal pour l'archivage de podcasts, les pipelines de transcription ou le recyclage de contenu.

Vue d'ensemble

En passant quality: "audio" au téléchargeur HuntAPI, vous obtenez un extrait MP3 au lieu de la vidéo complète. Ce guide construit un pipeline complet d'extraction audio incluant la soumission du job, l'interrogation et la sauvegarde.

Prérequis

  • Une clé API HuntAPI — obtenez-en une sur app.huntapi.com
  • Installez les dépendances pour votre langage :
pip install requests

Aucune dépendance supplémentaire — utilise l'API native fetch (Node 18+).

Extension curl activée (par défaut).

Aucune dépendance supplémentaire — utilise net/http (Go 1.18+).

Aucune dépendance supplémentaire — utilise java.net.http (Java 11+).

Aucune dépendance supplémentaire — utilise System.Net.Http (.NET 6+).

# Cargo.toml
[dependencies]
reqwest = { version = "0.12", features = ["json"] }
tokio = { version = "1", features = ["full"] }
serde_json = "1"

Étapes

Soumettre un job d'extraction audio

Utilisez le même endpoint /v1/video/download avec quality=audio.

import requests

API_KEY   = "YOUR_API_KEY"
VIDEO_URL = "https://www.youtube.com/watch?v=dQw4w9WgXcQ"

response = requests.get(
    "https://api.huntapi.com/v1/video/download",
    headers={"x-api-key": API_KEY},
    params={"url": VIDEO_URL, "quality": "audio"},
)
data   = response.json()
job_id = data["job_id"]
print(f"Job audio soumis : {job_id}")
const API_KEY   = "YOUR_API_KEY";
const VIDEO_URL = "https://www.youtube.com/watch?v=dQw4w9WgXcQ";

const params   = new URLSearchParams({ url: VIDEO_URL, quality: "audio" });
const response = await fetch(`https://api.huntapi.com/v1/video/download?${params}`, {
  headers: { "x-api-key": API_KEY },
});
const { job_id } = await response.json();
console.log(`Job audio soumis : ${job_id}`);
<?php
$apiKey   = "YOUR_API_KEY";
$videoUrl = "https://www.youtube.com/watch?v=dQw4w9WgXcQ";

$params = http_build_query(["url" => $videoUrl, "quality" => "audio"]);
$ch     = curl_init("https://api.huntapi.com/v1/video/download?{$params}");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, ["x-api-key: {$apiKey}"]);
$data  = json_decode(curl_exec($ch), true);
curl_close($ch);
$jobId = $data["job_id"];
echo "Job audio soumis : {$jobId}\n";
package main

import (
    "encoding/json"
    "fmt"
    "io"
    "net/http"
    "net/url"
    "os"
    "time"
)

const (
    APIKey   = "YOUR_API_KEY"
    VideoURL = "https://www.youtube.com/watch?v=dQw4w9WgXcQ"
)

func get(apiKey, rawURL string) map[string]any {
    req, _ := http.NewRequest("GET", rawURL, nil)
    req.Header.Set("x-api-key", apiKey)
    resp, _ := http.DefaultClient.Do(req)
    defer resp.Body.Close()
    body, _ := io.ReadAll(resp.Body)
    var m map[string]any
    json.Unmarshal(body, &m)
    return m
}

func main() {
    params := url.Values{"url": {VideoURL}, "quality": {"audio"}}
    data   := get(APIKey, "https://api.huntapi.com/v1/video/download?"+params.Encode())
    jobID  := data["job_id"].(string)
    fmt.Println("Job audio soumis :", jobID)
}
import java.net.URI;
import java.net.URLEncoder;
import java.net.http.*;
import java.nio.charset.StandardCharsets;
import org.json.*;

var apiKey   = "YOUR_API_KEY";
var videoUrl = URLEncoder.encode("https://www.youtube.com/watch?v=dQw4w9WgXcQ", StandardCharsets.UTF_8);
var client   = HttpClient.newHttpClient();

var req  = HttpRequest.newBuilder()
    .uri(URI.create("https://api.huntapi.com/v1/video/download?url=" + videoUrl + "&quality=audio"))
    .header("x-api-key", apiKey).GET().build();
var resp  = client.send(req, HttpResponse.BodyHandlers.ofString());
var jobId = new JSONObject(resp.body()).getString("job_id");
System.out.println("Job audio soumis : " + jobId);
using System.Net.Http;
using System.Text.Json;

var apiKey   = "YOUR_API_KEY";
var videoUrl = Uri.EscapeDataString("https://www.youtube.com/watch?v=dQw4w9WgXcQ");
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("x-api-key", apiKey);

var body  = await client.GetStringAsync($"https://api.huntapi.com/v1/video/download?url={videoUrl}&quality=audio");
var jobId = JsonDocument.Parse(body).RootElement.GetProperty("job_id").GetString()!;
Console.WriteLine($"Job audio soumis : {jobId}");
use reqwest::Client;
use serde_json::Value;

#[tokio::main]
async fn main() -> Result<(), reqwest::Error> {
    let client    = Client::new();
    let api_key   = "YOUR_API_KEY";
    let video_url = "https://www.youtube.com/watch?v=dQw4w9WgXcQ";

    let data = client.get("https://api.huntapi.com/v1/video/download")
        .header("x-api-key", api_key)
        .query(&[("url", video_url), ("quality", "audio")])
        .send().await?.json::<Value>().await?;

    let job_id = data["job_id"].as_str().unwrap();
    println!("Job audio soumis : {}", job_id);
    Ok(())
}

Interroger jusqu'à la fin

Vérifiez le statut du job toutes les 5 secondes jusqu'à ce que status == "done".

import time

def wait_for_job(job_id: str) -> dict:
    for _ in range(60):
        r      = requests.get(f"https://api.huntapi.com/v1/job/{job_id}",
            headers={"x-api-key": API_KEY})
        result = r.json()
        status = result["status"]
        print(f"  [{status}]")
        if status == "done":
            return result
        if status == "error":
            raise RuntimeError(result.get("error", "Erreur inconnue"))
        time.sleep(5)
    raise TimeoutError("Timeout du job")

result       = wait_for_job(job_id)
download_url = result["download_url"]
async function waitForJob(jobId: string) {
  for (let i = 0; i < 60; i++) {
    const res    = await fetch(`https://api.huntapi.com/v1/job/${jobId}`, {
      headers: { "x-api-key": API_KEY },
    });
    const result = await res.json();
    console.log(`  [${result.status}]`);
    if (result.status === "done")  return result;
    if (result.status === "error") throw new Error(result.error ?? "Erreur inconnue");
    await new Promise(r => setTimeout(r, 5000));
  }
  throw new Error("Timeout");
}

const result      = await waitForJob(job_id);
const downloadUrl = result.download_url;
function waitForJob(string $apiKey, string $jobId): array {
    for ($i = 0; $i < 60; $i++) {
        $ch = curl_init("https://api.huntapi.com/v1/job/{$jobId}");
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_HTTPHEADER, ["x-api-key: {$apiKey}"]);
        $result = json_decode(curl_exec($ch), true);
        curl_close($ch);
        $status = $result["status"] ?? "";
        echo "  [{$status}]\n";
        if ($status === "done")  return $result;
        if ($status === "error") throw new RuntimeException($result["error"] ?? "Inconnu");
        sleep(5);
    }
    throw new RuntimeException("Timeout");
}

$result      = waitForJob($apiKey, $jobId);
$downloadUrl = $result["download_url"];
func waitForJob(apiKey, jobID string) string {
    for i := 0; i < 60; i++ {
        data   := get(apiKey, "https://api.huntapi.com/v1/job/"+jobID)
        status := data["status"].(string)
        fmt.Printf("  [%s]\n", status)
        if status == "done"  { return data["download_url"].(string) }
        if status == "error" { panic("Job échoué : " + fmt.Sprint(data["error"])) }
        time.Sleep(5 * time.Second)
    }
    panic("Timeout")
}

downloadURL := waitForJob(APIKey, jobID)
static String waitForJob(HttpClient client, String apiKey, String jobId) throws Exception {
    for (int i = 0; i < 60; i++) {
        var req    = HttpRequest.newBuilder()
            .uri(URI.create("https://api.huntapi.com/v1/job/" + jobId))
            .header("x-api-key", apiKey).GET().build();
        var resp   = client.send(req, HttpResponse.BodyHandlers.ofString());
        var result = new JSONObject(resp.body());
        var status = result.getString("status");
        System.out.println("  [" + status + "]");
        if ("done".equals(status))  return result.getString("download_url");
        if ("error".equals(status)) throw new RuntimeException(result.optString("error"));
        Thread.sleep(5000);
    }
    throw new RuntimeException("Timeout");
}

var downloadUrl = waitForJob(client, apiKey, jobId);
async Task<string> WaitForJob(HttpClient client, string jobId)
{
    for (int i = 0; i < 60; i++)
    {
        var body   = await client.GetStringAsync($"https://api.huntapi.com/v1/job/{jobId}");
        var result = JsonDocument.Parse(body).RootElement;
        var status = result.GetProperty("status").GetString();
        Console.WriteLine($"  [{status}]");
        if (status == "done")  return result.GetProperty("download_url").GetString()!;
        if (status == "error") throw new Exception(result.GetProperty("error").GetString());
        await Task.Delay(5000);
    }
    throw new TimeoutException();
}

var downloadUrl = await WaitForJob(client, jobId);
use tokio::time::{sleep, Duration};

async fn wait_for_job(client: &Client, api_key: &str, job_id: &str) -> String {
    for _ in 0..60 {
        let result = client.get(format!("https://api.huntapi.com/v1/job/{}", job_id))
            .header("x-api-key", api_key)
            .send().await.unwrap().json::<Value>().await.unwrap();
        let status = result["status"].as_str().unwrap_or("");
        println!("  [{}]", status);
        if status == "done"  { return result["download_url"].as_str().unwrap().to_string(); }
        if status == "error" { panic!("Job échoué : {}", result["error"]); }
        sleep(Duration::from_secs(5)).await;
    }
    panic!("Timeout")
}

Sauvegarder le fichier audio

Téléchargez le MP3 et sauvegardez-le sur disque.

output_file = "audio.mp3"
with requests.get(download_url, stream=True) as r:
    r.raise_for_status()
    with open(output_file, "wb") as f:
        for chunk in r.iter_content(chunk_size=8192):
            f.write(chunk)

print(f"Audio sauvegardé dans {output_file} ({os.path.getsize(output_file) // 1024} Ko)")
import { createWriteStream } from "fs";
import { Readable } from "stream";

const fileRes = await fetch(downloadUrl);
const writer  = createWriteStream("audio.mp3");
Readable.fromWeb(fileRes.body as any).pipe(writer);
await new Promise((resolve, reject) => { writer.on("finish", resolve); writer.on("error", reject); });
console.log("Audio sauvegardé dans audio.mp3");
$fp = fopen("audio.mp3", "wb");
$ch = curl_init($downloadUrl);
curl_setopt($ch, CURLOPT_FILE, $fp);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_exec($ch);
curl_close($ch);
fclose($fp);
echo "Audio sauvegardé dans audio.mp3\n";
resp, _ := http.Get(downloadURL)
defer resp.Body.Close()
file, _ := os.Create("audio.mp3")
defer file.Close()
io.Copy(file, resp.Body)
fmt.Println("Audio sauvegardé dans audio.mp3")
import java.net.URL;
import java.nio.file.*;

Files.copy(new URL(downloadUrl).openStream(), Path.of("audio.mp3"), StandardCopyOption.REPLACE_EXISTING);
System.out.println("Audio sauvegardé dans audio.mp3");
using var audioStream = await new HttpClient().GetStreamAsync(downloadUrl);
using var file        = File.Create("audio.mp3");
await audioStream.CopyToAsync(file);
Console.WriteLine("Audio sauvegardé dans audio.mp3");
use std::{fs::File, io::Write};

let bytes = reqwest::get(download_url).await?.bytes().await?;
let mut file = File::create("audio.mp3").unwrap();
file.write_all(&bytes).unwrap();
println!("Audio sauvegardé dans audio.mp3");

L'audio extrait est livré en MP3. Vous pouvez le transmettre directement à un service de transcription (ex. OpenAI Whisper ou Deepgram) pour le sous-titrage automatique ou l'indexation par recherche.

Sur cette page