Примеры кода

Примеры кода

Полные примеры для основных операций API.

Python

Транскрипция аудиофайла

import requests
import time
import os

API_KEY = os.environ["NAGOVORI_API_KEY"]
BASE_URL = "https://api.nagovori.ru/v1"
HEADERS = {"Authorization": f"Bearer {API_KEY}"}


def transcribe(file_path: str, language: str = "auto") -> str:
    """Загрузить и транскрибировать аудиофайл. Возвращает текст."""
    filename = os.path.basename(file_path)
    file_size = os.path.getsize(file_path)

    # 1. Получаем presigned URL для загрузки
    presign = requests.post(
        f"{BASE_URL}/uploads/presign",
        headers=HEADERS,
        json={
            "filename": filename,
            "content_type": "audio/mpeg",
            "size_bytes": file_size,
        },
    ).json()

    # 2. Загружаем файл
    with open(file_path, "rb") as f:
        requests.put(
            presign["upload_url"],
            data=f,
            headers={"Content-Type": "audio/mpeg"},
        )

    # 3. Создаём задание на транскрипцию
    job = requests.post(
        f"{BASE_URL}/transcriptions",
        headers=HEADERS,
        json={
            "object_key": presign["object_key"],
            "filename": filename,
            "content_type": "audio/mpeg",
            "size_bytes": file_size,
            "language": language,
        },
    ).json()

    # 4. Ожидаем завершения
    while job["status"] in ("queued", "processing"):
        time.sleep(3)
        job = requests.get(
            f"{BASE_URL}/transcriptions/{job['id']}",
            headers=HEADERS,
        ).json()

    if job["status"] == "failed":
        raise RuntimeError(f"Транскрипция не удалась: {job.get('error_message')}")

    return job["transcript_text"]


if __name__ == "__main__":
    text = transcribe("meeting.mp3")
    print(text)

TypeScript / Node.js

Транскрипция аудиофайла

import fs from "node:fs";
import path from "node:path";

const API_KEY = process.env.NAGOVORI_API_KEY!;
const BASE_URL = "https://api.nagovori.ru/v1";

async function api<T>(endpoint: string, init?: RequestInit): Promise<T> {
  const res = await fetch(`${BASE_URL}${endpoint}`, {
    ...init,
    headers: {
      Authorization: `Bearer ${API_KEY}`,
      "Content-Type": "application/json",
      ...init?.headers,
    },
  });
  if (!res.ok) throw new Error(`Ошибка API ${res.status}: ${await res.text()}`);
  return res.json() as Promise<T>;
}

async function transcribe(filePath: string, language = "auto"): Promise<string> {
  const filename = path.basename(filePath);
  const fileBuffer = fs.readFileSync(filePath);
  const sizeBytes = fileBuffer.length;

  // 1. Presign
  const presign = await api<{ upload_url: string; object_key: string }>(
    "/uploads/presign",
    {
      method: "POST",
      body: JSON.stringify({
        filename,
        content_type: "audio/mpeg",
        size_bytes: sizeBytes,
      }),
    }
  );

  // 2. Загрузка
  await fetch(presign.upload_url, {
    method: "PUT",
    body: fileBuffer,
    headers: { "Content-Type": "audio/mpeg" },
  });

  // 3. Создание транскрипции
  let job = await api<{ id: string; status: string; transcript_text?: string }>(
    "/transcriptions",
    {
      method: "POST",
      body: JSON.stringify({
        object_key: presign.object_key,
        filename,
        content_type: "audio/mpeg",
        size_bytes: sizeBytes,
        language,
      }),
    }
  );

  // 4. Ожидание
  while (job.status === "queued" || job.status === "processing") {
    await new Promise((r) => setTimeout(r, 3000));
    job = await api(`/transcriptions/${job.id}`);
  }

  if (job.status === "failed") throw new Error("Транскрипция не удалась");
  return job.transcript_text ?? "";
}

// Использование
const text = await transcribe("meeting.mp3");
console.log(text);

Go

Транскрипция аудиофайла

package main

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

const baseURL = "https://api.nagovori.ru/v1"

var apiKey = os.Getenv("NAGOVORI_API_KEY")

