Files
2nd/10_Wiki/Topics/Backend/my_videos_check.md
T
Antigravity Agent f8b21af4be Wiki cleanup: error-doc removal, dedup merge, link normalization
10_Wiki/Topics 대규모 정리:
- 오류 캡처/미완성 stub 문서 227개 제거
- 교차폴더 중복 43클러스터 병합 (63파일 → redirect)
- 링크명 정규화: 깨진 링크 수정·redirect 직결·개념 매핑 ~2,400건
- 카테고리 MOC 6개 신규 생성
- Graph 섹션 미해결 related-keyword 링크 10,058건 제거

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 23:52:15 +09:00

7.0 KiB
Raw Blame History

id, title, category, status, canonical_id, aliases, duplicate_of, source_trust_level, confidence_score, verification_status, tags, raw_sources, last_reinforced, github_commit, tech_stack
id title category status canonical_id aliases duplicate_of source_trust_level confidence_score verification_status tags raw_sources last_reinforced github_commit tech_stack
wiki-2026-0508-my-videos-check my_videos_check (Personal YouTube Channel Monitor) 10_Wiki/Topics verified self
Channel Health Monitor
YT Self-monitor
Video Stats Watcher
none A 0.85 applied
youtube-api
monitoring
cron
analytics
creator-tooling
2026-05-10 pending
language framework
Python 3.12 YouTube Analytics API + DuckDB + cron

my_videos_check (Personal YouTube Channel Monitor)

매 한 줄

"매 own 의 YouTube 채널 의 매 video 마다 매 view/like/comment/CTR/AVD 의 daily snapshot 을 매 fetch → DuckDB → 매 anomaly alert". 2026 creator workflow 의 기본 component. 매 YouTube Studio 의 dashboard 보다 훨씬 매 customizable + 매 multi-channel 비교 + 매 LLM 기반 insight.

매 핵심

매 Data sources

  • YouTube Data API v3: video metadata, current snapshot stats.
  • YouTube Analytics API v2: time-series (impressions, CTR, AVD, retention, traffic source) — 매 OAuth 필요.
  • YouTube Reporting API: bulk daily CSV (매 large channel 에 적합).

매 Snapshot schema

  • video_id, captured_at, views, likes, comments, watch_time_min, avd_sec, ctr, impressions.
  • Time-series: (video_id, day, metric) — 매 partitioned.

매 Alerts

  • View rate (24h growth) 가 매 baseline 의 3σ 밖.
  • 매 Comment rate spike — possible viral 또는 controversy.
  • CTR drop > 30% on recent uploads.
  • 매 watch time 의 sudden cliff at specific timestamp (retention curve).

매 응용

  1. 매 daily morning briefing (Telegram bot).
  2. Auto-thumbnail A/B 결정.
  3. 매 evergreen vs. 매 short-lived video classification.
  4. Topic-level trending in own catalog.

💻 패턴

OAuth setup (one-time)

from google_auth_oauthlib.flow import InstalledAppFlow
SCOPES = ['https://www.googleapis.com/auth/yt-analytics.readonly',
          'https://www.googleapis.com/auth/youtube.readonly']
flow = InstalledAppFlow.from_client_secrets_file('client_secret.json', SCOPES)
creds = flow.run_local_server(port=0)
with open('token.json', 'w') as f: f.write(creds.to_json())

Daily snapshot

from googleapiclient.discovery import build
from google.oauth2.credentials import Credentials
import duckdb, datetime as dt

creds = Credentials.from_authorized_user_file('token.json')
yt = build('youtube', 'v3', credentials=creds)
yta = build('youtubeAnalytics', 'v2', credentials=creds)
con = duckdb.connect('mychannel.db')

con.execute("""CREATE TABLE IF NOT EXISTS snapshots(
  video_id VARCHAR, captured_at TIMESTAMP, views BIGINT, likes BIGINT,
  comments BIGINT, watch_min DOUBLE, avd_sec DOUBLE, ctr DOUBLE, impressions BIGINT,
  PRIMARY KEY (video_id, captured_at)
)""")

def list_my_videos():
    res = yt.search().list(forMine=True, type='video', part='id', maxResults=50).execute()
    return [item['id']['videoId'] for item in res['items']]

