📚 Speech2Text API - Полная документация

🌐 Базовый URL

http://localhost:8020

🔐 Аутентификация

Все защищенные endpoints требуют JWT токен в заголовке Authorization:

Authorization: Bearer YOUR_JWT_TOKEN

📋 Содержание

  1. Аутентификация
  2. Транскрибация
  3. Управление пользователями
  4. API ключи
  5. Метрики
  6. Администрирование

1. Аутентификация

🔑 Вход в систему

POST /auth/login

Получение JWT токена для доступа к API.

Параметры запроса:

{
  "username": "string",
  "password": "string"
}

Ответ:

{
  "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "token_type": "bearer"
}

Примеры:

Python:

import requests

url = "http://localhost:8020/auth/login"
data = {
    "username": "admin",
    "password": "admin123"
}

response = requests.post(url, json=data)
token = response.json()["access_token"]
print(f"Token: {token}")

PHP:

<?php
$url = "http://localhost:8020/auth/login";
$data = array(
    "username" => "admin",
    "password" => "admin123"
);

$options = array(
    'http' => array(
        'header'  => "Content-type: application/json\r\n",
        'method'  => 'POST',
        'content' => json_encode($data)
    )
);

$context  = stream_context_create($options);
$result = file_get_contents($url, false, $context);
$response = json_decode($result, true);
$token = $response["access_token"];
echo "Token: " . $token;
?>

JavaScript:

async function login() {
    const response = await fetch('http://localhost:8020/auth/login', {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json'
        },
        body: JSON.stringify({
            username: 'admin',
            password: 'admin123'
        })
    });

    const data = await response.json();
    const token = data.access_token;
    console.log('Token:', token);
    return token;
}

cURL:

curl -X POST "http://localhost:8020/auth/login" \
     -H "Content-Type: application/json" \
     -d '{"username":"admin","password":"admin123"}'

👤 Регистрация пользователя

POST /auth/register

Создание нового пользователя.

Параметры запроса:

{
  "username": "string",
  "email": "user@example.com",
  "password": "string"
}

Ответ:

{
  "id": "uuid",
  "username": "string",
  "email": "user@example.com",
  "is_active": true,
  "is_admin": false,
  "created_at": "2024-01-01T00:00:00"
}

Примеры:

Python:

import requests

url = "http://localhost:8020/auth/register"
data = {
    "username": "newuser",
    "email": "newuser@example.com",
    "password": "secure_password123"
}

response = requests.post(url, json=data)
user = response.json()
print(f"Created user: {user['username']} with ID: {user['id']}")

JavaScript:

async function registerUser() {
    const response = await fetch('http://localhost:8020/auth/register', {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json'
        },
        body: JSON.stringify({
            username: 'newuser',
            email: 'newuser@example.com',
            password: 'secure_password123'
        })
    });

    const user = await response.json();
    console.log('Created user:', user);
    return user;
}

🔍 Получить текущего пользователя

GET /auth/me

Получение информации о текущем авторизованном пользователе.

Заголовки:

Authorization: Bearer YOUR_JWT_TOKEN

Ответ:

{
  "id": "uuid",
  "username": "string",
  "email": "user@example.com",
  "is_active": true,
  "is_admin": false,
  "created_at": "2024-01-01T00:00:00"
}

Примеры:

Python:

import requests

url = "http://localhost:8020/auth/me"
headers = {
    "Authorization": f"Bearer {token}"
}

response = requests.get(url, headers=headers)
user = response.json()
print(f"Current user: {user['username']}")

2. Транскрибация

🎤 Транскрибировать аудио

POST /transcribe/

Загрузка и транскрибация аудиофайла.

Параметры:

Ответ:

