# 오디오 텍스트 변환(STT)



음성 파일 한 개를 올리면 말한 내용을 전체 텍스트와 구간별(시작·끝 시각 포함) 텍스트로 돌려줍니다.



인증: Authorization: Bearer $APICK_API_KEY

본문 있는 REST 요청: multipart/form-data. GET 본문 및 MCP JSON-RPC 규격은 해당 명세를 따릅니다.

인증키는 서버에 보관하세요. 모든 예제는 정적 자료입니다.



## POST /rest/stt 응답 필드

- `data` (object): 요청 처리 결과 묶음입니다. 조회한 값·작업 상태·오류 설명이 이 안에 들어 있으며, 실제 하위 필드 구성은 서비스마다 다릅니다. 값이 없으면 null·빈 배열·필드 생략 중 해당 서비스의 규칙을 따릅니다.

- `data.text` (string): 이 요청의 결과 텍스트입니다. 게시물 조회에서는 본문, STT·요약·교정에서는 처리된 문장이 들어가며, 줄바꿈이 포함될 수 있습니다.

- `data.segments` (array): 말한 구간별 결과입니다. 시간 순서입니다. 각 항목의 구성은 서비스에 따라 다르며, 값이 없으면 빈 배열입니다. 항목 수와 순서를 함께 확인하세요.

- `data.segments[].id` (integer): 구간 번호(0부터)입니다. 대상의 고유 식별자입니다. 같은 대상을 다시 조회해도 같은 값이 옵니다.

- `data.segments[].start` (number): 구간 시작 시각(초)입니다. 숫자로 오며, 단위·범위는 같은 응답의 다른 필드나 이 문서의 설명을 확인하세요.

- `data.segments[].end` (number): 구간 끝 시각(초)입니다. 숫자로 오며, 단위·범위는 같은 응답의 다른 필드나 이 문서의 설명을 확인하세요.

- `data.segments[].text` (string): 구간의 텍스트입니다. 문자열로 오며, 값이 없으면 빈 문자열이거나 필드가 생략됩니다. 같은 응답의 다른 필드와 함께 해석하세요.

- `data.segments[].suspect` (boolean): 비음성 문구로 의심되는 구간이면 true입니다. artifact_filter=flag일 때만 담깁니다. true = 비음성 문구(잡음·안내 멘트 등)로 추정되는 구간인 경우, false = 실제 발화로 판단된 경우입니다. flag 옵션을 켰을 때만 이 필드가 포함됩니다.

- `data.language` (string): 변환에 사용한 언어 코드입니다. 콘텐츠의 언어 코드입니다. 예: ko, en. 자동 감지 값이므로 실제 언어와 다를 수 있습니다.

- `data.duration` (number): 요청한 영상 길이(초)입니다. 제품·등급별 허용 범위가 다르며, 접수 후에는 변경할 수 없습니다.

- `data.success` (integer): 업무 처리 결과 코드입니다. 1은 정상 결과, 0은 실패 또는 무료 응답입니다. 서비스에 따라 2·3처럼 추가 코드를 쓰므로 같은 응답의 status·msg·error 필드도 함께 확인하세요.

- `data.artifact_filter` (object): 비음성 문구 처리 결과입니다. artifact_filter를 보냈을 때만 담깁니다.

- `data.artifact_filter.mode` (string): 요청한 값 flag 또는 remove입니다. 선택한 처리 모드입니다. 문자열로 오며, 값이 없으면 빈 문자열이거나 필드가 생략됩니다. 같은 응답의 다른 필드와 함께 해석하세요. 가능한 값은 2가지입니다. flag = 문제 구간을 삭제하지 않고 suspect 같은 표시만 남기는 값입니다. 원문을 보존해야 할 때 사용합니다. remove = 문제 구간을 제거하고 본문을 다시 구성하는 값입니다. 결과 텍스트가 원문과 달라질 수 있습니다.

- `data.artifact_filter.applied` (boolean): 처리가 적용됐는지 여부입니다. false면 원래 결과 그대로입니다. true/false로 오며, 값이 없으면 필드가 생략되거나 null일 수 있습니다. true = 요청한 후처리(잡음 제거 등)가 실제로 적용된 경우, false = 조건을 만족하지 못해 원래 결과를 그대로 돌려준 경우입니다.

- `data.artifact_filter.suspect_count` (integer): 표시한 구간 수입니다(flag). 숫자로 오며, 단위·범위는 같은 응답의 다른 필드나 이 문서의 설명을 확인하세요.