def fetch_snapshot(video_ids):
    res = yt.videos().list(part='statistics,contentDetails,snippet', id=','.join(video_ids)).execute()
    rows = []
    for v in res['items']:
        s = v['statistics']
        rows.append({
            'video_id': v['id'],
            'views': int(s.get('viewCount', 0)),
            'likes': int(s.get('likeCount', 0)),
            'comments': int(s.get('commentCount', 0)),
        })
    return rows

def fetch_analytics(video_id, days=7):
    end = dt.date.today()
    start = end - dt.timedelta(days=days)
    res = yta.reports().query(
        ids='channel==MINE', startDate=str(start), endDate=str(end),
        metrics='views,estimatedMinutesWatched,averageViewDuration,impressions,impressionsCtr',
        dimensions='video', filters=f'video=={video_id}',
    ).execute()
    return res.get('rows', [[]])[0] if res.get('rows') else None

Anomaly detector (Z-score)

import statistics
def is_spike(video_id, metric='views', window=14, z=3.0):
    rows = con.execute(f"""
      SELECT {metric} FROM snapshots WHERE video_id=?
      ORDER BY captured_at DESC LIMIT {window+1}
    """, [video_id]).fetchall()
    if len(rows) < window + 1: return False
    today, hist = rows[0][0], [r[0] for r in rows[1:]]
    deltas = [hist[i] - hist[i+1] for i in range(len(hist)-1)]
    today_delta = today - hist[0]
    if not deltas or statistics.pstdev(deltas) == 0: return False
    return abs(today_delta - statistics.mean(deltas)) / statistics.pstdev(deltas) > z

Telegram alert

import requests, os
def alert(msg):
    requests.post(
        f"https://api.telegram.org/bot{os.environ['TG_TOKEN']}/sendMessage",
        json={'chat_id': os.environ['TG_CHAT'], 'text': msg, 'parse_mode': 'Markdown'},
    )

for vid in list_my_videos():
    if is_spike(vid):
        title = con.execute("SELECT title FROM videos WHERE video_id=?", [vid]).fetchone()[0]
        alert(f"*Spike*: [{title}](https://youtu.be/{vid})")

LLM weekly digest (Claude)

from anthropic import Anthropic
top = con.execute("""
  SELECT v.title, s.views, s.ctr, s.avd_sec
  FROM snapshots s JOIN videos v USING(video_id)
  WHERE s.captured_at::DATE = current_date
  ORDER BY s.views DESC LIMIT 10
""").fetchall()

resp = Anthropic().messages.create(
    model='claude-opus-4-7',
    max_tokens=1000,
    messages=[{'role': 'user', 'content':
        f"Weekly channel digest. Identify 3 actions. Data:\n{top}"}],
)
print(resp.content[0].text)

Cron (systemd timer)

# ~/.config/systemd/user/yt-check.timer
[Unit]
Description=Daily YouTube channel snapshot
[Timer]
OnCalendar=*-*-* 09:00:00
Persistent=true
[Install]
WantedBy=timers.target

매 결정 기준

상황 Approach
Single channel, ≤ 500 videos API v3 + Analytics v2, daily
5k+ videos Reporting API bulk CSV
Real-time spike poll every 15m for new uploads only
Multi-channel agency per-channel OAuth tokens, rate-limit pool
Privacy / no Google 매 X — Analytics 의 own data 만 own 가 access

기본값: daily 09:00 cron + Analytics v2 + DuckDB + 3σ Z-score alert + Telegram + weekly LLM digest.

🔗 Graph

🤖 LLM 활용

언제: weekly digest, anomaly explanation, A/B thumbnail copy 의 generation. 언제 X: 매 ground-truth metric 의 fabrication — always cite raw numbers.

안티패턴

  • Polling stats every minute: quota 의 burn — 매 actual update lag 이 hours.
  • No baseline window: every uptick = "spike" = noise.
  • Storing only current snapshot: 매 trend 의 재구성 불가.
  • Hard-coded video list: 매 new upload 의 miss.
  • OAuth token in repo: revoke 즉시 필요. Use secret manager.

🧪 검증 / 중복

  • Verified (YouTube Data API v3, Analytics API v2 docs, YouTube Reporting API guide).
  • 신뢰도 A.

🕓 Changelog

날짜 변경
2026-05-08 Phase 1
2026-05-10 Manual cleanup — channel monitor + anomaly + LLM digest