Ir para o conteúdo principal

Desenvolvedores

SDKs e CLI do Hushscript

Bibliotecas oficiais para TypeScript, Python, Go e PHP, e uma ferramenta de linha de comando, que transformam um arquivo gravado em transcrição com uma única chamada.

Os SDKs oficiais encapsulam a API REST para código de servidor e scripts. Uma chamada transcreve um arquivo: ela envia a gravação, espera o job e devolve a transcrição. No meio do caminho, o SDK verifica o arquivo antes de qualquer minuto ser reservado, repete o que é seguro repetir, mantém vivo um envio longo e leva uma chave de idempotência em cada envio e em cada compra, para que uma nova tentativa nunca cobre duas vezes. A CLI é construída sobre o SDK de TypeScript e faz o mesmo a partir de um terminal.

Pacotes

Linguagem Pacote Registro Código-fonte
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

Versões mínimas de runtime:

Os SDKs são para servidores e scripts. A API não aceita origens de navegador, e um token em um bundle de navegador é um token vazado, então o SDK de TypeScript se recusa a iniciar onde existem window e document.

Obter um token

Todo SDK e a CLI se autenticam com um token de acesso pessoal. Crie um em Criar um novo token, na página MCP da conta, escolha os escopos de que seu código precisa e decida se ele pode comprar minutos. O token é exibido uma única vez e tem o formato hsr1:<region>:pat.<id>.<secret>. Os escopos e o funcionamento de um token estão na página da API.

Os SDKs leem o token de HUSHSCRIPT_TOKEN quando você não passa um:

export HUSHSCRIPT_TOKEN=hsr1:...

Um agente também pode abrir a própria conta, pagá-la em uma página de checkout hospedada e reivindicar o primeiro token por código: Hushscript.agent.signup() e Hushscript.agent.claim() em TypeScript, Hushscript.agent_signup() e Hushscript.agent_claim() em Python, AgentSignup e AgentClaim em Go, e Client::agentSignup() e Client::agentClaim() em PHP. O fluxo e suas regras estão em 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() aceita um caminho, um Blob, um Uint8Array ou um ReadableStream<Uint8Array>. Um stream precisa do size e do durationSeconds exatos. hs.balance() devolve os minutos que você pode gastar, hs.transcripts.list() percorre as transcrições concluídas e hs.buy("300min", { acknowledgeNoRefund: true }) compra um pacote. Toda operação /v1 também está disponível como hs.api, com as mesmas tentativas repetidas, os mesmos timeouts e a mesma ocultação de dados sensíveis.

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")

Toda chamada tem uma gêmea asyncio em AsyncHushscript, com os mesmos nomes. transcribe() aceita um caminho, bytes ou um objeto de arquivo binário; um objeto de arquivo que não permite seek precisa de size e duration_seconds. hs.balance(), hs.transcripts.list() e hs.buy("300min", acknowledge_no_refund=True) cobrem o saldo, a lista de transcrições e as 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 aceita um caminho, TranscribeReader um io.ReaderAt e seu tamanho exato, e TranscribeStream um leitor somente sequencial com seu tamanho e DurationSeconds. client.Balance, client.Transcripts.List e client.Buy cobrem o saldo, a lista de transcrições e as compras. As opções que podem estar desligadas, ligadas ou indefinidas são *bool, criadas com 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() aceita um caminho ou um stream aberto; um stream que não permite seek precisa das opções size e duration_seconds. As opções usam chaves de array em snake_case, e os resultados usam propriedades em camelCase. $hs->balance(), $hs->transcripts()->list() e $hs->buy('300min', true) cobrem o saldo, a lista de transcrições e as compras. No Laravel, vincule um único Client em um service provider e execute as transcrições em um job em fila, com uma opção idempotency_key estável.

CLI

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

A CLI pega o token de --token, depois de HUSHSCRIPT_TOKEN e, por fim, do que hushscript login armazenou. O login pede o token sem exibi-lo na tela e o guarda em um arquivo que só o seu usuário consegue ler; hushscript logout o apaga. Em CI, prefira a variável de ambiente.

Comando O que faz
login Pede um token e o armazena.
logout Apaga o token armazenado.
balance Mostra os minutos que você pode gastar.
transcribe <file> Envia uma gravação, espera e imprime a transcrição. Flags: --language, --translate, --format srt|vtt|txt|json, --out, --key.
resume <token> <file> Conclui uma transcrição que o transcribe deixou pela metade.
transcripts Lista as transcrições concluídas, da mais recente para a mais antiga.
transcript <id> Imprime uma transcrição.
jobs Lista os jobs; --active para os que ainda não terminaram.
packs Lista os pacotes de minutos que você pode comprar, com os preços.
buy <pack> Compra um pacote com o cartão padrão salvo. Flags: --yes, --key.

--json imprime um único documento JSON no stdout e nada além disso, e transforma o stderr em JSON Lines. O código de saída é 0 em caso de sucesso, 1 quando a API ou o SDK reportou um erro, 2 para um erro de uso (nada foi enviado) e 130 quando a execução foi interrompida.

Arquivos compatíveis

