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

204 lines
7.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
id: wiki-2026-0508-my-videos-check
title: my_videos_check (Personal YouTube Channel Monitor)
category: 10_Wiki/Topics
status: verified
canonical_id: self
aliases: [Channel Health Monitor, YT Self-monitor, Video Stats Watcher]
duplicate_of: none
source_trust_level: A
confidence_score: 0.85
verification_status: applied
tags: [youtube-api, monitoring, cron, analytics, creator-tooling]
raw_sources: []
last_reinforced: 2026-05-10
github_commit: pending
tech_stack:
language: Python 3.12
framework: 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)
```python
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
```python
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)
```python
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
```python
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)
```python
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)
```ini
# ~/.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
- 변형: [[comment_harvester]]
- 응용: [[Telegram-Notify]] · [[Anomaly-Detection]]
- Adjacent: [[DuckDB]]
## 🤖 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 |