- `data.artifact_filter.removed` (integer): 뺀 구간 수입니다(remove). 남은 구간의 id는 바뀌지 않으므로 번호가 건너뛸 수 있습니다.

- `api` (object): API 호출 메타데이터입니다. 이번 요청의 서버 처리 성공 여부(api.success), 실제 차감 포인트(api.cost), 결제 기록 ID(api.pl_id)를 담습니다. 처리 시간(api.ms)은 응답에 포함된 경우에만 제공됩니다. 업무 결과는 data에서 확인합니다.

- `api.success` (boolean): API 서버가 이번 요청을 정상 처리했는지 여부입니다. true여도 업무 결과가 실패일 수 있으므로 data.success·data.status와 함께 판단합니다. 인증 실패·잘못된 입력·서버 오류 응답에서는 false입니다.

- `api.cost` (integer): 이번 호출에서 실제로 차감된 포인트입니다. 유료 성공 응답에서만 단가만큼 차감되며, 실패·무료 조회·같은 요청의 멱등 재전송은 0입니다. 화면의 표시 단가와 실제 차감액이 다를 수 있으므로 정산은 이 값을 기준으로 합니다.

- `api.ms` (integer): 서버가 요청을 받아 응답 본문을 만들기까지 걸린 처리 시간(밀리초)입니다. 네트워크 왕복 시간과 클라이언트 대기 시간은 포함되지 않습니다.

- `api.pl_id` (integer): 포인트 차감 기록 ID입니다. 차감이 발생한 호출에만 값이 있으며, 과금 내역을 문의할 때 이 번호를 사용합니다. 무과금 응답은 -1·null이거나 필드가 생략됩니다.

## API 요청: POST /rest/stt



### 입력

- `audio` (file, 필수): 분석·변환할 오디오 파일입니다. 지원 형식과 최대 길이를 확인하세요.

- `language` (string, 선택): 음성에서 추출할 언어 코드입니다. 예: ko(한국어), en(영어), ja(일본어). 생략하면 ko로 인식하며, 실제 발화 언어와 다르면 정확도가 떨어집니다.

- `artifact_filter` (string, 선택): 무음·잡음 구간에서 생긴 비음성 문구 처리: flag=구간에 suspect 표시, remove=제거 후 text 재구성. 생략 시 기존과 동일 가능한 값은 2가지입니다. flag = 문제 구간을 삭제하지 않고 suspect 같은 표시만 남기는 값입니다. 원문을 보존해야 할 때 사용합니다. remove = 문제 구간을 제거하고 본문을 다시 구성하는 값입니다. 결과 텍스트가 원문과 달라질 수 있습니다. 허용값: flag, remove



### 응답 명세

```json

{
  "type": "object",
  "properties": {
    "data": {
      "type": "object",
      "properties": {
        "text": {
          "type": "string",
          "description": "전체 텍스트입니다. 앞에 공백이 붙어 올 수 있으니 필요하면 trim 하세요."
        },
        "segments": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "integer",
                "description": "구간 번호(0부터)입니다."
              },
              "start": {
                "type": "number",
                "description": "구간 시작 시각(초)입니다."
              },
              "end": {
                "type": "number",
                "description": "구간 끝 시각(초)입니다."
              },
              "text": {
                "type": "string",
                "description": "구간의 텍스트입니다."
              },
              "suspect": {
                "type": "boolean",
                "description": "비음성 문구로 의심되는 구간이면 true입니다. artifact_filter=flag일 때만 담깁니다."
              }
            }
          },
          "description": "말한 구간별 결과입니다. 시간 순서입니다."
        },
        "language": {
          "type": "string",
          "description": "변환에 사용한 언어 코드입니다."
        },
        "duration": {
          "type": "number",
          "description": "파일 재생시간(초)입니다. 요금 계산 기준입니다."
        },
        "success": {
          "type": "integer",
          "description": "처리 결과입니다. 1: 성공(과금), 0: 실패, 3: 시간 초과(과금 없음)."
        },
        "artifact_filter": {
          "type": "object",
          "description": "비음성 문구 처리 결과입니다. artifact_filter를 보냈을 때만 담깁니다.",
          "properties": {
            "mode": {
              "type": "string",
              "description": "요청한 값 flag 또는 remove입니다."
            },
            "applied": {
              "type": "boolean",
              "description": "처리가 적용됐는지 여부입니다. false면 원래 결과 그대로입니다."
            },
            "suspect_count": {
              "type": "integer",
              "description": "표시한 구간 수입니다(flag)."
            },
            "removed": {
              "type": "integer",
              "description": "뺀 구간 수입니다(remove). 남은 구간의 id는 바뀌지 않으므로 번호가 건너뛸 수 있습니다."
            }
          }
        }
      },
      "description": "변환 결과"
    },
    "api": {
      "type": "object",
      "properties": {
        "success": {
          "type": "boolean",
          "description": "요청을 정상 처리했는지 여부입니다."
        },
        "cost": {
          "type": "integer",
          "description": "이번 요청에서 차감된 포인트입니다."
        },
        "ms": {
          "type": "integer",
          "description": "처리 시간(밀리초)입니다."
        },
        "pl_id": {
          "type": "integer",
          "description": "결제 기록 번호입니다. 문의할 때 함께 알려 주세요."
        }
      },
      "description": "호출 공통 정보"
    }
  }
}

```

