asciinema로 터미널 녹화하기: 텍스트 기반 경량 스크린캐스트

asciinema로 터미널 녹화하기: 텍스트 기반 경량 스크린캐스트

CLI 도구 사용법을 누군가에게 설명할 때 어떻게 하시나요? 스크린샷을 여러 장 찍어서 붙이거나 OBS로 화면을 녹화해서 영상 파일을 만들 수도 있겠죠. 근데 솔직히 터미널 화면 녹화하자고 동영상 편집 프로그램까지 꺼내는 건 좀 과하잖아요.

asciinema(아스키네마)는 이 고민을 깔끔하게 풀어줍니다. 터미널에서 일어나는 입출력을 텍스트로 녹화해서 MP4 같은 무거운 동영상 파일 대신 몇 KB짜리 텍스트 파일을 만들어주거든요. 녹화된 내용에서 텍스트를 복사할 수도 있고 웹 페이지에 임베드하거나 GIF로 변환하는 것도 간단합니다.

2011년 “ascii.io”라는 이름으로 시작한 프로젝트인데 2024년 9월에 3.0을 내놓으면서 Python에서 Rust로 완전히 재작성됐어요. 라이브 스트리밍까지 추가되면서 이제는 단순한 녹화 도구가 아니라 터미널 공유 플랫폼에 가깝습니다.

설치

macOS에서는 Homebrew로 간편하게 설치할 수 있습니다.

brew install asciinema

Linux라면 각 배포판의 패키지 매니저를 사용하면 돼요.

# Ubuntu/Debian
sudo apt install asciinema

# Fedora
sudo dnf install asciinema

# Arch Linux
sudo pacman -S asciinema

다만 패키지 매니저 버전은 아직 2.x일 수 있습니다. Rust로 재작성된 최신 3.x를 쓰고 싶다면 Cargo로 직접 빌드하는 방법이 있어요.

cargo install --locked --git https://github.com/asciinema/asciinema

Rust 1.82 이상이 필요합니다. 빌드하면 정적 바이너리가 나오기 때문에 별도 런타임 의존성 없이 바로 실행할 수 있어요.

Docker를 선호한다면 이미지도 제공됩니다.

docker pull ghcr.io/asciinema/asciinema

설치가 잘 됐는지 확인해봅시다.

asciinema --version

터미널 녹화

rec 명령어에 저장할 파일명을 지정하면 바로 녹화가 시작됩니다.

asciinema rec demo.cast

녹화가 시작되면 평소처럼 터미널을 사용하면 됩니다. 명령어를 입력하고 출력을 확인하는 모든 과정이 기록되죠. 녹화를 마치려면 exit를 입력하거나 Ctrl+D를 누르면 돼요.

특정 명령어의 실행 과정만 녹화하고 싶을 때는 -c 옵션이 유용합니다.

asciinema rec -c "npm test" test-run.cast

이렇게 하면 npm test가 실행되고 끝나는 시점에 자동으로 녹화가 멈춥니다. 데모 영상을 만들 때 딱 좋아요.

타이핑하다가 생각하느라 한참 멈추면 녹화 결과가 지루해질 수 있는데요. -i 옵션으로 아이들 타임(idle time)에 상한을 걸면 됩니다.

asciinema rec -i 2 demo.cast

이 경우 아무 입출력 없이 2초 넘게 멈춘 구간은 전부 2초로 잘려요. 실제로는 10초 동안 고민했더라도 재생할 때는 2초만 멈추는 거죠.

녹화 재생

녹화된 파일은 play 명령으로 터미널에서 바로 재생할 수 있습니다.

asciinema play demo.cast

Space 키로 일시정지하고 다시 누르면 재개됩니다. Ctrl+C로 재생을 중단할 수도 있어요.

URL을 넘겨서 asciinema.org에 올라간 녹화를 바로 재생하는 것도 가능해요.

asciinema play https://asciinema.org/a/123456

동영상 플레이어 없이 터미널 안에서 바로 돌려볼 수 있다는 게 참 편합니다.

