녹화
사용 시기
녹음 버튼, 진행 중 도구 모음, 권한 프롬프트, 청크 업로드 흐름 또는 카메라 버블 등 녹음기를 건드릴 때마다 이 스킬을 참조하세요. 새 소스(예: 탭 캡처, iPhone 연속성 카메라)에 대한 지원을 추가하거나 서버 측에서 청크를 마무리하는 방식을 변경하는 경우, 이것이 안내 지도입니다.
관련 데이터 모델
recordings— 사용자가 녹음 버튼을 누르거나 소스를 가져오는 즉시 행이 생성됩니다. 네이티브/파일 녹화는uploading→processing→ready(또는failed)로 전환됩니다.videoUrl,durationMs,videoSizeBytes,width,height,hasAudio,hasCamera는 업로드가 스트리밍됨에 따라 채워집니다. Loom 가져오기는import-loom-recording을 사용하며, MP4 내보내기를 사용할 수 없는 경우 Clips 호스팅 MP4 또는 Loom 임베드와 함께 ready 상태가 됩니다.application_state.record-intent— 에이전트가 녹음을 시작하려 할 때 이 값을 씁니다. UI는 이를 읽고 지운 다음 권한을 요청합니다.application_state.navigation— 녹음기가 활성화되어 있는 동안{ view: "record" }로 설정됩니다.
바이너리 업로드는 actions이 아닌 사용자 정의 API 라우트(/api/uploads/:id/chunk 및 /api/uploads/:id/abort)를 사용합니다. actions는 바이너리 스트리밍 본문에 적합한 도구가 아니기 때문입니다. 마지막 청크는 finalize-recording을 호출합니다. Loom URL 가져오기는 메타데이터 전용이므로 import-loom-recording action을 통해 처리해야 합니다.
일부 녹화는 회의와 연결됩니다. recording 행에서 meeting_id가 null이 아닌 경우 start-meeting-recording을 통해 생성된 것이며, recording 및 meetings 스킬이 모두 적용됩니다. 양방향 링크에 대해서는 meetings 스킬을 참조하세요.
생명주기
- 의도. 사용자가 녹음 버튼을 클릭하거나(전역
Cmd+Shift+L) 에이전트가pnpm action start-recording --mode=screen을 호출합니다. 에이전트 버전은 application state에record-intent를 씁니다. UI가 이를 가져와 사용자 클릭과 동일한 흐름을 시작합니다. - 권한. 화면의 경우
navigator.mediaDevices.getDisplayMedia({ video, audio }), 카메라의 경우getUserMedia({ video, audio })를 호출합니다. 사용자 제스처 없이 프롬프트를 표시하지 마십시오. 에이전트 경로는 UI의 버튼에 의존합니다. 브라우저의 권한 모델을 우회하지 않습니다. - 행 생성. 스트림이 승인되는 즉시
create-recording을 호출하여status: "uploading"및 미리 생성된 ID로 행을 삽입합니다. 이 ID는 이후 모든 청크 업로드에 사용됩니다. - 녹화.
mimeType: "video/webm;codecs=vp9,opus"(vp8로 폴백, 그다음 브라우저 기본값)로MediaRecorder를 시작합니다.timeslice: 2000을 사용하여 2초마다 청크가 도착하도록 합니다. - 각 청크 업로드.
ondataavailable는 헤더X-Recording-Id및X-Chunk-Index와 함께 바이트를/api/uploads/chunk로 스트리밍하는 동시에 최상의 노력 백업으로IndexedDB에 원시 청크를 독립적으로 미러링합니다. 일시적인 전달 실패는 업로드를 일시 중지하고 현재 브라우저 탭이 열려 있는 동안에만 인메모리 소스를 재개합니다. 백그라운드 재전송 워커나 닫힌 탭 복구 약속은 없습니다.IndexedDB쓰기 실패는 캡처나 업로드를 차단하지 않습니다. - 실시간 전사. MediaRecorder와 함께
useLiveTranscription은 Web Speech API를 실행하여 실시간으로 전사 텍스트를 축적합니다. 중지 시 클라이언트는save-browser-transcript를 호출하여 결과를 즉시 저장합니다. API 키가 필요하지 않습니다. 데스크톱 녹화는 먼저 사용 가능한 경우 로컬 Whisper/macOS 음성을 사용하고, 비-Mac에서는 webview에서 Web Speech로 폴백한 다음 업로드 전사에 의존합니다. - 마무리. 중지 시 마지막 청크를
/api/uploads/:id/chunk?isFinal=1로 보냅니다. 라우트는finalize-recording을 호출하여 청크를 결합하고, 미디어를 시크 가능하게 만들고(아래 참조), 스토리지가 구성된 경우 완성된 미디어를 업로드하고,status를ready로 전환한 다음, 더 높은 품질의 출력을 위해request-transcript를 시작합니다(ai-video-tools참조). - 즉시 이동. 데스크톱 녹음기는 Stop이 마무리를 시작하는 즉시
/r/:id를 엽니다. recording 행은 이미 존재하므로 페이지는uploading또는processing에서ready로 폴링하는 동안 제목, 공유 링크 및 업로드 진행 상황을 표시할 수 있습니다. 페이지를 열기 위해 업로드/마무리 응답을 기다리지 마십시오.
모바일 컴패니언 생명주기
Agent-Native 모바일 앱은 동일한 recording 행 및 바이너리 업로드 라우트를 네이티브 캡처 프리미티브와 함께 사용합니다.
- 카메라 비디오/가져오기는
expo-camera/시스템 사진 선택기를 사용하고, 회의 오디오는 백그라운드 녹화가 활성화된expo-audio를 사용합니다. - 네이티브 파일은 문서 디렉터리에 복사되고 업로드가 시작되기 전에 타입화된 AsyncStorage 캡처 작업이 기록됩니다.
create-recording은 안정적인 클라이언트 생성 ID,sourceAppName: "Agent-Native Mobile"및 컨테이너 MIME 유형을 받습니다.- 업로드는 Expo FileHandle을 통해 최대 3MiB를 읽고 승인된 모든 POST 후에 다음 청크 인덱스를 유지합니다. 4MiB 서버 제한은 여전히 적용됩니다.
- 포그라운드/재개 조정은
/api/uploads/:id/status를 폴링합니다. 재시도 가능한 실패는 백오프되며 로컬 파일을 절대 폐기하지 않습니다. 완료는 로컬 알림을 게시할 수 있으며 녹화는 모든 곳의 Clips에 나타납니다.
모바일 오디오 M4A는 MP4 컨테이너이며 recording 라우트의 MP4 MIME 별칭을 사용합니다. 바이트는 변환되거나 전체가 JavaScript 메모리에 로드되지 않습니다.
전화는 네트워크 작업 전에 각 오디오/비디오 파일을 유지하고 내구성 있는 큐에서 바인딩된 청크 업로드를 재개하므로 일시적인 업로드 실패가 캡처를 손실하지 않습니다. 사용자에게 캡처 화면을 열어두거나 실패한 업로드 후 다시 녹화하도록 요청하지 마십시오. Clips에 다시 연결하고 모바일 홈에서 저장된 작업을 재시도하도록 안내하세요.
모바일 회의 캡처는 마이크 전용입니다. 데스크톱의 마이크+시스템 오디오 충실도가 있다고 주장하지 마십시오. 참석자 귀속에 대한 의미는 meetings 스킬을 참조하세요.
시크 가능한 재생(원시 MediaRecorder 출력을 제공하지 마십시오)
원시 MediaRecorder 파일은 점진적 HTTP 재생에 친화적이지 않아, 파일 다운로드는 정상임에도 "클립 로드에 몇 분 걸림" 및 "탐색할 때마다 다시 버퍼링"으로 나타납니다.
- MP4는
moov메타데이터 아톰이mdat_다음_에 기록되므로 플레이어가 시작하거나 탐색하기 전에 전체 파일을 가져와야 합니다. - WebM은 큐(seek index)가 없고 알 수 없는 Segment 지속 시간을 가진 라이브 스트림이므로 Chrome은
currentTime = X를 인식하지 못하고 스캔/다운로드해야 합니다.
finalize-recording은 업로드 전에 이 문제를 해결합니다. MP4는 순수-TS faststart(server/lib/faststart.ts)를, WebM은 SeekHead + Cues + 실제 지속 시간을 쓰는 무손실 ffmpeg -c copy 리먹스(server/lib/video-remux.ts)를 얻습니다. 둘 다 최상의 노력입니다. 실패 시 원본을 업로드하고 finalize를 차단하지 않습니다. CLIPS_INLINE_REMUX_MAX_BYTES(기본값 200MB)를 초과하는 녹화는 인라인 패스를 건너뛰고 백그라운드에서 복구됩니다.
스트리밍/재개 가능 업로드 경로는 원시 바이트를 공급자에게 직접 전달하고 인라인으로 다시 쓸 수 없으므로 finalize-recording은 해당 경로에 대해 백그라운드 ensureRecordingSeekable 패스를 예약합니다.
이전에(또는 스트리밍을 통해) 업로드된 클립을 복구하려면 reprocess-recording action을 호출하세요: --id, --ids='[...]', 또는 --all --limit=N. 공급자 미디어를 다시 가져와 다시 쓰고, 다시 업로드하고, 행을 다시 가리킵니다. 멱등적입니다(이미 시크 가능한 클립은 --force가 없으면 건너뜁니다). 호출자가 소유한 공급자 호스팅 클립에만 영향을 미칩니다. 사용자가 특정 느린/버퍼링 클립을 보고할 때 올바른 도구입니다.
시크 가능성 리먹스는 비디오 트랙에 큰 타임스탬프 간격(모바일 브라우저가 사용자가 앱을 전환한 후 카메라를 일시 중단할 때 일반적)이 있는 동안 오디오가 계속되는 녹화를 복구할 수 없습니다. 선언된 지속 시간 전에 정지되거나 중지되는 것처럼 보이는 클립의 경우 --normalizeTimeline=true와 함께 reprocess-recording을 호출하세요. 이 명시적 모드는 동일한 소유자 범위의 가져오기 및 업로드 흐름을 사용하지만 상수 30fps faststart MP4(H.264 + AAC)로 완전히 트랜스코딩합니다. 오디오를 보존하고 누락된 프레임 간격을 통해 마지막 디코딩된 비디오 프레임을 복제합니다. action은 새 미디어 객체에 업로드하고 검증된 출력이 저장된 경우에만 행을 원자적으로 다시 가리킵니다. 어떤 트랜스코드, 오디오 검증, 업로드 또는 동시 업데이트 실패도 원래 URL 및 형식을 그대로 둡니다.
Loom 가져오기
Loom 공유 또는 임베드 URL에는 import-loom-recording을 사용하세요. action은 Loom URL을 검증하고, Loom의 공개 엔드포인트에서 Loom oEmbed 메타데이터를 읽고, Loom의 임베드 URL, 썸네일, 제목, 지속 시간 및 치수로 ready recording을 생성합니다. Loom이 공유 페이지에 서명된 공개 전사 JSON URL을 노출하면 action은 해당 전사를 Clips로 가져와 정규화된 세그먼트를 저장합니다. Loom의 서명된 CDN URL을 저장하지 마십시오.
Loom이 다운로드 가능한 공개 MP4를 노출하면 import-loom-recording은 이를 다운로드하고, 바이트를 Clips 스토리지에 다시 업로드하고, ready 상태의 재생 가능한 Clips 호스팅 recording을 생성하며, 공유 페이지가 노출하는 경우 Loom의 공개 전사를 가져옵니다. Loom이 공개 재생을 허용하지만 MP4를 노출하지 않으면 action은 ready 상태의 임베드 백업 recording을 유지하고 가능한 경우 전사를 계속 가져옵니다.
임베드 백업 Loom 가져오기는 Loom iframe을 렌더링하고 네이티브 Clips 편집기를 숨깁니다. 다시 업로드된 Loom 가져오기는 Clips 네이티브 트리밍, 내보내기, 프레임 추출 및 업로드 기반 전사를 지원합니다. 임베드 백업 가져오기에 이러한 기능이 필요한 경우 사용자에게 원본 비디오 파일을 업로드하도록 요청하세요.
브라우저 진단 및 녹음기 설치 옵션
브라우저 녹화는 createBrowserDiagnosticsCapture를 통해 제한되고 정리된 진단을 저장할 수 있습니다: 콘솔 메시지와 fetch/XHR 메서드, URL, 상태, 지속 시간 및 오류. 브라우저 녹음기는 녹음기 페이지 자체의 활동만 캡처합니다. Clips Chrome 확장 프로그램은 브라우저 로그를 위한 활성 탭 경로입니다. 확장 프로그램 캡처 세션으로 /record를 시작하고 developerLogs=1/0을 전달한 다음 소스 extension으로 진단을 저장합니다.
웹 스토어 목록은 활성 상태이므로 공용 Chrome 확장 프로그램 옵션이 기본적으로 표시됩니다. 그렇지 않으면 "데스크톱 앱 다운로드"라고 표시되는 UI 프롬프트는 공유 설치 선택 구성 요소(CaptureInstallButton / CaptureInstallInlineLink)를 사용하여 두 가지 옵션을 제공합니다: 브라우저 로그용 Chrome 확장 프로그램과 가장 원활한 네이티브 캡처를 위한 데스크톱 앱. Chrome 옵션을 다시 숨기려면 VITE_CLIPS_CHROME_EXTENSION_ENABLED=0를 설정하거나 다른 목록을 가리키도록 VITE_CLIPS_CHROME_EXTENSION_URL을 설정하세요.
save-browser-diagnostics는 UI/내부 전용입니다. 제한된 콘솔 로그와 fetch/XHR 메서드, URL 경로/쿼리 키, 상태 및 지속 시간을 저장합니다. 헤더, 본문, 쿠키 또는 네트워크 URL 쿼리 값은 절대 캡처하지 않습니다. 콘솔 텍스트는 자격 증명처럼 보이는 키와 헤더를 정리하면서 유용한 비밀 아닌 값을 유지합니다. 편집기 액세스 권한이 있는 경우 전체 진단 페이로드는 get-recording-player-data를 사용하세요. 공용 에이전트 컨텍스트가 노출하는 더 좁은 정리된 스트림은 video-sharing 스킬을 참조하세요.
Chrome 확장 프로그램
확장 프로그램은 chrome-extension/에 있습니다. clipsExtensionId 및 clipsCaptureSessionId와 함께 /record를 시작하고, 녹음기는 CLIPS_CAPTURE_START / CLIPS_CAPTURE_STOP / CLIPS_CAPTURE_CANCEL을 확장 프로그램으로 다시 보냅니다. 사용자가 시작한 탭에서만, 녹화가 활성화된 동안에만 Chrome 디버거 API를 사용하며, save-browser-diagnostics에 의해 저장된 것과 동일한 정리된 진단 형태를 반환합니다.
확장 프로그램은 또한 GitHub 이슈 및 PR 마크다운을 향상시킵니다. 좁은 github.com 콘텐츠 스크립트가 Clips /r/, /share/ 및 /embed/ 링크를 감지한 다음, 확장 프로그램 소유 미리보기 iframe에서 기존 /embed/:id 플레이어를 렌더링하여 GitHub를 떠나지 않고 비디오를 재생할 수 있도록 합니다. 의도적인 권한 검토가 없는 한 이를 GitHub로 범위를 제한하세요.
폴더, 공간 및 대량 이동
단일 및 대량 폴더 이동 모두에 move-recording을 사용하세요. 단일 클립의 경우 id를, 선택된 클립의 경우 ids를 전달하고, 라이브러리 또는 공간 루트로 이동하려면 folderId: null을 전달하세요.
스크린샷
스크린샷은 kind = "image"인 recordings 행입니다(shared/recording-kind.ts의 isImageRecording). 클립과 폴더, 공간, 공유, 댓글 및 검색을 공유하며 비디오 부분(전사, 챕터, 필름스트립, 타임라인 또는 오디오)은 없습니다. list-recordings --kind=image로 나열합니다.
- 캡처, 주석 및 수정은 브라우저 작업입니다(
create-screenshot,save-screenshot-edits, 둘 다 UI 전용). 에이전트는get-recording-player-data또는/api/agent-frame.jpg를 통해 스크린샷을 읽으며, 이는 모든atMs에 대한 그림 자체를 반환합니다. imageUrl은 제공되는 그림이고,baseImageUrl은 편집기가 그리는 표시되지 않은 베이스입니다. 둘 다/api/thumbnail/:id를 통해 제공되며, 암호, 만료 및 수정 보류가 적용됩니다. 스토리지 URL을 절대 제공하지 마십시오.- 수정은 비디오와 마찬가지로 두 단계입니다. 상자는 보류 중인 오버레이로 저장되고(뷰어에게 보류됨), 그런 번인됩니다. 번인은 원본을 삭제하기 전에
editsJson.burnInProgress를 쓰고 그 후에 지웁니다.unreclaimedUrls는 아직 삭제되지 않은 이전 복사본을 나열합니다. 둘 다 서버 전용(server/lib/screenshot-edits.ts)이며 뷰어에게 절대 도달해서는 안 됩니다. - 비디오 편집 actions은
assertNativeRecordingMedia에서 스크린샷을 거부합니다.save-screenshot-edits만 스크린샷의editsJson을 씁니다.
일시 정지 / 재개
MediaRecorder.pause() / .resume()은 모든 최신 브라우저에서 지원됩니다. 일시 정지 전반에 걸쳐 단일 MediaRecorder 인스턴스를 유지하세요. 스트림을 해체하지 마십시오. 그렇지 않으면 권한 프롬프트가 다시 실행됩니다. 일시 정지된 동안 업로드 워커는 버퍼를 계속 비우므로 사용자가 중지하기 전에 따라잡을 수 있습니다.
카메라 버블
모드가 screen+camera일 때 "버블"은 두 가지 다른 것입니다.
- 화면 내 자기 보기.
CameraBubble은 사용자가 카운트다운/녹화 중에 자신의 프레임을 잡기 위해 드래그하는 일반적인 녹화되지 않은<video>요소를 렌더링합니다. 절대 캡처되지 않습니다. 로컬 프레이밍 UI일 뿐입니다. - 녹화된 합성. 디스플레이 캡처는 사용자가 다른 창/앱을 녹화할 때 해당 DOM 요소를 포함할 수 없으므로 저장된 비디오는
MediaRecorder가 시작되기 전에 카메라 원을 구워야 합니다.CameraBubble의 복사본은 모든timeslice전에recording-chunk-processor가 프레임 오프캔버스를 혼합합니다. 캡처된 카메라 비디오는ContentHint및navigator.mediaCapabilities.decodingInfo()(사용 가능한 경우)에 따라 플랫폼 코덱과 일치하도록 최대 H.264 BP L3.1로 인코딩됩니다(단, 사용 가능한 라이선스 제한 없음).
오류 상태
| 상태 | 의미 | 일반적인 원인 / 취할 조치 |
|---|---|---|
uploading | 청크가 스트리밍 중입니다. | 정상 작동 중. |
processing | 서버가 청크를 마무리하고 있습니다. | 잠시 후 ready 또는 failed로 전환됩니다. |
failed | 녹화가 완료되지 않았습니다. | failedReason을 확인하세요. reprocess-recording으로 복구를 시도할 수 있습니다. |
ready | 녹화가 완료되었고 재생 가능합니다. | 정상 완료됨. |
구성
| 변수 | 기본값 | 설명 |
|---|---|---|
CLIPS_INLINE_REMUX_MAX_BYTES | 200MB | 인라인 리먹스의 최대 파일 크기. 더 큰 파일은 백그라운드 복구를 예약합니다. |
VITE_CLIPS_CHROME_EXTENSION_ENABLED | 1 | 0으로 설정하여 Chrome 확장 프로그램 옵션을 숨깁니다. |
VITE_CLIPS_CHROME_EXTENSION_URL | Web Store URL | 대체 Chrome 확장 프로그램 목록 URL입니다. |
관련 작업
start-recording— 에이전트가 직접 녹화를 시작합니다.create-recording— 데이터베이스에 recording 행을 삽입합니다.finalize-recording— 청크를 결합하고 미디어를 시크 가능하게 만듭니다.import-loom-recording— Loom URL에서 녹화를 가져옵니다.reprocess-recording— 기존 녹화를 다시 처리하여 시크 가능성을 복구합니다.move-recording— 단일 또는 대량으로 녹화를 이동합니다.save-browser-transcript— 브라우저 전사를 저장합니다.get-recording-player-data— 녹화의 전체 데이터를 가져옵니다.createBrowserDiagnosticsCapture— 브라우저 진단을 생성합니다.save-screenshot-edits— 스크린샷 편집을 저장합니다.
참조
meetings스킬: 회의 관련 녹화 링크.ai-video-tools스킬: 전사 및 AI 비디오 도구.video-sharing스킬: 공용 컨텍스트 진단 및 공유.