func transcribe(filePath, language string) (string, error) {
	if language == "" {
		language = "auto"
	}

	fileInfo, err := os.Stat(filePath)
	if err != nil {
		return "", fmt.Errorf("stat file: %w", err)
	}

	// 1. Presign
	presignBody, _ := json.Marshal(map[string]interface{}{
		"filename":     fileInfo.Name(),
		"content_type": "audio/mpeg",
		"size_bytes":   fileInfo.Size(),
	})

	presignResp, err := apiCall("POST", "/uploads/presign", presignBody)
	if err != nil {
		return "", fmt.Errorf("presign: %w", err)
	}

	uploadURL := presignResp["upload_url"].(string)
	objectKey := presignResp["object_key"].(string)

	// 2. Загрузка
	fileData, err := os.ReadFile(filePath)
	if err != nil {
		return "", fmt.Errorf("read file: %w", err)
	}

	req, _ := http.NewRequest("PUT", uploadURL, bytes.NewReader(fileData))
	req.Header.Set("Content-Type", "audio/mpeg")
	if _, err := http.DefaultClient.Do(req); err != nil {
		return "", fmt.Errorf("upload: %w", err)
	}

	// 3. Создание транскрипции
	createBody, _ := json.Marshal(map[string]interface{}{
		"object_key":   objectKey,
		"filename":     fileInfo.Name(),
		"content_type": "audio/mpeg",
		"size_bytes":   fileInfo.Size(),
		"language":     language,
	})

	job, err := apiCall("POST", "/transcriptions", createBody)
	if err != nil {
		return "", fmt.Errorf("create transcription: %w", err)
	}

	// 4. Ожидание
	id := job["id"].(string)
	for {
		status := job["status"].(string)
		if status == "completed" {
			return job["transcript_text"].(string), nil
		}
		if status == "failed" {
			return "", fmt.Errorf("транскрипция не удалась: %v", job["error_message"])
		}
		time.Sleep(3 * time.Second)
		job, err = apiCall("GET", "/transcriptions/"+id, nil)
		if err != nil {
			return "", err
		}
	}
}

func apiCall(method, path string, body []byte) (map[string]interface{}, error) {
	var bodyReader io.Reader
	if body != nil {
		bodyReader = bytes.NewReader(body)
	}
	req, err := http.NewRequest(method, baseURL+path, bodyReader)
	if err != nil {
		return nil, err
	}
	req.Header.Set("Authorization", "Bearer "+apiKey)
	req.Header.Set("Content-Type", "application/json")

	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()

	var result map[string]interface{}
	if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
		return nil, err
	}
	if resp.StatusCode >= 400 {
		return nil, fmt.Errorf("ошибка api %d: %v", resp.StatusCode, result["error"])
	}
	return result, nil
}

func main() {
	text, err := transcribe("meeting.mp3", "auto")
	if err != nil {
		fmt.Fprintf(os.Stderr, "Ошибка: %v\n", err)
		os.Exit(1)
	}
	fmt.Println(text)
}

cURL

Полная пошаговая транскрипция

# Шаг 1: Получаем presigned URL
PRESIGN=$(curl -s -X POST https://api.nagovori.ru/v1/uploads/presign \
  -H "Authorization: Bearer $NAGOVORI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "filename": "meeting.mp3",
    "content_type": "audio/mpeg",
    "size_bytes": 5242880
  }')

UPLOAD_URL=$(echo $PRESIGN | jq -r '.upload_url')
OBJECT_KEY=$(echo $PRESIGN | jq -r '.object_key')

# Шаг 2: Загружаем файл
curl -X PUT "$UPLOAD_URL" \
  -H "Content-Type: audio/mpeg" \
  --data-binary @meeting.mp3

# Шаг 3: Создаём транскрипцию
JOB=$(curl -s -X POST https://api.nagovori.ru/v1/transcriptions \
  -H "Authorization: Bearer $NAGOVORI_API_KEY" \
  -H "Content-Type: application/json" \
  -d "{
    \"object_key\": \"$OBJECT_KEY\",
    \"filename\": \"meeting.mp3\",
    \"content_type\": \"audio/mpeg\",
    \"size_bytes\": 5242880,
    \"language\": \"auto\"
  }")

JOB_ID=$(echo $JOB | jq -r '.id')

# Шаг 4: Ожидаем результат
while true; do
  RESULT=$(curl -s https://api.nagovori.ru/v1/transcriptions/$JOB_ID \
    -H "Authorization: Bearer $NAGOVORI_API_KEY")
  STATUS=$(echo $RESULT | jq -r '.status')
  
  if [ "$STATUS" = "completed" ]; then
    echo $RESULT | jq -r '.transcript_text'
    break
  elif [ "$STATUS" = "failed" ]; then
    echo "Ошибка: $(echo $RESULT | jq -r '.error_message')"
    break
  fi
  
  sleep 3
done