Saltar al contenido principal

Desarrolladores

SDKs y CLI de Hushscript

Bibliotecas oficiales para TypeScript, Python, Go y PHP, y una herramienta de línea de comandos que convierten un archivo grabado en una transcripción con una sola llamada.

Los SDK oficiales envuelven la API REST para código de servidor y scripts. Una sola llamada transcribe un archivo: sube la grabación, espera el job y te entrega la transcripción. Por el camino, el SDK revisa el archivo antes de retener minutos, reintenta lo que es seguro reintentar, mantiene viva una subida larga y lleva una clave de idempotencia en cada subida y cada compra para que un reintento nunca cobre dos veces. La CLI está construida sobre el SDK de TypeScript y hace lo mismo desde una terminal.

Paquetes

Lenguaje Paquete Registro Código fuente
TypeScript @hushscript/sdk npm: www.npmjs.com/package/@hushscript/sdk github.com/Hushscript/hushscript-sdk-typescript
Python hushscript PyPI: pypi.org/project/hushscript github.com/Hushscript/hushscript-sdk-python
Go github.com/Hushscript/hushscript-sdk-go pkg.go.dev: pkg.go.dev/github.com/Hushscript/hushscript-sdk-go github.com/Hushscript/hushscript-sdk-go
PHP hushscript/sdk Packagist: packagist.org/packages/hushscript/sdk github.com/Hushscript/hushscript-sdk-php
CLI @hushscript/cli npm: www.npmjs.com/package/@hushscript/cli github.com/Hushscript/hushscript-cli

Versiones mínimas de cada entorno:

Los SDK son para servidores y scripts. La API no acepta orígenes de navegador, y un token en el bundle de un navegador es un token filtrado, así que el SDK de TypeScript se niega a iniciar donde existen window y document.

Obtén un token

Todos los SDK y la CLI se autentican con un token de acceso personal. Crea uno en Crear un token nuevo, en la página de MCP de la cuenta, elige los scopes que necesita tu código y decide si puede comprar minutos. El token se muestra una sola vez y tiene la forma hsr1:<region>:pat.<id>.<secret>. Los scopes y el funcionamiento de un token están en la página de la API.

Los SDK leen el token de HUSHSCRIPT_TOKEN cuando no le pasas uno:

export HUSHSCRIPT_TOKEN=hsr1:...

Un agente también puede abrir su propia cuenta, pagarla en una página de pago alojada y reclamar su primer token desde código: Hushscript.agent.signup() y Hushscript.agent.claim() en TypeScript, Hushscript.agent_signup() y Hushscript.agent_claim() en Python, AgentSignup y AgentClaim en Go, y Client::agentSignup() y Client::agentClaim() en PHP. El flujo y sus reglas están en Uso automatizado.

TypeScript

npm install @hushscript/sdk
import { writeFile } from "node:fs/promises";
import { Hushscript } from "@hushscript/sdk";

const hs = new Hushscript(); // reads HUSHSCRIPT_TOKEN
const transcript = await hs.transcribe("meeting.mp3");
console.log(transcript.text);
await writeFile("meeting.srt", transcript.toSRT());

transcribe() acepta una ruta, un Blob, un Uint8Array o un ReadableStream<Uint8Array>. Un stream necesita su size exacto y durationSeconds. hs.balance() devuelve los minutos que puedes gastar, hs.transcripts.list() recorre por páginas las transcripciones terminadas y hs.buy("300min", { acknowledgeNoRefund: true }) compra un paquete. Cada operación de /v1 también está disponible como hs.api, con los mismos reintentos, tiempos de espera y redacción.

Python

pip install hushscript
from pathlib import Path

from hushscript import Hushscript

with Hushscript() as hs:  # reads HUSHSCRIPT_TOKEN
    transcript = hs.transcribe("meeting.mp3")
    print(transcript.text)
    Path("meeting.srt").write_text(transcript.to_srt(), encoding="utf-8")

Cada llamada tiene un equivalente asyncio en AsyncHushscript con los mismos nombres. transcribe() acepta una ruta, bytes o un objeto de archivo binario; un objeto de archivo que no admite seek necesita size y duration_seconds. hs.balance(), hs.transcripts.list() y hs.buy("300min", acknowledge_no_refund=True) cubren el saldo, la lista de transcripciones y las compras.

Go

go get github.com/Hushscript/hushscript-sdk-go
package main

import (
	"context"
	"fmt"
	"log"
	"os"

	hushscript "github.com/Hushscript/hushscript-sdk-go"
)