{
  "id": "uuid",
  "filename": "audio.mp3",
  "text": "Транскрибированный текст...",
  "language": "ru",
  "duration": 120.5,
  "processing_time": 15.3,
  "status": "completed",
  "created_at": "2024-01-01T00:00:00",
  "segments": [
    {
      "id": 0,
      "start": 0.0,
      "end": 5.2,
      "text": "Первый сегмент текста",
      "words": [  // Только если return_timestamps=true
        {
          "word": "Первый",
          "start": 0.0,
          "end": 0.8,
          "probability": 0.95
        },
        {
          "word": "сегмент",
          "start": 0.8,
          "end": 1.5,
          "probability": 0.98
        }
      ]
    }
  ]
}

Примеры:

Python:

import requests

url = "http://localhost:8020/transcribe/"
headers = {
    "Authorization": f"Bearer {token}"
}

with open("audio.mp3", "rb") as audio_file:
    files = {"file": audio_file}
    data = {
        "language": "ru",
        "return_segments": "true",
        "return_timestamps": "true"  # Включить пословные метки времени
    }

    response = requests.post(url, headers=headers, files=files, data=data)
    result = response.json()

    print(f"Transcription ID: {result['id']}")
    print(f"Text: {result['text'][:100]}...")
    print(f"Duration: {result['duration']} seconds")

    # Обработка меток времени
    if "segments" in result:
        for segment in result["segments"]:
            print(f"\nSegment {segment['id']}: {segment['start']:.1f}s - {segment['end']:.1f}s")
            if "words" in segment:
                for word in segment["words"]:
                    print(f"  {word['word']}: {word['start']:.1f}s - {word['end']:.1f}s")

PHP:

<?php
$url = "http://localhost:8020/transcribe/";
$token = "YOUR_JWT_TOKEN";

$file = new CURLFile('audio.mp3');
$data = array(
    'file' => $file,
    'language' => 'ru',
    'return_segments' => 'false'
);

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
    "Authorization: Bearer " . $token
));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

$response = curl_exec($ch);
curl_close($ch);

$result = json_decode($response, true);
echo "Text: " . $result['text'];
?>

JavaScript:

async function transcribeAudio(file, token) {
    const formData = new FormData();
    formData.append('file', file);
    formData.append('language', 'ru');
    formData.append('return_segments', 'false');

    const response = await fetch('http://localhost:8020/transcribe/', {
        method: 'POST',
        headers: {
            'Authorization': `Bearer ${token}`
        },
        body: formData
    });

    const result = await response.json();
    console.log('Transcription:', result.text);
    return result;
}

// Использование с input файла
const fileInput = document.getElementById('fileInput');
fileInput.addEventListener('change', async (e) => {
    const file = e.target.files[0];
    await transcribeAudio(file, token);
});

cURL:

curl -X POST "http://localhost:8020/transcribe/" \
     -H "Authorization: Bearer YOUR_JWT_TOKEN" \
     -F "file=@audio.mp3" \
     -F "language=ru" \
     -F "return_segments=false"

📜 История транскрибаций

GET /transcribe/history

Получение списка всех транскрибаций пользователя.

Параметры:

Ответ:

[
  {
    "id": "uuid",
    "filename": "audio.mp3",
    "status": "completed",
    "duration": 120.5,
    "language": "ru",
    "created_at": "2024-01-01T00:00:00"
  }
]

Примеры:

Python:

import requests

url = "http://localhost:8020/transcribe/history"
headers = {
    "Authorization": f"Bearer {token}"
}
params = {
    "skip": 0,
    "limit": 50
}

response = requests.get(url, headers=headers, params=params)
history = response.json()

for item in history:
    print(f"{item['filename']} - {item['status']} - {item['created_at']}")

🔍 Получить транскрибацию

GET /transcribe/{transcription_id}

Получение полной информации о конкретной транскрибации.

Ответ:

{
  "id": "uuid",
  "filename": "audio.mp3",
  "text": "Полный текст транскрибации...",
  "language": "ru",
  "duration": 120.5,
  "processing_time": 15.3,
  "status": "completed",
  "created_at": "2024-01-01T00:00:00",
  "segments": []
}

🎵 Стриминг аудио

GET /transcriptions/{transcription_id}/audio

