탭을 트레일로: 읽지 않은 탭이 나만의 노트북으로 만들어진 산책길이 되다
요약
이 시스템은 읽지 않은 브라우저 탭들을 MP3 오디오 '산책길'로 변환하는 방법을 제시합니다. 사용자가 원하는 청취 시간에 맞춰 여러 탭의 내용을 선별하고, Gemma 4가 텍스트를 재작성하며 Kokoro 음성이 이를 읽어줍니다. 이 과정은 기기 내에서 이루어져 별도의 인터넷 연결이나 앱이 필요 없습니다.
핵심 포인트
- 브라우저 탭을 오디오 콘텐츠로 변환하는 독창적인 시스템입니다.
- Gemma 4가 청취에 최적화되도록 텍스트를 재작성합니다.
- MP3 파일 하나에 인트로, 본문, 알림음 등 모든 경험이 담깁니다.
- 별도의 앱이나 와이파이가 필요 없는 오프라인 환경을 지향합니다.
내가 만든 것
저의 독서 시스템은 제목만 보고 시간이 아깝지 않을 것 같아 열어둔 브라우저 탭들로 시작했습니다. 그리고 그 탭들은 제가 하루를 보내는 장소인 의자처럼, 몇 주 동안 계속 열려 있었습니다.
'Tabs to Trails'는 이러한 탭들을 산책길로 바꿉니다. "Walk this tab"이라는 이름의 북마클릿(bookmarklet)은 현재 보고 있는 페이지를 목록에 담아내고, 각 행에는 그 내용을 듣는 데 걸리는 시간이 몇 분인지 보여줍니다. 제가 20분 정도 시간을 확보하면, 20분을 선택합니다. 앱이 적합한 순서대로 (가장 오래된 것부터) 체크하며, 각 부분이 어떻게 읽힐지("전체 내용", "27분 분량에서 요약됨", "3부작 중 1부") 알려주고, 제 노트북은 그 길이 정도의 MP3 파일을 하나 만듭니다. Gemma 4가 청취에 맞게 텍스트를 다시 작성하고, Kokoro 음성이 이를 읽어주며, 이 모든 과정이 제 기기에서 이루어집니다. 저는 휴대폰으로 QR 코드를 스캔하여 파일을 다운로드한 뒤, 휴대폰을 주머니에 넣습니다.
산책길에 필요한 모든 것은 MP3 파일 안에 담겨 있습니다: 짧은 인트로, 본문 내용, 중간 지점의 알림음("절반 왔어요. 왕복이라면 지금 돌아가세요."), 그리고 집으로 가는 길에 대한 질문 하나입니다. 이 파일이 휴대폰에 저장되면, 휴대폰은 별도의 앱이나 와이파이가 필요 없습니다. 저는 디자인에 하나의 규칙을 세웠습니다: 앱은 제가 문에 도착하기 전에 완성되어야 합니다. 제품에서 유일하게 어두운 화면은 휴대폰의 플레이어이며, 그곳에는 "휴대폰을 주머니에 넣으세요."라는 문구와 그 외 아무것도 없습니다.
이 시스템을 '기사(article)를 팟캐스트로' 변환하는 것과 차별화시키는 세 가지 요소가 있습니다. 사용자가 읽고자 했던 콘텐츠 자체를 가져옵니다. 산책의 길이가 내용을 형성합니다. 그리고 내용은 충실하게 유지됩니다: 음성은 쓰여진 대로 적절한 산문을 읽고, Gemma는 내용이 맞지 않는 부분만 요약하며, 숫자 가드(number guard)는 재작성된 모든 숫자가 원본과 일치하는지 확인합니다. 코드 블록이나 표는 소리로 읽히기에는 노이즈가 되기 때문에, 설명되는 방식으로 처리됩니다.
데모
프로젝트 페이지에서 완성된 두 번의 산책 듣기: 제가 작성한 DEV 게시물(10:00 요청, 측정값 10:15)과 소로(Thoreau)의 "산책 (Walking)" 중 일부(20:00 요청, 측정값 19:39).
영상 속 기사에 대한 참고 사항입니다. 이 글은 @sylwia-lask의 "모든 소프트웨어 개발자는 ~를 비난해 왔다(Every Software Developer Has Blamed…)"입니다. 제가 실제 사례 테스트로 선택했으며, 오디오 버전 중 약 20초가 영상에 포함되었습니다. 실비아에게 제 게시물을 예시로 사용하는 것이 괜찮기를 바랍니다 😇😇😇
전체 글을 읽어보세요:
모든 소프트웨어 개발자는 ~를 비난해 왔다(Every Software Developer Has Blamed…)
[
공감할 수 있는 기술 유머와 공유된 불만들
](https://dev.to/sylwia-lask/every-software-developer-has-blamed-3a1o)
실비아 라스코프스카
팔로우하기
모든 소프트웨어 개발자는 ~를 비난해 왔다(Every Software Developer Has Blamed…)
4분 분량 읽기
코드
GitHub logo nazboyko / tabs-to-trails
읽을 분량(reading backlog)을 산책으로 변환하기: 로컬 Gemma 4와 Kokoro가 당신의 산책에 맞는 MP3를 만듭니다.
Tabs to Trails
읽을 분량을 산책으로 바꿔보세요.
지금 탭을 저장하고, 나중에 걸으며 듣습니다.
Tabs to Trails는 당신이 읽어야 할 분량을 산책 시간으로 측정합니다. 20분이 있다면, 20분을 선택하고 시스템이 적합한 내용을 제안합니다. 이 과정에서 컴퓨터가 그 길이의 MP3 하나로 만듭니다: Gemma 4가 듣기 좋게 텍스트를 다시 작성하고, Kokoro 음성이 이를 읽어주며, 모든 것이 당신의 기기 내에서 이루어집니다. QR 코드를 스캔하고 휴대폰을 주머니에 넣고 나가면 됩니다.
이 파일에는 산책에 필요한 모든 것이 담겨 있습니다: 짧은 인트로, 본문 내용, 중간 지점 알림음(chime)과 방향 전환 시점을 알려주는 신호(cue), 집으로 돌아가는 길에 대한 질문 하나, 그리고 마무리 인사입니다. 이 장들은 휴대폰 자체 플레이어에서 일시 정지 및 건너뛰기가 가능하게 하며, 오디오북 파일(.m4b)은 한 번의 탭만으로 접근할 수 있습니다. 파일이 휴대폰에 저장되면, 산책을 위해 더 이상 필요한 것은 없습니다.
…
Node와 TypeScript: Hono 서버, React 프론트엔드, Ollama를 통한 Gemma 4, kokoro-js를 통한 Kokoro-82M, MP3용 ffmpeg가 사용됩니다. Gemma 4와 Kokoro-82M은 Apache-2.0 라이선스이며, 전체 크레딧과 라이선스는 README에 있습니다.
구축 과정(How I Built It)
파이프라인:
link 또는 텍스트를 목록에 저장하고 한 번 읽음
-> 산책 길이에 맞춰 선택됨
-> 계획: 전체 분량으로, 혹은 단어 예산에 맞게 압축
...
모든 단계는 산책당 하나의 폴더에 쓰기 때문에 빌드가 멈추더라도 중단된 지점부터 재개할 수 있습니다. 음성 녹음 단계 중간에 kill -9를 테스트해봤는데, 다시 시작했을 때 서버가
음성 우선(The voice first). 제 보정 과정은 250단어 분량의 부드러운 지문을 분당 188.7 단어로 읽었고, 이후 저의 DEV 게시물(DEV post)을 10분 동안 처리하여 10:42에 완료되었습니다. 이 하나의 게시물을 통해 같은 음성이 섹션별로 분당 130단어에서 174단어까지 변화했는데, 이는 숫자, 콜론(:), 그리고 짧은 단락이 시간을 소모하기 때문입니다. 반면, 초당 글자 수(characters per second)는 14.3에서 15.9 사이를 유지했습니다. 따라서 이제 앱은 숫자가 포함된 지문으로 초당 글자 수를 보정하고, 이를 각 출처별 분당 단어 수로 변환합니다.
다음은 모델(The model)에 대한 내용입니다. Gemma는 완만한 축소(mild cut) 시 단어 수를 유지하지 못합니다. 939단어 섹션 중 697단어를 요청했음에도 불구하고, 1,027단어가 반환되어 원본보다 길어졌습니다. 짧은 목표의 경우도 마찬가지였습니다. 소로로(Thoreau)의 1,037단어 중 823단어를 요청했지만, 450단어만 작성했습니다. 따라서 각 섹션은 한 번의 보호된 축소 또는 확장 과정을 거치며, 과하거나 부족한 부분은 다음 섹션으로 이어집니다. 마지막에, 적합한 과정(fit pass)은 측정된 오디오를 단 한 번 살펴봅니다. 5% 이상 초과하면 가장 압축된 섹션을 줄이고, 8% 이상 미달이면 가장 많이 빠진 섹션에 시간을 할당합니다.
위의 예시는 저의 DEV 게시물을 1,726단어에서 1,531단어로 줄였으며, Apple M5 Max에서 모델 처리 시간은 4.1초, 음성 출력 시간은 63.5초로 총 오디오 길이는 10:15입니다. Kokoro는 여기서 실시간보다 약 9배 빠르게 읽기 때문에, 대부분의 대기 시간은 음성 출력에 할애됩니다. 앱은 작동하는 동안
가드는 한때 정확한 숫자를 잘못 표시했습니다. 위키피디아의 "150 퍼센트"는 "150 percent"로 나왔지만, 가드는 이를 두 개의 숫자로 읽었습니다. 이제는 이들을 합산합니다. 또한 볼 수 없는 것도 놓칩니다. "애들 화면이 시간을 알려줬어"(즉, 나의 저녁 시간)은 아무 숫자 없이 "the kid screen showed the time"으로 나왔습니다. 스크립트 뷰의 바닥글에는 중요한 것은 검토하라고 되어 있고, 저는 그것을 진심으로 말합니다.
단어에 맞춰 읽기 진행 (Read-along that lands on the word)
Kokoro는 몇 문장 단위로 말하며, 앱은 각 그룹이 어디서 시작하는지 알고 있습니다. 그룹 내부에서 제 첫 번째 버전은 시간 간격을 문자별로 문장에 분배했습니다. 오디오의 일시 정지를 기준으로 측정했을 때, 이러한 시작점들은 평균 0.3초 정도 벗어났는데, 이는 잘못된 문장을 표시하기에 충분한 시간이었습니다. 이제 각 시작점은 목소리의 가장 가까운 실제 일시 정지로 이동하며, 더 긴 간격을 선호합니다. 두 가지 샘플에서 232개의 문장 시작점 중 231개가 최소 4분의 1초의 일시 정지 지점에 위치하며, 이는 목소리가 다시 커지기 40밀리초 전입니다.
고쳐진 부분 (What broke)
- Kokoro는 호출당 최대 510개의 음소 토큰(phoneme tokens)으로 읽고 나머지는 아무 말 없이 건너뛰었습니다. 돈에 관한 294자 청크는 1,237개의 음소였습니다. 이제 각 청크는 동일한 음소화기(phonemizer)로 측정되어 들어갈 때까지 분할됩니다.
- 위키피디아가 각주를 소리 내어 읽었습니다: 예시로 [12] 같은 인용 표시가 "twelve"라고 나왔습니다. 앱은 이제 참고 문헌 목록과 각주를 제거하고, 무엇을 제외했는지 이름을 언급합니다.
- 첫 번째 실행에서 HTML 주석을 읽었습니다. 저의 포스트는
<!-- Thanks for participating! -->로 끝나는데, 목소리가 그것을 말했습니다.
외부로 가져가기 (I took it outside)
저는 산책하는 모습을 촬영하지 않았습니다. 위의 비디오는 실제 오디오와 함께 녹화된 화면 기록입니다. 10분 및 20분간의 산책은 문제없이 진행되었습니다. 더 긴 시간 동안에는 전화 통화로 인해 "여기서 재생(Play it here)"이 중단되었고, 저는 페이지를 열고 다시 시작해야 했습니다. 따라서 긴 산책의 경우 다운로드된 MP3 또는 오디오북 파일이 더 좋은 방법입니다.
제가 잘라낸 것과 다음 계획 (What I cut and what's next)
저는 gemma4:e2b 모델 비교를 제외했습니다. 이 모델은 제 노트북에 없었고, 단지 한 표 때문에 모델을 다운로드하고 싶지 않았기 때문입니다. 다음으로 각 목소리별 속도 설정을 시도해보고, 오디오북 파일과 알림 기능을 저의 휴대폰보다 더 많은 기기에서 테스트할 예정입니다.
Open Innovation은 왜 중요할까요?
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기



