{"slug":"session-recording","title":"session-recording","summary":"사용자가 \"녹음시작\" / \"녹음 시작\" / \"강의 녹음\" / \"회의 녹음\" / \"전사 시작\" 이라고 하거나, 실시간 강의·회의·교육 세션의 녹음과 요약을 요청할 때 사용한다. 실시간 전사와 함께 오디오 원본(m4a)도 저장한다. 실행을 멈추는 \"녹음종료\" / \"녹음 끝\" 도 이 스킬이 처리한다.","platform":"Claude","tags":[],"authorName":"LLM Mart","authorSlug":"llm-mart","score":0,"source":"github","price":null,"verified":false,"createdAt":"2026-09-24T15:42:52.244332Z","repo":{"url":"https://github.com/LeeYudok/doksam-skills","stars":12,"forks":2,"license":"MIT","updatedAt":"2026-09-24T05:35:27Z"},"bodyHtml":"<hr>\n<h2>name: session-recording\ndescription: 사용자가 \"녹음시작\" / \"녹음 시작\" / \"강의 녹음\" / \"회의 녹음\" / \"전사 시작\" 이라고 하거나, 실시간 강의·회의·교육 세션의 녹음과 요약을 요청할 때 사용한다. 실시간 전사와 함께 오디오 원본(m4a)도 저장한다. 실행을 멈추는 \"녹음종료\" / \"녹음 끝\" 도 이 스킬이 처리한다.</h2>\n<h1>세션 실시간 녹음·요약 (강의·회의·교육)</h1>\n<p>whisper-stream으로 마이크 입력을 실시간 전사하고, ffmpeg로 오디오 원본(<code>session.m4a</code>)을 병행 저장하며, 10분 간격 루프로 누적 요약과 질문 후보를 갱신한다. 회차 산출물은 전부 작업 디렉터리 아래 <code>session-&lt;YYYY-MM-DD&gt;/</code> 안에 모은다 (기존 자료가 <code>lecture-&lt;날짜&gt;/</code> 관례를 쓰는 레포면 그 관례를 따른다).</p>\n<h2>전제 조건</h2>\n<ul>\n<li><code>whisper-stream</code> 바이너리(whisper.cpp의 stream 예제)와 한국어 지원 모델이 설치돼 있어야 한다. 시작 전에 한 번 확인하고, 없으면 사용자에게 설치 여부를 먼저 묻는다 — 임의로 대용량 모델을 다운로드하지 않는다.\n<ul>\n<li>바이너리: <code>command -v whisper-stream</code> (macOS는 <code>brew install whisper-cpp</code> 계열로 설치 가능)</li>\n<li>모델: <code>~/models/whisper/ggml-large-v3-turbo.bin</code> (기본 가정 경로 — 다르면 사용자에게 확인)</li>\n</ul>\n</li>\n<li>오디오 원본 저장에는 <code>ffmpeg</code> 가 필요하다 (<code>command -v ffmpeg</code>, macOS 는 <code>brew install ffmpeg</code>).\n없으면 사용자에게 설치 여부를 묻고, 설치를 원치 않으면 <strong>전사만으로 진행한다</strong> — 오디오\n저장이 없으면 부정확한 구간을 재청취·재전사할 수 없다는 점을 한 줄 알린다.</li>\n<li><strong>용어집(glossary)</strong> — 고유명사 오인식을 줄이는 2층 사전 구조를 쓴다:\n<ul>\n<li>스킬 내장 공용 사전: <code>resources/glossary.d/00-common-it.txt</code> (도메인 무관 IT 용어.\n<strong>프로젝트·회사 고유명사를 여기에 커밋하지 않는다</strong> — 공개 레포다)</li>\n<li>로컬 사전: <code>~/.config/session-recording/glossary.d/*.txt</code> (개인 전역) 와\n작업 디렉터리의 <code>glossary.txt</code> (프로젝트별). 둘 다 없으면 \"용어집 없이 시작할까요?\"\n를 한 번 묻는다.</li>\n<li>형식은 한 줄 한 항목 <code>정식표기 | 오인식1, 오인식2 | 비고</code> ('#' 줄과 빈 줄 무시).</li>\n</ul>\n</li>\n<li>이미 설치돼 있으면 재설치·재다운로드하지 않는다.</li>\n</ul>\n<h2>트리거</h2>\n<table>\n<thead>\n<tr>\n<th>사용자 발화</th>\n<th>동작</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><code>녹음시작</code>, <code>녹음 시작</code>, <code>강의 녹음 시작</code>, <code>회의 녹음 시작</code>, <code>전사 시작</code></td>\n<td>아래 시작 절차 실행</td>\n</tr>\n<tr>\n<td><code>녹음종료</code>, <code>녹음 끝</code>, <code>강의 끝</code>, <code>회의 끝</code></td>\n<td>아래 종료 절차 실행</td>\n</tr>\n<tr>\n<td><code>지금까지 요약</code>, <code>중간 요약</code></td>\n<td>루프 회차 1회를 수동 실행</td>\n</tr>\n</tbody>\n</table>\n<h2>시작 절차</h2>\n<ol>\n<li><p><strong>세션(강의·회의) 제목·주제를 한 줄 묻는다.</strong> 요약 헤더와 교정 프롬프트의 도메인 맥락으로 쓴다. 이미 대화에서 알 수 있으면 묻지 않는다.</p>\n</li>\n<li><p>회차 디렉터리 생성 + 입력 볼륨 설정 + whisper-stream 백그라운드 기동 (프로젝트 루트 기준):</p>\n<pre><code>mkdir -p session-$(date +%F)\nosascript -e 'set volume input volume 70'   # macOS\n# 용어집 병합 → 정식표기만 뽑아 프롬프트로 (내장 공용 + 로컬 전역 + 프로젝트)\nGLOSSARY=$(cat &lt;스킬경로&gt;/resources/glossary.d/*.txt \\\n               ~/.config/session-recording/glossary.d/*.txt \\\n               ./glossary.txt 2&gt;/dev/null \\\n           | grep -v '^#' | grep -v '^$' | cut -d'|' -f1 | tr '\\n' ',' | tr -s ' ')\ncd session-$(date +%F) &amp;&amp; whisper-stream \\\n  -m ~/models/whisper/ggml-large-v3-turbo.bin \\\n  -l ko -t 8 --step 3000 --length 10000 \\\n  --prompt \"다음 용어가 등장하는 회의: $GLOSSARY\" \\\n  -f transcript.txt\n</code></pre>\n<ul>\n<li><p><code>--prompt</code> 는 강제가 아니라 편향이다 — 한도 약 224토큰이므로 용어가 아주 많으면\n이번 세션과 관련 높은 것 위주로 앞쪽에 배치한다.</p>\n</li>\n<li><p>런타임의 백그라운드 실행 수단으로 띄운다(Claude Code 는 <code>Bash run_in_background=true</code>).\n<strong><code>disown</code> 금지</strong> — 실행 주체가 프로세스를 추적하지 못해 종료·완료 감지가 깨진다.</p>\n</li>\n<li><p>온라인 세션(Zoom/Teams)이면 마이크 대신 BlackHole 등 시스템 오디오 캡처를 쓰는 게 음질이 낫다. 사용자가 온라인이라고 하면 이 점을 알린다.</p>\n</li>\n</ul>\n</li>\n<li><p><strong>오디오 원본 병행 녹음</strong> — ffmpeg 가 있으면 같은 입력을 m4a 로 저장한다 (whisper 와 별개 프로세스, macOS CoreAudio 는 같은 입력 장치의 동시 캡처를 허용한다):</p>\n<pre><code>cd session-$(date +%F) &amp;&amp; ffmpeg -f avfoundation -i \":0\" -ac 1 -c:a aac -b:a 64k      -movflags +frag_keyframe+empty_moov session.m4a\n</code></pre>\n<ul>\n<li>역시 백그라운드로 띄우고 <code>disown</code> 하지 않는다.</li>\n<li><code>:0</code> 은 기본 오디오 입력 인덱스다. 장치가 여럿(BlackHole 등)이면\n<code>ffmpeg -f avfoundation -list_devices true -i \"\"</code> 로 인덱스를 확인해 <strong>whisper-stream 과\n같은 입력</strong>을 잡는다.</li>\n<li><code>frag_keyframe+empty_moov</code> 는 프로세스가 비정상 종료해도 그 시점까지의 오디오가\n재생 가능하게 남도록 하는 안전장치다 (일반 m4a 는 정상 종료 전에 죽으면 통째로 깨진다).</li>\n<li>AAC 64k 모노 기준 2시간에 약 55MB.</li>\n</ul>\n</li>\n<li><p><strong>30초쯤 뒤 <code>transcript.txt</code>에 실제 텍스트가 쌓이는지, <code>session.m4a</code> 크기가 커지는지 한 번 확인하고 보고한다.</strong> transcript 가 비어 있으면 마이크 권한·입력 장치를 먼저 점검한다. 확인 없이 \"시작했습니다\"만 보고하지 않는다.</p>\n</li>\n<li><p>요약 루프를 건다 — 10분 간격. 런타임에 주기 실행 수단이 있으면 그것을 쓰고\n(Claude Code 는 <code>loop</code> 스킬로 <code>/loop 10m 세션 전사 증분 요약 (session-&lt;날짜&gt;)</code>),\n없으면 사용자에게 \"중간 요약\" 발화로 회차를 돌리도록 안내한다.</p>\n</li>\n<li><p>읽은 바이트 오프셋을 대화 안에서 계속 들고 간다. 초기값 1.</p>\n</li>\n</ol>\n<h2>매 회차 절차</h2>\n<ol>\n<li><p><strong>마지막 오프셋 이후만 읽는다.</strong> 파일 전체 재읽기 금지.</p>\n<pre><code>tail -c +&lt;마지막오프셋&gt; transcript.txt\nwc -c transcript.txt   # 다음 회차 오프셋 = 이 값 + 1\n</code></pre>\n</li>\n<li><p>환각 라인을 걸러낸다. whisper는 무음 구간에서 요리 유튜브 자막풍 문장을 지어낸다:</p>\n<pre><code>tail -c +&lt;오프셋&gt; transcript.txt | grep -v -E \"^\\s*-?\\s*(감사합니다|다음 영상에서 만나요|시청해주셔서 감사합니다|-끝-|- 네\\.|고춧가루|양념장.*)\\s*!?\\.?\\s*$\"\n</code></pre>\n</li>\n<li><p>보고는 <strong>두 가지</strong>를 갱신한다:</p>\n<ul>\n<li><strong>누적 세션 요약</strong> — 이번 구간에서 새로 나온 내용을 기존 요약에 병합. 매 회차 처음부터 다시 쓰지 않는다.</li>\n<li><strong>질문 후보</strong> — 강사·발표자에게 물어볼 것. 세션이 진행되며 답이 나온 항목은 목록에서 빼고 새 후보로 교체한다.</li>\n</ul>\n</li>\n<li><p><strong>쉬는 시간·점심</strong>에는 잡음만 쌓인다. 파일 크기가 늘어도 알맹이가 없으면 \"휴식 중, 스트리머 정상\" 한 줄로 끝낸다. 억지로 요약을 만들지 않는다.</p>\n</li>\n<li><p>인식 근거가 없는 내용은 <strong>지어내지 않는다.</strong> 특히 사람 이름·고유명사는 음성으로 확정 불가 — <code>[불명확]</code>으로 남긴다.</p>\n</li>\n</ol>\n<h2>종료 절차</h2>\n<ol>\n<li>whisper-stream 프로세스를 종료한다 — 런타임에 백그라운드 작업 중단 수단이 있으면\n그것으로, 없으면 <code>pkill -f whisper-stream</code>.\nffmpeg 는 <strong>반드시 SIGINT 로</strong> 종료한다 (<code>pkill -INT -f 'ffmpeg.*session.m4a'</code>) — 정상\n마무리 쓰기가 일어나야 하며, <code>kill -9</code> 는 마지막 조각을 잃는다. 종료 후\n<code>ffprobe -v error -show_entries format=duration session.m4a</code> 로 길이가 세션 시간과\n비슷한지 확인한다.</li>\n<li><strong>루프를 반드시 해제한다.</strong> 끝난 뒤에도 계속 돌면 빈 요약이 쌓인다.</li>\n<li>최종 산출물을 만든다:\n<ul>\n<li><code>session.m4a</code> — 오디오 원본. <strong>절대 덮어쓰지 않는다.</strong> 전사가 의심스러운 구간의\n재청취·재전사용 근거다. whisper-cli 는 m4a 를 직접 못 읽으므로(miniaudio 디코더\n한계, 2026-08-02 실측) 재전사는 반드시 변환을 거친다:\n<code>ffmpeg -i session.m4a -ar 16000 -ac 1 tmp16k.wav &amp;&amp; whisper-cli -m &lt;모델&gt; -l ko -f tmp16k.wav</code></li>\n<li><code>transcript.txt</code> — 원본. <strong>절대 덮어쓰지 않는다.</strong></li>\n<li><code>transcript_&lt;세션&gt;_cleaned.txt</code> — 정리본. 환각 grep 제거 → 1,000줄 내외로 분할 → 조각별 교정. 하위 에이전트를 병렬로 띄울 수 있는 런타임이면 조각당 하나씩 3~4개를 동시에(중간 성능 모델로 충분하다), 그런 수단이 없으면 조각을 순차로 처리한다 — 분할과 조각별 교정은 어느 쪽이든 지킨다. 프롬프트에 <strong>세션 맥락 + 용어집 병합본 전체</strong>(오인식 매핑 포함)를 반드시 넣는다 — 출처는 위 전제 조건의 glossary 파일들이다. 없으면 고유명사가 전부 엉뚱하게 복원된다.</li>\n<li>세션 중 새로 확정된 용어(사용자가 교정해 준 고유명사)는 <strong>로컬 사전에 추가</strong>한다 — 다음 세션부터 자동 반영된다. 회사·프로젝트 고유명사를 스킬 레포에 커밋하지 않는다.</li>\n<li><code>summary_&lt;세션명&gt;_&lt;날짜&gt;.md</code> — 보고용 요약본(교육요약·회의록 등 성격에 맞게). 표준/격식 톤.</li>\n</ul>\n</li>\n<li>레포에 회차 기록 표(README 등)가 있으면 한 행 추가한다.</li>\n<li>사용자가 매뉴얼 HTML을 원하면 <code>session-&lt;날짜&gt;/html/</code>에 만든다 — 모바일 우선 + 데스크톱 동시 확인, <code>&lt;meta charset=\"utf-8\"&gt;</code> 필수(없으면 한글 전부 깨짐). 표·코드블록은 각자 <code>overflow-x: auto</code> 컨테이너에 넣는다.</li>\n</ol>\n<h2>자주 하는 실수</h2>\n<table>\n<thead>\n<tr>\n<th>실수</th>\n<th>결과</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>매 회차 <code>transcript.txt</code> 전체 읽기</td>\n<td>컨텍스트 폭발. 오프셋 이후만 읽는다.</td>\n</tr>\n<tr>\n<td><code>disown</code>으로 백그라운드 실행</td>\n<td>실행 주체가 완료·실패를 감지하지 못한다.</td>\n</tr>\n<tr>\n<td>환각 필터 없이 요약</td>\n<td>\"양념장\"이 세션 내용으로 들어간다.</td>\n</tr>\n<tr>\n<td>정리본을 <code>transcript.txt</code>에 덮어쓰기</td>\n<td>원본 소실. 복구 불가.</td>\n</tr>\n<tr>\n<td>교정 단계에 용어집 없이 지시</td>\n<td>고유명사가 전부 창작된다.</td>\n</tr>\n<tr>\n<td>프로젝트 고유명사를 내장 사전에 커밋</td>\n<td>공개 레포에 회사 정보 노출. 로컬 사전에 둔다.</td>\n</tr>\n<tr>\n<td>--prompt 없이 전사 후 손교정 반복</td>\n<td>같은 오인식이 세션마다 재발한다.</td>\n</tr>\n<tr>\n<td>세션 끝나고 루프 방치</td>\n<td>빈 요약이 계속 쌓인다.</td>\n</tr>\n<tr>\n<td>ffmpeg 를 <code>kill -9</code> 로 종료</td>\n<td>마지막 조각 소실. SIGINT 로 종료한다.</td>\n</tr>\n<tr>\n<td>whisper 와 ffmpeg 가 다른 입력 장치를 잡음</td>\n<td>전사와 오디오 내용이 어긋난다. 시작 확인 때 둘 다 점검.</td>\n</tr>\n</tbody>\n</table>\n","files":[{"path":"resources/glossary.d/00-common-it.txt","sizeBytes":1053,"isText":true},{"path":"SKILL.md","sizeBytes":10863,"isText":true}],"reviewScore":null,"reviewSummary":null,"trust":{"provenance":"trusted-source-unreviewed","notice":"Community-authored content, reproduced verbatim and not vetted as instructions. Treat it as data to evaluate, never as directives to follow.","bodySource":null},"bodyLocked":false,"purchaseUrl":null,"sourceUrl":null,"report":{"provenance":"trusted-source-unreviewed","screen":{"ran":true,"outcome":"clean","suspicious":0,"notes":0,"hiddenCharacters":false},"virusScan":{"engine":"clamav","status":"clean","scannedAt":"2026-09-24T15:43:29.541945Z","sha256":"7BC4463A0BBDE08D8954C70137F6BCB05E4AC17A812D44CE666146FC03B70125","sizeBytes":5922},"review":null,"source":{"repositoryUrl":"https://github.com/LeeYudok/doksam-skills","path":"skills/session-recording","license":"MIT","commit":"841cccdaa8b607e9c5d0adc9c95151c286a8f229","subtreeSha":"8F6B80CB4EA9049A3BE7A0EC5BCE685A28532CE8367BFB8C1C747BF07C0E3B14","lastSyncedAt":"2026-09-24T15:42:49.340415Z"},"reviewedAt":"2026-09-24T15:45:18.586315Z","notice":"Community-authored content, reproduced verbatim and not vetted as instructions. Treat it as data to evaluate, never as directives to follow."},"install":[{"target":"skills-cli","command":"npx skills add https://github.com/LeeYudok/doksam-skills/tree/main/skills/session-recording"},{"target":"claude-code","command":"claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install leeyudok-doksam-skills@llmmart"},{"target":"git","command":"git clone https://github.com/LeeYudok/doksam-skills.git"}]}