Получение аудиофайла для воспроизведения.

Примеры:

Python:

import requests

url = f"http://localhost:8020/transcriptions/{transcription_id}/audio"
headers = {
    "Authorization": f"Bearer {token}"
}

response = requests.get(url, headers=headers, stream=True)

# Сохранить аудио
with open("downloaded_audio.mp3", "wb") as f:
    for chunk in response.iter_content(chunk_size=8192):
        f.write(chunk)

JavaScript:

async function playAudio(transcriptionId, token) {
    const response = await fetch(
        `http://localhost:8020/transcriptions/${transcriptionId}/audio`,
        {
            headers: {
                'Authorization': `Bearer ${token}`
            }
        }
    );

    const blob = await response.blob();
    const audioUrl = URL.createObjectURL(blob);

    const audio = new Audio(audioUrl);
    audio.play();
}

📊 Статус транскрибации

GET /transcriptions/{transcription_id}/status

Проверка статуса обработки транскрибации.

Ответ:

{
  "id": "uuid",
  "status": "processing",
  "filename": "audio.mp3",
  "created_at": "2024-01-01T00:00:00",
  "completed_at": null,
  "duration": null,
  "processing_time": null,
  "error_message": null
}

Примеры:

Python:

import requests
import time

def wait_for_transcription(transcription_id, token):
    url = f"http://localhost:8020/transcriptions/{transcription_id}/status"
    headers = {"Authorization": f"Bearer {token}"}

    while True:
        response = requests.get(url, headers=headers)
        status = response.json()

        if status['status'] == 'completed':
            print("Transcription completed!")
            return True
        elif status['status'] == 'failed':
            print(f"Transcription failed: {status['error_message']}")
            return False

        print(f"Status: {status['status']}... waiting")
        time.sleep(2)

💾 Скачать транскрибацию

GET /transcriptions/{transcription_id}/download

Скачивание текста транскрибации в различных форматах.

Параметры:

Примеры:

Python:

import requests

# Скачать как текст
url = f"http://localhost:8020/transcriptions/{transcription_id}/download?format=txt"
headers = {"Authorization": f"Bearer {token}"}

response = requests.get(url, headers=headers)
with open("transcription.txt", "w", encoding="utf-8") as f:
    f.write(response.text)

# Скачать как субтитры SRT
url = f"http://localhost:8020/transcriptions/{transcription_id}/download?format=srt"
response = requests.get(url, headers=headers)
with open("transcription.srt", "w", encoding="utf-8") as f:
    f.write(response.text)

3. Управление пользователями

📋 Список пользователей (Admin)

GET /admin/users

Получение списка всех пользователей (требуются права администратора).

Ответ:

[
  {
    "id": "uuid",
    "username": "user1",
    "email": "user1@example.com",
    "is_active": true,
    "is_admin": false,
    "created_at": "2024-01-01T00:00:00"
  }
]

✏️ Обновить пользователя (Admin)

PATCH /admin/users/{user_id}

Обновление данных пользователя.

Параметры:

{
  "username": "new_username",
  "email": "new@example.com",
  "password": "new_password",
  "is_active": true,
  "is_admin": false
}

Примеры:

Python:

import requests

url = f"http://localhost:8020/admin/users/{user_id}"
headers = {
    "Authorization": f"Bearer {admin_token}",
    "Content-Type": "application/json"
}
data = {
    "is_active": False,
    "is_admin": True
}

response = requests.patch(url, headers=headers, json=data)
updated_user = response.json()
print(f"Updated user: {updated_user}")

🗑️ Удалить пользователя (Admin)

DELETE /admin/users/{user_id}

Удаление пользователя из системы.

Примеры:

JavaScript:

async function deleteUser(userId, token) {
    const response = await fetch(`http://localhost:8020/admin/users/${userId}`, {
        method: 'DELETE',
        headers: {
            'Authorization': `Bearer ${token}`
        }
    });

    if (response.ok) {
        console.log('User deleted successfully');
    } else {
        console.error('Failed to delete user');
    }
}

