Zum Hauptinhalt springen

YouTube Models

Die YouTube-Domäne umfasst Video-Metadaten, tägliche Video-Statistiken, Video-Scores, Sync-Tracking, Related Channels, Research-Queries und den Pending-Import-Mechanismus.

YouTubeVideo

Metadaten eines YouTube-Videos. Verwendet video_id (string) als Primary Key statt auto-increment.

Tabelle: youtube_videos

FeldTypNullableBeschreibung
video_idstringPKYouTube Video-ID (z.B. dQw4w9WgXcQ)
social_profile_idbigint (FK)neinZugehöriges Channel-Profil
channel_idstringjaYouTube Channel-ID
titlestringjaVideo-Titel
descriptiontextjaVideo-Beschreibung
published_atdatetimejaVeröffentlichungsdatum
duration_isostringjaISO 8601 Duration (z.B. PT4M33S)
duration_secondsintegerjaDauer in Sekunden
definitionstringjaAuflösung (hd, sd)
captionstringjaUntertitel verfügbar
category_idstringjaYouTube-Kategorie-ID
live_statusstringjaLivestream-Status
live_streaming_detailsjsonjaLivestream-Metadaten
tagsjsonjaVideo-Tags (Array)
thumbnailsjsonjaThumbnail-URLs (verschiedene Größen)
thumbnail_urlstringjaStandard-Thumbnail-URL
thumbnail_pathstringjaR2 Thumbnail-Pfad (Original)
thumbnail_path_mediumstringjaR2 Thumbnail-Pfad (Medium-Variante)
thumbnail_path_thumbnailstringjaR2 Thumbnail-Pfad (Thumb-Variante)
thumbnail_blurhashtextjaBlurHash-Placeholder fuer Thumbnail (LQIP)
thumbnail_hashstringjaThumbnail Content-Hash
privacy_statusstringjapublic, unlisted, private
embeddablebooleanjaEinbettbar
made_for_kidsbooleanjaMade for Kids
datajsonjaRohdaten der YouTube API
is_removedbooleanjaVideo gelöscht/entfernt
removed_atdatetimejaZeitpunkt der Entfernung
is_shortbooleanjaAdmin-Markierung als YouTube Short (null = nicht markiert)
is_short_marked_atdatetimejaZeitpunkt der Admin-Markierung
created_atdatetimeneinErstellt am
updated_atdatetimeneinAktualisiert am

Relations:

MethodeTypRelated ModelFKBeschreibung
profile()belongsToSocialProfilesocial_profile_idZugehöriger Channel
dailyMetrics()hasManyYouTubeVideoDailyMetricyoutube_video_idTägliche Statistiken
scores()hasManyYouTubeVideoScoreyoutube_video_idScore-Verlauf
latestScore()hasOneYouTubeVideoScoreyoutube_video_idAktueller Score (whereNotNull('score')->orderByDesc('date'))
publishingStats()hasManyYouTubePublishingWeeklyStatsocial_profile_idPublishing-Statistiken pro Wochentag

Casts:

'published_at' => 'datetime',
'live_streaming_details' => 'array',
'tags' => 'array',
'thumbnails' => 'array',
'data' => 'array',
'embeddable' => 'boolean',
'made_for_kids' => 'boolean',
'is_removed' => 'boolean',
'removed_at' => 'datetime',
'is_short' => 'boolean',
'is_short_marked_at' => 'datetime',

Methoden:

MethodeReturnBeschreibung
isEffectiveShort()boolIst dieses Video ein YouTube Short? Admin-Markierung (is_short) hat Prioritaet, sonst Auto-Erkennung (duration_seconds ≤ 60)
getDisplayThumbnailUrl($size)stringBeste verfuegbare Thumbnail-URL mit 5-stufiger Fallback-Kette: R2-Variante → R2-Original → YouTube-URL → Thumbnails-JSON → Placeholder-SVG. Sizes: thumb, sm, medium, md, original, lg

Location: app/Models/YouTubeVideo.php


YouTubeVideoDailyMetric

Tägliche Statistiken eines YouTube-Videos (Views, Likes, Kommentare, Favorites).

Tabelle: youtube_video_daily_metrics

FeldTypNullableBeschreibung
idbigintPKPrimary Key
youtube_video_idstring (FK)neinZugehörige Video-ID
datedateneinDatum des Snapshots
view_countbigintjaAufrufe
like_countbigintjaLikes
comment_countbigintjaKommentare
favorite_countbigintjaFavorites
rawjsonjaRohdaten
created_atdatetimeneinErstellt am
updated_atdatetimeneinAktualisiert am

Relations:

MethodeTypRelated ModelFKBeschreibung
video()belongsToYouTubeVideoyoutube_video_idZugehöriges Video

Casts: date → date, raw → array

Location: app/Models/YouTubeVideoDailyMetric.php


YouTubeVideoScore

Berechneter Score (0–100) für ein Video. Gewichtung: 40% View Performance + 25% Engagement + 20% Growth + 15% Freshness. Differenziert zwischen regulären Videos und Shorts.

Tabelle: youtube_video_scores