### 정적 응답 예시

```json

{
  "data": {
    "text": " 절기상 대설인 오늘은 일교차를 유의하셔야겠습니다. 현재 서울 기온 1.3도로 어제 같은 시간보다 다소 공기가 차가워졌는데요. 날씨였습니다.",
    "segments": [
      {
        "id": 0,
        "start": 0,
        "end": 2.5,
        "text": " 절기상 대설인 오늘은 일교차를 유의하셔야겠습니다."
      },
      {
        "id": 1,
        "start": 3.74,
        "end": 7.24,
        "text": " 현재 서울 기온 1.3도로 어제 같은 시간보다 다소 공기가 차가워졌는데요."
      },
      {
        "id": 2,
        "start": 58.48,
        "end": 59.96,
        "text": " 날씨였습니다."
      }
    ],
    "language": "ko",
    "duration": 71.088,
    "success": 1
  },
  "api": {
    "success": true,
    "cost": 150,
    "ms": 7929,
    "pl_id": 1595684
  }
}

```

### curl

```curl

curl --fail-with-body --request POST 'https://apick.app/rest/stt' \
  --header "Authorization: Bearer $APICK_API_KEY" \
  --form 'audio=@./meeting.mp3' \
  --form-string 'language=ko'

```

### Node.js (서버 ESM)

```javascript

import { readFile } from "node:fs/promises";
const form = new FormData();
form.append("audio", new Blob([await readFile("./meeting.mp3")]), "meeting.mp3");
form.append("language", "ko");
const response = await fetch("https://apick.app/rest/stt", {
  method: "POST",
  headers: { Authorization: "Bearer " + process.env.APICK_API_KEY },
  body: form,
  signal: AbortSignal.timeout(120_000),
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
const result = await response.json();
console.log(result);

```

### python

```python

import os
import requests
parts = [
    ("audio", ("meeting.mp3", open("./meeting.mp3", "rb"))),
    ("language", (None, "ko")),
]
response = requests.request("POST", "https://apick.app/rest/stt",
    headers={"Authorization": "Bearer " + os.environ["APICK_API_KEY"]},
    files=parts,
    timeout=(10, 120))
response.raise_for_status()
result = response.json()
print(result)

```

### php

```php

<?php
$headers = ["Authorization: Bearer " . getenv("APICK_API_KEY")];
$form = [
    'audio' => new CURLFile('./meeting.mp3'),
    'language' => 'ko',
];
$curl = curl_init('https://apick.app/rest/stt');
curl_setopt_array($curl, [
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_HTTPHEADER => $headers,
    CURLOPT_POSTFIELDS => $form,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CONNECTTIMEOUT => 10, CURLOPT_TIMEOUT => 120,
]);
$body = curl_exec($curl);
if ($body === false) { throw new RuntimeException(curl_error($curl)); }
$status = curl_getinfo($curl, CURLINFO_HTTP_CODE);
curl_close($curl);
if ($status >= 400) { throw new RuntimeException($body); }
$result = json_decode($body, true, 512, JSON_THROW_ON_ERROR);
print_r($result);

```

## 사용 예시 1. 한국어 회의 녹음을 텍스트로

가장 기본적인 요청입니다. 언어를 생략하면 한국어로 처리합니다.

```bash

curl --fail-with-body --request POST 'https://apick.app/rest/stt' \
  --header "Authorization: Bearer $APICK_API_KEY" \
  --form 'audio=@./meeting.mp3' \
  --form-string 'language=ko'

```

