> ## Documentation Index
> Fetch the complete documentation index at: https://docs.tiro.ooo/llms.txt
> Use this file to discover all available pages before exploring further.

# 개요

> 워크스페이스 API 키로 Voice File Job을 만들고 오디오를 업로드한 뒤 전사 결과를 조회·삭제하는 전체 흐름을 알아보세요.

이 페이지는 Voice File Job을 생성하고, 오디오를 업로드하고, 결과를 가져오는 전체 흐름을 설명해요. 현재 구현은 클라이언트가 직접 호출하는 upload-complete 방식을 사용해요(S3 이벤트 없음).

## 필요한 것

* 워크스페이스 사용자 키 또는 워크스페이스 시스템 키: `Authorization: Bearer {id}.{secret}`
* Tiro 관리자가 해당 워크스페이스의 Voice File Job 정책을 활성화해야 해요.
* transcriptLocaleHints: 최대 1개 (선택)
  * **제공하지 않으면 언어가 자동으로 감지돼요**
* translationLocales: 최대 5개 (선택)

## 전체 체크리스트

1. Job 생성 → `{ id, uploadUri }` 수신
2. `uploadUri`에 오디오 업로드
3. `PUT /v1/external/voice-file/jobs/{jobId}/upload-complete` 호출
4. 완료될 때까지 job 상태 폴링
5. transcript 및 (선택적으로) translations 가져오기
6. 콘텐츠를 더 잘 이해하기 위해 paragraph summary 가져오기

## 웹훅으로 상태 변경을 받고 작업을 삭제하려면 어떻게 하나요?

폴링 대신 작업 상태 변경을 받으려면 `voice_file_job.created`, `voice_file_job.completed`, `voice_file_job.failed`, `voice_file_job.deleted`를 구독하세요. 웹훅 페이로드는 작업 메타데이터만 포함해요. Tiro는 전사 본문을 웹훅으로 전송하지 않으므로 `GET /v1/external/voice-file/jobs/{jobId}/transcript`로 가져오세요.

어떤 상태의 작업이든 `DELETE /v1/external/voice-file/jobs/{jobId}`로 삭제할 수 있어요. Tiro는 오디오와 생성된 결과를 삭제하고, 삭제 뒤 도착하는 처리 콜백은 무시해요.

## 오디오와 전사 데이터는 어떻게 보관되나요?

Tiro는 업로드한 오디오를 객체 저장소에, 전사·번역 결과를 서비스 데이터베이스에 저장해요. API에는 자동 보관 기간을 설정하는 기능이 없으므로, 데이터가 더 필요하지 않으면 `DELETE /v1/external/voice-file/jobs/{jobId}`를 호출하세요.

워크스페이스 사용자 키는 같은 워크스페이스에서 해당 사용자가 만든 작업에 접근할 수 있어요. 워크스페이스 시스템 키는 같은 워크스페이스의 작업에 접근할 수 있어요. 삭제 API를 호출하면 Tiro는 업로드한 오디오와 전사·번역 결과를 삭제해요. 삭제한 작업은 API에서 더 이상 조회할 수 없어요.

## 폴링 전략 (권장)

* `GET /v1/external/voice-file/jobs/{jobId}`를 exponential backoff로 폴링해요
  * 1\~2s 간격으로 시작해서 4s, 8s, 최대 30s까지 늘려요
  * 중단 조건:
    * 성공: `status` = `COMPLETED`
    * 실패: `status` = `FAILED`
  * 성공 후:
    * 항상 transcript를 가져와요: `GET /v1/external/voice-file/jobs/{jobId}/transcript`
    * translations를 요청했다면: `GET /v1/external/voice-file/jobs/{jobId}/translations` 또는 locale별 endpoint
    * paragraph summary 가져오기:
      * transcript의 경우: `GET /v1/external/voice-file/jobs/{jobId}/transcript/paragraph-summary`
      * translations의 경우: `GET /v1/external/voice-file/jobs/{jobId}/translations/{locale}/paragraph-summary`

<Note>
  처리가 성공했을 때의 최종 상태는 `COMPLETED`예요. 이는 transcript, translation(요청한 경우), 그리고 둘 다에 대한 paragraph summary를 포함한 모든 처리가 완료되었다는 의미예요.