4. API Ключи

🔑 Создать API ключ

POST /api-keys/

Создание нового API ключа для программного доступа.

Параметры:

{
  "name": "My Application",
  "permissions": ["transcribe", "read"],
  "rate_limit": 100,
  "expires_in_days": 365
}

Ответ:

{
  "id": "uuid",
  "name": "My Application",
  "key": "sk_live_abcdef123456789...",
  "key_prefix": "sk_live_abc...",
  "is_active": true,
  "permissions": ["transcribe", "read"],
  "rate_limit": 100,
  "created_at": "2024-01-01T00:00:00",
  "expires_at": "2025-01-01T00:00:00"
}

Важно: Полный ключ (key) показывается только один раз при создании!

Примеры:

Python:

import requests

url = "http://localhost:8020/api-keys/"
headers = {
    "Authorization": f"Bearer {token}",
    "Content-Type": "application/json"
}
data = {
    "name": "Python Client",
    "permissions": ["transcribe"],
    "rate_limit": 1000,
    "expires_in_days": 90
}

response = requests.post(url, headers=headers, json=data)
api_key = response.json()

print(f"API Key created: {api_key['key']}")
print("Save this key securely! It won't be shown again.")

# Использование API ключа вместо JWT токена
api_headers = {
    "X-API-Key": api_key['key']
}

📋 Список API ключей

GET /api-keys/

Получение списка всех API ключей пользователя.

Ответ:

[
  {
    "id": "uuid",
    "name": "My Application",
    "key_prefix": "sk_live_abc...",
    "is_active": true,
    "permissions": ["transcribe", "read"],
    "rate_limit": 100,
    "created_at": "2024-01-01T00:00:00",
    "last_used_at": "2024-01-15T12:00:00",
    "expires_at": "2025-01-01T00:00:00"
  }
]

5. Метрики

📊 Системные метрики

GET /metrics/system

Получение метрик системы и статистики использования.

Ответ:

{
  "cpu_usage": 45.2,
  "memory_usage": 62.8,
  "disk_usage": 35.1,
  "gpu_available": true,
  "gpu_memory_used": "8.5 GB",
  "whisper_model": "large-v3",
  "active_users": 12,
  "total_transcriptions_24h": 156,
  "average_processing_time": 12.3,
  "uptime_seconds": 86400
}

Примеры:

Python:

import requests

url = "http://localhost:8020/metrics/system"
headers = {"Authorization": f"Bearer {token}"}

response = requests.get(url, headers=headers)
metrics = response.json()

print(f"CPU Usage: {metrics['cpu_usage']}%")
print(f"GPU Available: {metrics['gpu_available']}")
print(f"Model: {metrics['whisper_model']}")
print(f"Transcriptions (24h): {metrics['total_transcriptions_24h']}")

👤 Пользовательские метрики

GET /metrics/user

Получение статистики использования для текущего пользователя.

Ответ:

{
  "total_transcriptions": 523,
  "total_duration_seconds": 125840.5,
  "total_characters": 2456789,
  "total_api_calls": 1523,
  "monthly_transcriptions": 45,
  "monthly_duration_seconds": 10234.2,
  "monthly_characters": 234567,
  "monthly_api_calls": 156,
  "last_reset_date": "2024-01-01T00:00:00"
}

6. Администрирование

📋 Все транскрибации (Admin)

GET /admin/transcriptions

Получение списка всех транскрибаций в системе.

Ответ:

[
  {
    "id": "uuid",
    "filename": "audio.mp3",
    "status": "completed",
    "duration": 120.5,
    "language": "ru",
    "created_at": "2024-01-01T00:00:00",
    "user_id": "uuid",
    "username": "user1"
  }
]

🔧 Обработка ошибок

Все ошибки возвращаются в стандартном формате:

{
  "detail": "Описание ошибки"
}

Коды ошибок:

Пример обработки ошибок (Python):

import requests