- `data.text`가 전체 텍스트입니다. 앞 공백은 `trim` 해서 저장하세요.

- `data.duration`(초)이 요금 계산 기준입니다. 30초 단위로 올림됩니다.

## 사용 예시 2. 영어 강의를 자막용 구간으로

영어 음성을 자막으로 만들 때 언어를 `en`으로 지정합니다.

```bash

curl --fail-with-body --request POST 'https://apick.app/rest/stt' \
  --header "Authorization: Bearer $APICK_API_KEY" \
  --form 'audio=@./lecture_en.wav' \
  --form-string 'language=en'

```

- `data.segments[]`의 `start`·`end`(초)와 `text`로 자막 한 줄씩을 만듭니다.

- 구간은 시간 순서로 오므로 `id` 순서대로 이어 붙이면 됩니다.

## 사용 예시 3. 무음 구간의 엉뚱한 문구 표시하기

음악·잡음이 긴 녹음에서 실제로 말하지 않은 문구를 사람이 검토하도록 표시만 하고 싶을 때 씁니다.

```bash

curl --fail-with-body --request POST 'https://apick.app/rest/stt' \
  --header "Authorization: Bearer $APICK_API_KEY" \
  --form-string 'language=ko' \
  --form 'audio=@./podcast.mp3' \
  --form-string 'artifact_filter=flag'

```

- `data.segments[].suspect`가 true인 구간을 검토 대상으로 보여 주세요.

- `data.artifact_filter.applied`가 false이면 처리 없이 원래 결과입니다.

## 사용 예시 4. 자막용 깨끗한 텍스트 받기

요약·자막에 바로 쓸 텍스트가 필요할 때 비음성 문구를 결과에서 뺍니다.

```bash

curl --fail-with-body --request POST 'https://apick.app/rest/stt' \
  --header "Authorization: Bearer $APICK_API_KEY" \
  --form-string 'language=ko' \
  --form 'audio=@./vlog.mp3' \
  --form-string 'artifact_filter=remove'

```

- `data.artifact_filter.removed`가 뺀 구간 수입니다. 남은 구간의 `id`는 바뀌지 않아 번호가 건너뛸 수 있습니다.

- `data.text`는 남은 구간으로 다시 구성된 텍스트입니다.

## 코드·오류

### 업무 실패 응답

입력 오류·대상 없음·일시 실패는 data.error(사유)와 data.success=0으로 오며 api.cost는 0(과금 없음)입니다. HTTP 상태는 400·404·408·424 중 하나입니다. 입력 오류는 값을 고쳐 다시 요청하고, 408·424는 잠시 후 한 번 다시 시도하세요.

```json

{
  "data": {
    "error": "입력값을 확인해 주세요.",
    "success": 0
  },
  "api": {
    "success": true,
    "cost": 0,
    "ms": 5
  }
}

```

## 상세 기능·요금

업로드 용량 제한: 1GB multipart/form-data 요청에 포함된 첨부파일 합계는 최대 1GB입니다. 처리시간은 재생시간, 페이지 수와 파일 형식에 따라 늘어날 수 있습니다. 제한을 초과하면 HTTP 413과 REQUEST_TOO_LARGE 오류가 반환되며 과금되지 않습니다. 이용 전 확인 회의·통화 녹음 기록, 강의 자막 초안, 음성 메모 검색처럼 말소리를 글로 남길 때 사용합니다. segments의 시작·끝 시각으로 자막 파일(SRT 등)을 바로 만들 수 있습니다. 항목조건 파일 형식mp3, wmv, wav. 동영상은 동영상 MP3 추출로 소리를 먼저 꺼내세요. 재생시간최대 2시간 지원 언어ko 한국어, en 영어, zh 중국어, de 독일어, es 스페인어, fr 프랑스어, ja 일본어 처리 시간재생시간에 비례해 늘어납니다. 긴 파일은 응답 대기 시간을 넉넉히(재생시간의 절반 이상) 잡으세요. 요금은 재생시간 30초당 50P이며 30초 미만은 올림합니다(71초 파일 = 3구간). 실패·시간 초과 응답은 과금되지 않습니다.

## 상세 요청

