Metadata-Version: 2.5
Name: genshiai-stt
Version: 5.3.1
Summary: GENSHI Voice STT SDK — high-accuracy domain-specific speech-to-text
Project-URL: Homepage, https://github.com/genshiai/genshiai-stt-sdk#readme
Project-URL: Documentation, https://github.com/genshiai/genshiai-stt-sdk#readme
Project-URL: Releases, https://github.com/genshiai/genshiai-stt-sdk/releases
Project-URL: Changelog, https://github.com/genshiai/genshiai-stt-sdk/blob/main/CHANGELOG.md
Project-URL: Issues, https://github.com/genshiai/genshiai-stt-sdk/issues
Author-email: "GENSHI AI Inc." <sdk@genshi.ai>
License: Copyright (c) 2026 GENSHI AI Inc. All rights reserved.
        
        GENSHI Voice STT SDK — Proprietary Software License
        
        1. Grant of License.
           Subject to the terms of this License and a valid GENSHI Voice API key or
           subscription, you are granted a non-exclusive, non-transferable,
           non-sublicensable, revocable license to use the GENSHI Voice STT SDK
           ("Software") solely for integrating with GENSHI Voice services in your
           own applications.
        
        2. Restrictions.
           You may NOT:
           (a) copy, modify, merge, or create derivative works of the Software;
           (b) distribute, sublicense, sell, lease, or otherwise transfer the
               Software or any portion thereof to any third party;
           (c) reverse-engineer, decompile, disassemble, or otherwise attempt to
               derive the source code of the compiled portions of the Software;
           (d) remove or alter any proprietary notices, labels, or marks;
           (e) use the Software to develop a competing product or service.
        
        3. Ownership.
           The Software, including all intellectual property rights therein, is and
           remains the exclusive property of GENSHI AI Inc.
        
        4. Termination.
           This License terminates automatically if you breach any of its terms or
           if your GENSHI Voice API key or subscription is revoked or expires. Upon
           termination, you must cease all use of the Software and destroy all
           copies in your possession.
        
        5. No Warranty.
           THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
           OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
           MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT.
        
        6. Limitation of Liability.
           IN NO EVENT SHALL GENSHI WORKS INC. BE LIABLE FOR ANY INDIRECT,
           INCIDENTAL, SPECIAL, CONSEQUENTIAL, OR PUNITIVE DAMAGES ARISING OUT OF
           OR RELATED TO THE USE OF THE SOFTWARE.
        
        7. Governing Law.
           This License shall be governed by the laws of Japan, without regard to
           conflict of law principles.
License-File: LICENSE
Keywords: asr,japanese,medical,speech-to-text,stt,transcription
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: License :: Other/Proprietary License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Topic :: Multimedia :: Sound/Audio :: Speech
Classifier: Typing :: Typed
Requires-Python: >=3.10
Requires-Dist: genshiai-stt-native>=5.3.1
Requires-Dist: numpy>=1.24
Provides-Extra: dev
Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
Requires-Dist: pytest>=8.0; extra == 'dev'
Description-Content-Type: text/markdown

# GENSHI Voice STT SDK

High-accuracy domain-specific speech-to-text SDK. Supports batch transcription and realtime streaming with built-in VAD and on-device STT inference.

## Installation

### Python

```bash
pip install genshiai-stt
```

### Node.js

```bash
npm install @genshiai/stt
```

The correct native addon for your platform is installed automatically via optional dependencies.

### Browser

```bash
npm install @genshiai/stt-web
```

### Swift

`sdk/swift` をSwift Package Managerの依存として追加する。iOS 15 / macOS 12以降に対応。

## Managed LLM generation

The SDK also exposes provider-neutral text generation. Callers choose only the
security route; concrete provider model IDs are managed by the server.

```python
async with GenshiSTTClient(api_key="gw-...", secure=True) as client:
    note = await client.llm.generate(
        transcript,
        instructions="診療録をSOAP形式に整理してください",
        max_output_tokens=2048,
    )
    print(note.output_text)
    print(note.processing_tier)  # "secure"
```

```typescript
const client = new GenshiSTTClient({ apiKey: 'gw-...', secure: true });
const note = await client.llm.generate(transcript, {
  instructions: '診療録をSOAP形式に整理してください',
  maxOutputTokens: 2048,
});
console.log(note.output_text);
```

- `secure: true` routes through the configured Bedrock model and fails closed
  if the key or plan cannot use Secure processing.
- `secure: false` routes through the configured OpenRouter model, unless a
  secure-only key forces every request onto Bedrock.
- The API key needs the `llm` scope. Publishable (`pk-...`) keys cannot use this
  endpoint; invoke it from a trusted backend.