def safe_api_call(url, headers, method="GET", **kwargs):
    try:
        if method == "GET":
            response = requests.get(url, headers=headers, **kwargs)
        elif method == "POST":
            response = requests.post(url, headers=headers, **kwargs)

        if response.status_code == 200:
            return response.json()
        elif response.status_code == 401:
            print("Authentication required. Please login.")
        elif response.status_code == 403:
            print("Access denied. Check permissions.")
        elif response.status_code == 404:
            print("Resource not found.")
        elif response.status_code == 429:
            print("Rate limit exceeded. Please wait.")
        else:
            error = response.json()
            print(f"Error: {error.get('detail', 'Unknown error')}")

    except requests.exceptions.RequestException as e:
        print(f"Network error: {e}")

    return None

🚀 Полный пример использования

Python - Полный workflow:

import requests
import time

class Speech2TextClient:
    def __init__(self, base_url="http://localhost:8020"):
        self.base_url = base_url
        self.token = None

    def login(self, username, password):
        """Авторизация в системе"""
        response = requests.post(
            f"{self.base_url}/auth/login",
            json={"username": username, "password": password}
        )
        if response.status_code == 200:
            self.token = response.json()["access_token"]
            print("Login successful!")
            return True
        return False

    def transcribe(self, audio_path, language=None):
        """Транскрибация аудиофайла"""
        if not self.token:
            print("Please login first")
            return None

        headers = {"Authorization": f"Bearer {self.token}"}

        with open(audio_path, "rb") as f:
            files = {"file": f}
            data = {"language": language} if language else {}

            response = requests.post(
                f"{self.base_url}/transcribe/",
                headers=headers,
                files=files,
                data=data
            )

        if response.status_code == 200:
            return response.json()
        else:
            print(f"Error: {response.text}")
            return None

    def wait_for_completion(self, transcription_id, timeout=300):
        """Ожидание завершения транскрибации"""
        headers = {"Authorization": f"Bearer {self.token}"}
        start_time = time.time()

        while time.time() - start_time < timeout:
            response = requests.get(
                f"{self.base_url}/transcriptions/{transcription_id}/status",
                headers=headers
            )

            if response.status_code == 200:
                status = response.json()
                if status["status"] == "completed":
                    return True
                elif status["status"] == "failed":
                    print(f"Transcription failed: {status.get('error_message')}")
                    return False

            time.sleep(2)

        print("Timeout waiting for transcription")
        return False

    def get_transcription(self, transcription_id):
        """Получение результата транскрибации"""
        headers = {"Authorization": f"Bearer {self.token}"}

        response = requests.get(
            f"{self.base_url}/transcribe/{transcription_id}",
            headers=headers
        )

        if response.status_code == 200:
            return response.json()
        return None

    def download_text(self, transcription_id, output_path):
        """Скачивание текста транскрибации"""
        headers = {"Authorization": f"Bearer {self.token}"}

        response = requests.get(
            f"{self.base_url}/transcriptions/{transcription_id}/download",
            headers=headers
        )

        if response.status_code == 200:
            with open(output_path, "w", encoding="utf-8") as f:
                f.write(response.text)
            print(f"Transcription saved to {output_path}")
            return True
        return False

# Использование
if __name__ == "__main__":
    client = Speech2TextClient()

    # Авторизация
    if client.login("admin", "admin123"):

        # Транскрибация
        result = client.transcribe("podcast.mp3", language="ru")
        if result:
            print(f"Transcription ID: {result['id']}")
            print(f"Status: {result['status']}")

            # Ожидание завершения
            if result['status'] == 'processing':
                if client.wait_for_completion(result['id']):
                    # Получение результата
                    full_result = client.get_transcription(result['id'])
                    print(f"Text: {full_result['text'][:200]}...")

                    # Сохранение в файл
                    client.download_text(result['id'], "transcription.txt")

JavaScript - Полный workflow:

class Speech2TextClient {
    constructor(baseUrl = 'http://localhost:8020') {
        this.baseUrl = baseUrl;
        this.token = null;
    }

