Автоматизация расшифровки полезна, когда у записи есть повторяемый путь: понятный способ поступления, единый результат анализа, ответственный за проверку и место, где команда использует итог. Сам по себе бот или импорт по ссылке решает только часть этой задачи.
Начните с одного сценария. Например: клиентский звонок → транскрипт → разбор продажи → проверенная заметка → карточка сделки. Ниже — способ организовать такой процесс без потери контекста и ошибочных обещаний от имени клиента.
Согласуйте результат, который нужен получателю
Учебная команда продаёт обучение для филиалов. После каждого звонка менеджеру нужны сведения о задаче клиента, участниках решения, условиях запуска и следующем шаге. Длинное резюме разговора он не успевает использовать.
Сначала заполните карточку процесса:
Источник: запись обсуждения с клиентом.
Результат: заметка о состоянии сделки и следующем действии.
Проверяющий: менеджер, который вёл разговор.
Получатель: команда в карточке нужной сделки.
Основания: название записи и фрагменты важных реплик.
Готовность: неясные условия обозначены, ответственные не придуманы.
Если команда не согласна с форматом, автоматическое создание большого числа заметок только увеличит путаницу. Сначала добейтесь полезного результата на одном разговоре.
Выберите обычный способ поступления записи
В разделе новой расшифровки Текстослава доступны варианты «Файл», «Ссылка», «Записать» и «Боты».
Файл. Подходит для записи, уже сохранённой на устройстве. Проверьте размер, длительность и понятное название.
Ссылка. Откройте «Какие ссылки поддерживаются», вставьте адрес и проверьте доступность. Запись должна открываться без входа и пароля. Если для рабочего файла нельзя расширять доступ, используйте разрешённую загрузку файла.
Записать. Этот путь ведёт к расширению Chrome для записи встречи. Заранее проверьте звук и выбранный способ сохранения на короткой пробе.
Боты. Переходите к официальному боту из кабинета. Там можно выбрать доступный канал и связать его с аккаунтом. Не отправляйте рабочие материалы боту, найденному только по похожему названию.
Для команды назначьте основной путь, а остальные оставьте для конкретных случаев. Иначе одна встреча может попасть в архив несколько раз: через файл, ссылку и пересылку.
Публичный API: файл → задание → готовый текст
Если записи уже поступают в вашу собственную систему, можно использовать публичный API Текстослава. Для собственного серверного скрипта подойдёт ключ API из кабинета. Он доступен на платном тарифе с публичным API; стартовый пробный план его не включает. Для приложения, которое подключают другие пользователи, предусмотрен OAuth — способ авторизации выбирают по сценарию.
Ниже — конкретный маршрут для локального файла и multipart-загрузки. Контракт сверён 10 октября 2026 года; актуальные поля и ограничения — в OpenAPI.
Прокрутите таблицу по горизонтали ↔
| Шаг | Запрос | Что сохраняем |
|---|---|---|
| Создать загрузку | POST /v1/uploads: имя, размер в байтах, MIME-тип, язык | upload_id, reserved_job_id; один Idempotency-Key на этот исходник |
| Передать файл | Получить URL частей, отправить каждую часть PUT по её URL | Состояние загрузки; ключ API к этим URL не добавляют |
| Завершить загрузку | POST /v1/uploads/{upload_id}/complete с {"parts":[]} | Полученный job_id; при ожидании проверяют ту же сессию |
| Дождаться текста | GET /v1/transcriptions/{job_id}/status | Состояние; при failed передача результата прекращается |
| Скачать | GET /v1/transcriptions/{job_id}/download?format=txt | Готовый TXT и связь с заданием |
Завершение с пустым списком parts разрешено: после успешной передачи всех частей сервис определяет их при завершении. Начало части номер N в файле — (N − 1) × part_size_bytes. Не подставляйте произвольную длину части, не загружайте весь файл по URL одной части.
Исполняемый пример Python
Нужен Python 3; дополнительных библиотек нет. Сохраните код в transcribe.py в своей рабочей папке и запустите:
python transcribe.py interview.m4a result.txtСкрипт спросит ключ скрытым вводом либо возьмёт TEXTOSLAV_API_KEY из окружения. Рядом с результатом он сохраняет файл состояния с идентификаторами и контрольной суммой исходника, без ключа и временных URL. При повторном запуске с теми же путями продолжит ту же загрузку. Исходный файл во время работы не меняйте. Для первого прогона используйте разрешённую учебную запись.
import email.utils
import getpass
import hashlib
import json
import mimetypes
import os
import random
import sys
import time
import urllib.error
import urllib.request
import uuid
from pathlib import Path
BASE = "https://api.textoslav.ru/v1"
source, output = map(Path, sys.argv[1:3])
state_path = Path(str(output) + ".state.json")
api_key = os.environ.get("TEXTOSLAV_API_KEY") or getpass.getpass("Ключ API: ")
deadline = time.monotonic() + 1800
def remaining():
seconds = deadline - time.monotonic()
if seconds <= 0:
raise RuntimeError("Истёк срок ожидания; состояние сохранено")
return seconds
def pause(seconds):
if seconds >= remaining():
raise RuntimeError("Ожидание превышает срок; повторите запуск позже")
time.sleep(seconds)
def request(url, method="GET", data=None, headers=None):
for attempt in range(4):
req = urllib.request.Request(url, data=data, headers=headers or {}, method=method)
try:
with urllib.request.urlopen(req, timeout=min(180, remaining())) as response:
return response.read()
except urllib.error.HTTPError as error:
if error.code not in (429, 500, 502, 503, 504) or attempt == 3:
raise RuntimeError(f"HTTP {error.code}; проверьте состояние и права") from None
retry_after = error.headers.get("Retry-After")
if retry_after:
try:
delay = float(retry_after)
except ValueError:
delay = email.utils.parsedate_to_datetime(retry_after).timestamp() - time.time()
else:
delay = 2 ** attempt + random.random()
pause(max(0, delay))
except (urllib.error.URLError, TimeoutError):
if attempt == 3:
raise RuntimeError("Сетевая ошибка; состояние сохранено") from None
pause(2 ** attempt + random.random())
def api(path, method="GET", body=None, key=None, raw=False):
headers = {"X-API-Key": api_key}
data = None
if body is not None:
data = json.dumps(body).encode("utf-8")
headers["Content-Type"] = "application/json"
if key:
headers["Idempotency-Key"] = key
result = request(BASE + path, method, data, headers)
return result if raw else json.loads(result)
def save():
temporary = Path(str(state_path) + ".tmp")
temporary.write_text(json.dumps(state), encoding="utf-8")
os.replace(temporary, state_path)
def fingerprint():
digest = hashlib.sha256()
with source.open("rb") as file:
for chunk in iter(lambda: file.read(1024 * 1024), b""):
digest.update(chunk)
return digest.hexdigest()
checksum = fingerprint()
if state_path.exists():
state = json.loads(state_path.read_text(encoding="utf-8"))
if state["sha256"] != checksum:
raise RuntimeError("Исходник изменён; не продолжайте старую загрузку")
else:
state = {"sha256": checksum, "key": str(uuid.uuid4()),
"body": {"filename": source.name, "size_bytes": source.stat().st_size,
"content_type": mimetypes.guess_type(source.name)[0] or "application/octet-stream",
"language": "auto"}}
save()
if not state.get("job_id"):
if not state.get("upload_id"):
created = api("/uploads", "POST", state["body"], state["key"])
state.update(upload_id=created["upload_id"], reserved_job_id=created["reserved_job_id"])
save()
upload_id = state["upload_id"]
upload = api(f"/uploads/{upload_id}")
if upload["upload_strategy"] != "multipart":
raise RuntimeError("Этот пример поддерживает multipart; проверьте выданную стратегию")
if upload["status"] in ("expired", "failed", "aborted"):
raise RuntimeError("Сессия завершена без результата; сначала выясните причину")
if upload["status"] != "completed":
multipart = upload["multipart"]
part_size = multipart["part_size_bytes"]
for number in multipart["missing_part_numbers"]:
signed = api(f"/uploads/{upload_id}/multipart/presign", "POST", {"part_numbers": [number]})
part = signed["parts"][0]
offset = (number - 1) * part_size
length = min(part_size, state["body"]["size_bytes"] - offset)
if length <= 0:
raise RuntimeError("Некорректный диапазон части")
with source.open("rb") as file:
file.seek(offset)
data = file.read(length)
if len(data) != length:
raise RuntimeError("Размер исходника изменился")
request(part["upload_url"], "PUT", data, part.get("headers", {}))
if fingerprint() != state["sha256"]:
raise RuntimeError("Исходник изменён во время загрузки")
while True:
completed = api(f"/uploads/{upload_id}/complete", "POST", {"parts": []})
if completed.get("job_id"):
state["job_id"] = completed["job_id"]
break
current = api(f"/uploads/{upload_id}")
if current["status"] == "completed":
state["job_id"] = current["reserved_job_id"]
break
if current["status"] in ("expired", "failed", "aborted"):
raise RuntimeError("Завершение загрузки не удалось")
pause(5)
else:
state["job_id"] = upload["reserved_job_id"]
save()
job_id = state["job_id"]
while True:
status = api(f"/transcriptions/{job_id}/status")
print("Задание:", job_id, "Статус:", status["status"])
if status["status"] == "failed":
raise RuntimeError("Расшифровка завершилась с ошибкой; проверьте задание")
if status["status"] == "completed":
break
pause(5)
output.write_bytes(api(f"/transcriptions/{job_id}/download?format=txt", raw=True))
print("Сохранён файл:", output)Проверка примера, 10 октября 2026 года. На короткой искусственно озвученной вымышленной записи проверили этот Python-код: загрузку, готовый TXT и повторное скачивание сохранённого задания без его пересоздания. Длинная запись и разрыв в середине загрузки этой проверкой не покрыты.
Это один последовательный клиент для одного исходника, а не готовый массовый обработчик очереди. У него есть общий предел 30 минут, до четырёх попыток одного запроса и повтор той же сессии. Большой файл или длительная обработка могут не уложиться в этот предел: завершите текущий запуск и продолжите с сохранённым состоянием. Не удаляйте файл состояния ради повторного скачивания — новый ключ может создать другую задачу и дополнительную обработку.
Если API выдал другую стратегию
У ответа создания загрузки есть upload_strategy, method, headers, form_data и upload_url. Пример выше намеренно останавливается для другой стратегии. В своём клиенте используйте конкретные инструкции ответа:
| Инструкция | Передача |
|---|---|
multipart | Части по выданному размеру и нумерации, PUT по URL каждой части |
Прямая загрузка с method: PUT | Байты всего файла по upload_url, выданные headers |
Прямая форма с method: POST | multipart/form-data: выданные поля form_data и файл; нельзя отправлять только JSON или заменять метод на PUT |
Временные адреса имеют срок действия. Для незавершённой multipart-сессии можно получить новые URL недостающих частей через /multipart/presign. Истечение самой сессии — другое событие: сначала выясните её состояние и отсутствие принятого задания, потом отдельно решайте новую отправку. Ключ API передают только API; к подписанному URL частей его не добавляют. Ключи и временные адреса не публикуют в журнале, скриншоте или заметке сделки.
Проверка статуса и JSON через curl
После получения job_id те же операции можно выполнить отдельно. Пример ниже для Bash; TEXTOSLAV_API_KEY содержит ваш ключ, JOB_ID — полученный идентификатор:
curl --fail-with-body --silent --show-error \
-H "X-API-Key: ${TEXTOSLAV_API_KEY:?}" \
"https://api.textoslav.ru/v1/transcriptions/${JOB_ID:?}/status"
curl --fail-with-body --silent --show-error \
-H "X-API-Key: ${TEXTOSLAV_API_KEY:?}" \
--output result.json \
"https://api.textoslav.ru/v1/transcriptions/${JOB_ID:?}/download?format=json"При completed ожидается готовый текст; failed требует разбора причины. В учебном прогоне искусственно озвученная вымышленная реплика прошла полный путь от файла до TXT/JSON и SRT. Это подтверждает маршрут интеграции, но не является обещанием времени обработки любого файла или точности любой записи. Форматы и приёмка результата подробно разобраны в статье об экспорте.
Ошибки: что повторять автоматически
| Сигнал | Действие |
|---|---|
| 429 | Соблюдать Retry-After; если срок превышает бюджет ожидания — продолжить позже |
| Временная сетевая ошибка, 502/503/504 | Ограниченный повтор; создание загрузки только с прежними телом и Idempotency-Key |
| 401/403 у API | Проверить ключ, доступ и тариф; не перебрать ключи и не создать новую задачу |
| 403 по временному URL части | Проверить срок и состояние сессии; получить новую ссылку недостающей части, не отправлять туда ключ API |
| 400/422 | Исправить запрос по контракту: имя, реальный размер, язык, допустимые поля |
| 409 | Проверить состояние существующей операции и причину конфликта; не маскировать новой загрузкой |
failed у задания | Зафиксировать идентификатор и видимое сообщение; пустой TXT не выдавать за результат |
Файл состояния связывает исходник и задание. Для передачи в CRM к этой связке добавьте идентификатор вашей сделки. Код скачивает транскрипт; он не выполняет автоматически анализ и не создаёт заметку в произвольной CRM. Эти следующие операции согласуют по публичным возможностям и контракту принимающей системы, как описано ниже.
Учебный пример результата
В разговоре клиент говорит: «Нам нужен единый курс для трёх филиалов, но руководитель обучения ещё не посмотрел программу». Менеджер обещает прислать образец урока. Дату запуска никто не подтверждает.
Полезная заметка:
Задача: единый курс для трёх филиалов.
Участник решения: руководитель обучения ещё не изучил программу.
Следующий шаг: менеджер отправляет образец урока.
Открыто: дата запуска и критерии согласования.
Источник: запись разговора, соответствующие реплики.
Слабая версия: «Клиент готов запускаться, осталось отправить урок». Она превращает отсутствие отказа в готовность к покупке. Такая ошибка особенно опасна при массовом создании заметок.
Попробуйте на своей записи
Получите расшифровку и подготовьте заметку, которую сможете передать в свой рабочий процесс.
60 пробных минут после регистрации · Без банковской карты
Расшифровку можно скачать. Экспорт ИИ-отчётов — на платных тарифах.
Настройте анализ под этот документ
Для одного звонка откройте «Аналитика» → «Новый отчёт» → «По одной записи» и выберите «Разбор продажи и следующий шаг». Прочитайте результат по источникам: ситуация, затруднение, последствия, событие, влияющее на срок, решение и следующий шаг должны опираться на разговор.
Если нужен собственный документ, задайте «Свой формат» на подходящем тарифе. Например:
Отдели слова клиента от предложений менеджера. Покажи подтверждённые потребности, условия решения, следующий шаг и отсутствующие сведения. Не считай предложение согласованным действием. Укажи основания важных выводов. В конце дай вопросы для следующего контакта отдельным разделом.
Сохраните полезный формат для команды. Он задаёт общий стандарт, но каждый результат всё равно требует проверки значимых условий.
Для серии звонков используйте общие данные
Если руководитель хочет понимать, какие препятствия повторяются, отдельные заметки неудобно сравнивать. Соберите записи в проект и создайте исследование с единым составом сведений.
Начните с сущностей «Ситуация клиента», «Барьер», «Условие решения», «Следующий шаг». Прямо названные сведения ищите «Из записи», предположения обозначайте отдельно как «Вывод ИИ». Связи помогают сохранить, к какой ситуации относится барьер.
В «Базе данных» просматривайте значения и цитаты. Для управленческого обзора создайте отчёт «По базе проекта» с нужной выборкой. Добавление новых записей не переписывает ранее созданный отчёт автоматически: перед следующим обсуждением подготовьте актуальный документ.
CRM: сначала правильная карточка и полезное содержание
Подготовить заметку и поместить её в CRM — разные действия. Не предполагайте, что выбранный сервис автоматически синхронизируется с любой CRM.
Начните с ручной передачи проверенного результата. В руководстве HubSpot по активностям, например, заметки и действия связаны с конкретными карточками. Для любого рабочего процесса сначала нужно определить, к какой сделке относится разговор.
Приложения к карточке также имеют свои правила доступа. Не считайте, что ссылка на источник автоматически откроется всем получателям. Проверьте это под правами обычного коллеги.
Если нужен автоматический перенос в вашу систему, отдельно согласуйте доступное подключение, состав передаваемых данных и ответственного. Проверка должна подтвердить полный путь до нужной карточки, включая повторную отправку и отсутствие дублей.
Предусмотрите обычные сбои
| Ситуация | Что должен сделать ответственный |
|---|---|
| Источник недоступен | Проверить адрес или получить разрешённый файл |
| Текст ещё не готов | Дождаться результата, не передавать пустую заметку |
| Есть сомнительное условие | Открыть источник и оставить вопрос, если ясности нет |
| Запись пришла повторно | Проверить дубликат до повторной работы |
| Выбрана не та сделка | Остановить передачу и исправить привязку |
| Получатель не видит источник | Проверить разрешения или передать допустимую выдержку |
Это план организации работы. Он помогает оценить, какие части уже выполняются выбранными инструментами, а какие нужно согласовать в вашей команде.
Проверьте процесс перед расширением
Проведите обычный звонок, сложный звонок с неопределённым сроком и повторную передачу той же записи. Убедитесь, что результат попадает нужному получателю, условия не теряются, а копии не распространяются лишним людям.
Правила выбранных подключений и внешних копий описаны в политике конфиденциальности. Отзыв доступа прекращает дальнейшее использование подключения, но сам по себе не удаляет уже переданные документы.
Текстослав в деле
Соберите повторяемый путь от записи до действия
Получите расшифровку и подготовьте заметку, которую сможете передать в свой рабочий процесс.
60 пробных минут после регистрации · Без банковской карты
Расшифровку можно скачать. Экспорт ИИ-отчётов — на платных тарифах.