func main() {
	client, err := hushscript.New() // reads HUSHSCRIPT_TOKEN
	if err != nil {
		log.Fatal(err)
	}
	transcript, err := client.Transcribe(context.Background(), "meeting.mp3", nil)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(transcript.Text(nil))
	if err := os.WriteFile("meeting.srt", []byte(transcript.SRT(nil)), 0o600); err != nil {
		log.Fatal(err)
	}
}

Transcribe acepta una ruta, TranscribeReader un io.ReaderAt y su tamaño exacto, y TranscribeStream un lector de solo avance con su tamaño y DurationSeconds. client.Balance, client.Transcripts.List y client.Buy cubren el saldo, la lista de transcripciones y las compras. Las opciones que pueden estar desactivadas, activadas o sin definir son *bool, creadas con hushscript.Bool.

PHP

composer require hushscript/sdk
<?php

require __DIR__ . '/vendor/autoload.php';

use Hushscript\Client;

$hs = new Client(); // reads HUSHSCRIPT_TOKEN

$transcript = $hs->transcribe('meeting.mp3');
echo $transcript->text();
file_put_contents('meeting.srt', $transcript->toSrt());

transcribe() acepta una ruta o un stream abierto; un stream que no admite seek necesita las opciones size y duration_seconds. Las opciones usan claves de array en snake_case, y los resultados usan propiedades en camelCase. $hs->balance(), $hs->transcripts()->list() y $hs->buy('300min', true) cubren el saldo, la lista de transcripciones y las compras. En Laravel, enlaza un solo Client en un service provider y ejecuta las transcripciones en un job en cola con una opción idempotency_key estable.

CLI

npm install --global @hushscript/cli
hushscript login
hushscript transcribe meeting.mp3 --format srt --out meeting.srt

La CLI toma el token de --token, luego de HUSHSCRIPT_TOKEN y, por último, del que guardó hushscript login. login pide el token sin mostrarlo en pantalla y lo guarda en un archivo que solo tu usuario puede leer; hushscript logout lo elimina. En CI, es preferible usar la variable de entorno.

Comando Qué hace
login Pide un token y lo guarda.
logout Elimina el token guardado.
balance Muestra los minutos que puedes gastar.
transcribe <file> Sube una grabación, espera e imprime la transcripción. Opciones: --language, --translate, --format srt|vtt|txt|json, --out, --key.
resume <token> <file> Termina una transcripción que transcribe dejó a medias.
transcripts Lista las transcripciones terminadas, de la más reciente a la más antigua.
transcript <id> Imprime una transcripción.
jobs Lista los jobs; --active para los que no han terminado.
packs Lista los paquetes de minutos que puedes comprar, con sus precios.
buy <pack> Compra un paquete con tu tarjeta predeterminada guardada. Opciones: --yes, --key.

--json imprime un único documento JSON en stdout y nada más, y convierte stderr en JSON Lines. El código de salida es 0 si todo salió bien, 1 cuando la API o el SDK informaron un error, 2 en un error de uso (no se envió nada) y 130 cuando se interrumpió la ejecución.

Archivos compatibles

MP3, M4A, MP4 y MOV (se usa la pista de audio de un video), WAV, FLAC y OGG con Vorbis u Opus, de 15 segundos a 10 horas. Los SDK verifican el formato a partir de los bytes del archivo y miden la duración antes de retener minutos. No convierten medios, así que convierte primero cualquier otro formato:

ffmpeg -i input -vn -c:a libopus output.opus

Errores

Todo error que lanza un SDK pertenece a una misma familia, así que un solo catch los cubre todos: HushscriptError en TypeScript y Python, *hushscript.Error en Go y HushscriptException en PHP. Un error incluye un code en forma de slug, como insufficient_balance, el código numérico, el estado HTTP, un mensaje, un hint que indica qué hacer a continuación, los detalles y retryAfter (en PHP el slug es errorCode; en Python, retryAfter es retry_after).

import { HushscriptError, InsufficientBalanceError } from "@hushscript/sdk";

try {
  await hs.transcribe("meeting.mp3");
} catch (error) {
  if (error instanceof InsufficientBalanceError) console.log(error.hint);
  else if (error instanceof HushscriptError) console.log(error.code, error.hint ?? error.message);
  else throw error;
}

Un PreflightError significa que el SDK rechazó el archivo antes de retener cualquier crédito. Que tu saldo cubra o no un archivo lo decide el servidor: se devuelve un 402 al crear la subida, antes de enviar ninguna parte.

Cobros y reintentos

Cada subida y cada compra lleva una clave de idempotencia, y los reintentos la reutilizan, así que una llamada reintentada repite la primera en lugar de iniciar una segunda.