.cast 파일 들여다보기

asciinema가 만들어내는 .cast 파일의 내부 구조를 살펴보면 이 도구의 철학이 잘 드러납니다. 3.0부터 도입된 asciicast v3 형식은 이렇게 생겼어요.

{"version": 3, "term": {"cols": 80, "rows": 24, "type": "xterm-256color"}, "timestamp": 1504467315}
[0.248, "o", "$ "]
[0.520, "i", "ls"]
[0.102, "o", "ls"]
[0.300, "o", "\nREADME.md  package.json  src/\n"]
[1.001, "o", "$ "]

첫 줄은 JSON 헤더로 녹화 환경 정보(터미널 크기, 타임스탬프 등)를 담고 있습니다. 이후 줄들은 [시간간격, 이벤트코드, 데이터] 형식의 이벤트예요.

이벤트 코드 "o"는 터미널 출력이고 "i"는 사용자 입력입니다. 시간 간격은 이전 이벤트로부터 몇 초 지났는지를 뜻해요. 이전 v2 형식에서는 절대 타임스탬프를 사용해서 중간에 이벤트를 삽입하거나 삭제하면 뒤따르는 타임스탬프를 전부 수정해야 했는데 v3에서는 상대 간격이라 편집이 훨씬 수월해졌습니다.

그 외에도 터미널 크기 변경을 나타내는 "r", 타임라인 마커를 찍는 "m", 세션 종료를 알리는 "x" 이벤트가 있습니다. #으로 시작하는 줄은 주석으로 처리되고요.

텍스트 파일이라 grep으로 검색하거나 sed로 수정하는 것도 가능합니다. 잘못 입력한 비밀번호가 녹화에 포함됐다면 텍스트 편집기로 해당 줄을 지워버리면 그만이에요. 동영상 파일이었으면 처음부터 다시 녹화했을 겁니다 😅

asciinema.org에 업로드

녹화 파일을 다른 사람과 공유하는 가장 간단한 방법은 asciinema.org에 업로드하는 거예요.

asciinema upload demo.cast

업로드하면 고유한 URL이 출력됩니다. 이 링크를 공유하면 누구나 웹 브라우저에서 녹화를 재생할 수 있어요.

다만 계정을 연결하지 않은 상태에서 업로드하면 7일 후에 자동 삭제됩니다. 영구 보존이 필요하다면 먼저 계정을 만들고 CLI를 연결해야 해요.

asciinema auth

이 명령을 실행하면 인증 URL이 출력되는데 브라우저에서 열어서 로그인하면 CLI가 계정에 연결됩니다. 이후 업로드하는 녹화는 계정에 귀속되어 삭제되지 않아요.

웹 페이지에 임베드하기

블로그나 문서에 터미널 녹화를 넣고 싶다면 asciinema-player를 사용합니다. npm으로 설치할 수 있어요.

bun add asciinema-player
# 또는
npm install asciinema-player

HTML에서는 이렇게 사용합니다.

<link rel="stylesheet" href="/asciinema-player.css" />
<div id="demo"></div>
<script src="/asciinema-player.min.js"></script>
<script>
  AsciinemaPlayer.create("/demo.cast", document.getElementById("demo"));
</script>

JavaScript 모듈로 가져와서 쓸 수도 있고요.

import * as AsciinemaPlayer from "asciinema-player";

AsciinemaPlayer.create("/demo.cast", document.getElementById("demo"));

플레이어에는 꽤 다양한 옵션이 있습니다.

AsciinemaPlayer.create("/demo.cast", document.getElementById("demo"), {
  autoPlay: true,
  loop: true,
  speed: 2,
  theme: "dracula",
  idleTimeLimit: 2,
  fit: "width",
  startAt: "0:30",
});

autoPlayloop로 자동 재생과 반복을 설정하고 speed로 재생 속도를 조절할 수 있어요. idleTimeLimit은 녹화 시 -i 옵션과 같은 효과인데 원본 녹화 파일은 건드리지 않고 재생할 때만 적용된다는 게 다릅니다.

