4 min read

[aniflux 2/5] 애니 에피소드 자동 수집 — 릴그룹 우선순위와 해상도 fallback

도입

매주 금요일 밤이면 같은 루틴을 반복했습니다.
커뮤니티 사이트에서 이번 주 에피소드 검색하고, 릴그룹 확인하고, 다운로드 클라이언트에 추가하고.
다운 끝나면 파일명 바꾸고, 시즌 폴더로 옮기고, Plex 스캔 돌리고.

구독하는 애니가 10개쯤 되니까 이게 매주 30분짜리 작업이 되더라고요.
자동화하자고 마음먹은 건 당연한 수순이었습니다.

배경

처음에는 AnimeTosho API를 썼습니다.
정리된 메타데이터를 JSON으로 주니까 파싱이 깔끔했거든요.
그런데 어느 날 갑자기 API가 응답을 안 하기 시작했습니다.
확인해보니 공개 API를 중단한 거였어요.

그래서 애니 커뮤니티 RSS로 갈아탔습니다.
카테고리별 RSS를 제공하는데, 검색어를 붙이면 필터된 피드를 받을 수 있습니다.
다만 RSS만으로는 부족한 경우가 있어서, 직접 페이지를 scrape하는 fallback도 넣었습니다.

SubsPlease는 보조 소스로 두었습니다.
자체 RSS가 안정적이고, 방영 직후 빠르게 올라옵니다.
대신 SubsPlease 릴리스만으로는 원하는 릴그룹을 못 잡으니까, 메인 소스를 primary로 두고 SubsPlease는 fallback용으로 쓰는 구조입니다.

과정

핵심 구조는 Source Chain이라고 부르는 패턴입니다.
primary 소스를 먼저 조회하고, 결과가 없으면 secondary를 조회합니다.

릴그룹 우선순위는 preferred와 banned로 나눴습니다.
preferred에 있는 그룹이 검색 결과에 있으면 그걸 선택하고, banned에 있으면 무조건 건너뜁니다.
둘 다 아니면 시더 수 기준으로 고릅니다.

type ReleasePreference struct {
    Preferred []string // ["SubsPlease", "Judas", "EMBER"]
    Banned    []string // ["HorribleSubs", "Erai-raws"]
}

에피소드 번호 추출은 regex 기반입니다.
[SubsPlease] Frieren - 03 (1080p) 같은 패턴에서 에피소드 번호와 해상도를 뽑아냅니다.
시즌 정보가 파일명에 없는 경우가 많아서, 시즌은 DB에서 가져온 매핑 데이터를 씁니다.

검색 결과에서 info hash를 가져와 public tracker를 붙여서 다운로드 링크를 빌드합니다.
이걸 다운로드 클라이언트 WebAPI로 넘기면 다운로드가 시작됩니다.

삽질

릴그룹마다 파일명 규칙이 제각각이라는 게 가장 큰 문제였습니다.

SubsPlease는 [SubsPlease] Title - 03 (1080p) [hash].mkv 형식인데, Judas는 [Judas] Title S01E03.mkv이고, EMBER는 또 Title.S01E03.1080p.WEB.x264-EMBER.mkv 형식입니다.
결국 regex를 여러 개 준비해서 순서대로 시도하는 방식으로 갔습니다.
깔끔하진 않은데, 현실적으로 이게 최선이었습니다.

해상도 fallback도 필요했습니다.
인기 없는 작품은 1080p 릴리스가 아예 없는 경우가 있거든요.
그래서 1080p로 먼저 검색하고, 결과가 0건이면 720p로 재검색합니다.

upgrade 로직도 넣었습니다.
720p를 먼저 잡았더라도, 6시간마다 재검색해서 1080p preferred 릴그룹 릴리스가 나오면 교체합니다.
이때 기존 파일을 삭제하고 새로 받는 건 자동이지만, Plex 시청 기록은 유지되도록 파일명을 동일하게 맞춰야 했습니다.

결과

지금은 구독 목록에 애니를 추가해두면, 방영 후 대략 30분 이내에 다운로드가 시작됩니다.
파일명 정리와 시즌 폴더 배치까지 자동이라 Plex에서 바로 시청할 수 있습니다.

다만 한계도 있습니다.
소스 사이트가 불안정하면 전체 파이프라인이 막힙니다.
그리고 릴그룹 파일명 패턴이 바뀌면 regex를 수동으로 수정해야 합니다.
완전한 자동화라기보다는, 90%를 자동화하고 나머지 10%는 알림 받고 대응하는 구조에 가깝습니다.

마무리

솔직히 AnimeTosho가 살아있었으면 이렇게 복잡하게 안 만들었을 겁니다.
커뮤니티 scraping은 언제든 깨질 수 있는 방식이니까요.
그래도 매주 반복하던 30분을 없앤 건 확실히 체감되고, 릴그룹 우선순위 로직은 만들어두길 잘했다고 생각합니다.
720p fallback + upgrade 패턴은 생각보다 자주 동작하더라고요.

참고

  • SubsPlease — 방영 직후 빠른 릴리스 피드
  • AniList API — 에피소드 수, 방영일 등 메타데이터
  • autobrr — IRC/RSS 기반 자동화 도구 (참고한 설계)