buy() cobra tu tarjeta predeterminada guardada. Comprar desde código está desactivado hasta que lo permitan tres interruptores: el token tiene el scope billing, el token tiene activada la opción “Permitir que este token compre minutos” y está activada la opción “Permitir que las aplicaciones conectadas compren minutos” para la cuenta. Si falta alguno, la llamada falla con pat_scope_missing. Muestra el aviso de no reembolso a tu comprador antes de llamarla.

Una compra se reintenta como máximo una vez, ante un error de red, un 502 o un 503, con la misma clave. Algunas respuestas prueban que no se cobró nada: un 400, 402, 404 o 422, y un 403 con el código 4021 (pat_purchase_requires_app, la tarjeta fue rechazada o no se puede cobrar sin ti) o 4023 (pat_purchase_requires_authentication, el banco quiere confirmar el pago). Después de un 4021 o un 4023, compra el paquete en la aplicación. Cualquier otro fallo después de enviar la solicitud, incluidos un 401 o un 429, significa que es posible que la tarjeta se haya cobrado. Ese error lleva la clave de idempotencia: vuelve a intentarlo con la misma clave y la compra nunca podrá ocurrir dos veces. En Python:

from hushscript import HushscriptError

try:
    purchase = hs.buy("300min", acknowledge_no_refund=True)
except HushscriptError as error:
    refused = error.status in {400, 402, 404, 422} or (
        error.status == 403 and error.numeric_code in {4021, 4023}
    )
    if error.idempotency_key is None or refused:
        raise  # only these refusals charged nothing; any other failure keeps the key for a retry
    purchase = hs.buy("300min", acknowledge_no_refund=True, idempotency_key=error.idempotency_key)

Una compra que falló antes de que se enviara su solicitud no lleva clave: no se cobró nada. Una clave que pases tú mismo debe tener de 1 a 128 caracteres de A-Za-z0-9_-; no la reutilices para un paquete distinto. La CLI imprime la clave cuando es posible que se haya enviado una compra:

hushscript buy 300min --yes --key <key>

Tokens de reanudación

Una vez que existe un job, un error lleva un token de reanudación junto a la clave de idempotencia. Una espera que se agota lanza WaitTimeoutError con el token, y el job sigue ejecutándose. Pasa el token a resume() para continuar sin un segundo cobro: un job que ya pasó la etapa de subida no necesita el archivo, y uno que aún está subiendo se continúa con el mismo archivo. En PHP:

try {
    $hs->transcribe($path, ['wait_timeout' => 60]);
} catch (\Hushscript\Exception\WaitTimeoutError $timeout) {
    $transcript = $hs->resume($timeout->resumeToken, $path);
}

En la CLI, Ctrl-C durante transcribe imprime el token de reanudación del job y el comando que lo continúa:

hushscript resume <token> meeting.mp3 --format srt --out meeting.srt

Registros y redacción

Los SDK no envían telemetría; el encabezado User-Agent es la única identificación del cliente. El registro está desactivado por defecto. HUSHSCRIPT_LOG=debug escribe una línea por solicitud en la salida de error estándar con el método, la ruta, el estado y el tiempo, y nunca un encabezado, un cuerpo, un título ni texto de la transcripción.

El token se redacta de todo error, línea de registro y forma impresa del cliente. En los mensajes de error, las sugerencias y las causas, una URL conserva su host y su ruta, pero su cadena de consulta pasa a ser ?[redacted], así que una URL de subida firmada nunca se imprime. Los resultados que te entregan un secreto, como un secreto de reclamo o un token nuevo, lo mantienen legible como campo pero muestran [redacted] al imprimirse; una exportación JSON es tuya y lleva el valor. La CLI limpia de stderr todos los tokens que conoce; sus resultados en stdout son tu salida y no se limpian.

Configuración

Ajuste Variable de entorno Valor por defecto
Token HUSHSCRIPT_TOKEN ninguno
URL base HUSHSCRIPT_BASE_URL https://api.hushscript.com
Nivel de registro HUSHSCRIPT_LOG off
Tiempo de espera de solicitud ninguna 60 segundos
Reintentos ninguna 3

Una opción pasada en código se impone sobre su variable de entorno, y un valor vacío cuenta como no definido. Los minutos salen del mismo saldo que la aplicación; los paquetes y los precios están en la página de precios.

Empieza a transcribir con 30 minutos para probar

Obtén una vista previa de hasta 5 minutos antes de crear una cuenta, y una cuenta personal nueva recibe una vista previa gratis de su primera subida en la aplicación. La transcripción completa requiere una cuenta y minutos; las cuentas personales elegibles reciben 30 minutos gratis una sola vez, tras verificar la tarjeta o con su primera compra. Sin suscripción.

Comenzar con 30 minutos gratis