- **Keys issued before 5.3.0 do not carry the `llm` scope**, and scopes cannot be
  changed after a key is created. Create a new key with `llm` selected under
  Console → API Keys; a key without it returns `403 insufficient_scope`.
- Generation is billed from provider-reported input/output token usage — not
  from recording time, and **not at the STT "secure +50%" rate**. LLM secure is
  a separate rate (1 pt = ¥10):

  | Tier | Input (pt / 1M tokens) | Output (pt / 1M tokens) |
  |---|---:|---:|
  | `normal` | 15 | 135 |
  | `secure` | 50 | 270 |

  Output costs more than input, so summarizing and reformatting — short output
  from long input — is the cheap shape. A 30-minute consultation turned into a
  SOAP note (~6,000 in / ~1,500 out) runs about ¥2.9 normal, ¥7.0 secure.
  Minimum charge is 1 unit (0.01 pt); failed requests are not billed.

## Long recordings and Longform

Long recordings are currently supported through the existing Batch and
Realtime APIs:

- Use `client.transcribe(...)` when the full recording can be processed after
  capture. The server processes the complete file with the async STT model.
- Use `client.stream(...)` when text must appear while recording, and always
  call `finalize()` to obtain the complete final result.

SDK 5.3.0 includes the dedicated `client.longform(...)` API. SDK 5.3.1 makes
Longform speaker diarization explicitly opt-in. Longform uses 120-second
rolling async windows, VAD-aligned boundaries, a sample-based timeline, and a
`replace_range` contract applied inside the SDK's growing transcript.

```python
async with client.longform(preview="off") as session:
    await session.push(pcm16_chunk)  # PCM16, 16 kHz, mono; keep silence
    print(session.transcript.text)
    result = await session.finalize()
```

Set `preview="realtime"` for live partial text. Speaker diarization is off by
default; pass `diarization=True` to enable it. Within an enabled diarization
session, `speaker_finalization="role"` is the default and maps speaker IDs to
doctor/patient labels. Set `speaker_finalization="full"` together with
`diarization=True` to add a full-length async speaker finalization pass. Failed
rolling chunks are retried three times and surfaced in
`result.gaps`; they are never silently dropped.

Python 3.10+ is supported, including standard (GIL-enabled) CPython 3.14 via an
`abi3` native wheel. Free-threaded CPython (`cp314t`) is not currently supported.

## Quick Start

### Python

```python
import asyncio

from genshi_stt import GenshiSTTClient

async def main() -> None:
    async with GenshiSTTClient(api_key="gw-...", secure=True) as client:
        with open("recording.wav", "rb") as f:
            result = await client.transcribe(
                f.read(),
                model="genshi-stt-v1-pro",
                domain="medical",
            )
        print(result.text)
        for seg in result.segments:
            print(f"[{seg.start:.2f}-{seg.end:.2f}] {seg.text}")

        async with client.stream(
            model="genshi-stt-v1-pro-plus",
            effort="normal",
            dictionary_ids=["dict_hospital"],
        ) as session:
            partials = await session.push(audio_chunk)  # PCM16 bytes
            print(partials[0].text if partials else "")

            refined = await session.drain_events()
            for event in refined:
                if event.type == "refined":
                    print(event.index, event.text)

            final = await session.finalize()
            print(final.text)

asyncio.run(main())
```

### Node.js / TypeScript

```typescript
import { GenshiSTTClient } from '@genshiai/stt';

const client = new GenshiSTTClient({ apiKey: 'gw-...', secure: true });

// Batch transcription
const result = await client.transcribe(audioBuffer, {
  model: 'genshi-stt-v1-pro',
  domain: 'medical',
});
console.log(result.text);
for (const seg of result.segments) {
  console.log(`[${seg.start.toFixed(2)}-${seg.end.toFixed(2)}] ${seg.text}`);
}

// Realtime streaming
const session = client.stream({
  model: 'genshi-stt-v1-pro-plus',
  effort: 'normal',
  dictionaryIds: ['dict_hospital'],
});
const partials = await session.push(pcm16Chunk);
console.log(partials[0]?.text);

const refined = await session.drainEvents();
for (const event of refined) {
  if (event.type === 'refined') {
    console.log(event.index, event.text);
  }
}

const final = await session.finalize();
console.log(final.text);
```

### Browser