FeldTypNullableBeschreibung
idbigintPKPrimary Key
youtube_video_idstring (FK)neinZugehörige Video-ID
social_profile_idbigint (FK)neinZugehöriger Channel
datedateneinBerechnungsdatum
scoreintegerneinGesamtscore (0–100)
statusstringneinpending, preliminary, stable, no_data
is_shortbooleanneinYouTube Short
view_performance_scoreintegerjaView-Performance-Komponente (40%)
engagement_scoreintegerjaEngagement-Komponente (25%)
growth_scoreintegerjaWachstums-Komponente (20%)
freshness_scoreintegerjaAktualitäts-Komponente (15%)
created_atdatetimeneinErstellt am
updated_atdatetimeneinAktualisiert am

Relations:

MethodeTypRelated ModelFKBeschreibung
video()belongsToYouTubeVideoyoutube_video_idZugehöriges Video
profile()belongsToSocialProfilesocial_profile_idZugehöriger Channel

Casts:

'date' => 'date',
'score' => 'integer',
'view_performance_score' => 'integer',
'engagement_score' => 'integer',
'growth_score' => 'integer',
'freshness_score' => 'integer',
'is_short' => 'boolean',

Location: app/Models/YouTubeVideoScore.php


YouTubeVideoSync

Tracking-Status der Video-Synchronisation pro Channel. Steuert die automatische Video-Pipeline und erfasst Fail-Streaks für Fehlerbehandlung.

Tabelle: youtube_video_syncs

FeldTypNullableBeschreibung
idbigintPKPrimary Key
social_profile_idbigint (FK)neinZugehoeriger Channel
requested_bybigint (FK)jaUser, der Sync ausgeloest hat
uploads_playlist_idstringjaYouTube Uploads-Playlist-ID
last_sync_atdatetimejaLetzter Sync-Zeitpunkt
auto_sync_enabledbooleanneinAutomatischer Sync aktiviert (default: false)
last_fail_datedatejaDatum des letzten Sync-Fehlers
consecutive_fail_daysintegerjaAufeinanderfolgende Fehler-Tage
rss_etagstringjaETag fuer RSS Conditional Polling (304 Not Modified)
rss_last_modifiedstringjaLast-Modified Header fuer RSS
rss_last_poll_atdatetimejaLetztes RSS-Feed-Polling
last_new_video_detected_atdatetimejaLetztes neues Video erkannt (WebSub/RSS)
video_tracking_start_datedatejaPRO-Startdatum fuer unbegrenztes Video-Tracking
created_atdatetimeneinErstellt am
updated_atdatetimeneinAktualisiert am

Relations:

MethodeTypRelated ModelFKBeschreibung
profile()belongsToSocialProfilesocial_profile_idZugehöriger Channel
requester()belongsToUserrequested_byAnfordernder User

Casts:

'last_sync_at' => 'datetime',
'auto_sync_enabled' => 'boolean',
'last_fail_date' => 'date',
'consecutive_fail_days' => 'integer',
'rss_last_poll_at' => 'datetime',
'last_new_video_detected_at' => 'datetime',
'video_tracking_start_date' => 'date',

Location: app/Models/YouTubeVideoSync.php


YouTubeRelatedChannel

Verwandte YouTube-Channels mit Relevanz-Score. Wird per youtube:auto-fill-related-channels (alle 5 Min) befüllt.

Tabelle: youtube_related_channels

FeldTypNullableBeschreibung
idbigintPKPrimary Key
social_profile_idbigint (FK)neinQuell-Channel
related_social_profile_idbigint (FK)neinVerwandter Channel
relevance_scoreintegerjaRelevanz (0–100)
search_querystringjaVerwendete Suchabfrage
created_atdatetimeneinErstellt am
updated_atdatetimeneinAktualisiert am

Relations:

MethodeTypRelated ModelFKBeschreibung
sourceProfile()belongsToSocialProfilesocial_profile_idQuell-Channel
relatedProfile()belongsToSocialProfilerelated_social_profile_idVerwandter Channel

Casts: relevance_score → integer

Ausschluss-Filter: Bei Anzeige in der UI immer den Related-Channel gegen notExcluded() filtern, damit keine gesperrten/sanitized/archivierten Profile erscheinen.

Location: app/Models/YouTubeRelatedChannel.php


YouTubeResearchQuery

Gespeicherte YouTube-Recherche-Abfragen mit Ergebnissen. Für das Admin-Feature "YouTube Research".

Tabelle: youtube_research_queries

FeldTypNullableBeschreibung
idbigintPKPrimary Key
querystringneinSuchbegriff
topic_idstringjaYouTube Topic-ID
result_countintegerjaAnzahl Ergebnisse
result_urlsjsonjaGefundene Channel-URLs
response_payloadjsonjaYouTube API Response
error_payloadjsonjaFehlerdaten bei API-Fehler
error_messagetextjaFehlermeldung
imported_atdatetimejaImportiert am
batch_iduuidjaBatch-Identifier (gruppiert Batch-Suchen)
relevance_languagestringjaISO 639-1 Sprache fuer Suche
region_codestringjaISO 3166-1 Region fuer Suche
min_subscribersintegerjaMin. Subscriber-Filter
min_videosintegerjaMin. Video-Filter
filtered_countintegerjaErgebnis-Anzahl nach Qualitaetsfilter
statusstringjapending, running, completed, failed
created_atdatetimeneinErstellt am
updated_atdatetimeneinAktualisiert am