</Note>

## 파일 제한 및 요구사항

### 지원하는 오디오 포맷

업계 표준 STT 역량을 기반으로 Tiro는 다음 포맷을 지원해요:

**오디오 포맷:**

| Format  | MIME Type  | Extension |
| ------- | ---------- | --------- |
| **MP3** | audio/mpeg | .mp3      |
| **WAV** | audio/wav  | .wav      |
| **M4A** | audio/mp4  | .m4a      |

**비디오 포맷 (오디오 추출):**

| Format  | MIME Type | Extension |
| ------- | --------- | --------- |
| **MP4** | video/mp4 | .mp4      |

### 파일 크기 및 길이 제한

| 제한 종류        | 값              | 비고                     |
| ------------ | -------------- | ---------------------- |
| **최대 파일 크기** | 500 MB         | 대부분의 사용 사례에 적합한 실질적 제한 |
| **최대 길이**    | 4시간            | 대부분의 회의와 인터뷰를 커버       |
| **최소 샘플레이트** | 8 kHz          | 음성 인식 최소 기준            |
| **권장 샘플레이트** | 16 kHz+        | 정확도에 최적                |
| **최대 샘플레이트** | 48 kHz         | 스튜디오 품질 지원             |
| **채널**       | Mono 또는 Stereo | 다중 화자 지원               |

### 처리 시간 예상치

처리 시간은 긴 파일에 대해 병렬 처리로 최적화돼요:

| 파일 길이  | 일반적인 처리 시간 |
| ------ | ---------- |
| 5분 미만  | 45-75초     |
| 5-20분  | 1-3분       |
| 20-60분 | 3-6분       |
| 1-4시간  | 6-18분      |

## Paragraph Summary 기능

Paragraph Summary 기능은 오디오 콘텐츠를 지능적으로 요약해서, transcript나 translation을 이해하기 쉬운 단락 단위 요약으로 나눠줘요.

### 동작 방식

1. **Transcript 처리**: 전사가 완료되면 텍스트가 CompositeTextSplitter를 사용해 논리적 단락으로 자동 분할돼요
2. **Summary 생성**: 각 단락이 ParagraphSummarizer를 거쳐 간결한 요약으로 만들어져요
3. **Translation 통합**: translations를 요청하면 각 locale의 번역된 콘텐츠를 기반으로 요약이 다시 생성돼요
4. **비동기 처리**: 요약 생성은 transcript/translation 완료 후 비동기로 이루어져요

## 시퀀스

```mermaid theme={"system"}
sequenceDiagram
    participant Client
    participant API as Tiro API
    participant Storage as File Storage
    participant Worker as Tiro Worker
    participant STT as STT Engine
    participant TR as Translation Engine
    participant WH as Webhook Service

    %% Job creation
    Client->>API: POST /v1/external/voice-file/jobs (transcriptLocaleHints, translationLocales)
    API->>Storage: Generate upload URL
    API-->>Client: 201 Created {id, uploadUri}

    %% File upload
    Client->>Storage: PUT audio file
    Client->>API: PUT /v1/external/voice-file/jobs/{jobId}/upload-complete

    %% Pipeline
    API->>Worker: Enqueue job (start processing)
    Worker->>STT: Speech-to-text
    STT-->>Worker: transcript
    alt translations requested
        Worker->>TR: Translate to requested locales
        TR-->>Worker: translations
    end
    Worker->>API: mark job = COMPLETED or FAILED
    opt Webhook configured
        API-->>WH: POST {jobId, status=COMPLETED}
    end

    %% Results
    Client->>API: GET /v1/external/voice-file/jobs/{jobId}
    API-->>Client: status, timestamps
    Client->>API: GET /v1/external/voice-file/jobs/{jobId}/transcript
    API-->>Client: transcript
    Client->>API: GET /v1/external/voice-file/jobs/{jobId}/translations
    API-->>Client: translations[]
```

직접 해보고 싶으세요? [단계별 튜토리얼](/ko/developers/voice-file/tutorial)에서 전체 흐름을 따라가 보세요. 업로드, 폴링, 그리고 첫 transcript 가져오기까지 끝까지 안내해요.