```typescript
import { GenshiSTTClient, createMicStream } from '@genshiai/stt-web';

const client = new GenshiSTTClient({ apiKey: 'gw-...', secure: true });
await client.init();

const session = client.stream({
  model: 'genshi-stt-v1-pro-plus',
  effort: 'normal',
  dictionaryIds: ['dict_hospital'],
});

const mic = await createMicStream({
  onChunk: async (chunk) => {
    const partials = await session.push(chunk);
    console.log(partials[0]?.text);

    const refined = await session.drainEvents();
    for (const event of refined) {
      if (event.type === 'refined') {
        console.log(event.index, event.text);
      }
    }
  },
});

// When done:
mic.stop();
const result = await session.finalize();
console.log(result.text);
```

Prefer `await session.finalize()` when you need the final corrected text.
`await session.close()` now performs a best-effort finalize for cleanup.
Use `session.abort()` only for intentional force-abort without billing finalize.

## Choosing A Mode

| Mode | During recording | Correction cadence | Recommended for |
|---|---|---|---|
| `batch` | Nothing is emitted until the request finishes | One final full-text pass | File upload, post-processing |
| `realtime` + `effort="normal"` | `partial` text appears immediately | Background correction is sparse | Dictation, meeting notes, standard live input |
| `realtime` + `effort="high"` | `partial` text appears immediately | Background correction is more frequent | Live captions, simultaneous charting, terminology-sensitive input |

## Realtime Mental Model

- `push()` returns immediate `partial` events from local STT
- `drain_events()` / `drainEvents()` returns queued `refined` / `error` events from background correction
- `effort: "normal"` batches corrections sparsely, `effort: "high"` refines more often
- `finalize()` still performs the final full-text correction pass

Public SDK configuration is intentionally centered on `model`, optional `domain`, `dictionaryIds` or `dictionaries="bound"`, and `effort`.
`secure=True` / `secure: true` is honored only when the API key is configured as `flexible`; `normal` keys ignore it and `secure-only` keys force it on every request. Configure the policy at key creation time in Console.
Low-level VAD and local model tuning are not part of the public API.

## Realtime Event Example

`push()` returns a `partial` event:

```json
{
  "type": "partial",
  "text": "ほんじつのけつあつは130の80です。",
  "index": 0,
  "processing_time_ms": 0
}
```

`drain_events()` / `drainEvents()` returns a `refined` event for the same segment:

```json
{
  "type": "refined",
  "text": "本日の血圧は130の80です。",
  "index": 0,
  "processing_time_ms": 88
}
```

## Response

```json
{
  "text": "本日の血圧は130の80です。次の患者さんをお願いします。",
  "processing_time_ms": 142,
  "segments": [
    {
      "id": 0,
      "start": 0.32,
      "end": 2.15,
      "text": "本日の血圧は130の80です。"
    },
    {
      "id": 1,
      "start": 3.2,
      "end": 4.8,
      "text": "次の患者さんをお願いします。"
    }
  ]
}
```

## Pricing

Point-based billing. 1pt = ¥10. Billed per audio hour.

| Model | Standard billing | `secure` billing |
|---|---|---|
| `genshi-stt-v1-lite` | 2 pt/h (¥20) | 5 pt/h (¥50) |
| `genshi-stt-v1-standard` | 6 pt/h (¥60) | 9 pt/h (¥90) |
| `genshi-stt-v1-pro` | 10 pt/h (¥100) | 13 pt/h (¥130) |
| `genshi-stt-v1-pro-plus` | 13 pt/h (¥130) | 15 pt/h (¥150) |

Validation matrix:

- `lite`: domain NG, dictionaries NG
- `normal`: domain NG, dictionaries NG
- `pro`: non-`general` domain required, dictionaries NG
- `pro-plus`: `dictionaryIds` or `dictionaries="bound"` required, both together NG

See https://docs.genshi.ai/stt/pricing for details.

## Supported Platforms

| Platform | Python | Node.js |
|----------|--------|---------|
| macOS ARM64 (Apple Silicon) | genshiai-stt-native | @genshiai/stt-native-darwin-arm64 |
| Linux x64 | genshiai-stt-native | @genshiai/stt-native-linux-x64 |
| Windows x64 | genshiai-stt-native | @genshiai/stt-native-windows-x64 |
| Browser | — | @genshiai/stt-web |

## Requirements

- Standard CPython 3.10–3.14 (`cp314t` excluded) / Node.js >= 20
- Valid GENSHI Voice API key
- `ffmpeg` for Python file/bytes decode and Node.js encoded audio decode

Browser SDK note:

- `await client.init()` is required before `transcribe()` or `realtime()`
- the npm package includes JSON metadata, and secured ONNX assets are fetched via `POST /v1/activate`

## Documentation

Full documentation: https://docs.genshi.ai/stt

## License

Proprietary. Copyright (c) 2026 GENSHI AI Inc. All rights reserved. See [LICENSE](./LICENSE).