Casts: result_urls → array, response_payload → array, error_payload → array, result_count → integer, imported_at → datetime, min_subscribers → integer, min_videos → integer, filtered_count → integer

Location: app/Models/YouTubeResearchQuery.php


YouTubeResearchKeywordCooldown

14-Tage-Cooldown fuer Keywords, die in der Research Batch-Suche als Suggestions verwendet wurden. Verhindert wiederholte Vorschlaege derselben Keywords.

Tabelle: youtube_research_keyword_cooldowns

FeldTypNullableBeschreibung
idbigintPKPrimary Key
keywordstringneinKeyword (unique)
used_atdatetimeneinLetzter Verwendungszeitpunkt
created_atdatetimeneinErstellt am
updated_atdatetimeneinAktualisiert am

Casts: used_at → datetime

Location: app/Models/YouTubeResearchKeywordCooldown.php


PendingYouTubeChannelImport

Queue für entdeckte YouTube-Channels, die noch importiert werden müssen. Unterstützt Retry-Logik mit konfiguriertem Maximum.

Tabelle: pending_you_tube_channel_imports

FeldTypNullableBeschreibung
idbigintPKPrimary Key
source_social_profile_idbigint (FK)neinEntdeckt über diesen Channel
youtube_channel_idstringneinYouTube Channel-ID zum Importieren
relevance_scoreintegerjaRelevanz-Score
search_querystringjaVerwendete Suchabfrage
retry_countintegerneinBisherige Retry-Versuche
last_retry_atdatetimejaLetzter Retry-Zeitpunkt
last_errortextjaLetzte Fehlermeldung
created_atdatetimeneinErstellt am
updated_atdatetimeneinAktualisiert am

Relations:

MethodeTypRelated ModelFKBeschreibung
sourceProfile()belongsToSocialProfilesource_social_profile_idEntdeckender Channel

Casts: relevance_score → integer, retry_count → integer, last_retry_at → datetime

Konstanten: MAX_RETRIES = 5, MAX_AGE_DAYS = 7

Methoden: canRetry(), isExpired(), recordFailure()

Location: app/Models/PendingYouTubeChannelImport.php


YouTubePublishingWeeklyStat

Aggregierte Publishing-Statistiken pro YouTube-Kanal pro Wochentag (Plan 13). Wird woechentlich durch youtube:aggregate-publishing-stats neu berechnet.

Tabelle: youtube_publishing_weekly_stats

FeldTypNullableBeschreibung
idbigintPKPrimary Key
social_profile_idbigint (FK)neinZugehoeriger Channel
weekdaytinyintneinISO-Wochentag (1=Montag, 7=Sonntag)
video_countintegerneinAnzahl regulaere Videos
shorts_countintegerneinAnzahl YouTube Shorts
vfr_mediandecimal(10,4)jaVFR-Median (Views/Followers)
best_hour_utctinyintjaBeste Uploadstunde (UTC, 0-23)
hour_distributionjsonbjaUpload-Verteilung pro Stunde {hour: count}
engagement_rate_mediandecimal(10,6)jaMedian Engagement-Rate (Likes+Comments)/Followers
like_to_view_ratio_mediandecimal(10,6)jaMedian Like-to-View-Ratio
prev_video_countintegerjaVideo-Anzahl der Vorwoche (Trend E11)
prev_vfr_mediandecimal(10,4)jaVFR der Vorwoche (Trend E11)
vfr_p25decimal(10,4)jaVFR 25. Perzentil (Konfidenz E12)
vfr_p75decimal(10,4)jaVFR 75. Perzentil (Konfidenz E12)
week_startdatejaMontag der berechneten Woche
sample_sizeintegerneinGesamtanzahl analysierter Videos
created_atdatetimeneinErstellt am
updated_atdatetimeneinAktualisiert am

Unique Constraint: (social_profile_id, weekday) — eine Zeile pro Kanal pro Wochentag.

Relations:

MethodeTypRelated ModelFKBeschreibung
profile()belongsToSocialProfilesocial_profile_idZugehoeriger Channel

Accessors:

AccessorReturnBeschreibung
weekday_namestringDeutscher Wochentag (Montag, Dienstag, ...)
weekday_shortstringKurz-Wochentag (Mo, Di, Mi, ...)

Casts:

'weekday' => 'integer',
'video_count' => 'integer',
'shorts_count' => 'integer',
'vfr_median' => 'float',
'best_hour_utc' => 'integer',
'hour_distribution' => 'array',
'engagement_rate_median' => 'float',
'like_to_view_ratio_median' => 'float',
'prev_video_count' => 'integer',
'prev_vfr_median' => 'float',
'vfr_p25' => 'float',
'vfr_p75' => 'float',
'week_start' => 'date',
'sample_size' => 'integer',

Location: app/Models/YouTubePublishingWeeklyStat.php