# 미디어 및 보이스 명령

> CLI의 voice, media, audio, edit 명령으로 트랙의 목소리를 바꾸고, 자막을 입히고, 오버레이를 만들고, 오디오를 처리하고, 편집을 계획하고, 팟캐스트 에피소드를 다듬습니다.

Source: https://nodaro.ai/ko/docs/developers/cli/media-commands

Nodaro CLI의 **미디어 및 보이스 명령**은 오디오, 동영상, 이미지를 직접 다룹니다. `voice` 그룹은 트랙의 목소리를 바꾸고 보이스를 디자인합니다. `media`는 미디어를 가져오고, 자르고, 자막을 넣고, 합성합니다. `audio`는 소리를 처리하고 텍스트로 변환합니다. `edit`는 팟캐스트와 긴 동영상의 편집을 계획하고 적용합니다. 각 명령은 에디터에서 대응하는 노드와 같은 엔진으로 실행됩니다.

작업을 시작하는 모든 명령은 결과를 기다리는 `--watch`, 폴링 간격을 설정하는 `--poll-interval <ms>`, 그리고 `--json`을 받습니다. [출력과 종료 코드](https://nodaro.ai/docs/developers/cli/output)를 참고하세요.

## 보이스
```bash
nodaro voice list [--clones] [--json]
nodaro voice changer --voice <id> --audio <url>|--video <url> [--model <id>] [--stability <0..1>] [--similarity <0..1>] [--style <0..1>] [--use-speaker-boost] [--seed <n>] [--remove-background-noise] [--watch] [--poll-interval <ms>] [--json]
nodaro voice recast --audio <url>|--video <url> --voices <v1,v2,...>|--voices-json <json> [--model <id>] [--output video|stems] [--analysis-json <json>|--analysis-file <path>] [--no-preserve-background] [--separation-quality fast|best] [--music-volume-mode match|normalize|manual] [--music-volume <0-200>] [--remove-background-noise] [--voice-fx <preset>] [--voice-fx-mix <0-100>] [--voice-fx-delay <20-2000>] [--voice-fx-decay <0-1>] [--watch] [--poll-interval <ms>] [--json]
nodaro voice analyze --audio <url>|--video <url> [--separation-quality fast|best] [--suggest-title] [--watch] [--poll-interval <ms>] [--json]
nodaro voice export --source <videoUrl> --tracks-json <json>|--tracks-file <path> [--voice-fx <preset>] [--voice-fx-mix <0-100>] [--voice-fx-delay <20-2000>] [--voice-fx-decay <0-1>] [--watch] [--poll-interval <ms>] [--json]
nodaro voice design --text <line> --description <desc> [--model <id>] [--loudness <-1..1>] [--guidance-scale <0-100>] [--seed <n>] [--quality <n>] [--enhance] [--user-prompt <text>] [--watch] [--poll-interval <ms>] [--json]
nodaro voice remix --text <text> --description <desc> [--user-prompt <text>] [--watch] [--poll-interval <ms>] [--json]
nodaro voice dub --audio <url> --target-language <code> [--source-language <code>] [--num-speakers <1-20>] [--disable-voice-cloning] [--drop-background-audio] [--watch] [--poll-interval <ms>] [--json]
nodaro voice clones list [--json]
nodaro voice clones delete <id> [--json]
```

| 명령 | 기능 |
| --- | --- |
| `voice list` | 기본 제공 보이스 목록을 보여 줍니다. `--clones`를 지정하면 내 클론을 보여 줍니다. 그 이름이나 ID를 `--voice`와 `--voices`에 사용하세요. |
| `voice changer` | [**보이스 체인저**](https://nodaro.ai/docs/nodes/audio/voice-changer) 노드처럼, 오디오 트랙 하나 또는 말하는 동영상 하나의 목소리를 하나의 보이스로 바꿉니다. `voice change`도 같은 명령입니다. |
| `voice recast` | [**보이스 체인저 Pro**](https://nodaro.ai/docs/nodes/audio/voice-changer-pro) 노드처럼, 녹음에 나오는 모든 화자의 목소리를 한 번에 바꿉니다. `voice pro`도 같은 명령입니다. |
| `voice analyze` | 목소리를 바꾸지 않고 화자를 감지하며, `--watch`를 지정하면 목록을 출력합니다. Nodaro Cloud 전용입니다. |
| `voice export` | 믹스한 트랙 세트로 최종 동영상을 렌더링합니다. Nodaro Cloud 전용입니다. |
| `voice design` | [**보이스 디자인**](https://nodaro.ai/docs/nodes/audio/voice-design) 노드처럼, 텍스트 설명으로 새로운 합성 보이스를 디자인합니다. |
| `voice remix` | [**보이스 리믹스**](https://nodaro.ai/docs/nodes/audio/voice-remix) 노드처럼, 클로닝 없이 설명한 보이스로 텍스트를 읽습니다. |
| `voice dub` | [**더빙**](https://nodaro.ai/docs/nodes/audio/dubbing) 노드처럼, 녹음을 다른 언어로 더빙하면서 각 화자의 목소리를 유지합니다. |
| `voice clones` | 클로닝 기능이 중단되기 전에 만든 보이스 클론의 목록을 보고 삭제합니다. |

### 여러 화자의 목소리 바꾸기
`voice recast`는 Nodaro Cloud에서 실행됩니다. 셀프 호스팅 설치에서는 [Nodaro Cloud 연결](https://nodaro.ai/docs/self-hosting/cloud-connect)을 통해 실행됩니다.

- `--voices`는 Nodaro가 화자를 감지한 순서대로 보이스를 화자에 연결합니다. `keep`이라는 단어는 그 화자의 원래 목소리를 유지합니다. 예: `--voices Rachel,keep,Aria`.
- `--voices-json`은 대신 SDK의 원시 배열을 받습니다. 보이스 ID, 보이스별 설정 객체, 또는 원래 목소리를 유지할 화자에는 `null`을 넣습니다.
- `--output stems`는 완성된 동영상 대신, 대화형 믹스를 위해 화자마다 효과가 없는 트랙을 하나씩 반환합니다. 믹스는 `voice export`로 렌더링하세요.
- `--analysis-file`은 저장해 둔 `voice analyze` 결과를 다시 사용하므로, 화자를 다시 감지하지 않습니다.

### 대화형 목소리 바꾸기 흐름
한 단계로 끝나는 `voice recast`는 한 번의 호출로 완성된 동영상을 렌더링합니다. 세 단계 흐름에서는 렌더링하기 전에 먼저 화자를 확인하고 결과를 믹스할 수 있습니다.

```bash
# 1. Detect the speakers. Save the job's output_data for step 2.
nodaro voice analyze --video https://example.com/panel.mp4 --watch --json > analyze.json
jq .output_data analyze.json > analysis.json

# 2. Recast to dry stems, reusing the analysis (no second detection)
nodaro voice recast --video https://example.com/panel.mp4 --voices Rachel,keep,Aria \
  --analysis-file analysis.json --output stems --watch

# 3. Set the level and mute of each track, then render
nodaro voice export --source https://example.com/panel.mp4 --tracks-file mix.json \
  --voice-fx hall --voice-fx-mix 25 --watch
```

3단계에서 `mix.json`의 각 트랙은 2단계의 스템에서 가져온 객체로, `url`, 0~200의 `gain`, `muted` 플래그, 그리고 선택 항목인 `kind`를 가집니다. 내보내기는 동영상 스트림을 그대로 복사하며, 다시 인코딩하지 않습니다.

## 미디어
```bash
nodaro media download <url> [--max-height <px>] [--section <a-b>] [--watch] [--json]
nodaro media metadata <url> [--json]
nodaro media trim-video --video <url> --start <sec> --end <sec>|--keep-first <sec>|--keep-last <sec> [--watch] [--poll-interval <ms>] [--json]
nodaro media trim-audio --video <url>|--audio <url> [--start <sec>] [--end <sec>] [--format mp3|wav|aac] [--watch] [--poll-interval <ms>] [--json]
nodaro media split-media --video <url>|--audio <url> --chunk-duration <sec> [--min-part-duration <sec>] [--format mp3|wav|aac] [--watch] [--poll-interval <ms>] [--json]
nodaro media add-captions <videoUrl> [options, see below]
nodaro media still-to-video --image <url> --audio <url> [--motion none|zoom-in|zoom-out|pan-left|pan-right|ken-burns] [--intensity <1-10>] [--resolution 720p|1080p|4K] [--aspect-ratio <W:H>] [--fps 24|30] [--fit cover|contain] [--pad-color <hex>] [--watch] [--poll-interval <ms>] [--json]
nodaro media slideshow --images <url...> [--audio <url>] [--durations "10,auto,auto"] [--per-image <sec>] [--transition <id>] [--transition-duration <sec>] [--motion none|zoom-in|zoom-out|ken-burns|alternate] [--intensity <1-10>] [--resolution 720p|1080p|4K] [--aspect-ratio <W:H>] [--fps 24|30] [--fit cover|contain] [--pad-color <hex>] [--watch] [--json]
nodaro media collage <imageUrls...> [--sizes <0-3,...>] [--numbered] [--label <text>...] [--badge-position top-left|top-right] [--layout smart|grid] [--resolution 2K|4K] [--aspect-ratio <W:H>] [--gap <px>] [--background-color <hex>] [--watch] [--poll-interval <ms>] [--json]
nodaro media overlay <imageUrl> [layerUrls...] [--layers-file <path>] [--anchor <anchor>] [--x <%>] [--y <%>] [--width <%>] [--opacity <0-1>] [--platform <id>...] [--qr-text <text>] [--mask-mode none|layers|around|outside] [--mask-spread <px>] [--canvas <WxH>] [--base-fit contain|cover] [--background-color <hex>] [--output-format png|jpg|webp] [--watch] [--poll-interval <ms>] [--json]
nodaro media overlay-placement <imageUrl> [--intent <text>] [--aspect <ratio>] [--safe-area <x,y,w,h>] [--json]
nodaro media video-overlay <videoUrl> [layerUrls...] [--at <start[-end]>...] [--preset card|corner-badge|full-frame] [--corner top-left|top-right|bottom-left|bottom-right] [--layers-file <path>] [--aspect 16:9|9:16|1:1|4:5] [--base-fit cover|contain] [--background-color <hex>] [--watch] [--poll-interval <ms>] [--json]
nodaro media video-mask <videoUrl> <prompt> [--threshold <n>] [--model sam-3.1|sam-3] [--watch] [--poll-interval <ms>] [--json]
nodaro media mask-composite <foregroundUrl> <backgroundUrl> <maskUrl> [--invert] [--feather <px>] [--grow <px>] [--background-fit cover|contain|stretch] [--audio foreground|background|mix|none] [--watch] [--poll-interval <ms>] [--json]
nodaro media save <url> [--filename <name>] [--type image|video|audio] [--watch] [--poll-interval <ms>] [--json]
```

| 명령 | 기능 |
| --- | --- |
| `media download` | YouTube, TikTok, Instagram, X, Facebook의 동영상을 내 저장소로 가져옵니다. `--section`은 초 단위로 지정한 시간 구간 하나만 가져옵니다. `--watch`는 진행 상황을 실시간으로 스트리밍하며, 나중에 폴링할 작업은 없습니다. |
| `media metadata` | 미디어 URL을 다운로드하지 않고 길이, 크기, 제목을 읽습니다. |
| `media trim-video` | 시작 시간과 종료 시간으로 동영상을 자르거나, 처음 또는 마지막 몇 초만 남깁니다. |
| `media trim-audio` | 동영상이나 오디오 파일의 오디오를 잘라 MP3, WAV, AAC로 저장합니다. |
| `media split-media` | 동영상, 오디오 파일 또는 둘 다를 최대 `--chunk-duration`초, 최소 `--min-part-duration`초인 구간으로 자릅니다. 기본 최솟값은 4초입니다. 구간은 작업의 `videoUrls`와 `audioUrls`에 담깁니다. [구간 분할](https://nodaro.ai/docs/nodes/video/split-into-chunks)을 참고하세요. |
| `media add-captions` | 동영상에 자막을 입힙니다. [자막](#captions)을 참고하세요. |
| `media still-to-video` | 정지 이미지 한 장과 오디오 파일 하나를 MP4로 만들며, 0크레딧이 듭니다. 동영상 길이는 오디오 길이와 같으므로 길이 옵션은 없습니다. `--motion`은 정지 이미지에 움직임을 줍니다. |
| `media slideshow` | 이미지 2~100장을 오디오와 함께 또는 오디오 없이 MP4 슬라이드쇼로 만들며, 0크레딧이 듭니다. |
| `media collage` | 이미지 2~30장을 하나의 큰 이미지로 합성합니다. |
| `media overlay` | AI 없이, 기본 이미지 위에 레이어를 최대 12개까지 픽셀 단위로 정확하게 배치합니다. |
| `media overlay-placement` | 레이어 하나를 어디에 두어야 할지 비전 모델에게 묻습니다. |
| `media video-overlay` | AI 없이, 동영상 위에 시간이 지정된 이미지 레이어를 1~20개 배치하며, 22크레딧이 듭니다. |
| `media video-mask` | 텍스트로 설명한 대상을 동영상 전체에서 추적해, 대상이 있는 곳은 흰색인 흑백 마스크 동영상을 반환합니다. 기본값은 SAM 3.1이며, `--model sam-3`은 절반 가격입니다. `--threshold`는 0.05~0.95이며 기본값은 0.5입니다. 값이 낮을수록 더 많이 찾습니다. [동영상 마스크](https://nodaro.ai/docs/nodes/video/video-mask)를 참고하세요. |
| `media mask-composite` | 마스크를 통해 전경을 배경 위에 배치하며, 흰색이 전경입니다. 결과의 시작된 5초마다 11크레딧이 듭니다. `--feather`는 0~20픽셀, `--grow`는 -10~10입니다. [마스크 합성](https://nodaro.ai/docs/nodes/video/mask-composite)을 참고하세요. |
| `media save` | 미디어 URL을 이미지, 동영상 또는 오디오 파일로 내 저장소에 저장합니다. |

### 슬라이드쇼
오디오가 있으면 오디오가 슬라이드쇼의 길이를 정합니다. `--durations`로 고정한 길이는 비율에 맞게 조정되며, CLI가 이를 알려 줍니다. 오디오가 없으면 슬라이드쇼는 소리 없이 이미지 수에 `--per-image`를 곱한 시간만큼 재생됩니다.

### 콜라주
- `--sizes`는 이미지 순서대로 각 이미지에 상대적인 크기 힌트를 줍니다. `0`은 자동, `1`은 크게(너비 약 2배), `2`는 중간, `3`은 작게(너비 약 절반)입니다. 크기 힌트는 스마트 레이아웃에서만 작동합니다.
- `--numbered`는 스토리보드용으로, 각 이미지의 한쪽 모서리에 1부터 시작하는 순번을 찍습니다.
- `--badge-position`은 그 모서리를 정합니다. 기본값인 `top-left` 또는 `top-right`입니다. 라벨의 위치도 이것으로 정해집니다.
- `--label`은 번호 뒤에 캡션을 추가합니다. 이미지마다 한 번씩 순서대로 반복하세요. 빈 `""`는 이미지 하나를 건너뜁니다.

### 이미지 오버레이
- 기본 이미지 뒤에 오는 이미지 URL은 이미지 레이어입니다. 이 레이어들은 `--anchor`, `--x`, `--y`, `--width`, `--opacity`를 공유하므로 워터마크에 적합합니다.
- `--layers-file`은 대신 레이어 전체의 JSON 배열을 받습니다. 레이어별 옵션과 텍스트, QR 코드, 도형 종류를 지정할 수 있습니다.
- 배치는 기본 이미지에 대한 퍼센트로 지정하므로, 하나의 명령이 1K 미리보기와 4K 렌더링에 모두 맞습니다.
- 반복해서 지정할 수 있는 `--platform`은 합성 이미지를 해당 플랫폼의 크기로도 렌더링합니다. 기본 렌더링에는 11크레딧이 들고, 플랫폼마다 가격이 추가됩니다. 작업 출력에는 추가 렌더링이 `variants`로 나열됩니다.
- `overlay-placement`는 같은 퍼센트 단위로 앵커, `x`, `y`, `width`, 그리고 한 줄짜리 이유를 답합니다. 폴링할 작업 없이 바로 답하며, 이미지-텍스트 변환 호출 1회의 비용이 듭니다.

### 동영상 오버레이
- 이미지 URL마다 `--at`을 하나씩 순서대로 지정하세요. `3`은 3초부터 끝까지, `1.2-2.6`은 1.2초부터 2.6초까지를 뜻합니다.
- `--preset`과 `--corner`는 URL로 지정한 모든 이미지 레이어에 적용됩니다.
- `--layers-file`은 대신 레이어 배열 전체를 받으며, 레이어마다 박스, 불투명도, 애니메이션, 쌓는 순서를 지정합니다.
- `--base-fit`과 `--background-color`에는 `--aspect`가 필요합니다.
- 기본 동영상의 오디오는 그대로 유지됩니다.

레이어 옵션은 [**동영상 오버레이**](https://nodaro.ai/docs/nodes/video/video-overlay) 노드를 참고하세요.

## 자막
```bash
nodaro media add-captions <videoUrl> [--text <text>] [--captions-file <file.json>] [--style subtitle|word-highlight|karaoke|tiktok-words|word-pop|bouncy] [--look outline|clean] [--position bottom|top|center] [--position-y <pct>] [--font-size <px>] [--font-family <name>] [--font-weight <100-900>] [--color <c>] [--background-color <c>] [--stroke-color <c>] [--stroke-width <px>] [--highlight-color <c>] [--uppercase|--no-uppercase] [--max-words-per-line <1-20>] [--animate|--no-animate] [--no-auto-transcribe] [--transcribe-provider elevenlabs-stt|incredibly-fast-whisper|whisper] [--segments-file <file.json>] [--watch] [--poll-interval <ms>] [--json]
```

`media add-captions`에는 [**자막 추가**](https://nodaro.ai/docs/nodes/video/add-captions) 노드처럼 두 종류의 스타일이 있습니다.

| 스타일 | 표시 방식 |
| --- | --- |
| `subtitle` | 단어 애니메이션이 없는 정적 자막입니다. |
| `word-highlight`, `karaoke`, `tiktok-words`, `word-pop`, `bouncy` | 단어 단위로 움직이는 키네틱 자막입니다. `word-highlight`, `karaoke`, `bouncy`는 한 번에 한 줄을 유지해 보여 줍니다. |

### 자막 텍스트
- `subtitle`에서는 `--text`가 동영상 전체에 하나의 정적 블록으로 입혀집니다. 음성 텍스트 변환 결과로 대체되는 일은 없습니다. 음성에 자막을 넣으려면 `--text`를 생략하세요.
- 키네틱 스타일에서는 `--text`가 음성 텍스트 변환 결과가 비어 있을 때나 `--no-auto-transcribe`를 지정했을 때만 대신 쓰입니다.
- `--captions-file`은 단어별 시간이 지정된 항목의 JSON 배열 `[{ text, startMs, endMs }]`이며, 키네틱 스타일에서는 단어마다 항목이 하나입니다. `nodaro audio transcribe` 결과의 `words`를 그대로 넣을 수 있습니다. 이 파일은 `--no-auto-transcribe`와 함께 사용하세요.
- `--segments-file`은 시간 구간마다 스타일, 룩, 위치를 따로 지정합니다. 구간은 서로 겹치면 안 됩니다.

### 스타일 지정
- 다음 스타일 옵션은 `subtitle`에도 적용됩니다: `--look`, `--font-family`, `--font-weight`, `--stroke-color`, `--stroke-width`, `--uppercase`, `--position-y`, `--max-words-per-line`. 스타일을 지정한 `subtitle`은 키네틱 가격으로 청구되고, 기본 `subtitle`은 더 낮은 가격 그대로입니다.
- `--highlight-color`와 `--animate`는 키네틱 스타일에서만 작동합니다. `subtitle`에서는 거부됩니다.
- `--animate`는 기본으로 켜져 있습니다. `--no-animate`는 각 단어의 움직임을 멈추고, 단어 묶음과 하이라이트 색상은 유지합니다.
- `--look`을 지정하지 않으면 키네틱 스타일은 `outline`으로, `subtitle`은 `clean`으로 렌더링됩니다.
- `--max-words-per-line`은 자막 한 줄, 또는 `tiktok-words`의 한 페이지에 들어가는 단어 수를 1~20개로 제한합니다. 프레임 너비, 문장 끝, 0.5초 이상의 멈춤에서도 줄이 바뀝니다. 한두 단어로 하면 빠르고 강렬하게 읽히며, 지정하지 않으면 너비를 채웁니다. `--text` 자막에서는 줄바꿈만 정하며, `word-pop`에는 영향이 없습니다.
- 키네틱 렌더링이나 스타일을 지정한 렌더링은 원본의 프레임 레이트를 15~60fps 사이의 정수로 유지합니다. 가변 프레임 레이트이거나 매우 긴 원본은 30fps로 렌더링됩니다.

### 음성 텍스트 변환 엔진
`--transcribe-provider`는 음성을 텍스트로 변환할 엔진을 선택합니다. 키네틱 스타일에는 단어 타이밍이 필요하며, 기본값인 `incredibly-fast-whisper` 또는 `elevenlabs-stt`가 이를 제공합니다. `subtitle`에는 구 단위 타이밍만 있으면 되므로 `whisper`도 사용할 수 있습니다.

## 오디오
```bash
nodaro audio separate --audio <url> [--mode vocal_instrumental|stems] [--quality auto|fast|best] [--watch] [--poll-interval <ms>] [--json]
nodaro audio isolate --audio <url> [--watch] [--poll-interval <ms>] [--json]
nodaro audio fx --audio <url> [--preset <preset>] [--mix <0-100>] [--delay <20-2000>] [--decay <0-1>] [--eq-low <db>] [--eq-high <db>] [--watch] [--poll-interval <ms>] [--json]
nodaro audio mix --audio <url> --audio <url> ... [--volumes <csv>] [--duck-under <index>] [--duck-amount <0-100>] [--watch] [--poll-interval <ms>] [--json]
nodaro audio adjust-volume --audio <url>|--video <url> [--volume <0-200>] [--normalize] [--fade-in <sec>] [--fade-out <sec>] [--watch] [--poll-interval <ms>] [--json]
nodaro audio pitch-tempo --audio <url>|--video <url> [--semitones <-12..12>] [--tempo <0.5-2>] [--no-preserve-formants] [--watch] [--poll-interval <ms>] [--json]
nodaro audio combine --segment <url[@a-b]> --segment ... [--watch] [--poll-interval <ms>] [--json]
nodaro audio transcribe --audio <url> [--provider elevenlabs-stt|incredibly-fast-whisper|whisper] [--language <code>] [--diarize] [--tag-audio-events] [--word-timestamps] [--watch] [--poll-interval <ms>] [--json]
```

| 명령 | 기능 | 노드 |
| --- | --- | --- |
| `audio separate` | 보컬과 반주를 분리하거나, 스템으로 나눕니다. | [**음원 분리**](https://nodaro.ai/docs/nodes/audio/audio-separation) |
| `audio isolate` | 목소리만 남기고 나머지를 제거합니다. | [**음성 추출**](https://nodaro.ai/docs/nodes/audio/voice-extractor) |
| `audio fx` | 믹스, 딜레이, 디케이, 이퀄라이저 설정과 함께 효과 프리셋을 적용합니다. | [**오디오 효과**](https://nodaro.ai/docs/nodes/audio/audio-fx) |
| `audio mix` | 트랙마다 볼륨을 하나씩 지정해 여러 트랙을 믹스합니다. `--duck-under`를 쓰면 0부터 시작하는 인덱스로 지정한 트랙 아래로 다른 트랙의 볼륨이 낮아집니다. `--duck-amount`는 낮추는 정도이며 기본값은 75입니다. | [**오디오 믹스**](https://nodaro.ai/docs/nodes/audio/mix-audio) |
| `audio adjust-volume` | 볼륨을 바꾸고, 노멀라이즈하고, 페이드 인 또는 페이드 아웃합니다. | [**볼륨 조절**](https://nodaro.ai/docs/nodes/audio/adjust-volume) |
| `audio pitch-tempo` | 피치를 반음 단위로 옮기거나, 피치를 바꾸지 않고 템포를 바꿉니다. `--no-preserve-formants`를 쓰면 피치와 함께 목소리의 성격도 바뀝니다. | [**피치 및 템포**](https://nodaro.ai/docs/nodes/audio/pitch-tempo) |
| `audio combine` | 세그먼트를 차례로 이어 붙입니다. `url@a-b`는 파일의 시간 구간 하나를 가져옵니다. | [**오디오 합치기**](https://nodaro.ai/docs/nodes/audio/combine-audio) |
| `audio transcribe` | 음성을 텍스트로 변환합니다. | [**음성 텍스트 변환**](https://nodaro.ai/docs/nodes/audio/transcribe) |

이 명령들은 **보이스 체인저 Pro**가 조합하는 구성 요소를 각각 따로 사용할 수 있게 한 것입니다.

### 음성 텍스트 변환 엔진 목록
| 엔진 | 단어 타이밍 | 추가 지원 |
| --- | --- | --- |
| `elevenlabs-stt` | 항상 | `--diarize`(누가 언제 말하는지)와 `--tag-audio-events` |
| `incredibly-fast-whisper` | `--word-timestamps` 지정 시 | |
| `whisper` | 없음, 구 단위 세그먼트만 반환합니다. `--word-timestamps`는 크레딧이 쓰이기 전에 거부됩니다 | |

`--provider`를 생략하면 `whisper` 엔진이 실행됩니다. 단어 타이밍이 필요할 때는 반드시 엔진을 지정하세요.

완료된 작업의 `output_data`에는 `text`, `words`(단어마다 항목 하나, 밀리초 단위), `json`(정규화된 텍스트 변환 결과, 역시 밀리초 단위)이 들어 있습니다. 최상위의 `segments` 목록(초 단위)은 `whisper`와 `incredibly-fast-whisper`에만 있습니다. `elevenlabs-stt`는 이를 반환하지 않으므로 `words`를 읽으세요. 키네틱 렌더링에는 `words`를 `media add-captions --captions-file`에 전달하세요.

## 편집
편집 명령은 팟캐스트와 긴 동영상을 위한 편집 구성 요소입니다. `edit tighten-episode`는 팟캐스트 편집 전체를 명령 하나로 실행합니다.

```bash
nodaro edit silence-detect <audioUrl> [--threshold-db=-35] [--min-silence-ms <ms>] [--pad-ms <ms>] [--watch] [--poll-interval <ms>] [--json]
nodaro edit audio-sync (--source <[id=]url> ... | --sources-file <file.json>) [--reference <id>] [--watch] [--poll-interval <ms>] [--json]
nodaro edit apply-edl --edl <file.json> [--transcript <file.json>] [--source <url> ...] [--output video|audio] [--quality proxy|final] [--crossfade-ms <ms>] [--clip-key <inMs-outMs>] [--watch] [--poll-interval <ms>] [--json]
nodaro edit plan --mode tighten|clips|chapters|trailer --plan-tier economy|standard|premium --transcript <file.json> (--source <[id=]url[@audio|@video]> ... | --sources-file <file.json>) [--silence <file.json>] [--offsets <file.json>] [--transcript-source <id>] [--instructions <text>] [--style-guide <text>] [--count <n>] [--target-duration-sec <n>] [--target-aspect 16:9|9:16|1:1|4:5] [--platform <name>] [--watch] [--poll-interval <ms>] [--json]
nodaro edit switch-cameras --edl <file.json> --transcript <file.json> [--speaker-map <file.json>] [--speaker-names <file.json>] [--min-shot-ms <ms>] [--lead-ms <ms>] [--max-shot-ms <ms>] [--wide-every <n>] [--layout-hints] [--watch] [--poll-interval <ms>] [--json]
```

| 명령 | 기능 | 노드 |
| --- | --- | --- |
| `edit silence-detect` | 녹음에서 무음 구간을 찾습니다. | [**무음 감지**](https://nodaro.ai/docs/nodes/audio/silence-detect) |
| `edit audio-sync` | 같은 이벤트를 녹음한 오디오 또는 동영상 2~6개를 정렬합니다. | [**오디오 동기화**](https://nodaro.ai/docs/nodes/audio/audio-sync) |
| `edit plan` | 텍스트 변환 결과를 바탕으로 편집을 계획합니다. 속도를 조이거나, 클립을 자르거나, 챕터를 표시하거나, 트레일러를 만듭니다. | [**편집 계획**](https://nodaro.ai/docs/nodes/video/edit-plan) |
| `edit apply-edl` | 편집 결정 목록(EDL)을 동영상이나 오디오 파일로 렌더링합니다. | [**EDL 적용**](https://nodaro.ai/docs/nodes/video/apply-edl) |
| `edit switch-cameras` | 편집의 각 컷을 말하는 사람의 카메라로 바꿉니다. 텍스트 변환 결과에 화자 레이블이 있어야 합니다. | [**카메라 전환**](https://nodaro.ai/docs/nodes/video/camera-switch) |
| `edit tighten-episode` | 녹음 하나를 완성된 에피소드로 다듬습니다. 텍스트 변환, 계획, 렌더링을 실행하고, 설정에 따라 자막, 음악, 프레이밍을 더합니다. | [**에피소드 다듬기**](https://nodaro.ai/docs/nodes/video/tighten-episode) |
| `edit continue-use-case` | **에피소드 다듬기** 실행을 새 작업으로 이어 갑니다. | [**에피소드 다듬기**](https://nodaro.ai/docs/nodes/video/tighten-episode) |

`edit audio-sync`는 `id=url` 형식으로 ID를 지정하지 않으면 녹음에 `source-1`, `source-2` 같은 이름을 붙입니다. 그 `output_data.json`에는 필드 세 개가 있습니다.

- `reference`: 다른 녹음을 맞추는 기준이 되는 녹음입니다. `--reference`로 선택하세요.
- `offsets`: 녹음마다 항목 하나이며, `sourceId`, `offsetMs`, `confidence`, `driftMsPerHour`를 가집니다.
- `notes`: 정렬에 관한 메모입니다.

녹음 안의 시간은 `referenceMs = sourceMs + offsetMs`로 기준 녹음의 시간으로 변환됩니다.

`edit apply-edl --quality proxy`는 검토용 미리 보기를 렌더링합니다. 미리 보기는 비공개이며 더 낮은 미리 보기 요금으로 청구됩니다. `--quality final`은 납품용 최종본을 렌더링합니다. `--clip-key`는 클립 모드 계획에서 이 렌더링이 자르는 클립을 `<first inMs>-<last outMs>` 형식으로 지정합니다. 결과는 이 값을 `output_data.quality` 옆에 `output_data.clipKey`로 돌려줍니다.

멀티캠 녹음에서는 `edit plan --offsets`에 같은 소스 ID로 실행한 `edit audio-sync` 작업의 `output_data.json`을 넘깁니다. 계획은 시작하기 전에 각 소스의 오프셋을 적용합니다. 측정되지 않았거나 약하게 일치한 소스는 거부됩니다. 그럴 때는 `--sources-file`에서 그 소스의 `offsetMs`를 지정하세요. 멀티캠 편집은 다음 명령을 순서대로 실행합니다.

1. `audio transcribe --provider elevenlabs-stt --diarize`: 화자 레이블이 있는 텍스트 변환 결과를 만듭니다.
2. `edit audio-sync`: 오프셋을 측정합니다.
3. `edit plan --offsets`: 편집을 계획합니다.
4. `edit switch-cameras`: 각 컷을 화자의 카메라로 바꿉니다.
5. `edit apply-edl --quality proxy`로 검토한 다음, `edit apply-edl --quality final`로 납품용을 렌더링합니다.

### 에피소드 전체 다듬기
```bash
nodaro edit tighten-episode --media <url> [--music <url>] [--output video|audio] [--framing 16:9|9:16|1:1|4:5 [--layout auto|single|side-by-side|stacked|grid|pip]] [--no-captions] [--review] [--plan-tier economy|standard|premium] [--instructions <text>] [--watch] [--poll-interval <ms>] [--json]
nodaro edit continue-use-case <jobId> --mode from-failed|render-final [--edit <file.json>] [--idempotency-key <key>] [--watch] [--poll-interval <ms>] [--json]
```

`edit tighten-episode`는 최대 3시간 길이의 동영상 또는 오디오 녹음 하나를 받습니다. 녹음을 텍스트로 변환하고, 다듬은 컷을 계획해 렌더링하며, 설정에 따라 자막, 음악, 프레이밍을 더합니다. `--layout`은 `--framing`과 함께 쓸 때만 작동합니다. 실행 비용은 각 단계의 자체 요금에 실행당 고정 수수료를 더한 값입니다. `--review`는 사람이 확인할 수 있도록 미리보기에서 멈춥니다.

`edit continue-use-case`는 **에피소드 다듬기** 실행을 새 작업으로 이어 가며, 모드는 두 가지입니다.

- `from-failed`는 끝난 단계를 유지하고 나머지를 실행합니다. 실패한 실행의 수수료가 환불되었으므로 수수료가 다시 예약됩니다.
- `render-final`은 `--review` 미리보기 이후 미리보기의 설정으로 최고 품질의 에피소드를 렌더링하며, 수수료가 없습니다. `--edit`는 검토자가 수정한 계획을 EDL 파일로 받습니다.

다른 작업을 가리키는 거부는 그 코드와 작업을 출력합니다. `already_running`은 그 작업을 따라가라는 뜻입니다. `continuation_superseded`는 대신 그 작업을 이어 가라는 뜻입니다. `render_final_already_rendered`는 그 작업의 결과를 쓰라는 뜻입니다. `--json`을 쓰면 거부는 표준 출력에 `{ "error": { "code", "message" }, "jobId" }`로 쓰이고, 종료 코드는 1입니다.

```bash
nodaro edit tighten-episode --media https://cdn.example.com/episode-12.mp4 --framing 9:16 --review --watch
nodaro edit continue-use-case <jobId> --mode render-final --watch
```

## 자주 묻는 질문

### CLI에서 동영상 속 여러 화자의 목소리를 바꾸려면 어떻게 하나요?

--video와 --voices를 지정해 nodaro voice recast를 실행하세요. --voices에는 화자가 감지된 순서대로 화자마다 보이스를 하나씩 적습니다. 원래 목소리를 유지할 화자에는 --voices Rachel,keep,Aria처럼 keep을 적으세요.

### 단어 타이밍을 반환하는 음성 텍스트 변환 엔진은 무엇인가요?

elevenlabs-stt는 항상 단어 타이밍을 반환하고, incredibly-fast-whisper는 --word-timestamps를 지정하면 반환합니다. whisper는 구 단위 세그먼트만 반환합니다. --provider를 생략하면 whisper 엔진이 실행되므로, 단어가 필요할 때는 반드시 엔진을 지정하세요.

### still-to-video와 slideshow에 크레딧이 드나요?

아니요. nodaro media still-to-video와 nodaro media slideshow는 AI 모델 없이 동영상을 렌더링하므로 0크레딧입니다.

### 직접 수정한 단어로 동영상에 자막을 넣으려면 어떻게 하나요?

단어 단위 엔진으로 오디오를 텍스트로 변환하고, 저장된 JSON 파일에서 단어를 수정한 다음, 그 파일을 --captions-file 및 --no-auto-transcribe와 함께 nodaro media add-captions에 전달하세요.

### Nodaro Cloud가 필요한 미디어 명령은 무엇인가요?

voice analyze와 voice export는 Nodaro Cloud에서만 실행됩니다. voice recast는 Nodaro Cloud에서 실행되며, 셀프 호스팅 설치에서는 Nodaro Cloud 연결을 통해 실행됩니다.
