Oficjalne SDK opakowują REST API na potrzeby kodu serwerowego i skryptów. Jedno wywołanie transkrybuje plik: przesyła nagranie, czeka na zadanie i zwraca transkrypcję. Po drodze SDK sprawdza plik, zanim zostaną zarezerwowane jakiekolwiek minuty, ponawia to, co można bezpiecznie ponowić, podtrzymuje długie przesyłanie i dołącza klucz idempotentności do każdego przesłania i zakupu, więc ponowienie nigdy nie obciąży dwa razy. CLI jest zbudowane na SDK dla TypeScript i robi to samo z terminala.
Pakiety
| Język | Pakiet | Rejestr | Źródło |
|---|---|---|---|
| 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 |
Minimalne wersje środowisk:
- TypeScript: Node 22 lub nowszy. Bun 1.2+ i Deno 2+ są sprawdzane tylko pod kątem importu pakietu, nie ich obsługi HTTP.
- Python: 3.10 lub nowszy.
- Go: 1.25 lub nowszy.
- PHP: 8.2 lub nowszy, z
ext-jsoniext-mbstring;ext-curldo współbieżnego przesyłania części. - CLI: Node 22 lub nowszy.
SDK są przeznaczone dla serwerów i skryptów. API nie przyjmuje źródeł
przeglądarkowych (origin), a token w paczce dla przeglądarki to wyciekły token,
więc SDK dla TypeScript odmawia uruchomienia tam, gdzie istnieją window i
document.
Uzyskaj token
Każde SDK i CLI uwierzytelniają się osobistym tokenem dostępu. Utwórz go w
sekcji Create a new token na stronie MCP w koncie,
wybierz zakresy potrzebne twojemu kodowi i zdecyduj, czy token może kupować
minuty. Token jest pokazywany raz i wygląda tak:
hsr1:<region>:pat.<id>.<secret>. Zakresy i sposób działania tokenu opisano na
stronie API.
Jeśli nie podasz tokenu, SDK odczytują go ze zmiennej HUSHSCRIPT_TOKEN:
export HUSHSCRIPT_TOKEN=hsr1:...
Agent może też sam otworzyć własne konto, opłacić je na hostowanej stronie
płatności i odebrać swój pierwszy token z poziomu kodu: Hushscript.agent.signup()
i Hushscript.agent.claim() w TypeScripcie, Hushscript.agent_signup() i
Hushscript.agent_claim() w Pythonie, AgentSignup i AgentClaim w Go oraz
Client::agentSignup() i Client::agentClaim() w PHP. Przebieg i jego zasady
opisuje przewodnik Automatyzacja.
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() przyjmuje ścieżkę, Blob, Uint8Array lub
ReadableStream<Uint8Array>. Strumień wymaga podania dokładnych wartości size
i durationSeconds. hs.balance() zwraca minuty, które możesz wydać,
hs.transcripts.list() stronicuje gotowe transkrypcje, a
hs.buy("300min", { acknowledgeNoRefund: true }) kupuje pakiet. Każda
operacja /v1 jest dostępna także jako hs.api, z tymi samymi ponowieniami,
limitami czasu i ukrywaniem danych wrażliwych.
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")
Każde wywołanie ma odpowiednik asyncio w AsyncHushscript o tych samych
nazwach. transcribe() przyjmuje ścieżkę, bytes lub binarny obiekt pliku;
obiekt pliku, który nie obsługuje przewijania, wymaga size i
duration_seconds. hs.balance(), hs.transcripts.list() oraz
hs.buy("300min", acknowledge_no_refund=True) obsługują saldo, listę
transkrypcji i zakupy.
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 przyjmuje ścieżkę, TranscribeReader przyjmuje io.ReaderAt i
jego dokładny rozmiar, a TranscribeStream czytnik tylko do przodu wraz z
rozmiarem i DurationSeconds. client.Balance, client.Transcripts.List i
client.Buy obsługują saldo, listę transkrypcji i zakupy. Opcje, które mogą
być wyłączone, włączone lub nieustawione, mają typ *bool i buduje się je
przez 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() przyjmuje ścieżkę lub otwarty strumień; strumień, który nie
obsługuje przewijania, wymaga opcji size i duration_seconds. Opcje używają
kluczy tablicy w snake_case, a wyniki mają właściwości w camelCase.
$hs->balance(), $hs->transcripts()->list() i $hs->buy('300min', true)
obsługują saldo, listę transkrypcji i zakupy. W Laravelu zwiąż jeden Client w
dostawcy usług (service provider) i uruchamiaj transkrypcje w zadaniu w kolejce
ze stałą opcją idempotency_key.
CLI
npm install --global @hushscript/cli
hushscript login
hushscript transcribe meeting.mp3 --format srt --out meeting.srt
CLI bierze token z --token, potem z HUSHSCRIPT_TOKEN, a na końcu z tego,
który zapisał hushscript login. login prosi o token bez wyświetlania go na
ekranie i zapisuje go w pliku czytelnym tylko dla twojego użytkownika;
hushscript logout go usuwa. W CI wybieraj zmienną środowiskową.
| Polecenie | Co robi |
|---|---|
login |
Prosi o token i go zapisuje. |
logout |
Usuwa zapisany token. |
balance |
Pokazuje minuty, które możesz wydać. |
transcribe <file> |
Przesyła nagranie, czeka i wypisuje transkrypcję. Flagi: --language, --translate, --format srt|vtt|txt|json, --out, --key. |
resume <token> <file> |
Kończy transkrypcję, którą transcribe zostawiło niedokończoną. |
transcripts |
Wypisuje gotowe transkrypcje, od najnowszej. |
transcript <id> |
Wypisuje jedną transkrypcję. |
jobs |
Wypisuje zadania; --active pokazuje te, które się nie zakończyły. |
packs |
Wypisuje pakiety minut, które możesz kupić, z cenami. |
buy <pack> |
Kupuje pakiet zapisaną kartą domyślną. Flagi: --yes, --key. |
--json wypisuje na stdout jeden dokument JSON i nic więcej, a stderr zamienia
na JSON Lines. Kod wyjścia to 0 przy sukcesie, 1, gdy błąd zgłosiło API lub
SDK, 2 przy błędzie użycia (nic nie zostało wysłane) i 130, gdy uruchomienie
przerwano.
Obsługiwane pliki
MP3, M4A, MP4 i MOV (używana jest ścieżka audio wideo), WAV, FLAC oraz OGG z Vorbis lub Opus, od 15 sekund do 10 godzin. SDK sprawdzają format po bajtach pliku i badają czas trwania, zanim zostaną zarezerwowane jakiekolwiek minuty. Nie konwertują multimediów, więc wszystko inne najpierw przekonwertuj:
ffmpeg -i input -vn -c:a libopus output.opus
Błędy
Każdy błąd zgłaszany przez SDK należy do jednej rodziny, więc jeden catch
obejmuje wszystko: HushscriptError w TypeScripcie i Pythonie, *hushscript.Error
w Go oraz HushscriptException w PHP. Błąd zawiera tekstowy code, na przykład
insufficient_balance, kod liczbowy, status HTTP, komunikat,
hint podpowiadający, co zrobić dalej, szczegóły oraz retryAfter (w PHP slug nazywa się errorCode, a w Pythonie
retryAfter to 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;
}
PreflightError oznacza, że SDK odrzuciło plik, zanim zarezerwowano
jakiekolwiek środki. To, czy saldo wystarcza na plik, rozstrzyga serwer: kod
402 wraca przy tworzeniu przesyłania, zanim zostanie wysłana jakakolwiek
część.
Obciążenia i ponowienia
Każde przesłanie i każdy zakup niesie klucz idempotentności, a ponowienia używają go ponownie, więc ponowione wywołanie odtwarza pierwsze zamiast rozpoczynać drugie.
buy() obciąża twoją zapisaną kartę domyślną. Kupowanie z kodu jest
wyłączone, dopóki nie zezwolą na nie trzy przełączniki: token ma zakres
billing, token ma włączoną opcję “Let this token buy minutes”, a dla konta
włączona jest opcja “Let connected apps buy minutes”. Jeśli brakuje któregoś z
nich, wywołanie kończy się błędem pat_scope_missing. Przed wywołaniem pokaż
kupującemu informację o braku zwrotów.
Zakup jest ponawiany co najwyżej raz, po błędzie sieci, odpowiedzi 502 lub 503,
z tym samym kluczem. Niektóre odpowiedzi dowodzą, że nic nie obciążono: 400,
402, 404 lub 422 oraz 403 z kodem 4021 (pat_purchase_requires_app, karta
została odrzucona albo nie można jej obciążyć bez ciebie) lub 4023
(pat_purchase_requires_authentication, bank chce potwierdzić płatność). Po
4021 lub 4023 kup pakiet w aplikacji. Każda inna porażka po wysłaniu żądania,
także 401 lub 429, oznacza, że karta mogła zostać obciążona. Taki błąd niesie
klucz idempotentności: ponów próbę z tym samym kluczem, a zakup nigdy nie
wykona się dwa razy. W Pythonie:
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)
Zakup, który zawiódł przed wysłaniem żądania, nie ma klucza: nic nie zostało
obciążone. Klucz, który podajesz samodzielnie, musi mieć od 1 do 128 znaków z
zestawu A-Za-z0-9_-; nie używaj go ponownie dla innego pakietu. CLI wypisuje
klucz, gdy zakup mógł zostać wysłany:
hushscript buy 300min --yes --key <key>
Tokeny wznowienia
Gdy zadanie już istnieje, błąd niesie token wznowienia obok klucza
idempotentności. Oczekiwanie, które się wyczerpie, zgłasza WaitTimeoutError
z tokenem, a zadanie nadal trwa. Przekaż token z powrotem do resume(), aby
kontynuować bez drugiego obciążenia: zadanie po etapie przesyłania nie
potrzebuje pliku, a to, które jeszcze się przesyła, jest kontynuowane z tym
samym plikiem. W PHP:
try {
$hs->transcribe($path, ['wait_timeout' => 60]);
} catch (\Hushscript\Exception\WaitTimeoutError $timeout) {
$transcript = $hs->resume($timeout->resumeToken, $path);
}
W CLI naciśnięcie Ctrl-C podczas transcribe wypisuje token wznowienia zadania
i polecenie, które je kontynuuje:
hushscript resume <token> meeting.mp3 --format srt --out meeting.srt
Logowanie i ukrywanie danych
SDK nie wysyłają telemetrii; jedyną identyfikacją klienta jest nagłówek
User-Agent. Logowanie jest domyślnie wyłączone. HUSHSCRIPT_LOG=debug zapisuje
na standardowym wyjściu błędów jedną linię na żądanie, z metodą, ścieżką,
statusem i czasem, i nigdy z nagłówkiem, treścią, tytułem ani tekstem
transkrypcji.
Token jest ukrywany w każdym błędzie, linii logu i wypisanej postaci klienta.
W komunikatach błędów, podpowiedziach i przyczynach adres URL zachowuje host i
ścieżkę, ale jego ciąg zapytania zmienia się w ?[redacted], więc podpisany
adres przesyłania nigdy się nie wypisze. Wyniki, które przekazują ci sekret,
takie jak sekret odbioru lub nowy token, zachowują go jako czytelne pole, ale
po wypisaniu pokazują [redacted]; eksport JSON jest twój i zawiera tę
wartość. CLI usuwa ze stderr każdy znany mu token; jego wyniki na stdout to
twoje dane wyjściowe i nie są czyszczone.
Konfiguracja
| Ustawienie | Zmienna środowiskowa | Domyślnie |
|---|---|---|
| Token | HUSHSCRIPT_TOKEN |
brak |
| Bazowy adres URL | HUSHSCRIPT_BASE_URL |
https://api.hushscript.com |
| Poziom logowania | HUSHSCRIPT_LOG |
off |
| Limit czasu żądania | brak | 60 sekund |
| Ponowienia | brak | 3 |
Opcja podana w kodzie ma pierwszeństwo przed swoją zmienną środowiskową, a pusta wartość jest traktowana jak nieustawiona. Minuty pochodzą z tego samego salda co w aplikacji; pakiety i ceny znajdziesz na stronie cennika.