theme으로 컬러 테마를 바꾸고 fit"width"로 설정하면 플레이어가 컨테이너 너비에 맞춰 크기를 조절해요. poster 옵션에 "npt:1:17" 같은 타임코드를 넣으면 재생 전에 보여줄 프레임도 지정할 수 있습니다.

한 가지 멋진 기능은 마커 지원이에요.

AsciinemaPlayer.create("/demo.cast", document.getElementById("demo"), {
  markers: [
    [3, "설치"],
    [10, "설정"],
    [20, "실행"],
  ],
  pauseOnMarkers: true,
});

녹화의 특정 시점에 마커를 달아두면 타임라인에 표시되고, pauseOnMarkers를 켜면 마커 지점에서 자동으로 일시정지합니다. 단계별 튜토리얼을 만들 때 유용해요.

플레이어는 JavaScript와 Rust(WebAssembly)로 구현되어 있어서 브라우저에서도 빠르게 돌아갑니다.

GIF로 변환하기

GitHub README나 슬랙 메시지처럼 웹 플레이어를 쓸 수 없는 곳에서는 GIF가 필요할 때가 있어요. agg(asciinema gif generator)가 .cast 파일을 애니메이션 GIF로 변환해줍니다.

cargo install --git https://github.com/asciinema/agg

사용법은 간단합니다.

agg demo.cast demo.gif

테마나 폰트, 재생 속도도 조절할 수 있어요.

agg --theme monokai --font-size 20 --speed 2 demo.cast demo.gif

gifski 라이브러리를 사용해서 GIF 품질이 꽤 좋고, 이모지도 지원합니다. asciinema.org URL을 직접 넣어서 변환하는 것도 가능해요.

agg https://asciinema.org/a/123456 demo.gif

라이브 스트리밍

3.0에서 추가된 stream 명령어로 터미널 세션을 실시간으로 공유할 수 있습니다.

로컬 네트워크에서 공유하려면 -l 플래그를 씁니다.

asciinema stream -l

내장 HTTP 서버가 뜨면서 로컬 URL이 출력됩니다. 같은 네트워크에 있는 사람이 브라우저로 접속하면 내 터미널 화면을 실시간으로 볼 수 있어요. 데이터가 외부 서버로 나가지 않으니 보안이 걱정되는 환경에서도 쓸 수 있습니다.

인터넷을 통해 공유해야 한다면 -r 플래그로 리모트 모드를 사용합니다.

asciinema stream -r

asciinema 서버를 경유하는 공유 가능한 URL이 생성돼요. 페어 프로그래밍이나 라이브 데모할 때 유용합니다.

둘을 동시에 켤 수도 있고요.

asciinema stream -l -r

녹화와 스트리밍을 동시에 하고 싶다면 session 명령어를 사용합니다.

asciinema session demo.cast -l

터미널 세션이 .cast 파일로 녹화되면서 동시에 로컬 스트리밍도 됩니다. 워크숍에서 참가자들이 실시간으로 따라보면서 나중에 녹화본으로 복습하게 하는 식으로 활용할 수 있어요.

여러 녹화 파일 합치기

튜토리얼을 여러 파트로 나눠서 녹화했다면 cat 명령어로 하나로 합칠 수 있습니다.

asciinema cat part1.cast part2.cast > combined.cast

3.x에서 cat의 의미가 바뀌었는데요. 2.x에서는 녹화의 원본 출력을 텍스트로 덤프하는 기능이었지만 3.x에서는 여러 파일을 이어붙이는 기능으로 변경됐어요. 원본 출력을 추출하려면 대신 convert 명령어를 사용합니다.

asciinema convert --output-format raw demo.cast

convert 명령어는 파일 형식 변환에도 쓰입니다. 2.x에서 녹화한 v2 파일을 v3로 변환할 때 유용해요.

asciinema convert old-v2.cast new-v3.cast

설정 파일

