command-tracker는 스트리트파이터라는 1대1 격투 게임 영상에서 플레이어의 커맨드 입력을 자동 추출해 주는 서비스입니다.
일반적으로 커맨드가 영상에 포함되지 않은 경우, 녹화된 영상을 보며 수동으로 입력을 추정해야 하며, 이는 초보자에게 높은 진입장벽이 됩니다.
이 서비스는 RTMPose 기반의 관절 추출 모델과 후처리 로직을 활용하여, 플레이어의 동작을 분석하고 이를 커맨드로 변환, 최종적으로 자막 형태로 영상에 삽입해 줍니다. 이로써 초보자들도 원하는 캐릭터의 커맨드를 손쉽게 확인해 볼 수 있습니다.
RTM-Pose는 사람의 관절 위치를 추정해주는 최신 인체 포즈 추정 AI 모델입니다.
- 사용자가 분석할 유튜브 영상 주소를 입력하고 커맨드를 추출할 부분을 컷 편집할 수 있는 웹 UI 제공합니다.
- 사용자가 영상을 제출하고, 결과를 받을 이메일을 입력하는 인터페이스 제공합니다.
- 주요 기능
- 유튜브 영상 링크 입력 UI
- 이메일 입력 및 제출
- 클라이언트의 요청을 받아 저장하고, 작업 요청을 RabbitMQ로 발송하거나 결과를 수신하여 이메일로 최종 영상을 전송하는 Express API 서버입니다.
- 클라이언트와 AI 서버를 직접 연결하지 않고, 역할을 분담하여 유지보수성과 안정성을 증가. 이를 위한 중계 서버 역할을 합니다.
- 주요 기능
- Youtube 영상 다운로드 처리
- AI 서버로 작업 요청 메시지를 RabbitMQ에 발행
- 추출 완료된 최종 영상의 URL을 받아 이메일로 전송
- RabbitMQ로부터 수신한 작업 요청을 기반으로, RTM-pose로 관절 추출 및 커맨드 인식을 수행하는 Python 서버입니다.
- 고성능 모델을 실행하고 비동기 큐 기반으로 독립된 연산 서버가 필요하여 별도로 분리된 서버입니다.
- 주요 기능
- RTM-pose로 관절 위치 추정
- 관절 위치 정보를 기반으로 커맨드 추정
- 추정 결과를 자막에 담아 최종 영상 URL을 메시지 큐로 전송
영상 속 관절 추정을 하는 작업은 굉장히 오래 걸리는 작업입니다. 웹 요청으로 처리할 때 요청과 응답이 될 때까지 기다려야 할 뿐만 아니라 양측 서버 모두 안정성에 악영향을 끼칠 수 있습니다. 영상 분석 작업을 분리함으로써, 서버의 안정성을 확보했습니다.
AI 서버는 단순히 큐를 소비하고, 결과물을 응답만 하면 되기 때문에, 웹 프레임워크 없이 동작할 수 있습니다. 이에 따라 AI 서버가 가벼워지고 라우팅 처리, HTTP 처리 등을 하지 않고 영상 분석 같은 주 로직에만 집중할 수 있습니다.
POC 과정에서 여러 관절 추정 모델을 검토한 결과, RTM-Pose가 속도와 정확성 모두에서 우수했습니다. 해당 모델을 사용하기 위해서는 PyTorch 환경이 필요했고, 이를 기반으로 모델 로드·추론·후처리 과정을 안정적으로 구현할 수 있었습니다.
- AI 서버: 캐릭터별 모델 학습 한계를 좌/우 구분 방식으로 전환하고, 관절 추정 기반 커맨드 인식 로직을 구현
- 웹 서버:
.mp4
포맷에서 발생하던 스트리밍 저장 오류를.webm
으로 전환해 안정화하고, 편집 처리 구조를 단순화 - 클라이언트: 긴 영상 컷 편집 시 썸네일 개수가 누락되는 문제를, 프레임 로드 완료 후 순차 캡처 방식으로 개선
게임 속 캐릭터의 커맨드를 추정하려면, AI가 해당 캐릭터의 자세를 인식하고 이를 관절 데이터로 변환해야 했습니다.
하지만 대상이 실제 인물이 아닌 게임 캐릭터이기 때문에, 사람으로는 불가능한 과장된 동작이나 사람과 다른 신체 구조로 인해 관절 추정 정확도가 낮아지는 문제가 발생했습니다.
초기에는 팀원과 함께 약 3,000장의 이미지를 라벨링하여 하나의 캐릭터를 객체 식별할 수 있도록 학습했습니다.
이 방식은 외형이 고정된 경우 높은 정확도를 보였지만, 스킨 변경이나 다른 캐릭터로 전환될 경우 인식률이 크게 저하되었고, 게임 전체 캐릭터 다양성을 고려하면 확장성이 떨어졌습니다.
범용성과 유지보수를 위해 캐릭터를 좌측/우측으로 단순 구분하는 구조로 변경했습니다.
게임이 1:1 구조이므로, 사용자가 분석 요청 시 좌/우를 선택하면 이를 기준으로 후속 AI 분석이 진행됩니다.
관절 추정에는 RTMPose
를 사용하였으며, 프레임 단위로 2D 관절 좌표를 얻어 어깨–팔꿈치–손목의 각도를 계산하는 방식으로 특정 동작을 판별했습니다.
현재는 좌/우 선택을 사용자가 직접 해야 하며, 플레이 도중 위치가 바뀌면 대응이 어렵습니다.
프레임 단위 위치 추적이나 ID 매칭 로직으로 자동화할 수 있으나, 개발 비용과 정확도 문제로 서비스 적용은 보류 중입니다.
또한 캐릭터별 30개 이상의 동작 판별 로직을 수동 정의해야 하므로 유지보수 비용이 높지만, 판별 기준을 세밀하게 조정할 수 있는 유연성은 확보하고 있습니다.
커맨드 추정이 완료되면, 해당 커맨드를 게임 영상에 시각적으로 표시하여 사용자가 직관적으로 확인할 수 있도록 구현했습니다.
표시 방식은 실제 격투 게임의 입력 기록 UI에서 착안하여, 새로운 커맨드가 이전 커맨드 위에 누적되어 쌓이는 스택형 자막 방식을 목표로 했습니다.
위치 제어와 스타일링을 정밀하게 하기 위해 .srt
대신 .ass
자막 포맷을 선택했고,
시간 코드와 자막 스타일을 동적으로 생성하여 ffmpeg로 영상에 삽입하는 방식을 구현했습니다.
이 구조를 통해 누적 표시는 정상적으로 작동했지만, 실제 게임 UI와는 레이아웃과 타이포그래피가 달라서 몰입감이 떨어졌고,
커맨드 흐름이 한눈에 들어오지 않아 가독성 문제가 있었습니다. 특히 긴 입력 기록이 쌓일 경우, 화면이 과도하게 복잡해지는 부작용도 있었습니다.
스택형 대신 구간형 자막 방식을 적용해, 커맨드가 특정 시간 구간에만 표시되도록 변경할 계획입니다.
또한 자막의 위치와 스타일을 게임 UI에 더 가깝게 조정하고, 표시 개수를 제한하여 시각적 부담을 줄이는 방향으로 개선할 예정입니다.
이를 통해 커맨드 흐름을 명확하게 전달하고, 사용자 경험과 몰입감을 동시에 향상시키는 것이 목표입니다.
사용자가 입력한 유튜브 링크에서 원하는 구간만 잘라 커맨드 추정에 사용하는 기능이 필요했습니다.
유튜브 영상의 길이는 다양하고, 전체 영상을 처리하기에는 자원 낭비가 크기 때문에 컷 편집은 필수였습니다.
처음에는 ffmpeg
를 사용하여 유튜브 스트림을 그대로 pipe 처리하였고, 출력 확장자는 일반적으로 많이 사용하는 .mp4
를 선택했습니다.
그러나 이 방식에서는 영상이 저장되지 않거나, 저장되더라도 영상이 깨지거나 디코딩 오류가 발생하는 문제가 반복되었습니다.
초기에는 스트림 처리 방식 자체에 문제가 있다고 판단하여, 임시 디렉터리에 파일로 저장한 후 편집을 수행해 보았습니다.
이 방식은 안정적으로 동작했지만, 사용자 요청마다 서버에 영상 파일이 남는 문제가 있었습니다.
이에 문제의 근본 원인을 찾기 위해 확장자를 조사하였고, 스트리밍 환경에 적합한 포맷인 .webm
의 존재를 확인했습니다.
실험 결과 .webm
확장자를 사용할 때 pipe 스트리밍 방식에서도 영상이 안정적으로 저장되고 편집되는 것을 확인하였고, 이를 최종 구조로 채택하였습니다.
현재는 Node.js 서버에서 클라이언트로부터 전달받은 시작 점과 종료 점을 기반으로 ffmpeg
명령어를 실행하고, .webm
포맷으로 출력된 편집 영상 파일을 Google Cloud Storage 버킷에 업로드하고 있습니다.
현재 컷 편집에만 수십 초가 소요되어 사용자 응답이 지연되는 문제가 있습니다.
해상도를 낮추면 속도는 빨라지지만, 사용자 경험과 AI 영상 분석 성능에 악영향을 끼칠 수 있습니다.
따라서 요청 시 우선 성공 응답을 반환하고, 이후 내부적으로 컷 편집과 분석을 진행하는 비동기 처리 방식으로 UI를 개선할 계획입니다.
긴 영상에서 타임라인 썸네일을 일정 간격으로 생성할 때, 화면에 표시해야 하는 개수와 실제 생성된 개수가 맞지 않는 문제가 발생했습니다. 특히 마지막 썸네일이 누락되는 문제가 있었습니다.
문제 원인은 프레임 로드 시점에 있었습니다. 영상이 특정 시점으로 이동(seek)되었을 때, 해당 프레임이 완전히 로드되기 전에 다음 시점으로 이동하면 일부 구간이 건너뛰어져 캡처되지 않았습니다. 이런 문제로 프레임 로드에 실패한 경우, 에러가 발생하여 영상 트리머에 썸네일이 나타나지 않았습니다.
화면 너비와 썸네일 크기를 기준으로 생성 개수를 미리 계산하여 간격을 일정하게 유지하였으며, 각 시점의 프레임이 완전히 로드된 후에만 다음 캡처를 진행하도록 순차적으로 처리했습니다.
긴 영상일수록 초기 썸네일 생성 시간이 길어집니다. 이를 개선하기 위해 다음 방안을 고려하고 있습니다.
- 사용자가 처음 확인하는 화면 구간부터 우선 생성하는 점진 로딩
- 해상도와 성능에 맞춰 썸네일 개수를 동적으로 조정
브랜치 전략은 Github Flow 전략을 채택했습니다. Git Flow는 develop, release, hotfix 등 브랜치가 많아서 관리가 복잡하고 작은 팀에서는 오히려 비효율적이라 생각했습니다. 반면 Github Flow는 main 브랜치를 기준으로 병합하기 때문에 빠른 개발 사이클을 가져갈 수 있어 개발 기간을 확보할 수 있다고 생각하여 적합하다고 판단했습니다. 머지는 스쿼시 머지를 사용하여 깃 히스토리를 단순화했습니다.
모든 PR은 관련 이슈 번호를 링크 형태로 포함하고, 팀의 PR 템플릿을 준수했습니다.
PR 제목은 변경 사항을 한 줄로 요약해 스쿼시 머지 시 커밋 메시지로 바로 사용할 수 있도록 작성했습니다. 본문에는 변경 요약과 체크리스트, 그리고 코드 리뷰어가 중점적으로 확인해야 할 지점을 간결하게 기술했습니다. 스쿼시 머지인 만큼, github 규칙을 이용해서 main 브랜치 병합을 막고, 최소 1명의 승인 후에만 병합하여 실수성 병합을 예방했습니다.
감정이 아닌 사실과 재현 가능한 근거를 기준으로 소통했습니다. 표현이 모호하거나 날카롭게 느껴지면 즉시 어조를 정정했고, 의도 확인 질문을 먼저 던진 뒤 의견을 제시했습니다. 덕분에 팀원이 겪는 문제의 원인을 빠르게 합의했고, 해결 방안을 신속하게 도출할 수 있었습니다.
수정 사항은 회의에서 공유해 합의 후 진행했고, 필요 시 관련 링크나 스크린샷 등 참고 자료를 함께 제공했습니다. 코드에서는 특히 변수명, 함수명이 길어지더라도 명확하게 작성하여 어떤 의도를 가진 변수인지 파악할 수 있게 하고자 했습니다. 그 결과 코드 리뷰에 불필요한 시간이 줄었고, 토론 핵심 주제에 집중할 수 있었습니다.
진행 기간 : 5주
팀원 : 차준우, 조성경 (총 2명)
- 1주차
- 아이디어 선정
- POC 진행 - 캐릭터의 커맨드를 추정하기 위한 관절 데이터 추출 성능 확인
- 2주차
- POC 진행 - 캐릭터의 커맨드를 추정하기 위한 관절 데이터 추출 성능 확인
- 칸반 작성
- 기술 스택 조사
- 3주차
- 프로젝트 환경 세팅
- 공통 컴포넌트 구현
- 영상 편집 구현
- 영상 업로드 구현
- 결과물 확인 링크 메일 전송 구현
- 4주차
- 영상 분석하여 관절 데이터 추출 구현
- Re-ID 성능 테스트
- 동작 학습 데이터 수집 및 AI 기반 커맨드 추출 테스트
- 관절 데이터 기반 커맨드 추출 구현
- 5주차
- 배포
이번 프로젝트에서는 ‘쓰고 싶은 기술’에 맞춘 주제가 아니라 누군가의 문제를 해결하는 데 집중했습니다. 그 결과 기능을 하나씩 완성할 때마다 사용자의 불편이 실제로 줄어드는지 빠르게 검증하고, 그에 따라 우선순위를 유연하게 조정할 수 있었습니다. 무엇보다 사용자가 겪는 문제를 명확히 정의하고 그에 맞는 해결책을 설계하는 일이 제품 완성도를 좌우한다는 점을 체감했습니다.
특히 AI 파트는 캐릭터별 학습에서 좌/우 구분 구조로 전환해, 정확도 극대화보다 유지보수성과 확장성을 우선했습니다. 덕분에 라벨링·재학습 부담을 줄였고, 신규 캐릭터나 패치 변화에도 안정적으로 대응할 수 있었습니다.
핵심 기능의 가장 기초가 AI 성능이었고, 그 성능에 따라 프로젝트의 실현 가능성이 갈렸습니다. 그래서 POC 단계에서 완벽함을 지나치게 추구했고, 그 결과 시간이 과도하게 소요되어 UX 개선과 코드 정리에 집중하지 못한 점이 아쉽습니다.
다음에는 초기부터 임시 성능 기준을 정해 POC를 기간 내 마무리하겠습니다. 달성한 성능을 전제로 제품 가치를 극대화하는 방향을 함께 설계하고, UX·코드 품질을 병행해 개선하는 흐름을 유지하겠습니다.
- 커맨드 조건 정교화로 정확도 향상
- 스택형 자막 → 구간형 자막 개선
- 영상 처리 구조를 비동기화해 UX 개선