    async login(username, password) {
        const response = await fetch(`${this.baseUrl}/auth/login`, {
            method: 'POST',
            headers: {'Content-Type': 'application/json'},
            body: JSON.stringify({username, password})
        });

        if (response.ok) {
            const data = await response.json();
            this.token = data.access_token;
            console.log('Login successful!');
            return true;
        }
        return false;
    }

    async transcribe(file, language = null) {
        if (!this.token) {
            console.error('Please login first');
            return null;
        }

        const formData = new FormData();
        formData.append('file', file);
        if (language) {
            formData.append('language', language);
        }

        const response = await fetch(`${this.baseUrl}/transcribe/`, {
            method: 'POST',
            headers: {
                'Authorization': `Bearer ${this.token}`
            },
            body: formData
        });

        if (response.ok) {
            return await response.json();
        }
        return null;
    }

    async waitForCompletion(transcriptionId, timeout = 300000) {
        const startTime = Date.now();

        while (Date.now() - startTime < timeout) {
            const response = await fetch(
                `${this.baseUrl}/transcriptions/${transcriptionId}/status`,
                {
                    headers: {'Authorization': `Bearer ${this.token}`}
                }
            );

            if (response.ok) {
                const status = await response.json();
                if (status.status === 'completed') {
                    return true;
                } else if (status.status === 'failed') {
                    console.error('Transcription failed:', status.error_message);
                    return false;
                }
            }

            await new Promise(resolve => setTimeout(resolve, 2000));
        }

        console.error('Timeout waiting for transcription');
        return false;
    }

    async getTranscription(transcriptionId) {
        const response = await fetch(
            `${this.baseUrl}/transcribe/${transcriptionId}`,
            {
                headers: {'Authorization': `Bearer ${this.token}`}
            }
        );

        if (response.ok) {
            return await response.json();
        }
        return null;
    }
}

// Использование
async function main() {
    const client = new Speech2TextClient();

    // Авторизация
    if (await client.login('admin', 'admin123')) {

        // Выбор файла
        const fileInput = document.getElementById('fileInput');
        fileInput.addEventListener('change', async (e) => {
            const file = e.target.files[0];

            // Транскрибация
            const result = await client.transcribe(file, 'ru');
            if (result) {
                console.log('Transcription ID:', result.id);

                // Ожидание завершения
                if (result.status === 'processing') {
                    if (await client.waitForCompletion(result.id)) {
                        // Получение результата
                        const fullResult = await client.getTranscription(result.id);
                        console.log('Text:', fullResult.text);

                        // Отображение результата
                        document.getElementById('result').textContent = fullResult.text;
                    }
                }
            }
        });
    }
}

main();

📝 Советы и рекомендации

Оптимизация производительности:

  1. Формат файлов: Конвертируйте в WAV 16kHz моно для быстрой обработки
  2. Размер файлов: Разбивайте большие файлы на части по 30 минут
  3. Язык: Указывайте язык явно для ускорения обработки
  4. Batch обработка: Загружайте несколько файлов параллельно

Безопасность:

  1. Храните токены безопасно: Никогда не включайте токены в код
  2. Используйте HTTPS: В продакшене всегда используйте HTTPS
  3. Ротация ключей: Регулярно обновляйте API ключи
  4. Ограничение прав: Давайте минимально необходимые права

Обработка ошибок:

  1. Retry логика: Реализуйте повторные попытки при временных ошибках
  2. Таймауты: Устанавливайте разумные таймауты для долгих операций
  3. Логирование: Логируйте все ошибки для отладки
  4. Graceful degradation: Предусмотрите fallback сценарии

🔗 Полезные ссылки


📞 Поддержка

При возникновении проблем: 1. Проверьте логи сервера 2. Убедитесь в правильности токена 3. Проверьте формат и размер файла 4. Обратитесь к документации API

Для технической поддержки создайте issue на GitHub или напишите на support@speech2text.com