Spaces:
Sleeping
Sleeping
Evgeny Naumov
Добавлена асинхронная транскрипция с отслеживанием прогресса и увеличенными таймаутами
6232404
| # Whisper API Документация | |
| ## Обзор | |
| Whisper API предоставляет REST API для транскрипции аудио файлов с использованием моделей Whisper. API работает на порту 3001 и поддерживает как синхронные, так и асинхронные запросы для длинных транскрипций. | |
| **Базовый URL:** `http://localhost:3001/api` | |
| ## Endpoints | |
| ### 1. Проверка здоровья сервера | |
| **GET** `/health` | |
| Проверяет, что сервер работает. | |
| **Ответ:** | |
| ```json | |
| { | |
| "status": "ok", | |
| "message": "Whisper API сервер работает", | |
| "timestamp": "2024-01-01T12:00:00.000Z" | |
| } | |
| ``` | |
| ### 2. Асинхронная транскрипция аудио файла | |
| **POST** `/transcribe` | |
| Загружает и транскрибирует аудио файл асинхронно. Возвращает ID задачи для отслеживания прогресса. | |
| **Параметры:** | |
| - `audio` (file) - аудио файл (обязательно) | |
| - `language` (string) - язык аудио (по умолчанию: "auto") | |
| - `model` (string) - модель Whisper (по умолчанию: "base") | |
| **Поддерживаемые форматы:** mp3, wav, m4a, webm, ogg | |
| **Максимальный размер файла:** 50MB | |
| **Пример запроса (cURL):** | |
| ```bash | |
| curl -X POST http://localhost:3001/api/transcribe \ | |
| -F "audio=@/path/to/audio.mp3" \ | |
| -F "language=ru" \ | |
| -F "model=base" | |
| ``` | |
| **Ответ:** | |
| ```json | |
| { | |
| "success": true, | |
| "taskId": "abc123def456", | |
| "status": "processing", | |
| "message": "Транскрипция началась", | |
| "timestamp": "2024-01-01T12:00:00.000Z" | |
| } | |
| ``` | |
| ### 3. Проверка статуса задачи | |
| **GET** `/status/{taskId}` | |
| Проверяет статус и прогресс транскрипции. | |
| **Пример запроса:** | |
| ```bash | |
| curl http://localhost:3001/api/status/abc123def456 | |
| ``` | |
| **Ответ:** | |
| ```json | |
| { | |
| "success": true, | |
| "task": { | |
| "id": "abc123def456", | |
| "filename": "audio.mp3", | |
| "language": "ru", | |
| "model": "base", | |
| "status": "processing", | |
| "progress": 45, | |
| "result": null, | |
| "error": null, | |
| "createdAt": "2024-01-01T12:00:00.000Z", | |
| "updatedAt": "2024-01-01T12:05:00.000Z" | |
| }, | |
| "timestamp": "2024-01-01T12:05:00.000Z" | |
| } | |
| ``` | |
| ### 4. Получение результата транскрипции | |
| **GET** `/result/{taskId}` | |
| Получает готовый результат транскрипции. | |
| **Пример запроса:** | |
| ```bash | |
| curl http://localhost:3001/api/result/abc123def456 | |
| ``` | |
| **Ответ (если транскрипция завершена):** | |
| ```json | |
| { | |
| "success": true, | |
| "status": "completed", | |
| "transcription": { | |
| "text": "Транскрибированный текст", | |
| "language": "ru", | |
| "model": "base", | |
| "duration": 120.5, | |
| "segments": [ | |
| { | |
| "start": 0, | |
| "end": 10, | |
| "text": "Первая часть текста" | |
| } | |
| ], | |
| "timestamp": "2024-01-01T12:10:00.000Z" | |
| }, | |
| "timestamp": "2024-01-01T12:10:00.000Z" | |
| } | |
| ``` | |
| **Ответ (если транскрипция еще выполняется):** | |
| ```json | |
| { | |
| "success": true, | |
| "status": "processing", | |
| "progress": 75, | |
| "message": "Транскрипция еще выполняется" | |
| } | |
| ``` | |
| **Ответ (если произошла ошибка):** | |
| ```json | |
| { | |
| "success": false, | |
| "status": "error", | |
| "error": "Описание ошибки" | |
| } | |
| ``` | |
| ### 5. Асинхронная транскрипция по URL | |
| **POST** `/transcribe/url` | |
| Транскрибирует аудио файл по URL асинхронно. | |
| **Тело запроса:** | |
| ```json | |
| { | |
| "url": "https://example.com/audio.mp3", | |
| "language": "ru", | |
| "model": "base" | |
| } | |
| ``` | |
| **Пример запроса (cURL):** | |
| ```bash | |
| curl -X POST http://localhost:3001/api/transcribe/url \ | |
| -H "Content-Type: application/json" \ | |
| -d '{ | |
| "url": "https://example.com/audio.mp3", | |
| "language": "ru", | |
| "model": "base" | |
| }' | |
| ``` | |
| **Ответ:** | |
| ```json | |
| { | |
| "success": true, | |
| "taskId": "def456ghi789", | |
| "status": "processing", | |
| "message": "Транскрипция по URL началась", | |
| "timestamp": "2024-01-01T12:00:00.000Z" | |
| } | |
| ``` | |
| ### 6. Список доступных моделей | |
| **GET** `/models` | |
| Возвращает список доступных моделей Whisper. | |
| **Ответ:** | |
| ```json | |
| { | |
| "models": [ | |
| { | |
| "id": "tiny", | |
| "name": "Tiny", | |
| "size": "39 MB", | |
| "languages": "multilingual" | |
| }, | |
| { | |
| "id": "base", | |
| "name": "Base", | |
| "size": "74 MB", | |
| "languages": "multilingual" | |
| }, | |
| { | |
| "id": "small", | |
| "name": "Small", | |
| "size": "244 MB", | |
| "languages": "multilingual" | |
| }, | |
| { | |
| "id": "medium", | |
| "name": "Medium", | |
| "size": "769 MB", | |
| "languages": "multilingual" | |
| }, | |
| { | |
| "id": "large", | |
| "name": "Large", | |
| "size": "1550 MB", | |
| "languages": "multilingual" | |
| } | |
| ], | |
| "default": "base" | |
| } | |
| ``` | |
| ### 7. Список поддерживаемых языков | |
| **GET** `/languages` | |
| Возвращает список поддерживаемых языков. | |
| **Ответ:** | |
| ```json | |
| { | |
| "languages": [ | |
| { | |
| "code": "auto", | |
| "name": "Автоопределение" | |
| }, | |
| { | |
| "code": "ru", | |
| "name": "Русский" | |
| }, | |
| { | |
| "code": "en", | |
| "name": "English" | |
| }, | |
| { | |
| "code": "es", | |
| "name": "Español" | |
| }, | |
| { | |
| "code": "fr", | |
| "name": "Français" | |
| }, | |
| { | |
| "code": "de", | |
| "name": "Deutsch" | |
| }, | |
| { | |
| "code": "it", | |
| "name": "Italiano" | |
| }, | |
| { | |
| "code": "pt", | |
| "name": "Português" | |
| }, | |
| { | |
| "code": "pl", | |
| "name": "Polski" | |
| }, | |
| { | |
| "code": "tr", | |
| "name": "Türkçe" | |
| }, | |
| { | |
| "code": "ja", | |
| "name": "日本語" | |
| }, | |
| { | |
| "code": "ko", | |
| "name": "한국어" | |
| }, | |
| { | |
| "code": "zh", | |
| "name": "中文" | |
| } | |
| ], | |
| "default": "auto" | |
| } | |
| ``` | |
| ## Коды ошибок | |
| - **400** - Неверный запрос (отсутствует файл, неподдерживаемый формат) | |
| - **404** - Endpoint не найден или задача не найдена | |
| - **500** - Внутренняя ошибка сервера | |
| - **202** - Задача в процессе выполнения (для `/result/{taskId}`) | |
| ## Таймауты | |
| - **Таймаут сервера:** 1 час (3600000 мс) | |
| - **Таймаут запроса:** 1 час | |
| - **Таймаут ответа:** 1 час | |
| ## Примеры использования | |
| ### Python | |
| ```python | |
| import requests | |
| import time | |
| # Асинхронная транскрипция файла | |
| with open('audio.mp3', 'rb') as f: | |
| files = {'audio': f} | |
| data = {'language': 'ru', 'model': 'base'} | |
| response = requests.post('http://localhost:3001/api/transcribe', files=files, data=data) | |
| result = response.json() | |
| task_id = result['taskId'] | |
| print(f"Задача создана: {task_id}") | |
| # Проверка статуса | |
| while True: | |
| status_response = requests.get(f'http://localhost:3001/api/status/{task_id}') | |
| status_data = status_response.json() | |
| if status_data['task']['status'] == 'completed': | |
| break | |
| elif status_data['task']['status'] == 'error': | |
| print(f"Ошибка: {status_data['task']['error']}") | |
| break | |
| print(f"Прогресс: {status_data['task']['progress']}%") | |
| time.sleep(5) # Проверяем каждые 5 секунд | |
| # Получение результата | |
| result_response = requests.get(f'http://localhost:3001/api/result/{task_id}') | |
| final_result = result_response.json() | |
| print(f"Транскрипция: {final_result['transcription']['text']}") | |
| # Асинхронная транскрипция по URL | |
| data = { | |
| 'url': 'https://example.com/audio.mp3', | |
| 'language': 'ru', | |
| 'model': 'base' | |
| } | |
| response = requests.post('http://localhost:3001/api/transcribe/url', json=data) | |
| result = response.json() | |
| task_id = result['taskId'] | |
| # Ожидание завершения и получение результата | |
| while True: | |
| result_response = requests.get(f'http://localhost:3001/api/result/{task_id}') | |
| result_data = result_response.json() | |
| if result_data['status'] == 'completed': | |
| print(f"Транскрипция: {result_data['transcription']['text']}") | |
| break | |
| elif result_data['status'] == 'error': | |
| print(f"Ошибка: {result_data['error']}") | |
| break | |
| print(f"Статус: {result_data['status']}, Прогресс: {result_data.get('progress', 0)}%") | |
| time.sleep(5) | |
| ``` | |
| ### JavaScript | |
| ```javascript | |
| // Асинхронная транскрипция файла | |
| async function transcribeFile(file) { | |
| const formData = new FormData(); | |
| formData.append('audio', file); | |
| formData.append('language', 'ru'); | |
| formData.append('model', 'base'); | |
| const response = await fetch('http://localhost:3001/api/transcribe', { | |
| method: 'POST', | |
| body: formData | |
| }); | |
| const result = await response.json(); | |
| return result.taskId; | |
| } | |
| // Проверка статуса | |
| async function checkStatus(taskId) { | |
| const response = await fetch(`http://localhost:3001/api/status/${taskId}`); | |
| return await response.json(); | |
| } | |
| // Получение результата | |
| async function getResult(taskId) { | |
| const response = await fetch(`http://localhost:3001/api/result/${taskId}`); | |
| return await response.json(); | |
| } | |
| // Полный процесс транскрипции | |
| async function transcribeWithProgress(file) { | |
| const taskId = await transcribeFile(file); | |
| console.log(`Задача создана: ${taskId}`); | |
| while (true) { | |
| const status = await checkStatus(taskId); | |
| if (status.task.status === 'completed') { | |
| const result = await getResult(taskId); | |
| console.log(`Транскрипция: ${result.transcription.text}`); | |
| break; | |
| } else if (status.task.status === 'error') { | |
| console.error(`Ошибка: ${status.task.error}`); | |
| break; | |
| } | |
| console.log(`Прогресс: ${status.task.progress}%`); | |
| await new Promise(resolve => setTimeout(resolve, 5000)); | |
| } | |
| } | |
| ``` | |
| ### C# | |
| ```csharp | |
| using System; | |
| using System.Net.Http; | |
| using System.Threading.Tasks; | |
| using Newtonsoft.Json; | |
| public class TranscriptionClient | |
| { | |
| private readonly HttpClient _client; | |
| private readonly string _baseUrl = "http://localhost:3001/api"; | |
| public TranscriptionClient() | |
| { | |
| _client = new HttpClient(); | |
| } | |
| public async Task<string> TranscribeFileAsync(string filePath, string language = "ru", string model = "base") | |
| { | |
| using var form = new MultipartFormDataContent(); | |
| using var fileStream = File.OpenRead(filePath); | |
| form.Add(new StreamContent(fileStream), "audio", Path.GetFileName(filePath)); | |
| form.Add(new StringContent(language), "language"); | |
| form.Add(new StringContent(model), "model"); | |
| var response = await _client.PostAsync($"{_baseUrl}/transcribe", form); | |
| var result = await response.Content.ReadAsStringAsync(); | |
| var data = JsonConvert.DeserializeObject<dynamic>(result); | |
| return data.taskId.ToString(); | |
| } | |
| public async Task<dynamic> GetStatusAsync(string taskId) | |
| { | |
| var response = await _client.GetAsync($"{_baseUrl}/status/{taskId}"); | |
| var result = await response.Content.ReadAsStringAsync(); | |
| return JsonConvert.DeserializeObject<dynamic>(result); | |
| } | |
| public async Task<dynamic> GetResultAsync(string taskId) | |
| { | |
| var response = await _client.GetAsync($"{_baseUrl}/result/{taskId}"); | |
| var result = await response.Content.ReadAsStringAsync(); | |
| return JsonConvert.DeserializeObject<dynamic>(result); | |
| } | |
| public async Task<string> TranscribeWithProgressAsync(string filePath) | |
| { | |
| var taskId = await TranscribeFileAsync(filePath); | |
| Console.WriteLine($"Задача создана: {taskId}"); | |
| while (true) | |
| { | |
| var status = await GetStatusAsync(taskId); | |
| if (status.task.status == "completed") | |
| { | |
| var result = await GetResultAsync(taskId); | |
| return result.transcription.text.ToString(); | |
| } | |
| else if (status.task.status == "error") | |
| { | |
| throw new Exception($"Ошибка транскрипции: {status.task.error}"); | |
| } | |
| Console.WriteLine($"Прогресс: {status.task.progress}%"); | |
| await Task.Delay(5000); | |
| } | |
| } | |
| } | |
| ``` | |
| ## Развертывание | |
| ### Локально | |
| ```bash | |
| cd whisper-web | |
| npm install | |
| npm run build | |
| node server/simple-server.js | |
| ``` | |
| ### На Hugging Face Spaces | |
| Проект автоматически развертывается на Hugging Face Spaces с использованием Gradio интерфейса. Сервер запускается на порту 3001. | |
| ## Примечания | |
| - Все транскрипции выполняются асинхронно для предотвращения таймаутов | |
| - Прогресс транскрипции можно отслеживать через endpoint `/status/{taskId}` | |
| - Результаты сохраняются в памяти сервера (не в базе данных) | |
| - Таймауты увеличены до 1 часа для поддержки длинных аудио файлов |