Skip to main content

Giggy Python SDK

Official Python SDK for the Giggy speech API: text-to-speech and recorded-audio transcription.

Install

python -m pip install giggy==0.1.3

Check python -m pip index versions giggy for release availability. The source installation below is also available for development.

Install from source

git clone https://github.com/giggy-ai/giggy-python.git
cd giggy-python
python -m pip install .

Requires Python 3.10 or newer. Create a Giggy API key in your Giggy account. The account voice endpoint GET https://giggy.ai/v1/voices requires that key as a bearer token; use voices[].voice_id as the voice_id UUID. Keep API keys server-side.

export GIGGY_API_KEY="giggy_sk_..."
export GIGGY_VOICE_ID="your-voice-uuid"

Generate speech

import os
from pathlib import Path
from giggy import Giggy

giggy = Giggy(api_key=os.environ["GIGGY_API_KEY"])
audio = giggy.speech.create(
    text="Hello from Giggy.",
    voice_id=os.environ["GIGGY_VOICE_ID"],
)
Path("speech.mp3").write_bytes(audio)

Stream speech

with giggy.speech.stream(
    text="Streaming from Giggy.",
    voice_id=os.environ["GIGGY_VOICE_ID"],
) as response:
    with open("speech.pcm", "wb") as output:
        while chunk := response.read(65536):
            output.write(chunk)

Streaming requests do not send an idempotency header. The SDK has no automatic retries.

Transcribe a recording in one SDK call

Prepare a WAV file with signed PCM16, mono, 16 kHz audio. Batch is free for 0.5–60 seconds; Fast accepts 0.5 seconds–12 hours and uses credits. The SDK reads the WAV in bounded chunks instead of loading the whole recording into memory.

import os
from giggy import Giggy

giggy = Giggy(api_key=os.environ["GIGGY_API_KEY"])
print(giggy.transcriptions.transcribe("recording.wav", mode="batch")["text"])

transcribe() submits once, polls the durable generation, then fetches its signed transcript URL without forwarding your API key. It stops on failure or after a configurable timeout (default 30 minutes); its failure message includes the generation UUID so you can inspect the operation. For submit-now/fetch-later workflows, use submit(), get(), and result() separately. A completed generation can have no downloadable result after retention cleanup. For a paid recording, pass mode="fast". Pass language="en" when you know the language; omit it for automatic detection. client_request_id accepts a caller-supplied UUID but does not make ambiguous upload retries safe. The SDK does not retry automatically.

Prepare a compatible WAV

The API accepts signed 16-bit PCM, mono, 16 kHz WAV for this path. For MP3, M4A, stereo, or another sample rate, convert before calling the SDK; this is a local preparation step, not another Giggy endpoint:

ffmpeg -i input.mp3 -ac 1 -ar 16000 -c:a pcm_s16le recording.wav
ffprobe -v error -show_entries stream=codec_name,sample_rate,channels -of default=noprint_wrappers=1 recording.wav

Check that ffprobe reports pcm_s16le, 16000, and 1. Use a 0.5–60 second file for Batch. If the server rejects the upload, check the WAV format and duration first; a file renamed .wav is not converted. Keep the input recording and the returned generation UUID until the result has been verified.

Stream transcript revisions from an uploaded WAV

Uploaded-recording Streaming uses the same WAV requirements and is paid. It sends cumulative provisional text over server-sent events. Replace displayed text with each newer transcript_chunk; do not append it. Completion must be checked through the durable generation before using the canonical result.

with giggy.transcriptions.stream("recording.wav") as events:
    generation_uuid = None
    for event, data in events:
        if event == "generation_created":
            generation_uuid = data["generation"]["generation_uuid"]
        elif event == "transcript_chunk":
            print("Replace preview:", data["text"])
    if not generation_uuid:
        raise RuntimeError("No admitted generation")
    print("Final:", giggy.transcriptions.result(generation_uuid)["text"])

stream() parses SSE frames and closes the response when its context exits. An interrupted or failed stream must be reconciled through get().

Live microphone PCM session

live() opens the existing paid Streaming SSE admission. This complete example records ten seconds from a microphone that supports mono 16 kHz PCM16. Install sounddevice (python -m pip install sounddevice) and allow microphone access first. The API key stays in the server-side Python process. The sender runs concurrently with the event reader, waits for microphone_ready, sends 100 ms frames in order, and sends a final empty frame. Run this with GIGGY_API_KEY set:

import os
from threading import Thread
import sounddevice as sd
from giggy import Giggy

giggy = Giggy(api_key=os.environ["GIGGY_API_KEY"])
errors = []
sender = None
generation_uuid = None

with giggy.transcriptions.live() as events:
    for event, data in events:
        if event == "generation_created":
            generation_uuid = data["generation"]["generation_uuid"]
        elif event == "microphone_ready":
            ready = dict(data)

            def send_audio():
                try:
                    with sd.RawInputStream(samplerate=16000, channels=1, dtype="int16", blocksize=1600) as microphone:
                        for sequence in range(100):
                            pcm, overflowed = microphone.read(1600)
                            if overflowed:
                                raise RuntimeError("Microphone capture overflowed")
                            giggy.transcriptions.send_live_frame(
                                generation_uuid=ready["generation_uuid"], input_token=ready["input_token"],
                                sequence=sequence, pcm=bytes(pcm))
                        giggy.transcriptions.send_live_frame(
                            generation_uuid=ready["generation_uuid"], input_token=ready["input_token"],
                            sequence=100, pcm=b"", complete=True)
                except Exception as error:
                    errors.append(error)

            sender = Thread(target=send_audio)
            sender.start()
        elif event == "transcript_chunk":
            print("Replace preview:", data["text"])

if sender:
    sender.join()
if errors:
    raise errors[0]
