Whatnot 또는 Fanatics Live 방송 분석하기
cardstream은 Whatnot, Fanatics Live를 비롯한 어떤 마켓플레이스에도 로그인하지 않습니다. 여러분이 이미 그곳으로 보내고 있는 것과 같은 영상을 여러분의 머신에서 지켜보며, 테이블에 올라오는 모든 카드의 이름을 알려 줍니다. 아무것도 없는 상태에서 라이브 오버레이까지 가는 전체 과정을 정리했습니다. 처음 한 번, 약 15분이면 됩니다.
카메라 근처의 컴퓨터
macOS, Linux, Windows 중 하나. 이미 OBS를 돌리고 있는 컴퓨터가 있다면 그 머신이 적임입니다. 분석은 로컬에서 이루어지므로 영상을 어디로도 보낼 필요가 없습니다.
이미 송출 중인 영상
OBS 장면, 웹캠, 캡처 카드, 인코더 중 무엇이든. cardstream은 지금 있는 것을 그대로 가져옵니다. 방송을 다시 세팅하라고 요구하지 않습니다.
Ximilar API 키
시스템 전체에서 유일한 자격 증명이며, 여러분의 머신 밖으로 나가지 않습니다. 마켓플레이스 계정도, 비밀번호도, 채팅에 들어오는 봇도 없습니다.
단독으로 실행해 보기
방송에 연결하기 전에, 노트북 웹캠으로 제대로 동작하는지 먼저 확인하세요. 명령어 세 개면 됩니다.
설치하기
이 스크립트는 ~/.cardstream에 가상 환경(venv)을 만들고, 릴리스 wheel을 체크섬으로 검증하고, 모델 가중치를 받아 온 뒤, 명령어를 PATH에 추가합니다. wheel, Docker, 소스 설치는 다운로드 페이지에 있습니다.
$ curl -fsSL https://raw.githubusercontent.com/Ximilar-com/cardstream/main/scripts/install.sh | sh 키 추가하기
식별은 기본적으로 Ximilar collectibles/v2를 통해 이루어지며, 그 자리에 자체 시스템을 쓸 수도 있습니다. 읽어 들이는 환경 변수는 XIMILAR_API_KEY 하나뿐입니다. 방송 당일에 재부팅해도 남아 있도록 셸 프로필에 넣어 두세요.
$ export XIMILAR_API_KEY=your-key
노트북에 카드 들어 보이기
이 명령어는 내장 웹캠으로 브라우저 UI를 엽니다. 카드를 잠깐 가만히 들고 있어 보세요. 오버레이에 상태 머신이 판단하는 과정이 보이고, 이어서 이름, 세트, 신뢰도가 나타나며, 매칭 결과 옆에는 식별 호출에 걸린 실제 시간이 표시됩니다. 이것이 제품의 전부입니다. 이 페이지의 나머지는 픽셀을 어디서 가져올지에 관한 이야기일 뿐입니다.
$ cardstream-web # → http://127.0.0.1:8001
방송에 연결하기
아래에서 한 줄을 고르세요. 어느 것을 고를지는 질문 하나로 결정됩니다. 데스크톱에서 방송하시나요, 아니면 휴대폰에서 하시나요?
할 수 없는 것
공개된 Whatnot이나 Fanatics 재생 페이지에 cardstream을 향하게 하는 것. 자기 방송의 송출 스트림 URL은 존재하지 않으며, 플레이어를 스크래핑하면 플랫폼 약관 문제에 더해 몇 초의 지연 시간까지 생깁니다. 아래의 모든 경로는 마켓플레이스보다 상류에서 영상을 가져옵니다. 바로 그래서 cardstream에는 마켓플레이스의 계정도, 비밀번호도, API 키도 필요 없습니다.
OBS 가상 카메라
OBS는 합성된 장면을 일반 웹캠처럼 운영체제에 보여 줄 수 있습니다. cardstream은 그것을 다른 카메라와 똑같이 엽니다. 두 번째 인코딩도, 인코더의 추가 부하도, ffmpeg 설치도 필요 없습니다.
- OBS의 제어 독에서 가상 카메라 시작을 클릭하세요.
- 그것을 웹캠 인덱스로 지정해 cardstream을 실행합니다. 인덱스 0은 보통 내장 카메라이므로 가상 카메라는 대개 1입니다. 자신의 장면이 보일 때까지 0, 1, 2를 차례로 시도하세요.
$ cardstream-web --source 1 방송 중이 아니라 방송 전에 한 번 시험해 두세요. macOS에서는 터미널에 카메라 권한이 필요하며, 사용 중인 머신에서 OpenCV가 가상 장치를 열지 못한다면 어디서나 동작하는 경로 B를 쓰면 됩니다.
OBS의 두 번째 출력
cardstream이 여러분의 머신에서 대기하고, OBS가 그곳으로 사본을 밀어 넣습니다. Whatnot이나 Fanatics는 이전과 정확히 같은 것을 계속 받습니다. 이것은 추가 대상이지, 리디렉션이 아닙니다.
- 먼저 리스너를 시작합니다. 푸시를 기다리다가 끊기면 스스로 재연결합니다.
- OBS의 방송 출력은 하나뿐이므로 사본은 두 번째 출력에서 보냅니다.
obs-multi-rtmp플러그인을 쓰거나, 설정 → 출력 → 녹화 → 사용자 지정 출력(FFmpeg)에서 유형을 URL로 출력, URL을rtmp://127.0.0.1:1935/live, 컨테이너를flv로 지정한 뒤 녹화 시작을 누르세요. - 이 경로는 시스템의 ffmpeg 바이너리를 호출합니다. 먼저
brew install ffmpeg를 실행하세요.
$ cardstream-web --listen \ --source rtmp://0.0.0.0:1935/live
테이블 전용 카메라
휴대폰에서 앱으로 바로 송출하면 분기할 영상이 없습니다. 그러니 송출 스트림을 쫓는 대신, 같은 테이블을 보는 cardstream 전용 시점을 마련하세요. 머리 위의 두 번째 웹캠이든, 카메라의 HDMI 출력을 캡처 카드에 연결하든 좋습니다.
- 카드를 공개하는 자리에 웹캠이나 캡처 카드를 향하게 하세요.
- 그 카메라 옆에 있는 머신에서 실행합니다.
$ cardstream-web --source 0 구매자가 보는 앵글일 필요는 없습니다. 조명이 좋은 근접 오버헤드 샷이 압축된 마켓플레이스 피드보다 훨씬 더 잘 식별됩니다.
URL이 있는 것이라면 무엇이든
rtsp://, rtmp://, srt://는 직접 가져오며, 직접 만든 장비라면 ws:// JPEG 피드도 됩니다. 재연결은 상한이 있는 백오프로 이루어지므로, 브레이크 도중 스튜디오 회선이 끊겨도 손대지 않아도 되돌아옵니다.
- 인코더가 이미 내보내고 있는 URL을 지정합니다.
- 브라우저 페이지는 수동적인 뷰어가 됩니다. 브라우저를 열어 두지 않아도 분석은 계속 돌아갑니다.
$ cardstream-web \ --source rtsp://studio/stream1
오늘 방송에 맞게 튜닝하기
기본값도 충분히 믿을 만하지만, 브레이크는 평범한 카메라 피드가 아닙니다. 무엇을 개봉할지는 보통 열기 전에 이미 알고 있으니까요.
무엇을 브레이크하는지 알려 주기
게임이나 세트를 미리 지정하면 검색 범위가 좁아져 호출은 빨라지고 매칭은 정확해집니다. 규칙은 하나입니다. --game을 넘길 때는 반드시 --alphabet도 함께 넘기세요. 게임을 지정하면 엔드포인트 자체의 문자 체계 감지가 꺼지고 라틴 문자로 가정하기 때문에, 일본어 카드가 영어판에 매칭되어 버립니다.
$ cardstream-web --source 1 \ --game "Pokémon" --alphabet japanese --set-code M4
방송 중에 바꾸기
다음 로트가 다른 게임이어도 아무것도 재시작할 필요가 없습니다. 카테고리, 게임, 세트 코드, 문자 체계, 결과 임계값, 선명도 임계값은 방송이 돌아가는 동안에도 브라우저 설정 대화 상자에서 바꿀 수 있습니다. 그 밖의 것(디텍터, 게이트, 해상도)은 시작할 때 한 번만 읽히므로 지금 정해 두세요.
로그는 남기고, 포트는 닫아 두기
--split-results를 붙이면 반복 등장을 합치지 않고 등장할 때마다 한 줄씩 기록합니다. 보여 준 순서대로 정리된 목록이 만들어지므로 나중에 주문과 대조하기 좋습니다. --host는 기본값 127.0.0.1 그대로 두세요. 이 프로세스는 여러분의 키를 갖고 있고 로컬 UI에는 인증이 없으므로, LAN에서 접근할 수 있게 해서는 절대 안 됩니다.
$ cardstream-web --source 1 --split-results 다음 날 아침을 위해 방송 저장하기
--ximilar-stream NEW를 추가하면 그 기록의 모든 행(카드, 가격, 방송에 머문 시간, 식별에 쓰인 크롭)이 방송하는 동안 여러분의 Ximilar 계정 안의 세션에 저장됩니다. 방송이 끝나면 Ximilar 앱의 Cardstream 섹션에서 방송 전체(총 가치, 가장 값비싼 카드, 이미지가 붙은 모든 카드)를 볼 수 있고, 바로 그곳에서 팔린 카드를 표시하고 잘못된 매칭을 바로잡습니다. 방송 도중에 클라이언트가 재시작되면 NEW 대신 출력된 세션 id로 다시 시작하세요. 같은 방송이 그대로 이어집니다. 팀 워크스페이스에 저장하려면 --ximilar-workspace를 쓰세요.
$ cardstream-web --source 1 --price-stats --ximilar-stream NEW # 재시작한 뒤: $ cardstream-web --source 1 --price-stats --ximilar-stream <session-id>
이제 방송을 진행하세요. 감지, 움직임 판정, 동일성 게이트는 모두 여러분의 머신에서 로컬로 돌아가고, 식별 호출은 테이블에 올린 카드 한 장당 한 번만 나갑니다. 한 시간에 약 100회로, 그 한 시간에 담긴 54,000프레임과 비교해 보세요. 계산은 여기에 있습니다.
실제로 일어나는 여섯 가지 문제
가상 카메라가 목록에 없습니다
--source 0, 1, 2를 차례로 시도하세요. 인덱스는 OS가 배정하는 값입니다. macOS에서는 시스템 설정 → 개인정보 보호 및 보안에서 터미널에 카메라 접근을 허용하세요. 그래도 OpenCV가 열지 못한다면 경로 B로 바꾸세요.
“ffmpeg not found”가 표시됩니다
시스템 바이너리를 호출하는 것은 --listen과 --ffmpeg뿐입니다. 설치(brew install ffmpeg)한 뒤 다시 실행하세요. 가상 카메라, 웹캠, 단순 풀 경로에는 추가로 필요한 것이 없습니다.
OBS에서 두 번째 스트림을 추가할 수 없습니다
이것은 cardstream이 아니라 OBS의 한계입니다. 방송 출력이 하나뿐이기 때문입니다. obs-multi-rtmp 플러그인은 진짜 추가 대상을 만들어 주고, 경로 B의 사용자 지정 출력(FFmpeg) 녹화 방식은 기본 OBS만으로 동작합니다.
카드는 찾지만 매칭이 전혀 되지 않습니다
거의 항상 해상도나 움직임이 원인입니다. 보내는 프레임 안에서 카드 번호가 읽혀야 합니다. OBS를 1080p로 유지하고, 공개하는 순간 카드를 잠깐 가만히 든 다음, 그래도 안 될 때 비로소 --result-threshold를 완화하세요(기본값 0.9. 높일수록 약한 매칭도 남기며 1.0이면 전부 남깁니다).
같은 카드가 두 번 식별됩니다
동일성 게이트가 두 화면의 점수를 --similarity-threshold(기본값 0.85) 미만으로 매겨 새 카드로 판단한 것입니다. 조금 낮춰 보세요. 카드를 내려놓았다가 다시 집어 드는 경우라면 대신 --forget-after를 올리세요. 2초 동안 화면에서 사라진 카드는 설계상 새 카드로 취급됩니다.
아무것도 감지되지 않습니다
--show-detection을 붙여 실행하면 감지 상자가 그려집니다. 감지는 항상 돌아가고 있으며 기본적으로 그리지 않을 뿐입니다. 상자가 없다면 프레임 안에서 카드가 너무 작거나 너무 빠른 것이고, 상자는 있는데 매칭이 없다면 바로 위 항목을 보세요.
그래도 해결되지 않나요? README에 모든 플래그가 문서화되어 있고, 문서 허브는 하려는 작업별로 정리해 두었습니다.