비디오 편집기은(는) 무엇을 하나요?
개요
세 가지 엔진으로 구동되는 AI 기반 비디오 워크플로우:
- ffmpeg -- 기존 영상 편집 (자르기, 압축, 병합, 크기 변경, 속도 조절, 안정화, 워터마크, 오디오, GIF, 썸네일, 전환 효과, 자막)
- Remotion -- 새 비디오 콘텐츠 생성 (타이틀 카드, 로우어 서드, 엔드 카드, 티저, 애니메이션 오버레이)
- Whisper -- 받아쓰기 및 자막 생성
추가 기능:
- Apple Silicon 하드웨어 가속 (
h264_videotoolbox / hevc_videotoolbox)
~/design-assets/color-palettes/ 디자인 에셋과의 테마 통합
- YouTube, Instagram, TikTok, Twitter 등 플랫폼 프리셋
- Remotion의 반복
npm install을 피하기 위한 워크스페이스 캐싱
사용 시기
사용자의 다음 의도 중 하나라도 감지되면 실행하세요:
| 카테고리 | 키워드 |
|---|
| 기본 편집 | 자르기, 트림, 클립, 줄이기, 분할 |
| 압축 | 압축, 크기 줄이기, 축소, 더 작게, 최적화 |
| 병합 | 병합, 결합, 연결, 이어붙이기, 스티치 |
| 크기 변경 | 크기 변경, 스케일, 자르기, 패딩, 화면비, 세로, 가로, 정사각형 |
| 속도 | 속도 올리기, 느리게, 슬로우 모션, 타임랩스, 빨리 감기, 역재생 |
| 안정화 | 안정화, 흔들림, 부드럽게, 떨림 제거 |
| 전환 효과 | 페이드, 크로스페이드, 디졸브, 와이프, 전환 |
| 자막 | 자막, 캡션, SRT, 받아쓰기, 음성을 텍스트로 |
| 타이틀 카드 | 타이틀 카드, 인트로, 오프닝, 애니메이션 텍스트 |
| 로우어 서드 | 로우어 서드, 이름표, 자막바, 이름 바 |
| 엔드 카드 | 엔드 카드, 아웃트로, 엔드 스크린, 클로징 |
| 티저 | 티저, 트레일러, 프로모, 하이라이트 릴, 몽타주 |
| 썸네일 | 썸네일, 포스터, 프레임 추출, 스크린샷 |
| GIF | GIF, 애니메이션 이미지, 루프, 밈 |
| 워터마크 | 워터마크, 로고 오버레이, 브랜딩 |
| 오디오 | 오디오, 볼륨, 노멀라이즈, 라우드니스, 음소거, 페이드 인, 페이드 아웃, 믹스, 오디오 추출 |
| 정보 | 정보, 세부 정보, 재생 시간, 해상도, 코덱, 비트레이트, 메타데이터 |
| 파이프라인 | 파이프라인, 배치, 워크플로우, 다단계 |
| 플랫폼 | YouTube, Instagram, TikTok, Twitter, Reels, Shorts |
명령어 참조
편집 명령어 (ffmpeg)
| 명령어 | 설명 | 예시 |
|---|
/trim | 비디오에서 구간 자르기 | "video.mp4 0:30부터 1:45까지 자르기" |
/compress | 품질 조절로 파일 크기 줄이기 | "10MB 미만으로 압축" |
/merge | 여러 클립을 하나로 결합 | "clip1.mp4와 clip2.mp4 페이드 효과로 병합" |
/resize | 크기, 화면비, 자르기, 패딩 변경 | "1080x1080 정사각형으로 크기 변경" |
/speed | 속도 올리기, 늦추기, 역재생 | "2배속" 또는 "0.5배 슬로우 모션" |
/stabilize | 카메라 흔들림 제거 (vidstab 2-pass) | "shaky.mp4 안정화" |
/watermark | 비디오에 이미지 또는 텍스트 오버레이 | "logo.png 오른쪽 아래에 추가" |
/audio | 볼륨, 노멀라이즈, 믹스, 페이드, 추출, 음소거 | "오디오를 -14 LUFS로 노멀라이즈" |
/thumbnail | 프레임을 이미지로 추출 | "0:15 지점 썸네일" |
/gif | 비디오 구간에서 애니메이션 GIF 생성 | "0:05부터 0:10까지 320px GIF" |
/extract | 오디오 또는 자막 트랙 추출 | "오디오를 mp3로 추출" |
/info | 비디오 메타데이터 및 스트림 정보 표시 | "video.mp4 정보" |
생성 명령어 (Remotion)
| 명령어 | 설명 | 예시 |
|---|
/title-card | 테마 지원 애니메이션 타이틀 카드 | "타이틀 카드: Coming Soon, wad 테마, 줌 애니메이션" |
/lower-third | 애니메이션 이름/직함 오버레이 | "로우어 서드: John Doe, CEO, 모던 스타일" |
/end-card | CTA 및 소셜 미디어 포함 애니메이션 아웃트로 | "엔드 카드: 구독!, @handle, ea 테마" |
/teaser | 전환 효과와 타이틀이 포함된 멀티클립 몽타주 | "clips/ 폴더에서 30초 티저" |
받아쓰기 명령어 (Whisper)
| 명령어 | 설명 | 예시 |
|---|
/transcribe | 음성으로 SRT/VTT 생성 | "interview.mp4 받아쓰기" |
/add-captions | 받아쓰기 후 비디오에 자막 입히기 | "talk.mp4에 자막 추가" |
조정 명령어
| 명령어 | 설명 | 예시 |
|---|
/pipeline | 다단계 처리 체인 | "자르기, 타이틀 카드 추가, Instagram용 압축" |
워크플로우
1단계: 사용 가능한 도구 확인
which ffmpeg ffprobe && echo "ffmpeg: ok"
node --version && echo "node: ok"
which whisper && echo "whisper: ok" || echo "whisper: 설치되지 않음 (자막은 수동 .srt 필요)"
ffmpeg -encoders 2>/dev/null | grep videotoolbox && echo "hw accel: ok" || echo "hw accel: 사용 불가"
ffmpeg -filters 2>/dev/null | grep vidstab && echo "vidstab: ok" || echo "vidstab: 사용 불가 (brew install ffmpeg --with-libvidstab)"
ffmpeg가 없으면: "brew install ffmpeg로 설치"
Node.js가 없으면: "https://nodejs.org에서 설치하거나 brew install node로 설치"
vidstab이 없으면: "ffmpeg를 vidstab과 함께 재설치: brew install ffmpeg --with-libvidstab"
2단계: 요청 분류
| 사용자 의도 | 엔진 | 경로 |
|---|
| 기존 영상 편집 | ffmpeg | 3a단계 |
| 새 비디오 콘텐츠 생성 | Remotion | 3b단계 |
| 오디오 조작 | ffmpeg 오디오 필터 | 3a단계 |
| 정보/검사 | ffprobe | 3a단계 |
| 결합 파이프라인 | 두 엔진 조정 | 3c단계 |
| 플랫폼 게시 | 크기 변경 + 압축 프리셋 | 3a단계 |
| 받아쓰기 | Whisper + ffmpeg | 3a단계 |
3a단계: ffmpeg 경로
- 제공되지 않은 경우 입력 파일 요청
- ffprobe로 검사:
ffprobe -v quiet -print_format json -show_format -show_streams "<file>"
- 하드웨어 가속 감지 (macOS Apple Silicon):
ffmpeg -encoders 2>/dev/null | grep h264_videotoolbox
- 출물 파일 충돌 처리:
OUTPUT="trimmed_video.mp4"
COUNTER=2
while [ -f "$OUTPUT" ]; do
OUTPUT="trimmed_video_${COUNTER}.mp4"
COUNTER=$((COUNTER + 1))
done
- ffmpeg 명령어 구성
- 각 플래그를 평이한 영어로 설명
- 출력 파일 이름 명시 (절대 원본 덮어쓰지 않음)
- 질문: "실행할까요?"
- 실행 후 확인:
if [ $? -eq 0 ]; then
echo "성공"
ffprobe -v quiet -print_format json -show_format "$OUTPUT" | grep -E '"duration"|"size"'
else
echo "오류 — 위 ffmpeg 출력 확인"
fi
- 출력 경로 + 파일 크기 + 재생 시간 보고
출물 파일 명명 규칙:
| 명령어 | 출력 패턴 |
|---|
| 자르기 | trimmed_<filename> |
| 압축 | compressed_<filename> |
| 병합 | merged_output.<ext> |
| 크기 변경 | resized_<filename> |
| 속도 | speed_<factor>x_<filename> |
| 안정화 | stabilized_<filename> |
| 워터마크 | watermarked_<filename> |
| 자막 | captioned_<filename> |
| 오디오 추출 | <name>.mp3 |
| 오디오 수정 | audio_<filename> |
| 자막 추출 | <name>.srt |
| 썸네일 | thumb_<name>_<timecode>.jpg |
| GIF | <name>.gif |
3b단계: Remotion 경로
- Node.js 설치 확인
- 워크스페이스 캐싱 -- 기존 워크스페이스 재사용:
WORKSPACE="/tmp/remotion-workspace"
if [ -d "$WORKSPACE/node_modules" ]; then
echo "캐시된 Remotion 워크스페이스 재사용"
else
echo "Remotion 워크스페이스 생성 (최초 실행)..."
mkdir -p "$WORKSPACE"
cp -r ~/project-templates/remotion-video/* "$WORKSPACE/"
cd "$WORKSPACE" && npm install
fi
~/design-assets/color-palettes/에서 테마 로딩:
- 필요에 따라 컴포지션 소스 파일 작성 또는 업데이트
- 사용 가능한 컴포지션:
TitleCard -- 여러 애니메이션 프리셋이 있는 애니메이션 타이틀
LowerThird -- 악센트 바가 있는 이름/직함 오버레이
EndCard -- CTA, 소셜 미디어, 로고가 포함된 아웃트로
Teaser -- TransitionSeries가 포함된 멀티클립 몽타주
- 렌더링:
cd "$WORKSPACE"
npx remotion render src/index.ts <CompositionId> /path/to/output.mp4 \
--props='{"text":"Title","bg":"#09090B","fg":"#FFFFFF","accent":"#7C3AED"}'
- 출력을 사용자의 작업 디렉토리로 복사
- 출력 경로 + 재생 시간 보고
3c단계: 결합 파이프라인
다단계 요청(예: "타이틀 카드, 클립, 엔드 카드로 티저 만들기")의 경우:
- 계획 -- 실행 전 각 단계를 사용자에게 설명
- 생성 -- 먼저 Remotion 콘텐츠 생성 (타이틀 카드, 엔드 카드)
- 처리 -- ffmpeg로 소스 클립 자르기/크기 변경
- 조립 -- ffmpeg로 전환 효과를 포함한 모든 조각 병합
- 완료 -- 대상 플랫폼이 지정된 경우 압축
- 주요 단계(생성 vs 편집 vs 조립) 사이에 확인
ffmpeg 빠른 참조
자르기 (무손실)
ffmpeg -ss <start> -to <end> -i input.mp4 -c copy trimmed_input.mp4
압축 -- 웹 (CRF 23)
ffmpeg -i input.mp4 -c:v libx264 -crf 23 -preset medium -c:a aac -b:a 128k compressed_input.mp4
압축 -- 하드웨어 가속 (macOS)
ffmpeg -i input.mp4 -c:v h264_videotoolbox -b:v 5M -c:a aac -b:a 128k compressed_input.mp4
페이드 전환 효과로 병합
ffmpeg -i clip1.mp4 -i clip2.mp4 \
-filter_complex "[0][1]xfade=transition=fade:duration=1:offset=<offset>,format=yuv420p[v];[0:a][1:a]acrossfade=d=1[a]" \
-map "[v]" -map "[a]" merged_output.mp4
크기 변경 / 스케일
ffmpeg -i input.mp4 -vf "scale=1920:1080" resized_input.mp4
ffmpeg -i input.mp4 -vf "scale=1080:-1" resized_input.mp4
ffmpeg -i input.mp4 -vf "crop=min(iw\,ih):min(iw\,ih)" cropped_input.mp4
ffmpeg -i input.mp4 -vf "scale=1080:1080:force_original_aspect_ratio=decrease,pad=1080:1080:(ow-iw)/2:(oh-ih)/2:black" padded_input.mp4
속도 변경
ffmpeg -i input.mp4 -vf "setpts=0.5*PTS" -af "atempo=2.0" speed_2x_input.mp4
ffmpeg -i input.mp4 -vf "setpts=2.0*PTS" -af "atempo=0.5" speed_0.5x_input.mp4
ffmpeg -i input.mp4 -vf "setpts=0.25*PTS" -af "atempo=2.0,atempo=2.0" speed_4x_input.mp4
ffmpeg -i input.mp4 -vf "reverse" -af "areverse" reversed_input.mp4
워터마크 오버레이
ffmpeg -i input.mp4 -i logo.png \
-filter_complex "overlay=W-w-20:H-h-20" watermarked_input.mp4
ffmpeg -i input.mp4 -i logo.png \
-filter_complex "overlay=20:20" watermarked_input.mp4
ffmpeg -i input.mp4 -i logo.png \
-filter_complex "[1]format=rgba,colorchannelmixer=aa=0.3[wm];[0][wm]overlay=(W-w)/2:(H-h)/2" watermarked_input.mp4
ffmpeg -i input.mp4 \
-vf "drawtext=text='My Brand':fontsize=24:[email protected]:x=W-tw-20:y=H-th-20" watermarked_input.mp4
비디오 안정화 (vidstab 2-pass)
ffmpeg -i shaky.mp4 -vf vidstabdetect=shakiness=10:accuracy=15 -f null -
ffmpeg -i shaky.mp4 -vf vidstabtransform=smoothing=30:input=transforms.trf stabilized_shaky.mp4
오디오 조작
ffmpeg -i input.mp4 -af "volume=1.5" audio_input.mp4
ffmpeg -i input.mp4 -af "loudnorm=I=-14:TP=-1:LRA=11" audio_input.mp4
ffmpeg -i video.mp4 -i music.mp3 \
-filter_complex "[0:a]volume=1.0[a1];[1:a]volume=0.3[a2];[a1][a2]amix=inputs=2:duration=first[a]" \
-map 0:v -map "[a]" audio_input.mp4
ffmpeg -i input.mp4 -af "afade=t=in:ss=0:d=3,afade=t=out:st=<end-3>:d=3" audio_input.mp4
ffmpeg -i input.mp4 -an muted_input.mp4
ffmpeg -i input.mp4 -i newtrack.mp3 -c:v copy -map 0:v:0 -map 1:a:0 replaced_audio_input.mp4
GIF 생성 (품질 위한 2-pass 팔레트)
ffmpeg -ss <start> -t <duration> -i input.mp4 \
-vf "fps=15,scale=320:-1:flags=lanczos,palettegen" palette.png
ffmpeg -ss <start> -t <duration> -i input.mp4 -i palette.png \
-filter_complex "[0:v]fps=15,scale=320:-1:flags=lanczos[v];[v][1:v]paletteuse" output.gif
rm palette.png
썸네일 추출
ffmpeg -ss <timestamp> -i input.mp4 -frames:v 1 -q:v 2 thumb_input_<timestamp>.jpg
ffmpeg -i input.mp4 -vf "fps=1/<interval>,scale=320:-1,tile=4x4" thumb_grid_input.jpg
.srt 자막 입히기
ffmpeg -i input.mp4 -vf "subtitles=captions.srt:force_style='FontSize=24,PrimaryColour=&H00FFFFFF'" captioned_input.mp4
오디오 추출
ffmpeg -i input.mp4 -vn -c:a libmp3lame -q:a 2 output.mp3
비디오 정보
ffprobe -v quiet -print_format json -show_format -show_streams input.mp4
Remotion 빠른 참조
캐시된 워크스페이스 설정
WORKSPACE="/tmp/remotion-workspace"
if [ ! -d "$WORKSPACE/node_modules" ]; then
cp -r ~/project-templates/remotion-video/* "$WORKSPACE/"
cd "$WORKSPACE" && npm install
fi
TitleCard 컴포지션
import { AbsoluteFill, spring, useCurrentFrame, useVideoConfig, Img } from 'remotion';
type Animation = 'fade' | 'slide-up' | 'slide-down' | 'zoom' | 'typewriter' | 'glitch' | 'blur-in';
export const TitleCard: React.FC<{
text: string;
subtitle?: string;
bg?: string;
fg?: string;
accent?: string;
animation?: Animation;
logo?: string;
}> = ({ text, subtitle, bg = '#09090B', fg = '#FFFFFF', accent = '#7C3AED', animation = 'fade', logo }) => {
const frame = useCurrent
…
[나머지는 번역을 위해 생략됨]