if not generation_uuid:
    raise RuntimeError("No admitted generation")
print("Final:", giggy.transcriptions.result(generation_uuid)["text"])

Each frame is at most 32,000 bytes. Await acceptance before incrementing sequence. Closing the live stream before completion cancels unfinished work. Do not reconnect or retry an ambiguously accepted frame. See the full live input contract for readiness, framing, duration, cancellation, and billing. The SDK does not implement microphone capture or turn detection; sounddevice is an example-only dependency.

Transcription method reference

All methods belong to giggy.transcriptions. SDK defaults select free Batch; the REST endpoint defaults to paid Fast.

Method Inputs and defaults Returns
transcribe(audio_path, *, mode="batch", language=None, client_request_id=None, poll_interval=2.5, timeout=1800) Local WAV; Batch or Fast; finite positive seconds Final transcript dictionary after one submission
submit(audio_path, *, mode="batch", language=None, client_request_id=None, timeout=1800) Local WAV; one admission; network inactivity timeout in seconds Admission dictionary containing generation.generation_uuid
get(generation_uuid, *, timeout=30) UUID; one status request Generation dictionary with status and optional result.url
result(generation_uuid, *, timeout=30) A completed generation; status and signed-artifact retrieval share the timeout budget Transcript dictionary; key is not sent to the artifact host
stream(audio_path, *, language=None, client_request_id=None) Completed WAV; paid Streaming Context manager yielding (event, data) pairs
live(*, client_request_id=None) Paid live admission; automatic language detection Context manager yielding the same event pairs
send_live_frame(*, generation_uuid, input_token, sequence, pcm, complete=False) Ordered PCM16 bytes; maximum 32,000 bytes, even length; empty only for completion None after acceptance; raises on rejection

transcribe(timeout=...) starts its wall-clock deadline before upload and bounds waiting for submission, status and artifact I/O. Python uses one bounded I/O thread for this method; on timeout it stops waiting and cancels pending calls, while an in-flight blocking request may finish later. A timeout does not cancel an admitted recording. The exception includes its UUID when admission was received. Individual submit/get/result network timeouts also bound socket inactivity; use transcribe when you need a deadline for the complete workflow.

The existing events are generation_created (admitted generation), microphone_ready (UUID, attempt and private input token), transcript_chunk (cumulative text, sequence, replace=true and complete), and generation_updated (status and optional generation). An event's complete flag is not durable generation completion. After EOF, inspect get() and fetch result() only after status=completed. These pairs are annotated with the exported TranscriptionEvent union and MicrophoneReady, TranscriptChunk, GenerationUpdated, and TranscriptionAdmission TypedDict payloads. Unknown named events raise an explicit contract error; heartbeat comments are ignored.

Troubleshooting and migration

Symptom Action
HTTP 401/403 Check the key and its owning Personal space or Workspace. Never substitute another user's key.
HTTP 429 Stop new submissions and honor the server response. An unambiguous rejection is different from an upload whose acceptance is unknown.
Timeout before a UUID Keep the original WAV and request identity; inspect History before another submission. client_request_id is not an idempotency guarantee.
Timeout or SSE EOF after a UUID Call get(uuid); the recording may still be queued or processing. Do not upload it again automatically.
Completed generation without a result URL, or expired signed URL Read current status again using the owning key. Use a refreshed result URL if one exists; retention/deletion can make the content permanently unavailable.
Live sender fails Exit the live context to close its SSE connection, then reconcile the UUID. Closing unfinished live input invokes canonical cancellation; closing uploaded-WAV SSE does not.
Empty final text The valid recording contained no detected speech. Check the recording; do not invent a transcript.

HTTP failures raise GiggyAPIError with status and raw response body. Invalid parameters raise ValueError. Deadline expiry raises TimeoutError; malformed responses, unavailable results and durable failed/cancelled/admission_failed operations raise RuntimeError. Avoid logging live input tokens or signed URLs.

When migrating from AssemblyAI, replace transcriber.transcribe(audio) with giggy.transcriptions.transcribe(wav_path) and transcript.text with result["text"]. Convert MP3/video/URL inputs locally to PCM16 mono 16 kHz WAV before submitting. Speaker labels, word times, confidence, subtitle exports and speech-analysis options have no equivalent in this transcript contract; remove those options and explain the difference to your application users. Map provisional turn text to cumulative transcript_chunk revisions, and explicitly finish each live input within Giggy's 30-second audio/35-second readiness limit.

For complete commands and recording-to-text applications, see the Python recording walkthrough and framework STT guide.

Metadata

Release files for giggy 0.1.3

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for giggy 0.1.3
File Size Uploaded
giggy-0.1.3.tar.gz 12.7 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for giggy 0.1.3
File Interpreter ABI Platform
giggy-0.1.3-py3-none-any.whl Python 3 none any Details

Total release size: 24.0 kB

Release files / giggy-0.1.3.tar.gz

Download URL giggy-0.1.3.tar.gz
Size 12.7 kB
Tags Source
SHA-256 checksum
How to use checksums
72c662d6efd4339afa5293e15ac95ead0bf1ca935f6011c9b3ac2ec70d6a2161
BLAKE2b-256 checksum
How to use checksums
240f211cebaf33d2bea132702084a064a8e38d054aff6adb59f6403f920c9b91
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 13, 2026.

Transparency log

Release files / giggy-0.1.3-py3-none-any.whl

Download URL giggy-0.1.3-py3-none-any.whl
Size 11.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
f1df5f930410c7b7b53c27edb0fbb79086641a85a74a94388838fea7ec4d5c22
BLAKE2b-256 checksum
How to use checksums
a0cecf88d2773806c3074e6539cd837633c850bc03c5fb689a9fc0702d821633
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 13, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.1.3 This release

2 release files

0.1.2

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page