항목설정 메서드·주소POST https://apick.app/rest/stt 인증 헤더Authorization: Bearer 내 계정의 API 인증키 본문 형식multipart/form-data 요청 예시 form-data 전체 예제 보기 비음성 문구 처리 옵션 (artifact_filter) 무음·음악·잡음 구간에서 "시청해 주셔서 감사합니다", "구독과 좋아요 부탁드립니다", 같은 말의 반복, 효과음 표기처럼 실제로 말하지 않은 문구가 결과에 섞일 수 있습니다. 이런 구간을 찾아 표시하거나 뺄 때 이 옵션을 씁니다. 화자가 실제로 그 말을 한 구간은 유지됩니다. 추가 요금은 없습니다. 값언제 쓰나 flag원문을 그대로 보관하면서 사람이 검토할 구간만 표시하고 싶을 때. 의심 구간을 조금 넓게 표시합니다. remove자막·요약에 바로 쓸 깨끗한 텍스트가 필요할 때. 비음성으로 판단이 확실한 구간만 뺍니다. 처리가 적용되지 않으면 data.artifact_filter.applied가 false이며 원래 결과가 그대로 옵니다.

## 상세 응답

필드타입설명 dataobject변환 결과 textstring전체 텍스트입니다. 앞에 공백이 붙어 올 수 있으니 필요하면 trim 하세요. segmentsarray말한 구간별 결과입니다. 시간 순서입니다. {}object구간 하나 idinteger구간 번호(0부터)입니다. startnumber구간 시작 시각(초)입니다. endnumber구간 끝 시각(초)입니다. textstring구간의 텍스트입니다. suspectboolean비음성 문구로 의심되는 구간이면 true입니다. artifact_filter=flag일 때만 담깁니다. languagestring변환에 사용한 언어 코드입니다. durationnumber파일 재생시간(초)입니다. 요금 계산 기준입니다. artifact_filterobject비음성 문구 처리 결과입니다. artifact_filter를 보냈을 때만 담깁니다. modestring요청한 값 flag 또는 remove입니다. appliedboolean처리가 적용됐는지 여부입니다. false면 원래 결과 그대로입니다. suspect_countinteger표시한 구간 수입니다(flag). removedinteger뺀 구간 수입니다(remove). 남은 구간의 id는 바뀌지 않으므로 번호가 건너뛸 수 있습니다. successinteger처리 결과입니다. 1: 성공(과금), 0: 실패, 3: 시간 초과(과금 없음). apiobject호출 공통 정보 successboolean요청을 정상 처리했는지 여부입니다. costinteger이번 요청에서 차감된 포인트입니다. msinteger처리 시간(밀리초)입니다. pl_idinteger결제 기록 번호입니다. 문의할 때 함께 알려 주세요. 응답 예시 { "data": { "text": " 절기상 대설인 오늘은 일교차를 유의하셔야겠습니다. 현재 서울 기온 1.3도로 어제 같은 시간보다 다소 공기가 차가워졌는데요. 날씨였습니다.", "segments": [ { "id": 0, "start": 0, "end": 2.5, "text": " 절기상 대설인 오늘은 일교차를 유의하셔야겠습니다." }, { "id": 1, "start": 3.74, "end": 7.24, "text": " 현재 서울 기온 1.3도로 어제 같은 시간보다 다소 공기가 차가워졌는데요." }, { "id": 2, "start": 58.48, "end": 59.96, "text": " 날씨였습니다." } ], "language": "ko", "duration": 71.088, "success": 1 }, "api": { "success": true, "cost": 150, "ms": 7929, "pl_id": 1595684 } }

## 상세 코드·정책

오류와 대처 실패하면 data.error에 문구가 담기고 api.cost는 0입니다. HTTPdata.error대처 400파일 유형이 맞지 않습니다. mp3, wmv, wav 형식의 파일만 허용됩니다.파일을 mp3 또는 wav로 변환해 다시 요청하세요. 424첨부파일이 없습니다.파일 필드 이름을 audio로 보냈는지 확인하세요. 424artifact_filter 값이 올바르지 않습니다. flag 또는 remove 만 허용됩니다.artifact_filter를 빼거나 flag·remove 중 하나로 보내세요. 424재생시간이 2시간을 초과합니다. 2시간 이내의 오디오 파일만 허용됩니다.파일을 2시간 이하로 나눠 요청하고 결과를 이어 붙이세요. 408처리 시간 초과로 실패했습니다.data.success가 3입니다. 파일을 짧게 나눠 다시 요청하세요.

## 상세 예제

호출 예시 같은 요청을 JavaScript와 Python으로 옮긴 예시입니다. 키는 환경변수 APICK_API_KEY 에서 읽습니다. JavaScript 예시 form-data 전체 예제 보기 Python 예시 form-data 전체 예제 보기
