# Canlı transkripsiyon

> Mikrofon veya sekme sesini WebSocket üzerinden transcript1'e gönderin; konuşma sürerken isteğe bağlı gerçek zamanlı çeviriyle altyazı satırları alın.

Canonical: https://transcript1.com/tr/docs/live
Language: tr
Last updated: 2026-11-03

Canlı transkripsiyon, insanlar hâlâ konuşurken ses akışını altyazı satırlarına çevirir. İstemciniz ham PCM sesi WebSocket üzerinden gönderir; transcript1 önce taslak olarak başlayan, sonra kesinleşen satırlar geri yollar. `translate_to` eklerseniz her satır çevirisiyle birlikte gelir. Oturum bitince sonuç normal bir transkripsiyon olarak kaydedilir.

Canlı için ayrı plan yoktur: canlı transkripsiyon, diğer her şeyle aynı dakika bakiyesini kullanır. Bağlantı süresinin nasıl sayıldığını [Ücretlendirme](https://transcript1.com/tr/docs/live#billing) bölümünde bulabilirsiniz.

## Canlı ne zaman kullanılır?

| Şu durumda canlıyı seçin | Şu durumda [normal transkripsiyonu](https://transcript1.com/tr/docs/getting-started) seçin |
|---|---|
| Ses hâlâ üretiliyor: bir görüşme, konuşma, yayın ya da izlediğiniz bir video. | Elinizde bir bağlantı ya da bitmiş bir dosya var. |
| Altyazıya konuşmadan bir iki saniye sonra ihtiyacınız var. | En yüksek doğruluğu istiyor ve sonucu bekleyebiliyorsunuz. |
| Her satırın yanında gerçek zamanlı çeviri istiyorsunuz. | Bitmiş bir transkriptin ya da birden çok dilin çevirisini istiyorsunuz. |

Canlı yalnızca ham PCM ses alır. Video bağlantılarını, dosya yüklemelerini, WebM, Opus ve MP3'ü kabul etmez. Sesi istemcinizde yakalayıp önce PCM'e dönüştürün. [Tarayıcıda ses yakalama](https://transcript1.com/tr/docs/live#capture-audio-in-a-browser) bölümü bunun nasıl yapıldığını gösterir.

## SDK ile hızlı başlangıç

SDK 1.5.0 veya daha yenisini kurun: `npm i @transcript1/sdk@latest`. `t1.live.start` oturumu oluşturur, bağlanır ve oturum başladığında tamamlanır; böylece sesi hemen göndermeye başlayabilirsiniz.

```javascript
import { createReadStream } from 'node:fs';
import { setTimeout as sleep } from 'node:timers/promises';
import { Transcript1 } from '@transcript1/sdk';

const t1 = new Transcript1(); // reads TRANSCRIPT1_API_KEY

const live = await t1.live.start({ language: 'en', translateTo: 'es', sampleRate: 16000 });

live.on('line', line => {
  const mark = line.final ? 'final  ' : 'partial';
  console.log(mark, line.text, '→', line.translation?.text ?? '');
});
live.on('warning', warning => console.warn(warning.code));

// speech.pcm: 16 kHz, mono, signed 16-bit little-endian, no header
for await (const chunk of createReadStream('./speech.pcm', { highWaterMark: 3200 })) {
  live.send(chunk);
  await sleep(100); // 3,200 bytes are 100 ms of audio: send at real-time speed
}

const result = await live.end();
console.log(result.reason, result.transcriptionId, result.minutesCharged);
```

Satırlar yerinde güncellenir. Aynı `id` ile yeni bir satır geldiğinde elinizdekini değiştirin ya da hepsini `live.lines` üzerinden okuyun. `end()` oturumu bitirir, son satırları bekler ve transkripti kaydeder. Tüm yöntemler ve olaylar için [Node.js SDK](https://transcript1.com/tr/docs/sdk#live-transcription) sayfasına bakın.

## Ham WebSocket ile hızlı başlangıç

SDK olmadan iki adım gerekir: HTTPS üzerinden bir oturum oluşturun, sonra dönen tek kullanımlık token ile WebSocket'i açın.

### Oturum oluşturma

```bash
curl -X POST https://api.transcript1.com/v1/live/sessions \
  -H "Authorization: Bearer $TRANSCRIPT1_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"language": "en", "translate_to": "es", "sample_rate": 16000}'
```

API `201` ile yanıt verir:

```json
{
  "id": "lv_8fK2Lm0PqRsTuVwXyZaBcD",
  "status": "waiting",
  "transcription_id": "tr_3NcQvXy7BtHjKd5ErFgLmA",
  "websocket_url": "wss://api.transcript1.com/v1/live/sessions/lv_8fK2Lm0PqRsTuVwXyZaBcD/stream",
  "token": "Zk3x...",
  "token_expires_at": "2026-11-02T12:01:00Z",
  "rate": 1
}
```

`save` değeri `false` ise `transcription_id` `null` olur. Token tek kullanımlıktır ve 60 saniye sonra geçersiz olur; hemen bağlanın. `rate`, bu oturumun başlayan her dakikası için kaç bakiye dakikası düşüldüğünü gösterir; bkz. [Ücretlendirme](https://transcript1.com/tr/docs/live#billing).

İstek gövdesi şu alanları alır. Hepsi isteğe bağlıdır; gereken yetki `transcriptions:write`'tır:

| Alan | Varsayılan | Kural |
|---|---|---|
| `language` | `auto` | `auto` ya da canlının desteklediği iki harfli bir dil kodu. |
| `translate_to` | yok | İki harfli bir dil kodu. Oturum başına tek hedef dil. Bkz. [Canlı çeviri](https://transcript1.com/tr/docs/live#translate-live). |
| `diarize` | `false` | Konuşmacıları etiketler. Bazı kurulumlar konuşmacı etiketleyemez, örneğin `language: "auto"` ile birlikte; bu durumda API `422` döndürür. [Yetenekleri](https://transcript1.com/tr/docs/live#capabilities) kontrol edin. |
| `audio_format` | `pcm_s16le` | Tek geçerli değer. Alan, ileride yeni biçimler eklenebilsin diye var. |
| `sample_rate` | `16000` | 8000 ile 48000 arasında bir tam sayı. Yalnızca mono. |
| `save` | `true` | `false` olursa oturum bittikten sonra hiçbir şey saklanmaz. Bkz. [Kaydedilen transkriptler](https://transcript1.com/tr/docs/live#saved-transcripts). |

### Bağlanma ve akış

WebSocket'i, token ikinci alt protokol olacak şekilde açın. Bu, tarayıcılarda ve Node 22+ sürümünde özel başlık olmadan çalışır. Ses göndermeden önce `session.started` olayını bekleyin: daha erken gönderilen ikili kareler atılır ve `audio_dropped` uyarısı alırsınız.

```javascript
import { createReadStream } from 'node:fs';
import { setTimeout as sleep } from 'node:timers/promises';

const session = await fetch('https://api.transcript1.com/v1/live/sessions', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.TRANSCRIPT1_API_KEY}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ language: 'en', translate_to: 'es', sample_rate: 16000 }),
}).then(response => response.json());

const ws = new WebSocket(session.websocket_url, ['t1-live', session.token]);
const lines = new Map();

ws.addEventListener('message', async message => {
  const event = JSON.parse(message.data);

  if (event.type === 'session.started') {
    for await (const chunk of createReadStream('./speech.pcm', { highWaterMark: 3200 })) {
      ws.send(chunk);
      await sleep(100);
    }
    ws.send(JSON.stringify({ type: 'end' }));
  } else if (event.type === 'line') {
    lines.set(event.line.id, event.line); // the full current state: replace by id
    console.log(event.line.final, event.line.text, event.line.translation?.text);
  } else if (event.type === 'session.ended') {
    console.log('ended:', event.reason, event.minutes_charged);
  }
});

ws.addEventListener('close', event => console.log('closed', event.code));
```

Node 20'de yerleşik `WebSocket` yoktur: aynı `new WebSocket(url, protocols)` biçimine sahip `ws` paketini kullanın.

Sunucu, geçerli bir token'a yalnızca `t1-live` alt protokolüyle yanıt verir. Hatalı token el sıkışmayı asla düşürmez: soket açılır, bir `error` olayı alırsınız ve soket 4xxx koduyla kapanır. Böylece tarayıcı genel bir 1006 yerine gerçek nedeni gösterir. Bkz. [Kapanış kodları](https://transcript1.com/tr/docs/live#close-codes).

## Tarayıcıda ses yakalama

Canlı ses, oturumun `sample_rate` değerinde 16 bit işaretli little-endian mono PCM olmalıdır. Tarayıcılar kayan noktalı örnekler verir; bunları bir `AudioWorklet` içinde dönüştürün. Aşağıdaki örnek mikrofonu 100 ms'lik parçalarla 16 kHz PCM olarak yakalar ve tarayıcı SDK girişiyle gönderir. `getAccessToken` bir OAuth erişim token'ı döndürür; tarayıcıya asla API anahtarı koymayın. Bkz. [Güvenlik](https://transcript1.com/tr/docs/live#security).

```javascript
import { createLiveClient } from '@transcript1/sdk/live';

const workletSource = `
class Pcm16Processor extends AudioWorkletProcessor {
  constructor() {
    super();
    this.buffer = new Int16Array(1600); // 100 ms at 16 kHz
    this.filled = 0;
  }

  process(inputs) {
    const channel = inputs[0][0];
    if (!channel) return true;
    for (let i = 0; i < channel.length; i++) {
      const sample = Math.max(-1, Math.min(1, channel[i]));
      this.buffer[this.filled++] = sample < 0 ? sample * 0x8000 : sample * 0x7fff;
      if (this.filled === this.buffer.length) {
        this.port.postMessage(this.buffer.slice());
        this.filled = 0;
      }
    }
    return true;
  }
}
registerProcessor('pcm16', Pcm16Processor);
`;

const client = createLiveClient({ getAccessToken: () => myApp.getOAuthAccessToken() });

const stream = await navigator.mediaDevices.getUserMedia({ audio: { channelCount: 1 } });
const context = new AudioContext({ sampleRate: 16000 });
const moduleUrl = URL.createObjectURL(new Blob([workletSource], { type: 'text/javascript' }));
await context.audioWorklet.addModule(moduleUrl);

// the context's real rate: a browser that cannot do 16 kHz picks its own
const live = await client.start({ language: 'auto', sampleRate: context.sampleRate });
live.on('line', renderLine);

const microphone = context.createMediaStreamSource(stream);
const capture = new AudioWorkletNode(context, 'pcm16');
capture.port.onmessage = event => live.send(event.data); // an Int16Array
const mute = context.createGain();
mute.gain.value = 0;
microphone.connect(capture).connect(mute).connect(context.destination);

async function stop() {
  stream.getTracks().forEach(track => track.stop());
  await context.close();
  return live.end();
}
```

Worklet 16 kHz için yazılmıştır. Bağlam başka bir hızda çalışırsa parça artık 100 ms olmaz, ancak `sampleRate` bağlamla eşleştiği için PCM doğru kalır. Mikrofon yerine bir sekmenin ya da videonun sesini yakalamak için `MediaStream` nesnesini `getDisplayMedia` ile veya bir medya öğesinin `captureStream()` çağrısıyla oluşturun ve aynı şekilde bağlayın.

## Canlı çeviri

Oturuma `translate_to` ekleyin; transcript1 her satırı söylenirken çevirir.

- Oturum başına tek hedef dil vardır. Daha fazla dili sonradan kaydedilen transkripte [çeviri endpoint'i](https://transcript1.com/tr/docs/live#saved-transcripts) ile ekleyebilirsiniz.
- Her `line` bir özgün metne (`text`, `final`) ve bir `translation` nesnesine (`language`, `text`, `final`) sahiptir. `translate_to` ayarlı değilse `translation` `null` olur.
- Özgün metin ve çeviri birbirinden bağımsız kesinleşir: bir satırın özgün metni kesinleşmişken çevirisi hâlâ değişiyor olabilir. Satırı, ikisi de kesinleşince kesin olarak gösterin.
- Zaten hedef dildeki bir satır kendi metnini çeviri olarak kullanır ve satır kapandığında kesinleşir.
- Bir satır şu durumlarda kapanır: konuşmacı duraklar, konuşmacı değişir, kelimeler arasındaki boşluk 0.9 saniyeyi aşar, satır iki altyazı satırına (84 karakter) ya da 15 saniyeye ulaşır veya `finalize` gönderirsiniz. Çeviri açıkken, çeviri gelirken bir satırın kapanması yaklaşık 3 saniye daha uzun sürebilir. Bu durumda çeviri açık kalabilir (`final: false`) ve özgün metin kesinleştikten sonra da uzamaya devam edebilir.
- Çeviri ücretsizdir. Dakika harcamaz.

Hangi hedef dillerin ve dil çiftlerinin kullanılabildiği canlı konuşma sağlayıcısına bağlıdır. Kuralları koda gömmek yerine [yetenekleri](https://transcript1.com/tr/docs/live#capabilities) okuyun. Desteklenmeyen bir hedef `422 unsupported_translation` döndürür. Örneğin bir sağlayıcı `auto` yerine açık bir `language` isteyebilir ya da yalnızca İngilizceyi içeren çiftlere izin verebilir.

## WebSocket protokolü

### Bağlanma

```javascript
new WebSocket(websocket_url, ['t1-live', token]);
```

Token, WebSocket alt protokolü olarak taşınır. Hiçbir zaman bir URL'de ya da erişim günlüğünde görünmez. `Authorization` başlığı göndermeyin: kimlik bilgisi token'ın kendisidir. Sunucu her 30 saniyede bir ping gönderir; tarayıcılar ve `ws` paketi otomatik yanıt verir. 60 saniye boyunca pong göndermeyen soket düşürülür.

Zaten bir sokete sahip bir oturuma yapılan geçerli bir bağlantı eskisinin yerini alır. Bkz. [Devam etme ve devralma](https://transcript1.com/tr/docs/live#resume-and-takeover).

### İstemci mesajları

| Mesaj | Anlamı |
|---|---|
| İkili kare | Ses: oturumun `sample_rate` değerinde PCM s16le mono. Her karenin uzunluğu çift olmalı ve en fazla 256 KB olmalıdır. Kare başına yaklaşık 100 ms iyi bir boyuttur. |
| `{"type":"finalize"}` | Geçerli satırı hemen kapatır, örneğin video duraklatıldığında. |
| `{"type":"end"}` | Oturumu bitirir ve kaydeder. Sunucu `session.ended` ile yanıt verir ve soketi kapatır. |
| Diğer her şey | `invalid_message` kodlu, ölümcül olmayan bir `error` olayı. |

Tek uzunluklu ya da aşırı büyük bir kare protokol ihlalidir ve soketi `4008` ile kapatır.

Sesi `session.started` olayından sonra göndermeye başlayın. Sesi gerçek zamandan hızlı gönderen bir istemciden bağlantı süresi yerine ses süresi ücretlendirilir ([Ücretlendirme](https://transcript1.com/tr/docs/live#billing) bölümüne bakın); bu yüzden sesi üretildiği hızda gönderin.

### Sunucu olayları

Her olay, `type` alanı olan bir JSON metin karesidir.

| Olay | Ne zaman gönderilir |
|---|---|
| `session.started` | Bağlantı kabul edildi. Bundan sonra ses gönderin. |
| `line` | Bir altyazı satırı oluşturuldu veya değişti. |
| `usage` | Her ücretlendirmeden sonra. |
| `warning` | Dikkat gerektiren bir durum var, ancak oturum sürüyor. |
| `error` | Ölümcül olmayan bir sorun ya da hemen kapanmanın nedeni. |
| `reconnect` | Sunucu yeniden başlamak üzere. Oturuma devam edin. |
| `session.ended` | Oturum bitti ve kaydedildi. Normal bir kapanıştan önceki son olay. |

`session.started`, bunun bir devam olup olmadığını ve oturumun şimdiye kadar ne kadar ses işlediğini bildirir:

```json
{
  "type": "session.started",
  "session_id": "lv_8fK2Lm0PqRsTuVwXyZaBcD",
  "transcription_id": "tr_3NcQvXy7BtHjKd5ErFgLmA",
  "resumed": false,
  "offset_ms": 0
}
```

`line`, tek bir satırın tam güncel durumunu taşır; bu yüzden aynı `id`'ye sahip satırı değiştirin. Bkz. [Satır nesnesi](https://transcript1.com/tr/docs/live#the-line-object).

```json
{
  "type": "line",
  "line": {
    "id": 12,
    "start_ms": 53120,
    "end_ms": 56040,
    "speaker": null,
    "language": "en",
    "text": "Welcome back to the stream",
    "final": true,
    "translation": { "language": "es", "text": "Bienvenidos de nuevo", "final": false }
  }
}
```

`usage`, her ücretlendirmeden sonra; bağlantı süresi, ses süresi, şimdiye kadar düşülen bakiye dakikaları ve kalan dakikalarla birlikte gönderilir:

```json
{
  "type": "usage",
  "connected_ms": 61240,
  "audio_ms": 60100,
  "minutes_charged": 2,
  "minutes_remaining": 898
}
```

`warning` bir `code` taşır:

| `code` | Anlamı |
|---|---|
| `balance_low` | Bir sonraki ücretlendirme başarısız olur. Zamanı geldiğinde oturum `balance_exhausted` ile biter. [Otomatik yükleme](https://transcript1.com/tr/docs/billing-and-limits#auto-top-up) açıkken gönderilmez. |
| `audio_dropped` | Ses, oturum hazır olmadan geldi ya da konuşma sağlayıcısı bağlanırken çok fazla ses geldi. En eski ses atıldı. |
| `idle_timeout_soon` | 4 dakikadır ses yok. Oturum, 5 dakika sessizlikten sonra biter. Oturumu korumak için ses gönderin. |

```json
{ "type": "warning", "code": "idle_timeout_soon" }
```

`error` bir `code` ve bir `message` taşır. Canlı soketten şu kodlar gelebilir:

| `code` | Ölümcül | Anlamı |
|---|---|---|
| `invalid_message` | Hayır | `finalize` ya da `end` olmayan bir metin karesi. |
| `invalid_token` | Evet | Token geçersiz, süresi dolmuş ya da zaten kullanılmış. Soket `4001` ile kapanır. |
| `not_found` | Evet | Oturum yok. Soket `4004` ile kapanır. |
| `session_ended` | Evet | Oturum zaten bitmiş. Soket `4004` ile kapanır. |

```json
{ "type": "error", "code": "invalid_message", "message": "Expected {\"type\":\"finalize\"} or {\"type\":\"end\"}" }
```

`reconnect`, sunucu soketi `1012` ile kapatmadan önce gelir, örneğin bir dağıtım sırasında. Yeni bir token alın ve oturuma devam edin.

```json
{ "type": "reconnect", "reason": "server_restart" }
```

`session.ended` her oturumun son olayıdır. Sayılar nihai toplamlardır:

```json
{
  "type": "session.ended",
  "reason": "client_ended",
  "transcription_id": "tr_3NcQvXy7BtHjKd5ErFgLmA",
  "minutes_charged": 3,
  "connected_ms": 142500,
  "audio_ms": 141900
}
```

### Satır nesnesi

| Alan | Anlamı |
|---|---|
| `id` | Her satırda bir artan, 0'dan başlayan numara. Kaydedilen transkriptteki segment dizinidir. |
| `start_ms`, `end_ms` | Oturumun ses zamanına göre başlangıç ve bitiş. Bu zaman yeniden bağlanmalarda kesintisiz sürer. |
| `speaker` | `diarize` açıkken konuşmacı etiketi, aksi halde `null`. Etiketler normal transkriptlerdekiyle aynıdır. |
| `language` | Satırın algılanan ya da verilen dili; henüz bilinmiyorsa `null`. |
| `text` | Şimdiye kadarki özgün metin. |
| `final` | Özgün metin artık değişmeyecekse `true`. |
| `translation` | `translate_to` yoksa `null`, aksi halde `language`, `text` ve `final`. |

`final: false` olan satırları daha soluk bir stille gösterin: metinleri hâlâ değişebilir. `final: true` olan bir satırın metni bir daha değişmez ve kesinleşmiş bir satır asla kaldırılmaz.

SDK satır alanlarında `camelCase` kullanır: `startMs`, `endMs`.

### Bitiş nedenleri

`session.ended` ve `GET /v1/live/sessions/:id` bir `end_reason` verir:

| Neden | Anlamı |
|---|---|
| `client_ended` | `end` gönderdiniz. |
| `balance_exhausted` | Bir sonraki ücretlendirme başarısız oldu. Oturum dakika sınırında biter ve kaydedilir. |
| `idle_timeout` | 5 dakika boyunca ses gelmedi. |
| `max_duration` | Oturum 300 dakika bağlı kaldı. Yeni bir tane başlatın. |
| `disconnected` | İstemci, devam etmeden 2 dakikadan uzun süre ortadan kayboldu. |
| `upstream_error` | Konuşma sağlayıcısı başarısız oldu. |
| `internal_error` | Bizim tarafımızda bir sorun oluştu. |
| `not_connected` | Oturuma 5 dakika içinde hiç bağlanılmadı. Asla ücretlendirilmez ve yalnızca `GET` ile görülebilir. |

### Kapanış kodları

| Kod | Anlamı |
|---|---|
| `1000` | Normal kapanış. Her zaman `session.ended` olayını izler. |
| `1011` | Beklenmeyen sunucu hatası. Oturumu sunucu kurtarır: yeni bir token ile devam edin. |
| `1012` | Sunucu yeniden başlıyor. `reconnect` olayını izler: yeni bir token ile devam edin. |
| `4001` | Token geçersiz, süresi dolmuş ya da zaten kullanılmış. |
| `4004` | Oturum bulunamadı ya da zaten bitti. |
| `4008` | Protokol ihlali: tek uzunluklu ya da aşırı büyük bir ikili kare. |
| `4010` | Aynı oturuma yapılan daha yeni bir bağlantıyla değiştirildi. |

API yeniden başlarken yeni bir WebSocket isteği HTTP `503` ile yanıtlanabilir. Kısa bir süre sonra yeniden deneyin.

## Devam etme ve devralma

Bir oturum ağ kopmasından, API dağıtımından ve çökmeden sağ çıkar. Kopmadan sonra 2 dakika sizi bekler; bu sürenin sonunda `disconnected` nedeniyle biter ve kaydedilir.

1. `POST /v1/live/sessions/:id/token` çağırın. Yanıt, oturumu oluştururkenki alanların aynısını içerir: `token`, `token_expires_at` ve `websocket_url`. Oturum bittikten sonra `409 session_ended` ile başarısız olur.
2. Bu token ile yeni bir WebSocket açın.
3. `session.started`, `resumed: true` ile gelir. `offset_ms`, oturumun şimdiye kadar işlediği ses miktarıdır: sesi bu noktadan devam ettirin. Satır kimlikleri kaldığı yerden sürer.

Zaten kesinleşmiş satırlar korunur. Kopma anındaki tamamlanmamış kuyruk kaybolur; bu yüzden sesi arabelleğe alıyorsanız `offset_ms` noktasından birkaç saniyelik sesi yeniden gönderin. Yeniden bağlanma boşlukları ücretlendirilmez.

Devralma aynı çağrıdır. Sunucu hâlâ bir soketin açık olduğunu düşünüyorsa yeni bir geçerli bağlantı onun yerini alır ve eski soket, satırları kaydedildikten sonra `4010` ile kapatılır. Eşzamanlı oturum limiti, devam etmeyi asla engellemez.

SDK bunların hepsini sizin için yapar: bir kopmada ya da `reconnect` olayında token alır ve 2 dakikaya kadar 0.5 ile 8 saniye arasında artan bekleme süreleriyle yeniden bağlanır; kopma sırasında gönderdiğiniz sesin son 10 saniyesini yeniden iletir.

## Ücretlendirme

Canlı transkripsiyon, normal transkripsiyonlarla aynı dakika bakiyesinden harcar.

- **Bağlantı süresi ücretlendirilir**: soketin kabul edildiği andan kapanışına kadar. Sessizlik ve duraklatılmış video da sayılır. Kopma ile devam etme arasındaki süre sayılmaz.
- **Başlayan her dakika için, en az 1.** İlk dakika ilk bağlantı kabul edildiğinde, sonraki her dakika başladığında ücretlendirilir.
- **Gerçek zamandan hızlı gönderim ses süresi olarak ücretlendirilir.** Gönderdiğiniz ses bağlantı süresinden uzunsa bunun yerine ses süresi ücretlendirilir.
- **Oran API'den okunur.** Başlayan bir dakika, yukarı yuvarlanarak `rate` bakiye dakikası tutar. Oran genellikle 1'dir ve ondalıklı olabilir. Canlı oranı `GET /v1/account` içindeki `rates.live` alanından, `GET /v1/live/capabilities` içindeki `rate` alanından ve oluşturduğunuz oturumdaki `rate` alanından okuyun. Bir oturumun oranı, oluşturulduktan sonra sabit kalır.
- **Çeviri ücretsizdir.**
- **Hiç bağlanılmadıysa ücret alınmaz.** 5 dakika içinde bağlanılmayan bir oturum `not_connected` olarak biter.
- **Başarısızlıklar iade edilir.** Bir oturum tek bir satır üretmeden `upstream_error` ya da `internal_error` ile biterse tüm ücretler iade edilir. Sessizlik yüzünden boş kalan bir oturum ücretlendirilir ve boş kaydedilir.
- **Bakiye bittiğinde** ve [otomatik yükleme](https://transcript1.com/tr/docs/billing-and-limits#auto-top-up) açıksa, oturum akmaya devam ederken transcript1 kayıtlı kartınızdan ödeme alır ve oturum devam eder. Otomatik yükleme kapalıysa ya da duraklatılmışsa veya ödeme başarısız olursa oturum sonlandırılır, kaydedilir ve dakika sınırında `balance_exhausted` ile biter. Otomatik yükleme açık değilse önce `balance_low` uyarısı gelir.

Kullanılabilir bakiyeniz geçerli orandaki bir başlayan dakikadan azsa oturum oluşturma `402 insufficient_minutes` döndürür. Otomatik yükleme açıksa transcript1 önce yükleme yapmayı dener. Bkz. [Ücretlendirme ve limitler](https://transcript1.com/tr/docs/billing-and-limits#live-transcription).

## Limitler

| | Free | Monthly | Annual |
|---|---|---|---|
| Aynı anda canlı oturum | 1 | 2 | 3 |

- Bir oturum `waiting`, `connected` ya da `disconnected` (2 dakikalık süresi içinde) durumundayken sayılır. Limit aşılırsa `POST /v1/live/sessions`, `Retry-After: 30` ile `429 too_many_live_sessions` döndürür.
- Canlı oturumlar aktif transkripsiyon limitinize sayılmaz.
- Bir oturum en fazla 300 dakika bağlı kalabilir. Ardından `max_duration` ile biter.
- 5 dakika boyunca sesi olmayan bir oturum `idle_timeout` ile biter; 4 dakika sonra `idle_timeout_soon` alırsınız. Duraklatılmış bir akış yine de bağlantı süresi ücretlendirir ve boşta sayılır; duraklama uzunsa oturumu bitirin.
- transcript1 tüm canlı oturumları birlikte sınırlar. Hepsi kullanımdayken `POST /v1/live/sessions`, yeniden denenebilir bir hata olan `503 live_capacity` döndürür. `Retry-After` süresini (30 saniye) bekleyip tekrar deneyin. Bu, yalnızca oturum oluşturulurken kontrol edilir; oturumun ortasında asla.
- Oturum oluşturma ve token alma, dakikalık istek limitinize sayılır.
- Ses yalnızca ham PCM'dir: `pcm_s16le`, mono, 8000 ile 48000 Hz arası.

## Yetenekler

`GET /v1/live/capabilities`, canlı transkripsiyonun şu anda neleri desteklediğini anlatır; böylece istemciler sağlayıcı kurallarını koda gömmez. Gereken yetki `transcriptions:read`'dir.

```json
{
  "available": true,
  "auto_language": true,
  "languages": ["en", "es"],
  "translation": {
    "targets": ["es", "de"],
    "pairs": "any",
    "requires_language": false
  },
  "diarize": true,
  "audio_formats": ["pcm_s16le"],
  "sample_rate": { "min": 8000, "max": 48000 },
  "max_session_minutes": 300,
  "rate": 1
}
```

Listeler burada kısaltılmıştır. Tam hâlini API'den okuyun.

- `translation.pairs`, `"any"` (algılanan her dilden her hedefe) ya da `from` ve `to` alanlı nesnelerden oluşan bir listedir.
- `translation.requires_language`, çevirinin `auto` yerine açık bir `language` gerektirdiği durumda `true`'dur.
- Canlı transkripsiyon yapılandırılmamışsa yanıt yalnızca `rate` ile `available: false` olur ve oturum oluşturma `503 live_unavailable` döndürür.

SDK ile: `await t1.live.capabilities()`.

## Oturumu okuma

`GET /v1/live/sessions/:id` bir oturumun durumunu döndürür. Gereken yetki `transcriptions:read`'dir.

```bash
curl https://api.transcript1.com/v1/live/sessions/lv_8fK2Lm0PqRsTuVwXyZaBcD \
  -H "Authorization: Bearer $TRANSCRIPT1_API_KEY"
```

```json
{
  "id": "lv_8fK2Lm0PqRsTuVwXyZaBcD",
  "status": "ended",
  "end_reason": "client_ended",
  "transcription_id": "tr_3NcQvXy7BtHjKd5ErFgLmA",
  "options": {
    "language": "en",
    "translate_to": "es",
    "diarize": false,
    "audio_format": "pcm_s16le",
    "sample_rate": 16000,
    "save": true
  },
  "connected_ms": 142500,
  "audio_ms": 141900,
  "minutes_charged": 3,
  "rate": 1,
  "created_at": "2026-11-02T11:58:12Z",
  "ended_at": "2026-11-02T12:00:35Z"
}
```

`status` değeri `waiting`, `connected`, `disconnected` ya da `ended` olabilir. Oturum bitene kadar `end_reason` `null`'dır. SDK ile: `await t1.live.get(id)`.

## Hatalar

İstek hataları olağan [hata yapısını](https://transcript1.com/tr/docs/errors) kullanır. `POST /v1/live/sessions` ve ona bağlı endpoint'lerin döndürdükleri şunlardır:

| HTTP durumu | `code` | Yeniden denenebilir | Ne zaman |
|---|---|---|---|
| 422 | `invalid_request` | Hayır | Bir alan eksik ya da geçersiz; örneğin 8000 ile 48000 dışında bir `sample_rate`. |
| 422 | `unsupported_language` | Hayır | `language` canlı transkripsiyonda desteklenmiyor. |
| 422 | `unsupported_translation` | Hayır | Hedef dil ya da dil çifti desteklenmiyor. |
| 402 | `insufficient_minutes` | Hayır | Kullanılabilir bakiyeniz geçerli orandaki bir başlayan dakikanın altında. |
| 403 | `email_not_verified` | Hayır | Önce e-posta adresinizi doğrulayın. |
| 429 | `too_many_live_sessions` | Evet | Planınızın eşzamanlı canlı oturumları kullanımda. `Retry-After` kadar bekleyin. |
| 503 | `live_capacity` | Evet | Tüm canlı kapasite kullanımda. `Retry-After` (30 saniye) kadar bekleyin. |
| 503 | `live_unavailable` | Hayır | Canlı transkripsiyon şu anda kullanılamıyor. |
| 409 | `session_ended` | Hayır | Bitmiş bir oturum için `POST /v1/live/sessions/:id/token`. |

Soketteki sorunlar `error` olayları ve [kapanış kodları](https://transcript1.com/tr/docs/live#close-codes) olarak gelir.

## Kaydedilen transkriptler

`save: true` (varsayılan) ile oturum bittiğinde normal bir transkripsiyon olarak kaydedilir. Ses hiçbir zaman saklanmaz.

- `transcription_id`, oturumu oluştururken döner. Durumu oturum sürerken `live`, bittikten sonra `completed` olur. Hiç bağlanılmayan bir oturum `canceled` durumunda bir transkripsiyon bırakır.
- Transkripsiyonda `source: { "platform": "live", "session_id": "lv_…" }` bulunur. Bağlantı ya da dosya yoktur. Panel onu canlı oturum olarak listeler.
- Her satır, satırın `id` değeriyle aynı dizine sahip bir segment olur. Transkripti diğer transkripsiyonlar gibi JSON, metin, SRT ya da VTT olarak okuyun: bkz. [API referansı](https://transcript1.com/tr/docs/api-reference).
- Canlı çeviri de onunla birlikte kaydedilir. [Çeviri](https://transcript1.com/tr/docs/translation#read-the-translation) sayfasında anlatıldığı gibi `translation` parametresiyle okuyun.
- Transkripsiyon `completed` olduktan sonra `POST /v1/transcriptions/:id/translations` ile daha fazla çeviri dili ekleyebilirsiniz. Bkz. [Çeviri](https://transcript1.com/tr/docs/translation#translate-an-existing-transcript).

`save: false` ile oturum bittikten sonra hiçbir şey saklanmaz: transkripsiyon yoktur ve `transcription_id` `null`'dır. Yine de her satırı soket üzerinden alırsınız ve olağan ücret uygulanır.

## Güvenlik

- Oturum oluştururken aldığınız token tek kullanımlıktır ve 60 saniye sonra geçersiz olur. URL'de değil, WebSocket alt protokolü olarak gönderilir; böylece erişim günlüklerine girmez. Sızan bir token, kullanıldıktan ya da süresi dolduktan sonra işe yaramaz.
- API anahtarını yalnızca kontrol ettiğiniz bir sunucudan kullanın. API anahtarını asla bir web sayfasına ya da eklentiye koymayın.
- Tarayıcıda ya da eklentide kullanıcıları OAuth ile giriş yaptırın ve OAuth erişim token'ını `createLiveClient` içindeki `getAccessToken` işlevine verin. Oturum başlatmak için token'ın `transcriptions:write` yetkisi olmalıdır. OAuth erişim token'larının süresi 1 saat sonra dolar ve her devam etme, `getAccessToken` işlevinden yeni bir token ister.
- Sunucunuz oturumu API anahtarıyla oluşturup tarayıcıya yalnızca `websocket_url` ve `token` değerlerini de verebilir. Bu durumda istemci doğrudan bağlanır. Sizden yeni bir token almadan devam edemez.
