What changed:
Added shared thumbnail helpers in
[includes/db.php](/Users/tyemeclifford/Documents/GH/mediaplayer/includes/db.php):YouTube
direct thumbnails
Dailymotion direct thumbnails
oEmbed thumbnails for Vimeo, Wistia, TikTok, SoundCloud, Spotify, etc.
optional first-frame thumbnail generation for local uploads when ffmpeg
is installed
Added an “Auto-grab thumbnail” checkbox to
[admin/add.php](/Users/tyemeclifford/Documents/GH/mediaplayer/admin/add.php)
and
[admin/edit.php](/Users/tyemeclifford/Documents/GH/mediaplayer/admin/edit.php).
Reused the new shared downloader in
[admin/youtube_import.php](/Users/tyemeclifford/Documents/GH/mediaplayer/admin/youtube_import.php).
Documented the behavior in
[README.md](/Users/tyemeclifford/Documents/GH/mediaplayer/README.md).
The bug was relative media paths like media/thumbs/... resolving under
routes such as /v/<slug>?page=2 or /search/<query>?page=2. I added
public_media_url() in
[includes/db.php](/Users/tyemeclifford/Documents/GH/mediaplayer/includes/db.php)
and updated public thumbnails, posters, and local player sources in
[index.php](/Users/tyemeclifford/Documents/GH/mediaplayer/index.php),
[catalogue.php](/Users/tyemeclifford/Documents/GH/mediaplayer/catalogue.php),
and [embed.php](/Users/tyemeclifford/Documents/GH/mediaplayer/embed.php)
to use root/base-aware URLs.
What changed:
Added pretty URL helpers/default setting in
[includes/db.php](/Users/tyemeclifford/Documents/GH/mediaplayer/includes/db.php).
Added root rewrite rules in
[.htaccess](/Users/tyemeclifford/Documents/GH/mediaplayer/.htaccess):/v/<slug>
/all
/search/<query>
Added Admin → Settings “Public URL Style” toggle in
[admin/settings.php](/Users/tyemeclifford/Documents/GH/mediaplayer/admin/settings.php),
defaulting to pretty URLs.
Updated public/player/catalogue/embed/admin preview links to use the
configured URL style.
Added redirects from legacy ?v= and ?q= URLs to pretty routes when
rewriting is enabled.
Documented deployment and fallback behavior in
[README.md](/Users/tyemeclifford/Documents/GH/mediaplayer/README.md).
It now handles more YouTube layouts:
Classic videoRenderer, gridVideoRenderer, and compactVideoRenderer
Shorts-style reelItemRenderer
Newer lockupViewModel channel grid objects
Raw HTML fallback by extracting watch?v=, /shorts/, /embed/, and
"videoId" matches
A second scrape attempt using YouTube’s older grid query:
view=0&sort=dd&flow=grid
So instead of stopping at “no videos found” when YouTube changes the
JSON shape, it now tries multiple extraction strategies and can still
import proper YouTube embed URLs with fallback thumbnails.
Added [admin/youtube_import.php (line
1)](/Users/tyemeclifford/Documents/GH/mediaplayer/admin/youtube_import.php:1),
which:
Accepts a channel URL, @handle, or UC... channel ID.
Scrapes the channel /videos page.
Extracts videos from ytInitialData.
Shows a preview with checkboxes.
Imports selected videos into videos and video_sources.
Stores each video as a canonical YouTube watch URL with mime_type =
text/html, so the existing YouTube embed playback path handles it
correctly.
Downloads scraped thumbnails into media/thumbs/ when possible.
Skips duplicates by matching existing remote YouTube URLs.
Also wired it into the admin navigation in [admin/index.php (line
172)](/Users/tyemeclifford/Documents/GH/mediaplayer/admin/index.php:172),
[admin/add.php (line
199)](/Users/tyemeclifford/Documents/GH/mediaplayer/admin/add.php:199),
[admin/edit.php (line
267)](/Users/tyemeclifford/Documents/GH/mediaplayer/admin/edit.php:267),
and [admin/settings.php (line
109)](/Users/tyemeclifford/Documents/GH/mediaplayer/admin/settings.php:109).
Updated [README.md (line
81)](/Users/tyemeclifford/Documents/GH/mediaplayer/README.md:81) with
usage notes.
What changed:
[includes/db.php (line
227)](/Users/tyemeclifford/Documents/GH/mediaplayer/includes/db.php:227)
now classifies YouTube, Vimeo, Dailymotion, Twitch, Facebook, TikTok,
Instagram, X/Twitter, SoundCloud, Spotify, Google Drive, Wistia,
Streamable, Loom, plus direct Dropbox/GitHub media rewrites.
[index.php (line
235)](/Users/tyemeclifford/Documents/GH/mediaplayer/index.php:235)
renders provider URLs as iframe embeds, while uploaded/direct files
still use Video.js.
[embed.php (line
198)](/Users/tyemeclifford/Documents/GH/mediaplayer/embed.php:198) now
supports those provider embeds too.
[admin/add.php (line
260)](/Users/tyemeclifford/Documents/GH/mediaplayer/admin/add.php:260)
and [admin/edit.php (line
383)](/Users/tyemeclifford/Documents/GH/mediaplayer/admin/edit.php:383)
now describe external URLs as embed-capable and store recognized
provider URLs as text/html.
[README.md (line
63)](/Users/tyemeclifford/Documents/GH/mediaplayer/README.md:63)
documents provider embed support.
Changed:
[includes/db.php (line
43)](/Users/tyemeclifford/Documents/GH/mediaplayer/includes/db.php:43)
adds source_type and source_url, with an automatic migration for
existing SQLite databases.
[admin/add.php (line
260)](/Users/tyemeclifford/Documents/GH/mediaplayer/admin/add.php:260)
and [admin/edit.php (line
383)](/Users/tyemeclifford/Documents/GH/mediaplayer/admin/edit.php:383)
now let each source be an upload or an external URL.
[index.php (line
226)](/Users/tyemeclifford/Documents/GH/mediaplayer/index.php:226) and
[embed.php (line
193)](/Users/tyemeclifford/Documents/GH/mediaplayer/embed.php:193)
resolve playback URLs based on where the source lives.
[catalogue.php (line
79)](/Users/tyemeclifford/Documents/GH/mediaplayer/catalogue.php:79) now
has public search for published videos only.
[README.md (line
63)](/Users/tyemeclifford/Documents/GH/mediaplayer/README.md:63)
documents local vs remote sources and public search.