소리꽃 KeyBloom TIL 9
영상 내보내기를 실시간 녹화에서 한 장씩 그려 내는 방식으로 바꾸고, 얇던 피아노 소리를 다시 만들며 나온 것들.
실시간에서 푸는 것
시간을 내주고 품질을 산다
내보내기가 화면을 실시간으로 녹화하는 방식이었다. 재생 속도대로 흘러가며 찍으니 무거운 설정에서는 컴퓨터가 못 따라가 장면이 군데군데 빠진다. 앞선 TIL 1에서 초기 버전엔 충분하다고 보고 “결과물 품질이 중요해지면 돌아온다”며 미뤄 둔 바로 그 자리다.
한 장씩 그려서 인코더에 넣는 방식(오프라인 렌더)으로 바꿨다. 시계를 보고 찍는 게 아니라 “몇 번째 프레임”으로 시간을 만드니, 기기가 느리면 오래 걸릴 뿐 빠지는 장면이 없다.
여기서 사용자에게 제안하는 거래가 바뀐다. 전에는 “빠르지만 기기에 따라 결과가 다름”이었고 지금은 “오래 걸리지만 결과는 항상 같음”이다. 결과물을 남에게 보여 줄 물건으로 만드는 도구라면 뒤쪽이 맞다. 실시간이 꼭 필요한 건 미리 보는 동안뿐이다.
사용자는 오래 걸리는 작업 중에 딴짓을 한다
영상 하나 뽑는 데 몇 분이 걸리면 사용자는 그 앞에 앉아 기다리지 않는다. 다른 창을 보러 간다.
그런데 브라우저는 사용자가 안 보는 탭의 작업을 일부러 늦춘다(백그라운드 스로틀링). 배터리를 아끼려는 것인데, 우리 입장에서는 사용자가 다른 창을 보는 동안 작업이 기어가는 셈이다. 소리 쪽도 같은 이유로 끊겼다.
오래 걸리는 작업을 만들 때는 “사용자가 이걸 보고 있지 않을 것”을 전제로 삼아야 한다. 그 전제 위에서 멈추지 않게 만드는 방법을 찾고, 끝나면 알려 줄 방법도 같이 생각해야 한다.
결과물이 크면 메모리에 쌓지 말고 흘려보낸다
긴 영상은 완성 파일이 수 GB가 된다. 다 만들어 놓고 마지막에 저장하는 방식이면 그 전부가 메모리에 있어야 하고, 어느 길이부터는 그냥 터진다.
그래서 만들면서 바로 디스크로 흘려보내게 했다(스트리밍 쓰기). 완성될 때까지 메모리에 있는 건 지금 만드는 조각뿐이다.
결과물 크기가 입력에 따라 커지는 기능은 어느 지점에서 한계가 오는지를 초기에 확인해야 한다. 짧은 것으로만 테스트하면 정상으로 보이고, 사용자는 대개 긴 것을 넣는다.
흉내와 진짜
흉내 내는 것보다 진짜를 가져오는 게 빠를 때가 있다
피아노 소리가 얇아서 제대로 만들어 보기로 했다. 실제 현이 울리는 원리를 따라 배음(기본음 위에 겹치는 정수배 진동)을 쌓고, 소리 크기가 시간에 따라 변하는 곡선(엔벨로프)을 때리는 순간과 여운 두 단으로 나누고, 세게 칠수록 밝게 들리도록 고음을 깎는 필터를 세기에 연동했다. 확실히 나아졌다.
그런데도 전자 피아노 느낌이 남았다. 결국 실제 피아노를 녹음한 소리로 통째로 갈아탔다. 몇 개 음만 녹음해 두고 그 사이는 재생 속도를 바꿔 음정을 맞추면(피치시프트) 88건반이 다 커버된다. 이렇게 여러 음을 나눠 녹음해 쓰는 방식을 멀티샘플링이라고 한다.
들인 시간이 아깝지만, 만들어 보고 나서야 “이 방향으로는 한계가 있다”를 알았다. 다시 한다면 순서를 바꿀 것 같다. 흉내로 어디까지 되는지 짧게 확인하고, 목표 수준이 그보다 높으면 처음부터 진짜를 가져오는 쪽으로 간다.
판단 기준은 “만들 수 있나”가 아니라 “우리가 원하는 수준이 흉내로 도달 가능한 범위 안인가”다. 소리·질감처럼 사람이 진짜를 아주 잘 아는 영역은 대개 범위 밖이다.
제한과 알림
제한은 우회 경로까지 본다
무료 버전에는 결과물에 워터마크를 남긴다. 처음엔 뽑은 영상에만 넣었는데, 그러면 화면을 다른 녹화 프로그램으로 찍으면 표시 없는 영상이 나온다.
그래서 미리보기 화면에도 같이 그렸다. 화면을 찍어도 표시가 따라간다.
제한을 걸 때는 “이걸 피하려면 어떻게 하겠나”를 한 번 생각해 봐야 한다. 완전히 막을 수는 없지만, 가장 쉬운 우회로 하나를 막는 것만으로 대부분이 걸러진다. 반대로 그 하나를 안 막으면 제한 자체가 의미를 잃는다.
사용자가 잃을 수 있는 것은 미리 알린다
이 앱은 작업을 서버에 저장하지 않는다. 새로고침하면 하던 작업이 사라진다.
이걸 안내에 명시했다. 구조를 바꿔 자동 저장을 넣는 게 더 좋겠지만, 그전까지는 최소한 알려야 한다. 알리지 않으면 사용자는 저장되는 줄 알고 작업하다 잃는다.
제품에 “이렇게 하면 잃는다”는 지점이 있으면 그건 알림 대상이다. 고칠 수 없어서 안 알리는 것과 고칠 때까지 알리는 것은 다르다.
자기완결과 규모
프로젝트 파일은 그것만으로 열려야 한다
작업 파일에 반주 음원을 통째로 넣었다. 경로만 기록하면 파일 크기는 작지만, 다른 컴퓨터에서 열면 음원을 못 찾는다. 웹에서는 애초에 경로를 기억할 수도 없다.
프로젝트 파일은 사용자가 남에게 보내거나 다른 기기로 옮기는 물건이다. 열었을 때 그것만으로 완전하지 않으면 사용자는 “파일이 깨졌다”고 받아들인다. 용량이 커지는 건 그다음 문제다.
규모가 작으면 정석이 아니라 가벼운 쪽이 맞다
다국어를 넣을 때 보통은 문구를 딕셔너리에 모아 두고 키(이름표)로 불러 쓴다. 규모가 커지면 그게 맞다.
이 앱은 문구가 많지 않아서, 문구가 필요한 자리마다 한국어와 영어를 나란히 적는 방식으로 갔다. 번역이 코드 옆에 있으니 문맥이 안 흩어지고, 새 문구를 추가할 때 파일을 오갈 일이 없다.
정석은 대체로 큰 규모를 전제로 만들어진다. 우리 규모가 그 전제 안에 있는지 먼저 보고, 아니면 가벼운 쪽을 골라도 된다. 나중에 커지면 그때 옮기는 비용이, 지금 무겁게 시작하는 비용보다 싼 경우가 많다.
기기(GPU)마다 지원하는 코덱 프로파일(영상 압축 규격의 화질 등급)이 달라서, 가장 좋은 것부터 시도하고 안 되면 한 단계씩 낮추는 폴백을 뒀다. 사용자 기기를 우리가 고를 수 없는 이상, “제일 좋은 것”을 고정으로 요구하면 누군가는 아예 못 쓴다.
요약
- 실시간에서 풀면 시간을 내주고 결과 품질을 산다 — 남에게 보여 줄 결과물이면 그 거래가 맞다
- 오래 걸리는 작업은 사용자가 안 보고 있을 것을 전제로 만든다
- 결과물 크기가 입력에 따라 커지면 한계 지점을 초기에 확인한다
- 흉내로 도달 가능한 범위를 먼저 재 본다 — 사람이 진짜를 잘 아는 영역은 대개 범위 밖이다
- 제한을 걸 땐 가장 쉬운 우회로 하나는 같이 막는다. 안 막으면 제한이 의미를 잃는다
- 잃을 수 있는 지점은 고치기 전까지 알린다
- 프로젝트 파일은 그것만으로 열려야 한다. 용량은 그다음 문제다
- 정석은 큰 규모를 전제로 한다 — 우리 규모가 그 전제 안인지 먼저 본다