asciinema 3.x는 TOML 형식의 설정 파일을 사용합니다. 2.x의 INI 형식에서 바뀌었어요.

~/.config/asciinema/config.toml
[session]
idle_time_limit = 2
command = "/bin/zsh"

[session] 섹션은 rec, stream, session 명령어에 공통으로 적용됩니다. 2.x에서는 [record] 섹션이었는데 명칭이 바뀌었어요.

매번 -i 2 옵션을 붙이기 귀찮다면 설정 파일에 idle_time_limit을 넣어두면 됩니다.

셀프 호스팅 서버

asciinema.org를 사용하는 대신 자체 서버를 운영할 수도 있습니다. 사내 문서에 터미널 녹화를 넣어야 하는데 외부 서비스에 올리기 곤란할 때 유용해요.

Elixir/Phoenix 기반의 서버 소프트웨어가 Docker Compose로 배포할 수 있도록 제공됩니다.

git clone https://github.com/asciinema/asciinema-server.git
cd asciinema-server
cp .env.production.sample .env.production

.env.production 파일에 호스트명과 시크릿 키를 설정한 뒤 docker compose up을 실행하면 PostgreSQL, 서버, Caddy(리버스 프록시)가 한 번에 뜹니다.

CLI에서 자체 서버를 가리키게 하려면 환경 변수를 설정하면 돼요.

# 3.x
export ASCIINEMA_SERVER_URL=https://asciinema.example.com

# 2.x
export ASCIINEMA_API_URL=https://asciinema.example.com

서버에는 녹화 호스팅 외에도 라이브 스트리밍이나 전문 검색, 공개/비공개 설정 같은 기능이 들어 있습니다. Apache 2.0 라이선스라 상업적으로도 자유롭게 쓸 수 있어요.

동영상 녹화와 뭐가 다를까

OBS로 터미널을 녹화하면 되지 않느냐고 생각할 수 있는데 실제로 써보면 차이가 꽤 큽니다.

우선 파일 크기가 압도적으로 작아요. 1분짜리 터미널 세션을 MP4로 녹화하면 수 MB에서 수십 MB가 나오지만 asciinema는 보통 몇 KB면 됩니다. 텍스트만 저장하니까 당연하죠.

텍스트 복사가 된다는 것도 큰 장점이에요. 동영상에서 명령어를 따라 치려면 눈으로 보고 일일이 타이핑해야 하는데 asciinema 플레이어에서는 화면 텍스트를 마우스로 드래그해서 그대로 복사할 수 있습니다. 튜토리얼을 따라할 때 이게 얼마나 편한지 직접 써보면 바로 느낄 거예요.

해상도에 구애받지 않는 점도 있습니다. 동영상은 녹화 시점의 해상도에 고정되지만 asciinema는 재생 환경에 맞춰 텍스트를 렌더링해서 어떤 화면에서든 선명해요.

물론 한계도 있습니다. 터미널 바깥의 UI는 녹화할 수 없어요. 브라우저 화면이나 GUI 앱을 보여줘야 한다면 동영상 녹화를 써야 합니다.

마치며

asciinema는 터미널 녹화를 텍스트 기반으로 풀어낸 도구입니다. 파일 크기가 작고 텍스트 복사가 되고 웹에 가볍게 임베드할 수 있어요. 3.0에서 Rust로 재작성되면서 성능도 좋아졌고 라이브 스트리밍까지 생겼습니다.

CLI 도구의 README에 사용법 데모를 넣을 때, 기술 블로그에 터미널 예제를 보여줄 때, 팀원에게 환경 설정 과정을 공유할 때 한번 써보세요. asciinema rec 한 번 써보면 동영상 녹화 프로그램으로 돌아가기 어려울 겁니다.

더 자세한 내용은 asciinema 공식 문서를 참고하세요.

This work is licensed under CC BY 4.0 CC BY

개발자를 위한 뉴스레터

달레가 정리한 AI 개발 트렌드와 직접 만든 콘텐츠를 전해드립니다.

Discord