MP3, M4A, MP4 e MOV (usa-se a trilha de áudio do vídeo), WAV, FLAC e OGG com Vorbis ou Opus, de 15 segundos a 10 horas. Os SDKs verificam o formato pelos bytes do arquivo e medem a duração antes de qualquer minuto ser reservado. Eles não convertem mídia, então converta qualquer outro formato antes:

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

Erros

Todo erro lançado por um SDK pertence a uma única família, então um só catch cobre tudo: HushscriptError em TypeScript e Python, *hushscript.Error em Go e HushscriptException em PHP. Um erro traz um code em formato de slug, como insufficient_balance, o código numérico, o status HTTP, uma mensagem, uma hint que diz o que fazer em seguida, os detalhes e retryAfter (em PHP o slug é errorCode; em Python, retryAfter é 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;
}

Um PreflightError significa que o SDK recusou o arquivo antes de qualquer crédito ser reservado. Se o seu saldo cobre um arquivo é decisão do servidor: um 402 volta quando o envio é criado, antes de qualquer parte ser enviada.

Cobrança e novas tentativas

Todo envio e toda compra levam uma chave de idempotência, e as novas tentativas a reutilizam, de modo que uma chamada repetida reproduz a primeira em vez de iniciar uma segunda.

buy() cobra o seu cartão padrão salvo. Comprar por código fica desativado até que três chaves o permitam: o token tem o escopo billing, o token está com “Permitir que este token compre minutos” ativado e “Permitir que aplicativos conectados comprem minutos” está ativado na conta. Se qualquer uma faltar, a chamada falha com pat_scope_missing. Mostre ao seu comprador o aviso de não reembolso antes de chamá-lo.

Uma compra é repetida no máximo uma vez, após um erro de rede, um 502 ou um 503, com a mesma chave. Algumas respostas provam que nada foi cobrado: um 400, 402, 404 ou 422, e um 403 com o código 4021 (pat_purchase_requires_app, o cartão foi recusado ou não pode ser cobrado sem você) ou 4023 (pat_purchase_requires_authentication, o banco quer confirmar o pagamento). Depois de 4021 ou 4023, compre o pacote no app. Qualquer outra falha depois de a requisição ter sido enviada, inclusive um 401 ou um 429, significa que o cartão pode ter sido cobrado. Esse erro traz a chave de idempotência: peça de novo com a mesma chave, e a compra nunca poderá acontecer duas vezes. Em 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)

Uma compra que falhou antes de a requisição ser enviada não traz chave: nada foi cobrado. Uma chave que você mesmo passa deve ter de 1 a 128 caracteres de A-Za-z0-9_-; não reutilize uma para outro pacote. A CLI imprime a chave quando uma compra pode ter sido enviada:

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

Tokens de retomada

Quando um job já existe, um erro traz um token de retomada junto com a chave de idempotência. Uma espera que estoura o tempo lança WaitTimeoutError com o token, e o job continua em execução. Passe o token de volta a resume() para seguir adiante sem uma segunda cobrança: um job que já passou do envio não precisa do arquivo, e um que ainda está sendo enviado continua com o mesmo arquivo. Em PHP:

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

Na CLI, Ctrl-C durante o transcribe imprime o token de retomada do job e o comando que o continua:

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

Logs e ocultação de dados

Os SDKs não enviam telemetria; o cabeçalho User-Agent é a única identificação do cliente. O registro de logs vem desativado por padrão. HUSHSCRIPT_LOG=debug escreve uma linha por requisição no erro padrão, com o método, o caminho, o status e o tempo, e nunca um cabeçalho, corpo, título ou texto de transcrição.

O token é ocultado em todo erro, linha de log e forma impressa do cliente. Em mensagens de erro, dicas e causas, uma URL mantém o host e o caminho, mas a query string vira ?[redacted], então uma URL de envio assinada nunca é impressa. Resultados que entregam um segredo, como um segredo de reivindicação ou um novo token, o mantêm legível como campo, mas mostram [redacted] quando impressos; uma exportação em JSON é sua e traz o valor. A CLI remove do stderr todo token que conhece; os resultados dela no stdout são a sua saída e não são limpos.

Configuração

Configuração Variável de ambiente Padrão
Token HUSHSCRIPT_TOKEN nenhum
URL base HUSHSCRIPT_BASE_URL https://api.hushscript.com
Nível de log HUSHSCRIPT_LOG off
Timeout da requisição nenhuma 60 segundos
Novas tentativas nenhuma 3

Uma opção passada no código vale mais que a variável de ambiente correspondente, e um valor vazio conta como não definido. Os minutos vêm do mesmo saldo do app; pacotes e preços estão na página de preços.

Comece a transcrever com 30 minutos para testar

Veja uma prévia de até 5 minutos antes de criar uma conta, e uma nova conta pessoal recebe uma prévia grátis do primeiro envio no aplicativo. A transcrição completa exige uma conta e minutos; contas pessoais elegíveis recebem 30 minutos grátis uma única vez, após a verificação do cartão ou com a primeira compra. Sem assinatura.

Começar com 30 minutos grátis