Video platform
Uploads, FFmpeg processing, renditions, Shorts, playlists, search, discovery, history, watch later, comments, reports, and Creator Studio.
Install, configure, operate, secure, and troubleshoot the complete PlayHub video, community, and multi-participant live streaming platform.
PlayHub is a self-hosted product for publishing on-demand video, running creator channels and communities, hosting real-time rooms, recording replays, monetizing engagement, and administering the complete service from one dashboard.
Uploads, FFmpeg processing, renditions, Shorts, playlists, search, discovery, history, watch later, comments, reports, and Creator Studio.
Browser and RTMP broadcasting, multi-participant rooms, screen sharing, control room, moderation, polls, goals, contributions, and replays.
Users, creators, roles, reports, ads, payments, storage, languages, backups, support, diagnostics, branding, and system configuration.
PlayHub is not a static PHP theme. Production operation requires CLI access, Redis, FFmpeg, a persistent queue worker, cron, Docker, open media ports, and valid HTTPS.
Version 0.9.13 follows 0.9.12 and updates playback, private cloud delivery, Shorts, responsive layouts, branding, signup roles, and content administration. The web version, native app build number, and API contract version have independent histories. See the React Native application guide for Android and iOS.
crossOrigin attributes. Remote JavaScript HLS/DASH manifests, segments, and captions still need their own valid origin headers.www hostname use the canonical HTTPS origin in APP_URL; the original saved import URL remains unchanged. Other domains, unrelated subdomains, credential-bearing URLs, and unrelated explicit ports are excluded..m3u8 URLs retain HLS classification. Watch, persistent playback, and embeds let HLS/DASH providers determine live, DVR, or on-demand status; ordinary files remain on demand.Media requests retain resource-specific authorization and expiring playback links. Authorized owners and administrators can receive signed viewer claims for media requests that cannot attach the website bearer token. Delivery rechecks current access, account restrictions, and private-profile ownership. Cloud playback authorizes the application request before redirecting to a bounded provider-signed URL; protected redirects use private, non-storable headers and cannot outlive the incoming application signature. Private objects have no public-CDN fallback when signing fails. Local delivery preserves byte ranges for seeking.
views_count values from the loaded feed, deduplicate case variants and repeated/hash-prefixed tags per video, and rank by views. These are feed totals; no synthetic multiplier, fallback tags, or site-wide aggregate is added.Mobile comment menus now render as scrollable sheets in the document body, keeping Delete reachable. Delete and report confirmations render above Shorts overlays. Delete remains permission-controlled and explains that deleting a parent removes its replies.
Opening or dragging the mobile sidebar restores the header and positions the drawer beneath its 64-pixel top bar. Dynamic viewport height and safe-area padding remove the gap caused by a hidden header. Small-screen headers and information pages wrap long content.
Creator Studio content tables reserve room before showing the summary rail. Intermediate widths scroll inside the table container; narrow screens show labeled cards with selection, metrics, and row actions. Admin content receives corresponding mobile selection and overflow fixes.
| Setting or action | New behavior |
|---|---|
| Image-only branding | Website Configuration accepts empty logo text, a Show logo text switch, and a 16–64 pixel logo image size. Saving another branding field preserves image-only presentation; public configuration uses the same values. |
| Default signup role | Select User or Creator. New local and social accounts receive the server-selected role; staff roles and client-supplied role escalation are rejected. Existing/returning social accounts keep their roles. Upload and Live access still follow publishing rules, restrictions, and allowlists. |
| Edit User / Change Role | Canonical saved values now agree across user rows, team rows, filters, and effective permissions. A channel owner changed to User displays User. Demotion clears legacy administrator flags while preserving other preferences; self-demotion safeguards remain. |
| Delete category | Confirmed administrator deletion works for empty and final categories. Videos become Uncategorized in the same transaction while media, engagement, and visibility remain intact. A failure rolls back detachment. Create a replacement category before an upload that requires one. |
Private cloud avatars and banners now use the application's signed /media/images route when no explicit public base URL is configured. User Settings and channel profiles preserve complete API avatar_url and cover_url signatures instead of reconstructing unsigned upload paths. Local editing previews retain priority.
Display links last six hours and accept only approved raster paths under avatars, covers, branding, logos, banners, gifts, and stickers. Signature validation happens before reading the private cache. Protected video thumbnails and community, comment, and message images retain their own access routes.
| Image operation | Provider requests | Behavior |
|---|---|---|
| Generate a signed URL | 0 | Signing is local; no preliminary existence HEAD request. |
| Fill a cold display-image cache entry | 1 authenticated GET | No separate existence, size, or MIME HEAD request. Validate MIME and raster bytes after download. |
| Serve a warm image | 0 | Also supports ETag / Last-Modified conditional responses and HTTP 304. |
| Cache retention | Local maintenance | Defaults: 30-day age, 1 GiB pruning target, 20 MiB per image. Daily scheduler and opportunistic hourly checks prune expired then older-used entries; active locks can defer removal. |
Oversized, malformed, HTML, and SVG objects are rejected. Successful application overwrites/deletions invalidate cache entries; failed remote changes keep the previous entry usable. Provider-side changes may remain cached until expiry or deliberate maintenance.
If an account has exhausted its Class B transaction cap, increase that cap in Backblaze before testing uncached reads. Cached images may stay available, but refused uncached objects cannot be downloaded. This fix does not alter keys, bucket privacy, provider CORS, billing settings, or normal object-read costs.
The shared backend exposes API v1 for native bootstrap, authentication, refresh, TV pairing, playback, resumable uploads, progress, and notifications. The website continues using its versionless API. Native direct-to-cloud multipart upload is not implemented.
FCM and APNs delivery now includes a durable outbox, queue dispatch, bounded retries, recovery, and registration/preference checks. Delivery defaults to disabled. Bootstrap enables it only with platform credentials and required tables ready. Supervise a worker for the configured push queue (default push); the ordinary videos,default worker does not consume it. Registration success alone does not prove device delivery.
The 9 October connected Android Live pass covers bidirectional real media, supported interaction and moderation, token revocation, recording, and physical replay playback against a local HTTPS backend. It supersedes the earlier blocked milestone notes. Fixes include starting an unchanged saved schedule after its due time, deterministic chat order with equal timestamps, clearing stale ended-summary errors, and reconciling abnormal host loss. See native Live setup and acceptance.
This is scoped development-device acceptance, with a 2,000 ms owner-selected latency gate. It does not establish production acceptance, iOS readiness, all Android GPUs, locked camera FPS, or release-build memory behavior. TURN UDP passed; TURN TCP/TLS were not configured, and optional RTMP ingress was not rerun.
Persistent and scroll miniplayers, standalone embeds, captions and chapters, provider imports, analytics/CSV exports, VAST and Google IMA, paid videos and community photo sets, wallet tips, boosts, creator earnings, withdrawal review, localized SEO/pages/email templates, plugin management, and transactional updates remain available from the 0.9.9–0.9.12 baseline. Review every documented web version below.
Use the distribution's supported update path and a matching application, locked dependency set, frontend manifest/assets, and database state. The historical 0.7.5 → 0.9.9 manual package has its own guarded procedure and is not a 0.9.13 updater.
build/ output and manifest together, with the configured /build/ base. Retain older chunks while open tabs can still request them.videos,default worker and Laravel scheduler running; image-cache pruning depends on the scheduler.APP_URL to the actual canonical HTTPS origin. Test direct-import manifests and relative segments there; configure remote adaptive-source CORS for each required origin.npm ci
npm run buildThe source records earlier isolated regression/build/browser checks; they do not validate a customer's credentials, cap, origin configuration, services, or deployment. Record the real deployment date and acceptance result. Rollback restores a coherent application/frontend/database release while preserving media and customer configuration.
Version 0.9.13 is documented above. The entries below preserve the existing published web release history. Native development milestones have their own application history.
Earlier release-note wording is historical. The current Live implementation uses monetary tip presets rather than coin currency, does not persist peak/unique-viewer or cumulative-watch-time analytics, and does not implement clip creation, active DVR seeking, or a stream-label editor/rendering surface. Use the current Live guide for the supported behavior.
Released September 7, 2026
Released September 7, 2026. This release adds Google IMA player advertising, a standalone Google AdSense plugin, manual wallet credits, Creator Studio analytics, refined navigation and recommendation loading, and extensive playback and plugin reliability fixes.
| Feature | Behavior |
|---|---|
| Google IMA Player Ads | Choose Google IMA per ad alongside Generic VAST, with official SDK lifecycle handling and managed pre-roll, mid-roll, and post-roll delivery. |
| Managed ad playback | Google-managed ad breaks support dynamic watch context, responsive and fullscreen rendering, autoplay and muted signals, controlled skipping, configurable timeouts, recovery, and cleanup. |
| Player Ads engine controls | Administrators can select an ad engine, configure 3-30 second load timeouts, enter Google Ad Manager tags, and retain Generic VAST skip timing. |
| Advertising lifecycle coverage | Backend and browser regression coverage protects VAST defaults, IMA tags, dynamic URLs, completion, skipping, no-fill, malformed tags, timeouts, duplicate requests, and cleanup. |
| Google AdSense plugin | A standalone plugin provides validated publisher and ad-unit settings, responsive units, optional Auto ads, non-personalized requests, placement management, and no-fill hiding. |
| Manual wallet credits | Administrators can credit any user wallet with a completed, auditable ledger transaction and an optional internal note. |
| Creator Studio Analytics | Creators can select reporting periods, compare performance, inspect audience activity and quality, review content mix and publishing distribution, analyze top content, and export CSV data. |
AdDisplayContainer, AdsLoader, AdsRequest, and AdsManager lifecycle handling.Plugins navigation item instead of displaying each extension as a top-level dashboard option.Upload or Sign in center-action text, and the configured accent color retained for its raised circular icon and active state.Load more action, removed scroll-triggered loading, and kept the complete recommendation panel pinned through its final item on large screens.Load more comments button instead of page scrolling.Released September 4, 2026
Released September 4, 2026. A major platform release introducing plugins and transactional updates alongside new monetization, playback, discovery, administration, and mobile experiences.
| Feature | Behavior |
|---|---|
| Plugin API v1 | Trusted PHP service providers, lifecycle hooks, compatibility checks, migrations, encrypted settings, actions, filters, and namespaced pages provide a complete extension framework. |
| Admin Plugins workspace | Administrators can install and update ZIP packages, configure plugins, run diagnostics, enable or disable extensions, and remove packages. |
| Hardened plugin packages | Plugin installation blocks traversal, symlinks, oversized archives, excessive files, unsafe file types, and server-control files with rollback-safe replacement. |
| Protected plugin assets | Plugins can declare CSS, JavaScript, modules, images, fonts, JSON, and WebAssembly through a protected delivery route and browser hook runtime. |
| Transactional system updater | Signed manifests, preflight checks, checksummed downloads, protected paths, backups, maintenance mode, database recovery, interruption monitoring, and rollback secure every update. |
| Standalone embed player | Iframe embeds load only the requested video in a dedicated player instead of embedding the complete video-details page. |
| Searchable hashtags and mentions | Hashtags open matching search results and mentions navigate to linked profiles in video comments, community posts, and community comments. |
| Paid community photo sets | Creators can sell protected photo sets through wallet purchases with platform fees, taxes, permanent buyer access, and seller notifications. |
| Upload playlist selection | Creators can add a new video to any of their own playlists while completing the upload workflow. |
| Responsive mobile navigation | Mobile users receive header search and a fixed bottom navigator with animated active states, guest login behavior, and role-aware Live and Profile actions. |
| Currency-aware account balance | The account menu displays wallet balances in the selected currency and provides direct access to Earnings. |
| Default website language | Administrators can choose the website default language while preserving each visitor's saved language preference. |
| Language availability controls | Website languages can be enabled or disabled with public catalog enforcement and safeguards that protect the default language. |
| Community post permissions | Post authors, community owners, platform moderators, and administrators can remove community posts according to their role. |
| Localized Admin Pages | Administrators can manage localized About, Contact, Developers, FAQ, Help, Refund, Privacy, Terms, and Cookie pages with sections, visibility, footer, search, and sitemap controls. |
| Localized email templates | Every system email can be edited, previewed, validated, and reset across installed languages using documented placeholders and update-safe overrides. |
| Automatic scroll miniplayer | Actively playing watch-page videos float when less than half visible and return inline on pause, completion, or viewport return. |
| Persistent in-tab playback | Videos continue across navigation and reloads with a responsive minimized player, queue controls, seek, mute, source refresh, full-player handoff, and Media Session support. |
| Homepage and Shorts recommendations | Deterministic recommendations combine freshness, engagement quality, momentum, exploration, viewer affinities, watch completion, and creator and category diversity. |
| Plugin Admin workspaces | Plugins can register namespaced Admin workspaces with authenticated requests, navigation, confirmation and alert dialogs, and deterministic cleanup. |
| Creator tips and donations | Viewers can support creators from channels and video pages using wallet-backed contributions with opt-out controls, limits, fees, idempotent transfers, and notifications. |
| Paid video sales | Creators can price videos for wallet purchase with platform commission, permanent buyer access, protected playback, purchase notifications, and a Purchased library. |
| Branded HTML email | Responsive system email uses the configured website name and accent colors with plain-text alternatives for SMTP, SendGrid, and native mail delivery. |
| Watch-page video deletion | Creators, moderators, and administrators can delete eligible videos from the watch page through a confirmed action. |
| Purchase tax controls | Administrators can configure VAT, GST, and Sales Tax for paid videos with buyer-visible totals and auditable tax records. |
| Mention autocomplete | Video and community composers support mention suggestions, keyboard selection, linked rendering, and preference-aware notifications. |
| Signup audit data | Immutable signup IP and registration-source data is recorded with admin-only IP visibility in user management. |
| AirPlay and Google Cast | Feature-detected casting is available for on-demand videos and live replays with Safari permissions and resumable default-receiver sessions. |
| Configurable route loading | Administrators can choose a top loading bar, loading text, or both while each destination completes its initial content requests. |
| Withdrawal approval workflow | Administrators can approve or reject withdrawals with protected decisions, reviewer audit data, creator notifications, and pending alerts for moderators. |
| Social sharing previews | Videos, Shorts, live streams, channels, community posts, and playlists receive server-rendered Open Graph and X cards with original artwork or a branded fallback. |
| Timestamped video descriptions | Formatting, Unicode, and emoji are preserved while clickable minute and hour timestamps seek the active player. |
| Automatic player chapters | Valid timestamped descriptions generate segmented seek bars, active titles, chapter navigation, and cover previews through native Vidstack tracks. |
| SEO and Sitemaps workspace | Administrators control metadata, canonical origin, verification, indexing policies, robots rules, social and structured data, and paginated content sitemaps. |
| Managed video chapters | Creators and administrators can import CUE files or timestamp lists, review unnamed duration-based segments, validate chapter data, and opt videos into native timeline chapters. |
| Community poll voters | Clickable vote counts open a paginated dialog showing each voter's public profile and selected option. |
| YouTube chapter import | Imported videos can collect chapters from native player markers or timestamped descriptions for editable Step 4 review with explicit opt-out. |
| Rich description formatting | Video descriptions safely render bold, italic, combined emphasis, external links, and original text layout. |
| Admin live-stream deletion | Administrators can confirm deletion of live streams together with active sessions, replays, related records, and media. |
| Automatic Up Next loading | The watch page loads additional Up Next recommendations near the end of the list while retaining the manual Show more control. |
| Imported Shorts detection | YouTube Shorts signals and verified portrait metadata from other providers identify imported short-form videos automatically. |
| Publishing access controls | Administrators can define upload and live role rules, strict username allowlists, timed restrictions, and profile-complete creator upgrades. |
| Contextual video recommendations | Related and Up Next results combine the current channel, category, language, and tags with private watch history, likes, saved videos, and subscriptions. |
| Video boost campaigns | Creators can promote videos with reserved wallet budgets, daily and event billing, paced relevant placement, qualified-event deduplication, reporting, and admin-defined limits. |
| Creator Studio earnings | Creators can review VAST, tip, video sale, and live revenue with source filters, fees, balances, supporter and content details, pagination, and notifications. |
| Draggable desktop miniplayer | The minimized player remembers bounded desktop positioning and supports resize compatibility, keyboard movement, and recovery after viewport changes. |
| Persistent theater mode | The watch page includes a remembered desktop theater layout with native player and keyboard controls, expanded playback, and responsive Up Next placement. |
#hashtag support and linked @mention profile navigation in video comments, community posts, and community comments.@mention autocomplete, keyboard selection, linked mention rendering, and preference-aware notifications for video comments, community posts, and community comments.m:ss and h:mm:ss timestamps that seek the active player.Current release
A distribution-ready release focused on installation reliability, licensing, language management, backups, and first-run operations.
| Feature | Behavior |
|---|---|
| Four-step web installer | Requirements, configuration, live installation console, and completion are presented as a guided production workflow. |
| Full server readiness scan | PHP, extensions, Redis, Node, npm, FFmpeg, Docker, storage, HTTPS, and disk capacity are checked before install. |
| Live dependency console | The installer streams real npm, Vite, migration, catalog import, and administrator provisioning output. |
| Owner account provisioning | Installation creates a verified owner account and channel without exposing credentials in the console. |
| Language file manager | Administrators can select, edit, and save any of the bundled language packs from the dashboard. |
| Configurable system backups | Database, source, media, and selected folders can be measured, selected, archived, and scheduled. |
| Bundled catalog restoration | Gifts, stickers, logo, and favicon remain available as core package content after a clean installation. |
Operations release
Platform-wide reporting, real administrative actions, account lifecycle tools, and customer-facing profile workflows.
| Feature | Behavior |
|---|---|
| Unified report workflow | Profiles, videos, comments, and community content share a real report dialog and moderation pipeline. |
| Report bulk actions | Moderators can select reports and apply status, assignment, priority, or resolution actions in one operation. |
| Real reported-item media | Admin reports display the actual profile avatar, video thumbnail, or content preview associated with the report. |
| Permanent user deletion | Administrators can remove an account completely and optionally delete all videos owned by that user. |
| Roles and permissions | Admin roles, permission groups, team members, invitations, scopes, and status controls are operational. |
| Channel favorites | Viewers can favorite channels and open a dedicated favorites collection from the profile menu. |
| Direct profile messaging | The profile Message action opens the real private conversation instead of a local composer placeholder. |
| Public playlist navigation | Playlist cards and titles open their respective public playlist pages across the website. |
Commerce release
Wallet payments, gifts, super stickers, advertising, and real monetization analytics for creators and operators.
| Feature | Behavior |
|---|---|
| Live gift catalog | Administrators can add, price, update, paginate, and delete locally stored gifts used during live streams. |
| Super sticker catalog | Categorized stickers work in live streams and comments with scrolling pagination and local file management. |
| Instant tips | Preset coins send their amount immediately while the custom coin opens a validated amount dialog. |
| Wallet top-ups | Stripe or PayPal checkout opens in a new tab and returns confirmed funds to the viewer wallet. |
| Contribution animations | Tips, gifts, and stickers animate in real time for hosts, participants, and viewers based on value. |
| Advertising manager | HTML and media ads can target sidebars, headers, footers, feeds, videos, and comments with date controls. |
| Revenue analytics | Memberships, creator earnings, commission, gifts, and tips are represented by real transactions and source totals. |
| Replay contributions | Gifts, tips, stickers, and super chats are stored as stream events and displayed again in replay context. |
Live collaboration release
A complete guest participation lifecycle, live moderators, composited recordings, and richer replays.
| Feature | Behavior |
|---|---|
| Participant join requests | Viewers request audio-only or audio-and-video participation and wait for host approval in real time. |
| Multi-participant rooms | Accepted guests publish inside the same room with responsive host and participant layouts. |
| Per-stream moderators | Hosts can appoint moderators who manage chat, bans, participant requests, and participant removal. |
| Participant system events | Chat records when participants join, leave, or are removed by the host or moderator. |
| Live polls with voters | Polls publish to every live role while only the host can inspect each voter and selected option. |
| Functional layout presets | Adaptive grid, host focus, split screen, and screen-share arrangements update the live stage. |
| Composited replay identity | Recorded multi-participant layouts display each participant name in the corresponding video tile. |
| Audio-only replay design | Audio participants receive a polished avatar, identity, and audio state instead of an empty black tile. |
| Cloud replay replication | Completed replay media is uploaded to the configured cloud disk while retaining storage metadata. |
Experience release
Consistent menus, dialogs, icon actions, responsive sheets, and functional content controls across the public application.
| Feature | Behavior |
|---|---|
| Shared dropdown system | Video, replay, profile, comment, and community actions reuse the same accessible dropdown patterns. |
| Mobile bottom sheets | Action menus adapt into touch-friendly bottom sheets with stable close behavior on small screens. |
| Custom confirmation dialogs | Destructive and sensitive actions use branded application dialogs instead of browser confirm prompts. |
| Watch later actions | Videos can be added to or removed from Watch Later through matching clock-based actions. |
| Pin and unpin controls | Profile videos expose clear pin states and correctly paired pin or unpin icons. |
| Responsive toast placement | Desktop notifications retain their position while mobile toasts become top-aligned and full-width. |
Live discovery release
Stream browsing, tags, pre-live configuration, diagnostics, and discoverable live metadata.
| Feature | Behavior |
|---|---|
| Live stream tags | Hosts add comma-separated tags before going live and viewers can use them to open matching search results. |
| Pre-live settings dialog | Streamers review and update title, required description, category, tags, participation, and recording options. |
| In-stream settings | The host can change supported stream settings without ending the active broadcast. |
| Stream diagnostics | Live bitrate, frame rate, latency, source state, tracks, network quality, and service status are inspectable. |
| Live browse page | Current streams and past replays use real category filters, sorting, and grid or list presentation. |
| Trending replay topics | Replay discovery topics are generated from real published replay data rather than demo content. |
Replay release
A complete replay page with adaptive playback, chat replay, chapters, moments, analytics, and creator context.
| Feature | Behavior |
|---|---|
| Adaptive replay player | Replay media fits its parent while portrait and landscape sources preserve their intended composition. |
| Chat replay | Visible live messages, system events, and contributions return at their recorded replay timestamps. |
| Replay chapters | Opening, midpoint, highlights, and wrap-up chapters seek the player to exact moments. |
| Top moments | Replay events surface meaningful checkpoints, gifts, and stream milestones with thumbnails. |
| Replay analytics | Views, likes, comments, gifts, peak viewers, and performance actions are available to the creator. |
| Replay action menu | Share, copy, save, watch later, playlist, report, and owner actions use the common menu system. |
| More from creator | Related replays present real thumbnails, descriptions, duration, views, and creator navigation. |
Streaming release
Browser and RTMP streaming, control room workflows, live chat, invitations, recording, and host operations.
| Feature | Behavior |
|---|---|
| Browser broadcasting | Hosts publish camera, microphone, and screen-share tracks with role-aware local controls. |
| RTMP ingress | External encoders receive a real LiveKit-backed RTMP URL and unique stream key. |
| Live control room | Hosts manage participants, backstage invitations, layout, spotlight, screen share, polls, and settings. |
| Guest invitations | Username suggestions find real users and send a live guest invitation with confirmation. |
| Live chat | Viewers, hosts, participants, and moderators exchange real-time messages and reactions. |
| Composite recording | Room recording captures the configured layout for processing into an on-platform replay. |
| Automatic reconnect | Reloaded control rooms attempt a safe session reconnect before displaying a manual action. |
Library release
Personal library navigation, private-state handling, collections, and channel-side information architecture.
| Feature | Behavior |
|---|---|
| Profile library tab | Channel profiles expose a dedicated Library tab with owner-aware private states. |
| Saved content collections | Liked videos, watch later, playlists, history, bookmarks, and favorites use distinct destinations. |
| Channel information rail | About details, joined date, videos, subscribers, views, likes, and comments appear in a stable side rail. |
| Profile search control | The profile navigation search icon opens channel-scoped search instead of acting as decoration. |
Search release
Database-backed search results for videos, channels, playlists, live streams, and creator tools.
| Feature | Behavior |
|---|---|
| Global search results | Videos, channels, playlists, categories, and live content are returned from real database queries. |
| Creator Studio search | Studio search filters real creator content, comments, playlists, and channel data. |
| Live profile search | The Live tab can search its current streams and replays without losing the active profile context. |
| Search result actions | Result menus open the same share, playlist, report, and save workflows used elsewhere. |
Interaction release
Functional subscription, share, block, report, notification, edit, and channel relationship actions.
| Feature | Behavior |
|---|---|
| Subscription controls | Subscribe and unsubscribe update the relationship and subscriber count in place. |
| Profile overflow menu | Copy, share, edit, mute, favorite, report, and block actions respect account permissions. |
| Verified identity system | The shared verified mark renders consistently beside account names across public and admin screens. |
| Channel social links | Configured Instagram, YouTube, Twitch, Facebook, TikTok, and LinkedIn links appear on profiles. |
Profile release
Responsive creator identity, cover media, channel navigation, metadata, and content sections.
| Feature | Behavior |
|---|---|
| Creator profile header | Cover media, avatar, identity, verification, subscriber count, and actions form one responsive header. |
| Channel navigation | Home, Videos, Live, Playlists, Shorts, Community, About, and Library are first-class profile tabs. |
| Channel statistics | Views, likes, comments, total length, joined date, and publishing counts use real data. |
| Profile owner controls | Channel owners receive edit and management actions without exposing them to visitors. |
Publishing release
A staged creator upload flow with metadata, validation, scheduling, checks, and playback preview.
| Feature | Behavior |
|---|---|
| Upload steps | File, details, visibility, checks, and publish stages give creators a clear upload path. |
| Chunked uploads | Large media uploads resume through configurable chunk sessions with progress feedback. |
| Real tag input | Creators enter individual tags with limits, duplicate prevention, and removable tokens. |
| Schedule publishing | A native date and time input keeps videos private until their configured release. |
| Upload preview | Thumbnail, title, progress, duration, and timeline provide a stable pre-publish preview. |
Channel content release
Dedicated profile content for live streams, playlists, Shorts, communities, about information, and libraries.
| Feature | Behavior |
|---|---|
| Profile Live tab | Active streams and past replays use real cards, status, descriptions, categories, and owner actions. |
| Profile Playlists tab | Public playlist collections are available to visitors and navigate to the selected playlist. |
| Profile Shorts tab | Vertical videos have a dedicated channel surface with creator metadata. |
| Profile Community tab | Channel posts, media, polls, comments, and reactions are available from the creator profile. |
| Profile About tab | Biography, details, links, and channel facts are organized in a dedicated view. |
Video profile release
Channel video cards, pinning, deletion, watch actions, metadata, and responsive grids.
| Feature | Behavior |
|---|---|
| Channel video grid | Published videos use real thumbnails, duration, title, views, age, and creator metadata. |
| Pinned profile video | Channel owners can pin or unpin a selected video from the overflow menu. |
| Owner video actions | Edit, playlist, share, copy, watch later, report, and delete actions respect ownership. |
| Profile video deletion | Deletion moves into the standard overflow menu with a custom confirmation dialog. |
Identity release
Creator channels, cover positioning, biographies, categories, social links, and audience actions.
| Feature | Behavior |
|---|---|
| Automatic creator channels | Registration creates a creator channel with an editable identity and unique slug. |
| Cover positioning | Creators upload and position responsive channel cover media. |
| Channel biography | A formatted creator description and About content introduce the channel. |
| Creator category | Channels associate with a content category used by discovery and profile metadata. |
| Profile audience actions | Visitors subscribe, share, message, favorite, report, or block from the channel header. |
Quality release
Responsive Creator Studio tables, side summaries, dropdown containment, and operational content states.
| Feature | Behavior |
|---|---|
| Responsive content table | Studio content changes from a dense desktop table to readable mobile rows without losing actions. |
| Performance summaries | Views, comments, visibility, monetization, status, and recent performance remain visible in context. |
| Stable action menus | Studio dropdowns stay within the viewport and above neighboring panels. |
| Content status system | Published, replay, draft, scheduled, and processing states use distinct real statuses. |
Content release
Searchable creator content, bulk selection, filters, visibility, monetization, scheduling, and performance tools.
| Feature | Behavior |
|---|---|
| Content inventory | Creators see videos, Shorts, live replays, drafts, and scheduled content in one inventory. |
| Content search | Search filters the creator content collection using real titles and metadata. |
| Content filters | Type, visibility, monetization, status, and date controls narrow the content table. |
| Bulk content selection | Checkbox selection prepares multi-item creator actions without changing table dimensions. |
| Recent performance | Top content and compact performance indicators summarize channel activity. |
Media release
Validated uploads, FFmpeg media processing, thumbnails, renditions, captions, import metadata, and storage controls.
| Feature | Behavior |
|---|---|
| Validated media upload | File type, extension, MIME, size, checksum, and ownership are validated before processing. |
| FFmpeg renditions | Configured output qualities create playback-ready renditions with real media metadata. |
| Thumbnail generation | Uploads create and store video thumbnails with owner-provided thumbnail support. |
| Caption storage | Creators can attach supported caption files and expose them during playback. |
| Video import metadata | YouTube, Vimeo, Dailymotion, and direct URL imports retain source details and status. |
| Local and S3 storage | Media storage can use the server disk or a configured S3-compatible provider. |
Creator release
A focused operating surface for channel analytics, recent comments, content, publishing, and creator actions.
| Feature | Behavior |
|---|---|
| Studio dashboard | Creators receive channel metrics, recent performance, comments, publishing actions, and shortcuts. |
| Recent comments | Real comments display creator, text, video thumbnail, age, and a functional action dropdown. |
| Channel analytics | Views, watch time, subscribers, content, and engagement metrics summarize channel activity. |
| Creator quick actions | Upload, go live, manage content, comments, playlists, and channel settings are directly accessible. |
Foundation release
The initial public video platform: home discovery, playback, creators, subscriptions, engagement, and personal viewing tools.
| Feature | Behavior |
|---|---|
| Home discovery | Featured, trending, recent, category, creator, and continue-watching content form the public homepage. |
| Video playback | Responsive playback, title, creator, actions, description, comments, and related videos share one watch page. |
| Explore and trending | Visitors browse real videos, creators, topics, and categories with sorting and discovery sections. |
| Channel subscriptions | Authenticated viewers subscribe to creators and browse their subscription feed. |
| Watch Later | Viewers save content into a dedicated Watch Later collection. |
| Likes and comments | Videos and comments support authenticated engagement with persisted counts. |
| Viewing history and progress | Playback position and history allow viewers to resume content across sessions. |
| Responsive light and dark themes | The platform defaults to light mode and supports a true-black dark appearance. |
Version 0.9.9 adds an extension platform, transactional updates, new paid-content workflows, persistent playback, deeper discovery, and expanded administration. Use this section as the operating reference for capabilities introduced in this release.
Version 0.9.9 does not deprecate any public PlayHub API. Plugin API v1 is the supported extension contract for new integrations.
Install extensions only from a source you trust. Plugin packages and system updates execute server-side code, so review compatibility, dependencies, requested configuration, and the package source before enabling them.
| Capability | How it works |
|---|---|
| Plugin API v1 | Plugins register trusted PHP service providers, lifecycle hooks, dependency and compatibility rules, migrations, encrypted settings, server-side actions and filters, and namespaced website or Admin Panel pages. |
| Admin Plugins workspace | Use the workspace to install or update a ZIP package, review diagnostics, configure settings, enable or disable the plugin, and remove its package. |
| Package hardening | Installation rejects traversal paths, symlinks, unsafe file types, server-control files, and archives that exceed package size or file-count limits. Package replacement is rollback-safe. |
| Declared plugin assets | Plugins may declare CSS, JavaScript, modules, images, fonts, JSON, and WebAssembly. PlayHub serves declared files through its protected asset route and browser hook runtime. |
| Transactional system updater | The updater verifies signed manifests and checksums, runs preflight checks, protects runtime paths, creates backups, controls maintenance mode, applies database recovery, monitors interruptions, and can roll back a failed update. |
| Plugin Admin workspaces | Namespaced Admin pages receive authenticated requests, navigation, confirmation and alert dialogs, and deterministic mount cleanup through Plugin API v1. |
Resolve failed server, dependency, compatibility, disk, permission, and protected-path checks before changing production files.
Confirm the updater has a recoverable application and database backup before maintenance mode begins.
Allow checksum validation, file replacement, migrations, cache refresh, and health checks to finish without manually replacing files in parallel.
If monitoring reports an interruption or failed health check, use the updater recovery state and rollback instead of retrying partial file copies.
The packaged Update_v0.9.9 manual update upgrades a verified PlayHub 0.7.5 installation directly to 0.9.9; the 0.7.6 and 0.7.7 packages are not required. Do not use this package on an older release. Run the update as the operating-system user that owns PlayHub and stop uploads, streams, queue jobs, and other writes first.
.env, database, uploads/, storage/, media, branding, plugins, and service configuration.php artisan down --retry=60.Update_v0.9.9/ into the existing root. Preserve customer environment files, runtime data, uploads, media, plugins, SSL files, and active server configuration.npm install, npm run build, composer install, or composer update. The production build is included and the Composer lock is unchanged.VERSION, /api/health, core pages, existing data, Plugins, queues, and real-time notifications.php update_database.phpDo not run php artisan migrate --force for this manual package. If update_database.php fails, keep maintenance mode enabled, preserve its output, and restore the verified backup before attempting any manual schema change.
Only after the database updater reports success, remove it from the public root and finish deployment:
rm update_database.php
php artisan optimize:clear
php artisan config:cache
php artisan route:cache
php artisan view:cache
php artisan queue:restart
php artisan reverb:restart
php artisan upIf the Artisan Reverb restart command is unavailable, restart Reverb with the installation's existing supervisor or service manager before leaving maintenance mode. LiveKit does not need a restart for this file and database update unless its service configuration also changed.
Use the dedicated Plugin development guide to create a Plugin API v1 package from an empty directory, add backend and browser integrations, package it safely, and test its complete lifecycle.
| Capability | Viewer or creator behavior |
|---|---|
| Standalone embed player | Iframe embeds render only the requested video and player instead of the complete video-details page. |
| Automatic scroll miniplayer | An actively playing watch-page video floats after it falls below 50% visibility and returns inline when paused, ended, or visible again. |
| Persistent in-tab playback | Playback can continue across website navigation and reloads with previous/next queue controls, seek, mute, secure source refresh, full-player handoff, and browser Media Session integration. |
| Homepage and Shorts recommendations | Recommendations combine freshness, engagement quality, momentum, daily exploration, viewer affinity, completed-watch suppression, and creator/category diversity. |
| AirPlay and Google Cast | Supported browsers expose feature-detected casting for on-demand video and live replays, including Safari media permission and resumable default-receiver sessions. |
| Timestamped descriptions | Descriptions preserve formatting, Unicode, and emoji. Clickable m:ss and h:mm:ss timestamps seek the active player. |
| Automatic chapters | Valid timestamped descriptions create native Vidstack chapter tracks with segmented seek bars, active titles, chapter navigation, and cover previews. |
| Managed chapters | Import CUE files or timestamp lists, review duration-based unnamed segments, validate chapter storage, and opt each video into native timeline chapters. |
| YouTube chapter import | Imported videos can read native player markers or timestamped descriptions and present an editable Step 4 chapter review with explicit opt-out. |
| Rich description formatting | Descriptions safely render inline bold, italic, combined emphasis, external links, and the original text layout. |
| Automatic Up Next loading | The watch page loads another recommendation page near the end of Up Next while preserving the manual Show more control. |
| Imported Shorts detection | YouTube Shorts signals or verified portrait metadata from other providers classify imported short-form videos. |
| Contextual recommendations | Related and Up Next results combine channel, category, language, and tags with a signed-in viewer's private history, likes, saved videos, and subscriptions. |
| Draggable miniplayer | Desktop users can move the minimized player within viewport bounds. Position and size persist, with constrained resizing, compact or expanded size, keyboard movement, and recovery after viewport changes. |
| Desktop theater mode | The watch page remembers theater mode, exposes native player and keyboard controls, expands playback, and keeps Up Next responsive. |
| Capability | Configuration and access |
|---|---|
| Paid community photo sets | Protected originals are unlocked through wallet purchase with platform fees, configured tax, permanent buyer access, and seller notification. |
| Currency-aware account balance | The account menu shows the wallet in the selected currency and links directly to Earnings. |
| Creator tips and donations | Creators may accept wallet-backed support on channel and video pages, opt out, and rely on configured contribution limits, fees, idempotent transfers, and notifications. |
| Paid video sales | Administrators enable sales and creators set eligible prices. Wallet checkout applies the platform commission, notifies the purchase participants, and grants permanent Purchased-library access through protected playback links. |
| Purchase taxes | Configure VAT, GST, or Sales Tax for paid videos. Checkout shows the buyer total and stores an auditable tax record. |
| Withdrawal approvals | Administrators or permitted moderators receive pending-request alerts, review requests, approve or reject once, retain reviewer metadata, and notify the creator of the decision. |
| Video boost campaigns | Creators reserve wallet budgets and choose daily, per-click, or per-view billing. Home and Trending placement is paced and relevance-aware, qualified events are deduplicated, promoted labels remain visible, creator controls and reporting are provided, and administrators define limits. |
| Creator Studio earnings | The earnings cabinet filters creator-scoped VAST, tip, video sale, and live revenue and shows fees, balances, supporter/content details, pagination, and complete notifications for tips, purchases, and channel subscriptions. |
Video advertising now supports VAST pre-roll, timed mid-roll, and post-roll breaks. Creator video payouts use completed VAST impressions with the VAST CPM or administrator fallback CPM, a configurable creator percentage, fractional accrual, self-view exclusion, hourly deduplication, and idempotent wallet crediting. Shorts cannot be sold as paid videos and are excluded from the standard player's Up Next and autoplay sequence.
| Capability | Workflow |
|---|---|
| Hashtags and linked mentions | Hashtags open search results and linked mentions open the referenced channel profile in video comments, community posts, and community comments. |
| Upload playlist selection | The upload workflow lets a creator add the new video to one of that creator's own playlists. |
| Responsive mobile navigation | The mobile header provides search and coordinates with a fixed bottom navigator, animated active state, guest login behavior, and role-aware Live/Profile availability. |
| Community post removal | Post authors, community owners, platform moderators, and administrators can remove posts according to their permissions. |
| Watch-page video deletion | Creators, moderators, and administrators receive a confirmed delete action when their role can remove the current video. |
| Mention autocomplete | Type @ in supported video or community composers to receive suggestions, use keyboard selection, render a linked mention, and send preference-aware notifications. |
| Community poll voters | Click a poll vote count to open paginated voter details with each public profile and selected option. |
| Publishing access controls | Administrators define upload and live role rules, a strict username allowlist, timed user restrictions, and profile-complete self-service creator upgrades for new User accounts. |
| Capability | Administration behavior |
|---|---|
| Default website language | Choose the default in Admin Languages. A returning visitor's saved language preference remains authoritative. |
| Language availability | Enable or disable public languages while default-language safeguards prevent an invalid catalog state. |
| Localized Admin Pages | Edit About, Contact, Developers, FAQ, Help, Refund, Privacy, Terms, and Cookie pages by language with repeatable sections, visibility, footer, search metadata, sitemap controls, and atomic update-safe override storage. |
| Localized email templates | Edit, preview, validate, or reset every system email for each installed language using the documented template placeholders and update-safe overrides. |
| Branded HTML email | System email uses the configured website name and accent colors with responsive HTML and plain-text alternatives through SMTP, SendGrid, or native mail. |
| Signup audit data | User management records immutable signup IP and registration source; full IP visibility remains admin-only. |
| Route loading mode | Website Configuration can show a top loading bar, loading text, or both until the destination's initial requests finish. |
| Social sharing previews | Videos, Shorts, live streams, channels, community posts, and playlists receive server-rendered Open Graph and X cards using original artwork or the branded 1200x630 fallback. |
| SEO and Sitemaps | Configure search metadata, canonical origin, verification, per-content indexing, dynamic robots rules, synchronized Open Graph/X/JSON-LD, and paginated content sitemaps. |
| Live-stream deletion | The Admin Live Streams row menu can delete an eligible stream after confirmation and clean the active session, replay, related records, and media. |
Version 0.9.9 removes the unlicensed LightGallery dependency in favor of PlayHub's native responsive image viewer. It also removes the mobile-header theme switcher, duplicate header Go Live action, sidebar user summary card, obsolete System Settings collapse control, and setup's Product license heading and instructional paragraph. License verification remains required.
PlayHub Plugin API v1 lets an extension add Laravel services, routes, migrations, settings, server hooks, browser hooks, website pages, and Admin workspaces without changing PlayHub core files. This guide builds a small but complete acme.example-tools plugin and explains how each part is loaded.
A plugin provider runs inside Laravel and can access the application, database, filesystem, and configured services. Develop and test on a non-production installation, review every dependency and file, and install packages only from trusted authors.
acme.example-tools and a matching PHP namespace such as Acme\ExampleTools.Create the following directory tree. Only plugin.json is always required; the other paths are included when declared by the manifest or used by the plugin.
acme.example-tools/
├── plugin.json
├── README.md
├── CHANGELOG.md
├── src/
│ ├── PluginServiceProvider.php
│ └── Lifecycle.php
├── routes/
│ └── api.php
├── database/
│ └── migrations/
│ └── 2026_09_06_000000_create_example_tools_notes.php
└── assets/
├── example-tools.js
└── example-tools.cssNamespace classes, routes, tables, cache keys, browser globals, and CSS classes with the vendor and plugin name. This prevents collisions with PlayHub and other extensions.
Place plugin.json at the package root. Provider and lifecycle classes must be covered by the declared PSR-4 namespace. Paths use forward slashes and must remain inside the package.
{
"id": "acme.example-tools",
"name": "Example Tools",
"version": "1.0.0",
"api": 1,
"description": "A complete PlayHub Plugin API v1 example.",
"homepage": "https://example.com/playhub-plugins/example-tools",
"author": {
"name": "Acme",
"url": "https://example.com"
},
"requires": {
"playhub": ">=0.9.9",
"php": ">=8.3.0",
"extensions": ["json"]
},
"dependencies": {},
"autoload": {
"psr-4": {
"Acme\\ExampleTools\\": "src/"
}
},
"providers": [
"Acme\\ExampleTools\\PluginServiceProvider"
],
"lifecycle": "Acme\\ExampleTools\\Lifecycle",
"migrations": "database/migrations",
"assets": {
"styles": ["assets/example-tools.css"],
"scripts": ["assets/example-tools.js"]
},
"settings": [
{
"key": "greeting",
"label": "Greeting",
"type": "text",
"description": "Text displayed by the example pages.",
"default": "Hello from Example Tools",
"required": true,
"public": true,
"max_length": 120
},
{
"key": "api_token",
"label": "External API token",
"type": "password",
"description": "Optional private credential used only on the server.",
"required": false,
"public": false
}
],
"capabilities": [
"Example website page",
"Example Admin workspace",
"Backend status endpoint"
]
}| Field | Purpose and rules |
|---|---|
id | Required stable identifier. Use lowercase letters and numbers separated by dots, dashes, or underscores. admin, core, playhub, and system are reserved. |
name, version | Required display name and semantic version such as 1.0.0, 1.1.0-beta.1, or 2.0.0+build.4. |
api | Set to 1. PlayHub rejects a package targeting an unsupported Plugin API version. |
description, homepage, author | Optional package metadata displayed in Admin Plugins. Homepage and author URLs must use HTTP or HTTPS. |
requires | PlayHub and PHP version constraints plus required PHP extensions. Declare the real minimum versions instead of relying on defaults. |
dependencies | Optional object mapping another plugin ID to a version constraint, for example "acme.base": "^1.2". Required plugins must be installed, compatible, and enabled. |
autoload.psr-4 | Maps each plugin PHP namespace to a package directory. Namespace keys must end in a backslash. PlayHub provides its own plugin class loader, so a Composer autoload rebuild is not required. |
providers | Laravel service-provider classes loaded when the plugin is enabled. Keep providers small and defer side effects to boot() or lifecycle methods. |
lifecycle | Optional class for enable, disable, settings-update, and uninstall behavior. |
migrations | Optional directory containing Laravel migrations. The declared directory must exist and migrations run when the plugin is enabled. |
assets | Declared CSS, JavaScript or module scripts, and additional image, font, JSON, or WebAssembly files. Only declared files are served by the protected plugin-asset route. |
settings | Admin-configurable fields stored as an encrypted array. Supported types are text, password, textarea, boolean, number, and select. |
capabilities | Short human-readable capability labels shown in Admin Plugins. |
Extend PlayHub's plugin provider, return the exact manifest ID, and use the plugin context for package paths, settings, actions, and filters. Register container bindings in register(); load routes and hooks in boot().
<?php
namespace Acme\ExampleTools;
use App\Plugins\PluginServiceProvider as PlayHubPluginServiceProvider;
use Illuminate\Support\Facades\Route;
final class PluginServiceProvider extends PlayHubPluginServiceProvider
{
protected function pluginId(): string
{
return 'acme.example-tools';
}
public function boot(): void
{
$context = $this->plugin();
Route::prefix('api/example-tools')
->group($context->path('routes/api.php'));
$context->addFilter(
'playhub.public_settings',
function (array $settings) use ($context): array {
$settings['example_tools'] = [
'greeting' => $context->setting(
'greeting',
'Hello from Example Tools'
),
];
return $settings;
}
);
}
}The provider is instantiated only for an enabled, compatible plugin. A provider exception disables that plugin's runtime contribution and is recorded in Admin Plugins. Do not perform slow remote requests during application bootstrap.
| Method | Use |
|---|---|
id(), version(), manifest() | Read the installed plugin identity and normalized manifest. |
settings(), setting($key, $default) | Read the plugin's decrypted server-side settings. Never log secret values. |
path($relativePath) | Resolve a validated path inside the installed plugin directory. Traversal and absolute paths are rejected. |
addAction(), action() | Register or dispatch server-side event hooks. |
addFilter(), filter() | Register or apply server-side value transformations. |
The provider above adds an /api/example-tools prefix. This read-only status route can be public. Any endpoint that reads private data or changes state must use auth:sanctum, validate its request, authorize the user in a controller or policy, and apply an appropriate throttle.
<?php
use Illuminate\Support\Facades\Route;
Route::get('/status', static fn () => response()
->json([
'ok' => true,
'plugin' => 'acme.example-tools',
'version' => '1.0.0',
])
->header('Cache-Control', 'no-store'))
->middleware('throttle:60,1');registerAdminPage() controls where a page appears; it does not authorize custom API routes. Require authentication and check the administrator, moderator, creator, owner, or resource permission again inside every protected controller action.
Use a plugin-specific table prefix and a globally unique migration filename. Add a new migration for every released schema change; never edit a migration that customers may already have run.
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::create('example_tools_notes', function (Blueprint $table): void {
$table->id();
$table->foreignId('user_id')->index();
$table->string('title', 160);
$table->text('body')->nullable();
$table->timestamps();
});
}
public function down(): void
{
Schema::dropIfExists('example_tools_notes');
}
};PlayHub runs declared pending migrations with --force while enabling the plugin. Disabling or removing a plugin does not automatically roll migrations back. Preserve customer data by default; if uninstall should remove owned tables, implement that decision explicitly and disclose it to administrators.
The lifecycle class is resolved through Laravel's container. Each method is optional. Keep enable and settings-update operations repeatable, avoid logging credentials, and leave the application consistent if an exception occurs.
<?php
namespace Acme\ExampleTools;
use App\Plugins\PluginContext;
use App\Plugins\PluginLifecycle;
final class Lifecycle extends PluginLifecycle
{
public function enable(PluginContext $context): void
{
logger()->info('Example Tools enabled.', [
'plugin' => $context->id(),
'version' => $context->version(),
]);
}
public function disable(PluginContext $context): void
{
logger()->info('Example Tools disabled.');
}
public function settingsUpdated(
PluginContext $context,
array $previousSettings
): void {
logger()->info('Example Tools settings updated.');
}
public function uninstall(PluginContext $context): void
{
// Remove only plugin-owned data that the administrator expects to lose.
}
}| Lifecycle method | When it runs |
|---|---|
enable($context) | After compatibility validation, class validation, and pending plugin migrations, before the plugin is marked enabled. |
disable($context) | When the plugin is disabled. Use it to pause plugin-owned jobs or external activity, not to destroy customer data. |
settingsUpdated($context, $previousSettings) | After new encrypted settings are stored for an enabled plugin. An exception restores the previous settings. |
uninstall($context) | When a previously enabled plugin is removed. Package removal continues even if this hook reports an error. |
Declared scripts load through PlayHub's protected asset route. Register with the exact plugin ID. A website page receives request, navigate, and user tools. An Admin workspace also receives PlayHub confirm and alert dialogs.
const PLUGIN_ID = 'acme.example-tools';
function mountExample(container, tools, greeting) {
const controller = new AbortController();
const section = document.createElement('section');
section.className = 'example-tools';
const title = document.createElement('h2');
title.textContent = greeting;
const status = document.createElement('p');
status.textContent = 'Checking the plugin API...';
section.append(title, status);
container.replaceChildren(section);
tools.request('/example-tools/status', {
signal: controller.signal,
trackPageLoading: false,
}).then((payload) => {
status.textContent = payload.ok
? `Plugin ${payload.version} is ready.`
: 'The plugin API reported a problem.';
}).catch((error) => {
if (error.name !== 'AbortError') {
status.textContent = error.message || 'The plugin API is unavailable.';
}
});
return () => {
controller.abort();
container.replaceChildren();
};
}
window.PlayHub.register(PLUGIN_ID, (plugin) => {
const greeting = String(
plugin.settings.greeting || 'Hello from Example Tools'
);
plugin.registerPage({
path: '/example-tools',
authRequired: false,
mount: (container, tools) =>
mountExample(container, tools, greeting),
});
plugin.registerAdminPage({
path: `/admin/extensions/${PLUGIN_ID}`,
label: 'Example Tools',
title: 'Example Tools',
subtitle: 'Verify the example plugin runtime and API.',
icon: 'plugin',
mount: (container, tools) =>
mountExample(container, tools, greeting),
});
});.example-tools {
max-width: 760px;
padding: 24px;
border: 1px solid var(--line, #dfe3ea);
border-radius: 8px;
background: var(--surface, #fff);
}
.example-tools h2 {
margin: 0 0 8px;
}
.example-tools p {
margin: 0;
}The mount function must return cleanup when it creates listeners, timers, observers, requests, or external DOM. PlayHub calls cleanup during route changes and Admin workspace unmounting. Use the provided navigation and request tools so authentication, language headers, and route loading remain integrated.
| API | Behavior |
|---|---|
window.PlayHub.register(id, setup) | Registers one enabled plugin. Duplicate IDs or an ID not present in the enabled plugin metadata are rejected. |
plugin.settings | Contains only manifest settings marked public: true. Never expose tokens, passwords, or private configuration. |
addAction(), addFilter() | Registers browser listeners. Filters must return synchronously; promise-returning browser filters are rejected. |
onReady(callback) | Runs after PlayHub's browser application is ready, or queues the callback until it is ready. |
registerPage(definition) | Adds a website route. Set authRequired: false only when the page and its API are safe for guests. |
registerAdminPage(definition) | Adds a route under /admin/extensions/<plugin-id> with label, title, subtitle, icon, and mount function. |
navigate(path, options) | Performs same-origin PlayHub navigation. Cross-origin targets are rejected. |
doAction(), applyFilters() | Dispatches a browser action or applies a browser filter chain when the plugin owns an integration contract. |
All plugin settings are encrypted at rest. The public flag controls whether a value is also sent to the browser, not whether it is stored encrypted. Keep public false unless frontend code genuinely needs the value; password fields can never be public.
| Setting type | Useful fields |
|---|---|
text, password, textarea | default, placeholder, required, public, and max_length. Textarea defaults to a larger maximum length. |
boolean | Use a true or false default. Suitable for feature switches. |
number | Use numeric default, min, and max values. |
select | Provide one or more options with value and label. The default must match an option value. |
A required field without a usable default must be configured in Admin Plugins before the plugin can be enabled. Server code reads every setting through PluginContext; browser code receives only public settings.
Actions announce an event and are appropriate for side effects. Filters receive a value and must return the value that the next listener should receive. Hook names start with a lowercase letter and may contain lowercase letters, numbers, dots, colons, dashes, and underscores. Priorities range from -1000 to 1000; lower values run first and equal priorities keep registration order.
| Verified core hook | Environment and purpose |
|---|---|
playhub.plugins.booted | Server action after enabled plugin providers finish booting. |
playhub.public_settings | Server filter for adding safe public configuration to the website payload. |
playhub.admin.page_data | Server filter for the authenticated Admin page-data payload. |
playhub.notification.payload | Server filter for notification presentation data. |
playhub.ready | Browser action after the main application is mounted. |
playhub.route.changed | Browser action after client-side navigation. |
playhub.navigation.groups | Browser filter for adding or adjusting navigation groups. |
playhub.navigation.target | Browser filter applied before same-origin navigation. |
Prefix custom hooks with the plugin ID, for example acme.example-tools.note.created. Catch expected integration failures inside the plugin and preserve the documented input and output type of every core filter.
Validate JSON and PHP syntax before packaging. The example below creates a ZIP whose root contains plugin.json; one wrapper directory is also accepted.
php -r 'json_decode(file_get_contents("plugin.json"), true, 64, JSON_THROW_ON_ERROR); echo "Manifest JSON is valid.\n";'
find . -name '*.php' -print0 | xargs -0 -n1 php -l
zip -r ../acme.example-tools-1.0.0.zip . -x '*.DS_Store' '.git/*'.env, .htaccess, .user.ini, or web.config..git/, node_modules/, tests, source maps, and unneeded vendor files. Package only reviewed runtime files you may redistribute.Open Admin Panel > Plugins, install the ZIP, and review its identity, version, requirements, dependencies, capabilities, checksum, and diagnostics. New packages are installed disabled.
Enter required values before enabling. Confirm private credentials are password fields with public: false.
PlayHub validates compatibility and dependencies, registers the PSR-4 loader, validates runtime classes, runs pending migrations, invokes enable(), and marks the plugin enabled.
Open /example-tools, then Admin Panel > Plugins > Example Tools. Test the API, settings, authorization, browser console, responsive layout, and Laravel logs.
Confirm routes, pages, hooks, listeners, jobs, and assets stop affecting PlayHub after disable. Test uninstall on disposable data and verify the documented data-retention behavior.
version in plugin.json and update the changelog.PlayHub creates a rollback-safe package replacement during installation, but plugin migrations and external side effects still require the plugin author's own forward-compatible design. An enabled dependent plugin prevents its required dependency from being disabled or removed.
| Error | Resolution |
|---|---|
| Manifest is missing or invalid | Put one valid plugin.json at the ZIP root or inside one wrapper directory and validate its JSON syntax. |
| Provider or lifecycle class cannot load | Confirm the namespace ends with a backslash in autoload.psr-4, the path exists, filename case matches, and the class is declared in the manifest. |
| Plugin is incompatible | Correct the PlayHub, PHP, extension, and plugin dependency constraints or update the staging environment. |
| Plugin cannot be updated | Disable the installed version first, keep the same plugin ID, increase its version, and upload the replacement ZIP again. |
| Required setting blocks enablement | Configure the field in Admin Plugins or provide a valid manifest default. |
| Admin page does not appear | Declare and load the script, call window.PlayHub.register(), keep the path under the plugin's Admin namespace, enable the plugin, and refresh the next request. |
| API request returns 401 or 403 | Confirm the route middleware and controller authorization match the intended audience and that the provided tools.request() helper is used. |
| Asset returns 404 | Confirm the exact relative path is declared in assets, exists in the ZIP, and the plugin is enabled. |
Use a VPS or dedicated server where you control PHP-FPM, background services, firewall rules, Docker, and process supervision. Shared hosting is suitable only when it exposes every requirement below.
| Component | Minimum or purpose | Verify |
|---|---|---|
| Web and CLI PHP | PHP 8.3 or newer. Keep PHP-FPM and CLI versions compatible. | php -v |
| MySQL or MariaDB | Empty database with a dedicated UTF-8 capable account. | mysql --version |
| Redis | Queues, cache, sessions, streaming runtime, and real-time coordination. | redis-cli ping |
| Node.js | 20.19.0 or newer for the production frontend build. | node --version |
| npm | Version 9 or newer. The installer uses the locked dependency graph. | npm --version |
| FFmpeg and FFprobe | Video probing, thumbnails, renditions, processing, and media inspection. | ffmpeg -version |
| Docker Engine | Runs the LiveKit server, RTMP ingress, and replay egress services. | docker version |
| Docker Compose | Compose v2 is required by the bundled runtime installer. | docker compose version |
| Nginx or Apache | URL rewriting, protected application files, large uploads, and WebSocket proxying. | Server-specific |
| TLS certificate | Required for camera, microphone, secure WebSockets, OAuth, and payments. | Open the domain with HTTPS |
bcmath ctype curl dom fileinfo filter gd intl json mbstring openssl
pdo pdo_mysql session tokenizer xml zip zlibImagick is recommended for improved image processing. The PHP-FPM user also needs access to exec(), proc_open(), and nohup so the installer can stream process output and start its temporary installation worker.
storage/, bootstrap/cache/, uploads/, and lang/..env, node_modules/, and build/.Install at a domain root such as https://video.example.com, not at https://example.com/playhub. The document root points to the package root, not the Laravel public/ folder.
Upload the complete package and preserve hidden files. The web installer generates environment-specific dependencies and production assets on the destination server.
| Path | Purpose | Customer action |
|---|---|---|
install.php | Four-step installation wizard and live installation console. | Open once, then remove after installation if desired. |
app/, routes/, config/ | Laravel application, API, jobs, services, and configuration. | Do not expose or edit without a backup. |
resources/ | React/Vite source and Blade resources. | Rebuild after frontend customization. |
vendor/ | Bundled Composer dependencies. | Keep present for installer startup. |
package.json, package-lock.json | Tested frontend dependency graph. | Do not delete the lock file. |
branding/ | Default logo and favicon imported during installation. | Keep; replace later from Website Configuration. |
gifts/, stickers/ | Bundled local contribution catalogs. | Keep so native catalog import succeeds. |
livekit/ | Docker runtime installer, templates, status exporter, and generated runtime files. | Run its installer with sudo after the web install. |
server-configs/ | Nginx and Apache root-domain examples. | Apply the matching server configuration. |
docs/ | This standalone documentation. | Open docs/index.html directly or publish it. |
.envProduction URL, database, Redis, mail, media, and runtime variables.node_modules/Installed with npm ci from the tested lock file.build/Vite production assets loaded by the public application.storage/app/installed.lock prevents accidental reinstallation.storage/app/license.json stores the signed installation activation.Prepare the domain and services before opening the installer. The installation process verifies the same critical dependencies again before writing production state.
Point a clean root domain or subdomain to the extracted PlayHub package and issue a valid SSL certificate.
Create an empty MySQL or MariaDB database and a dedicated account with privileges on that database only.
Record the host, port, username, password, and database number. Do not expose Redis publicly.
Have the administrator name, username, email, secure password, website URL, timezone, and CodeCanyon OR KNL (Kontackt Direct License) purchase code ready.
sudo chown -R <web-user>:<web-group> /var/www/playhub
sudo find /var/www/playhub/storage /var/www/playhub/bootstrap/cache /var/www/playhub/uploads -type d -exec chmod 775 {} \;
sudo find /var/www/playhub/storage /var/www/playhub/bootstrap/cache /var/www/playhub/uploads -type f -exec chmod 664 {} \;Give the web user ownership of runtime paths, then use normal directory and file modes. Broad write access exposes source, credentials, and uploaded files.
Use server-configs/nginx-root-install.conf inside the domain's existing server {} block. Keep the root pointed at the package directory, update fastcgi_pass for the installed PHP 8.3 socket, then validate and reload Nginx.
sudo nginx -t
sudo systemctl reload nginxEnable mod_rewrite, allow .htaccess overrides for the domain, and use server-configs/apache-vhost-example.conf as the virtual host reference. Preserve the root .htaccess file.
Open https://your-domain.com/install.php.
| Step | What happens | Expected result |
|---|---|---|
| 1. Requirements | Checks PHP, extensions, binaries, Docker, Redis, HTTPS, writable paths, disk, package files, and process support. | Required checks pass; warnings are understood. |
| 2. Configuration | Collects license, website, database, Redis, timezone, and initial owner details. | Connections and purchase code validate. |
| 3. Installation | Creates .env, installs frontend modules, builds assets, migrates tables, imports catalogs, caches config, and creates the owner. | Every console step ends with [OK]. |
| 4. Complete | Confirms the installed app and provides website/admin links. | Website and /admin open correctly. |
Keep the installation page open during Step 3. The console intentionally hides passwords, tokens, and service secrets.
/admin and review Website Configuration and System Settings.install.php after installation if your deployment policy requires it.The web request process must remain short. Video processing, replay finalization, notifications, scheduled publishing, retention, and backups run through queues and the scheduler.
Use a private Redis service with authentication. The application and LiveKit runtime may share the server but should use the configured database number. The installer default is database 2 for LiveKit coordination.
redis-cli -h 127.0.0.1 -p 6379 -a 'your-password' -n 2 pingcd /var/www/playhub
php artisan queue:work --queue=videos,default --sleep=3 --tries=3 --timeout=7200Run this through Supervisor or systemd. Do not leave it in an SSH terminal.
[program:playhub-worker]
process_name=%(program_name)s_%(process_num)02d
command=/usr/bin/php /var/www/playhub/artisan queue:work --queue=videos,default --sleep=3 --tries=3 --timeout=7200
directory=/var/www/playhub
autostart=true
autorestart=true
stopasgroup=true
killasgroup=true
user=www-data
numprocs=1
redirect_stderr=true
stdout_logfile=/var/www/playhub/storage/logs/worker.log
stopwaitsecs=7300sudo supervisorctl reread
sudo supervisorctl update
sudo supervisorctl start playhub-worker:*Set the active queue connection’s retry interval above its longest job timeout. Otherwise another worker may reserve a media job while the first still runs. The documented local configuration uses timeout 21600 seconds and DB_QUEUE_RETRY_AFTER=21660; Redis needs its own corresponding override rather than the 90-second fallback. Match these values to your supervised worker and actual workload.
Add exactly one cron entry for the web-server user. Laravel decides which internal tasks run each minute.
* * * * * cd /var/www/playhub && php artisan schedule:run >> /dev/null 2>&1The schedule handles future video publishing, replay finalization and retention, scheduled live polls, pruning, and configured automatic backups.
Both binaries must be executable by the queue-worker user. Set explicit paths in .env when they are not discoverable through that user's PATH.
PLAYHUB_FFMPEG_BINARY=/usr/bin/ffmpeg
PLAYHUB_FFPROBE_BINARY=/usr/bin/ffprobe
PLAYHUB_MAX_UPLOAD_MB=51200
PLAYHUB_CHUNK_SIZE_MB=8cd /var/www/playhub
php artisan optimize:clear
php artisan config:cache
php artisan queue:restartPlayHub uses a generated Docker runtime for WebRTC rooms, external-encoder ingress, and composite replay egress. The web installer prepares configuration, but the Docker installation must be run by a server administrator.
sudo /var/www/playhub/livekit/install.shIf automatic web-user detection is incorrect, pass the PHP-FPM account:
sudo /var/www/playhub/livekit/install.sh www-dataThe script creates livekit/runtime/, generates protected keys and service configuration, starts the Compose project, and registers a project-local manager through systemd when available. The generated project contains these services:
| Purpose | Default | Exposure |
|---|---|---|
| LiveKit signaling | TCP 7880 | Normally proxied through HTTPS/WSS; avoid direct public use. |
| WebRTC over TCP | TCP 7881 | Public inbound when used as ICE fallback. |
| WebRTC media | UDP 50000-60000 | Public inbound and outbound. |
| RTMP ingress | TCP 1936 | Public only when external encoders are enabled. |
| TURN UDP | UDP 3478 | Public for clients behind restrictive NAT. |
| TURN over TLS | TCP 5349 | Public when TURN TLS is enabled with valid certificates. |
Only media and signaling ports belong on the public firewall. LiveKit API credentials, Redis, generated YAML, and keys.yaml remain private. Publish and allow the effective turn.relay_range_start–turn.relay_range_end UDP range separately from the TURN listener and RTC media ports when using TURN relay.
In Admin Dashboard > System Settings > Live Streaming > LiveKit, set the public URL to a secure endpoint such as wss://video.example.com/livekit. The reverse proxy must preserve WebSocket upgrades and use a timeout appropriate for long-lived connections.
Adapt the shipped livekit/nginx-app-test-location.conf to the production host, PHP upstream, document root, and actual signaling port. Verify Nginx has http_auth_request_module. The include handles the LiveKit prefix and WebSocket upgrades; avoid duplicate competing locations.
The private /__playhub_livekit_admission FastCGI subrequest calls Laravel /api/livekit/admission and validates the JWT against current stream/account/stage authorization and server-held identity versions. Cached kicked or revoked grants remain denied after token refresh. Query and Bearer credentials must agree; the exact admitted credential is passed upstream. Keep direct core signaling host-private and do not expose a bypass join route.
Suppress token-bearing signaling access/error logs: the Windows include uses NUL; Unix deployments use /dev/null. Validate before reloading. A guarded missing-token request returning 403 is expected; prove real host/viewer media and cached-token rejoin separately. See the current Live service guide for networking, health checks, queues, and TURN.
| Setting | Use | Default |
|---|---|---|
| Enabled | Enables the real-time engine for public live workflows. | On |
| Public URL | Secure browser signaling endpoint. | APP_URL/livekit |
| API key / secret | Signs room and participant tokens. Treat both as secrets. | Generated |
| RTMP URL / port | Encoder endpoint displayed with the stream key. | Port 1936 |
| Redis | Host, port, username, password, and database used by the media services. | 127.0.0.1:6379, DB 2 on the host; bridge containers require a reachable authenticated listener through the configured host gateway. |
| Signal / RTC TCP | LiveKit signaling and WebRTC TCP transport. | 7880 / 7881 |
| RTC UDP range | WebRTC media ports. | 50000-60000 |
| External IP / node IP | Advertises the reachable media address to clients. | External IP on |
| Room timeouts | Empty-room and departure cleanup behavior. | 300s / 20s |
| Max participants | Optional room-wide participant ceiling; zero means engine default. | 0 |
| TURN | UDP or TLS relay for restrictive networks. | 3478 / 5349 |
| SSL/TURN certificates | Certificate directory, domain, certificate, and key paths. | Disabled until configured |
| Advanced JSON | Validated advanced server options and ICE server overrides. | Generated defaults |
docker compose -f /var/www/playhub/livekit/runtime/docker-compose.yml ps
node tools/live-health.cjs --jsondocker compose -f /var/www/playhub/livekit/runtime/docker-compose.yml restartWhen settings are changed from the admin dashboard, use its save/apply action so generated configuration and service status remain synchronized.
rtmp://video.example.com:1936/live.A stream key authorizes publishing to that live session. Do not show it on screen, include it in support screenshots, or reuse it outside the generated stream.
Camera hosting requires core LiveKit and Redis; RTMP ingress and recording egress are optional services required only for their workflows. In bridge networking, configure host access through host.docker.internal/host-gateway; container loopback cannot reach a host-only Redis listener. Start the configured optional services and verify their real listeners and dependencies.
The egress service loads the configured layout and records published participant tracks.
Participant names and designed audio-only tiles are part of the composite template, not browser overlays burned accidentally into the source.
The application records egress status and queues replay finalization when the stream ends.
The queue validates media, creates thumbnails and renditions, associates available chat/events, and moves the replay to ready state. Event checkpoints are distinct from authored video chapters.
When cloud storage is enabled, completed replay media is uploaded to the configured provider and retains its delivery metadata.
The control room diagnostics show actual connection state, source tracks, bitrate, frame rate, latency, network quality, room status, and runtime reachability. Check diagnostics before restarting services. A camera permission issue and a failed egress container require different fixes.
Most settings are available under Admin Dashboard > Website Configuration or Admin Dashboard > System Settings. Save each block independently and use its connection test where provided.
| Area | Settings | Operational note |
|---|---|---|
| Identity | Platform name, website title, logo text, logo file/URL, and favicon. | The configured website name is used in email, SMS, public copy, sharing metadata, and visible interface text. |
| Homepage panel | Presentation title, description, feature bullets, and brand mark fallback. | The uploaded logo replaces the fallback mark when available. |
| Theme | Light by default with optional dark mode; public and admin accent palettes. | Obsidian Gold is the package default. |
| Typography | Font family/import URL, sizes, weights, and navigation scale. | Only use trusted HTTPS font sources. |
| Layout | Content widths, sidebar dimensions, radii, controls, and design tokens. | Review mobile after changing dimensions. |
| Localization | Default timezone, items per page, default language, and enabled public languages. | Saved visitor language preferences override the default while their language remains enabled. |
| Block | Available settings | Default |
|---|---|---|
| Registration | Public signup, phone collection, required username, blocked IPs, and email/SMS/no verification. | Public on, no verification |
| Verification codes | Digits, expiry minutes, resend limit, invalid attempts, and IP block time. | 4 digits, 5 minutes, 3 attempts |
| Password policy | Strength meter and required strength from 0 to 10. | Enabled |
| Captcha | Simple PHP captcha or Google reCAPTCHA with site/secret keys. | Off |
| Login identifiers | Email, username, and phone number. | All three on fresh installations |
| Login protection | Two-factor authentication, max attempts, captcha threshold, and temporary ban. | 2FA on, 5 attempts, 15-minute ban |
| Social login | Google, Facebook, and Apple credentials plus callback URLs. | Off |
For OAuth, copy the exact callback URL displayed in the admin UI into the provider console. Scheme, domain, path, and trailing slash must match.
A fresh installation uses the log mailer until SMTP or SendGrid is configured. Password reset, verification, moderator, ban, and notification email will not reach users while delivery is unconfigured.
videos,default worker supervised for probing, thumbnails, and encoding.Enable only providers you intend to offer. Direct URL, YouTube, Vimeo, Dailymotion, and Twitch settings support provider-specific keys or tokens where required. The mass-import tool uses the enabled provider list and can apply category, visibility, tags, kids status, monetization, duplicate handling, and stop-on-error behavior.
| Area | Options | Package default |
|---|---|---|
| Creator tools | Webcam preview, scheduling, thumbnails, appearance, chat, replay, and advanced settings. DVR is stored as a setting; active RTC seeking is not exposed. | Feature-dependent |
| Monetization tools | Ads, Super Chat, super stickers, gifts, tips, goal bar, and alerts. | Configurable |
| Engagement | Polls, pinned messages, moderation, and slow mode. Stream-label settings are stored; a label editor/rendering surface is not implemented. | Standard moderation, 10s slow mode |
| Resolution | Auto, 480p, 720p, 1080p, 1440p, and 2160p. | Auto |
| Frame rate | 30 or 60 fps. | 30 fps |
| Latency | Normal, low, or ultra-low. | Low |
| Audience | Everyone, signed-in, subscribers, invited, or private. | Everyone |
| Replay retention | Off, 24 hours, 7, 30, or 90 days, or forever. | Forever |
| Limits | Schedule horizon, thumbnails, poll options/duration, labels, diagnostics sample, tips, and ads. | Review before launch |
Current validation supports up to 365 days for scheduling, 5 MB thumbnails, 6 poll options, 1440 poll minutes, storage of 8 stream-label settings, and a 512 KB diagnostic probe. Stored label settings do not establish a label editor or rendered overlay. Tip defaults are USD 1 minimum and USD 500 maximum unless changed.
The website ad manager supports media or trusted HTML, placement, status, schedule, targeting, display rules, and performance data. Placements include after header, left sidebar, before footer, home feed, video grid, comments, below player, watch sidebar, Shorts, search, channel, live, community, and floating bottom.
Player ads are configured separately for VAST pre-roll, timed mid-roll, and post-roll delivery. Configure tag URLs, break timing, skip timing, wrapper depth, MP4 preference, and tracking. Test the VAST response and media CORS from a browser before enabling it globally.
Monetization can be enabled globally with platform fees, paid-video commission, contribution limits, boost limits, purchase taxes, withdrawal review, and a creator share of completed VAST impressions. VAST revenue uses provider CPM metadata or the administrator fallback CPM with fractional earnings, self-view exclusion, hourly impression deduplication, and idempotent credits. Memberships, wallets, tips, paid videos, paid photo sets, boosts, creator earnings, and payouts depend on real transaction data and configured payment providers.
The Languages page manages the bundled 128 language packs. Select a default language, enable or disable public languages, review metadata and plural rules, edit translated PHP entries, and save. The default language cannot be disabled, and a visitor's saved preference is preserved while available. Back up customized lang/ files before applying an update.
Enable maintenance mode with a customer-facing message and optional allowed IP addresses or prefixes. Always include your administration IP before saving, then verify the public state in a private browser window.
PlayHub supports local uploads and S3-compatible cloud workflows, including Amazon S3, Google Cloud Storage interoperability, Backblaze B2, and Azure Blob configuration exposed by the admin storage page.
| Provider | Configuration | Delivery and limits |
|---|---|---|
| Default / Local | Configured video disk; standard public disk uses uploads/. Writable media/staging paths and disk headroom. | Keep protected routes for private/paid media. Switching providers does not move existing objects. |
| Amazon S3 / compatible | Access key/secret with optional session token or AWS credential chain; bucket, region, optional endpoint/public base, selectable path-style addressing. | ACL headers omitted by default for bucket-policy storage. R2-style endpoints are configurable; validate the actual service/account. |
| Google Cloud Storage | HMAC interoperability access key/secret, bucket, S3/XML endpoint, region, addressing flag, optional public base. | Uses S3 interoperability, not JSON service-account files. Private playback requires signing-capable credentials; uniform access omits ACLs. |
| Backblaze B2 | S3-compatible key ID/application key, bucket name, S3 endpoint/region, addressing/ACL flags, optional public base. | Endpoint region inferred if omitted; conflicts rejected. A native bucket ID alone is insufficient. Verify caps and read/write/delete permissions. |
| Azure Blob | Account/shared key, container, optional endpoint; or validated account-key connection string. Optional public base and prefix. | Private container; protected temporary links require shared-key signing. SAS-only backend access cannot mint temporary URLs in this adapter. Emulator support is for local development. |
Records prefixes are normalized and applied once. Endpoint/public-base URLs require HTTP(S) without credentials, queries, or fragments. S3-compatible adapters stream reads with bounded retries/timeouts and optional checksums only when required. Default ACL omission can be disabled for a provider requiring legacy ACLs.
Saved secrets are masked. Blank secret fields preserve current values; explicit clearing is validated, partial saves preserve other settings, and replacement refreshes cached disk connections. Test Connection uses the submitted configuration to write, verify, read, and delete a unique object, checks cleanup, and sanitizes errors. It performs real provider operations and does not save the tested settings.
Set a public base URL only for intentionally public delivery. Without one, private display images use signed application links and protected video uses authorized provider redirects. See image caching and private delivery fixes. Reported cloud capacity is administrator-configured, not a queried provider quota; membership quotas are application policy. Changing provider, bucket, or prefix requires an explicit object migration.
Starter, Plus, Premium, Pro, and VIP memberships can have independent storage quotas and monthly prices. VIP can be unlimited. A user-specific quota overrides the membership default when set by an administrator.
File type, size, storage quota, ownership, and chunk state are checked.
FFprobe reads duration, dimensions, streams, orientation, and codec metadata.
Configured renditions and thumbnails are generated without blocking the browser request.
Files remain local or are moved to the active cloud disk with their public URL metadata.
Visibility and moderation state determine when viewers can discover it.
A valid cloud configuration must support write, authorized playback, seeking, and deletion. Catalog gift and sticker files intentionally remain local.
This section explains where each major PlayHub feature appears and what must be configured for it to operate.
Authenticated creators can publish community posts with text and media. Users can react, comment, report, and use categorized stickers. Suggested communities and subscription actions use real channel data. Profile Message opens the existing private conversation or creates the correct conversation destination.
| Role | Publishing | Primary capabilities |
|---|---|---|
| Host | Camera, microphone, screen, or RTMP | Full control room, invites, layouts, settings, moderators, polls, goals, and end stream. |
| Participant / guest | Audio-only or audio/video after approval | Publishes assigned tracks and appears in stage plus replay composite. |
| Moderator | Only when separately accepted as participant | Delete chat, ban viewers, restrict comments, accept requests, and remove participants. |
| Viewer | No | Watch, chat, react, vote, contribute, and request participation when enabled. |
Completed recordings pass through replay finalization and video processing before playback is ready. Replay surfaces expose recorded media, available archived chat/events, timestamp checkpoints, likes, comments, creator information, and related replays. Checkpoints support manual seeking and are distinct from authored video chapters; archived chat is not a continuously playhead-synchronized feed. An existing Clips tab does not provide clip creation. Available counters do not establish peak/unique viewers or cumulative watch-time analytics. Multi-participant composites include participant identity tiles. See the current Live and replay capability guide for platform-specific behavior and acceptance.
The dashboard reads production data and applies real actions. Role and permission scopes determine which pages a team member can access.
| Page | What it manages | Important actions |
|---|---|---|
| Dashboard | Platform metrics, moderation queue, top creators, health, and quick actions. | Review reports, open analytics, inspect system health. |
| Users | Accounts, state, role, verification, storage quota, signup source/IP, activity, and deletion. | Edit, reset password, change role, ban, email, inspect admin-only signup data, permanently delete with optional videos. |
| Creators | Channels, category, subscribers, 28-day views, revenue, applications, and verification. | Verify, suspend, review, filter, and export. |
| Content | Videos, Shorts, posts, categories, imports, chapters, publishing access, and moderation. | Approve, reject, feature, edit, delete, import/review chapters, control publishing, bulk category, mass import, export. |
| Live Streams | Live, scheduled, and ended sessions with actual health and viewers. | Inspect, moderate, stop, open replay, delete with related media cleanup, and filter by category/health. |
| Gifts | Local gift image, name, price, status, and pagination. | Add, update, delete file plus record. |
| Stickers | Local sticker image, unique name, category, status, and pagination. | Add, categorize, update, and delete. |
| Ads | HTML/media creative, placement, schedule, targeting, display, and reporting. | Create, preview, enable, pause, edit, duplicate, and delete. |
| Reports | Profile, video, comment, and community reports with real previews. | Assign, prioritize, change status, resolve, bulk update, export. |
| Monetization | VAST revenue, paid videos, taxes, boosts, memberships, commission, contributions, withdrawals, and creator earnings. | Filter, inspect, export, configure limits/fees/shares, and approve or reject withdrawals. |
| Analytics | Growth, engagement, viewers, content, creators, and date-based performance. | Change range, inspect data, export. |
| Support | Customer tickets, system incidents, priority, agent, SLA, and replies. | Assign, respond, escalate, resolve, search, and filter. |
| Roles & Permissions | Admin roles, permission matrix, groups, invitations, scopes, and members. | Create/edit roles, invite member, change status, audit access. |
| Plugins | Plugin ZIP packages, compatibility, configuration, diagnostics, lifecycle state, and removal. | Install/update, configure, diagnose, enable/disable, and remove trusted packages. |
| Pages | Localized policy, support, company, and developer pages with repeatable sections and metadata. | Edit by language, control visibility/footer/search/sitemap state, and save update-safe overrides. |
| Email Templates | Localized templates, placeholders, responsive HTML, and plain-text alternatives. | Edit, preview, validate, reset, and test delivery. |
| SEO & Sitemaps | Search metadata, canonical origin, verification, indexing, robots, social cards, structured data, and content sitemaps. | Configure policy, verify public metadata, and inspect generated sitemap pages. |
| Website Configuration | Brand, homepage content, theme, colors, typography, navigation, and layout. | Preview, save, reset selected design values. |
| Languages | Installed language metadata, default/availability state, and PHP translation entries. | Set default, enable/disable, edit, validate, save, and restore with backup. |
| System Settings | Registration, login, live, storage, uploads, imports, ads, mail, SMS, integrations, moderation, and maintenance. | Navigate by section, use explicit Save/test actions, clear cache, inspect logs, backups, and cron jobs. |
Use the permission matrix to grant the smallest necessary scope. When a user is appointed as a platform or live moderator, PlayHub can send an in-app notification and configured email. Ban events can also send email; delivery requires SMTP or SendGrid.
Production reliability depends on repeatable backups, service supervision, log review, and tested updates.
The admin backup dialog inventories selectable folders and their sizes, includes the database, supports large-file behavior, compression level, retention count, and automatic frequency. Large media libraries may be better protected by storage-provider versioning plus database/application backups.
.env, the signed license receipt, and install lock privately.livekit/runtime/, especially keys, generated configuration, and certificates.Confirm the upgrade path, release notes, compatibility, server requirements, protected paths, and package signature.
Resolve disk, permissions, service, dependency, and database checks before the updater changes production state.
Keep database, environment, media, plugin settings, custom language, page/email overrides, catalogs, and runtime configuration.
The updater manages maintenance mode, checksummed downloads, protected files, replacement, migrations, cache refresh, and interruption monitoring.
Verify login, upload, playback, comments, live, replay, plugins, paid content, mail, SEO output, and administrator actions before reopening.
Use database recovery and the updater rollback when validation fails; do not leave a partially applied package in service.
Keep signaling and recording-template grants out of logs and support attachments. Prefer node tools/live-health.cjs --json, categorical status/errors, and sanitized diagnostics; raw Egress logs may contain token-bearing template URLs. Redact those URLs before sharing any retained diagnostic output.
storage/logs/laravel.logstorage/logs/worker.log when using the example.livekit/runtime/status/ and livekit/runtime/logs/.APP_ENV=production and APP_DEBUG=false..env, license files, Redis, database, LiveKit keys, and payment secrets.Start with the exact error, the service that owns the failing step, and the corresponding log. Avoid changing multiple systems at once.
Confirm DNS and outbound HTTPS access to registry.npmjs.org, then verify the PHP-FPM user can execute Node and npm and write storage/app/npm-cache plus the application root. Check proxy, hosting-panel, certificate, and firewall restrictions. Keep the original package-lock.json.
The locked npm install did not complete or node_modules/.bin is incomplete. Restore the original package.json and package-lock.json, remove the partial node_modules, verify write permissions and network access, then rerun installation.
Enable proc_open(), exec(), and nohup for PHP-FPM. Confirm the web user can write the application root and storage/app. Some shared hosts prohibit detached processes; use a server plan that permits them.
The installer can detect but cannot change PHP-FPM or hosting-panel policy. Allow the PlayHub root, /tmp, and required binary locations, then restart PHP-FPM. Keep web and CLI PHP versions/extensions aligned.
Inspect storage/logs/laravel.log, the PHP-FPM log, and web-server error log. Verify .env, APP_KEY, database access, writable runtime paths, and PHP extensions. Run php artisan optimize:clear. Never enable debug on a public production site.
PlayHub serves the generated build/ assets. Run npm ci when dependencies are missing, then npm run build. Clear application and reverse-proxy/CDN caches and confirm the generated asset filenames changed.
Open Admin Plugins diagnostics and verify the plugin's PlayHub/PHP compatibility, declared dependencies, package limits, and required settings. Rebuild the ZIP without traversal paths, symlinks, server-control files, unsupported file types, or unnecessary archive nesting. Install only the original package from a trusted source.
Do not copy another package over the interrupted transaction. Review the updater interruption state, preflight/checksum error, backup record, maintenance state, and application log. Use database recovery or rollback to return to the verified backup, resolve the root cause, and rerun preflight before retrying.
Compare the PlayHub upload limit with PHP upload_max_filesize/post_max_size, Nginx client_max_body_size, disk space, user quota, and write permissions. Large uploads also need compatible server timeouts.
Confirm the videos,default queue worker is running and FFmpeg/FFprobe are executable by that user. Inspect Laravel and worker logs, then run php artisan queue:failed. Fix the root cause before php artisan queue:retry all.
Check the active media disk, local/cloud write permission, bucket credentials, records prefix, image extension support, FFmpeg output, and available space. Use the admin storage connection test and verify write/read/delete, not only authentication.
The default log mailer does not send. Configure SMTP or SendGrid, save, test, clear/cache configuration, and inspect the provider activity/suppression list. Ensure the from address is authorized and the queue worker is running for queued mail.
Enable one supported provider, enter every required credential and sender, use international phone format, and run the admin test. Check provider balance, geographic permissions, sender approval, and delivery logs.
Confirm host, port, username, password, database number, bind address, and firewall. Test from the application host as the same network context. Do not use a public Redis endpoint without TLS/private networking and authentication.
Complete the web installation, then run sudo /var/www/playhub/livekit/install.sh. Confirm Docker daemon and Compose v2, inspect Compose status, and verify the admin LiveKit status snapshot updates.
Verify HTTPS, the public WSS URL, certificate, proxy WebSocket headers, API key/secret, LiveKit container health, and browser console. A public URL pointing to an unproxied internal port will not work from viewers' browsers.
Open control-room diagnostics and confirm a video track is published/subscribed, camera permission is granted, and the selected device is active. After reconnect, verify local tracks were republished. For replay only, inspect sanitized egress status/errors and the composite template.
This usually indicates NAT/firewall/TURN behavior. Open the RTC TCP and UDP range, advertise the correct external/node IP, and configure TURN or TURN TLS with a reachable domain and valid certificate.
Confirm ingress is healthy, TCP 1936 is open, the public RTMP host resolves to the server, and the stream key is current. Verify OBS uses the exact server URL and key generated for that stream. Inspect ingress logs while starting the encoder.
Inspect the egress container first, then Laravel and queue logs. Confirm recording started before the room ended, the egress output path is writable, the queue worker runs, FFmpeg can inspect the result, and cloud storage accepts the finalized file.
Confirm Stripe/PayPal live or sandbox mode matches the credentials, the checkout return URL uses the correct domain, webhooks can reach the server over HTTPS, and webhook secrets/events are configured as required. Check transaction and provider logs before crediting manually.
Copy the exact callback URL shown in System Settings to the provider console. Confirm APP_URL, HTTPS, proxy forwarded headers, and domain. Clear/cache config after correcting environment values.
Install the one-minute Laravel scheduler cron under the correct user. Run php artisan schedule:list and php artisan schedule:run -v, then inspect cron mail/system logs and Laravel logs.
Confirm the complete purchase code, correct installation domain/URL, outbound HTTPS to the license service, certificate validation, and accurate server clock. Contact support before moving an activated installation to another domain.
| Task | Command |
|---|---|
| Application status | php artisan about |
| Clear all application caches | php artisan optimize:clear |
| Build production config cache | php artisan config:cache |
| Run ordinary Laravel migrations (not the 0.9.9 manual update) | php artisan migrate --force |
| List scheduled tasks | php artisan schedule:list |
| Run scheduler now | php artisan schedule:run -v |
| List failed jobs | php artisan queue:failed |
| Retry failed jobs | php artisan queue:retry all |
| Restart workers | php artisan queue:restart |
| Install locked frontend modules | npm ci |
| Build frontend | npm run build |
| LiveKit status | docker compose -f livekit/runtime/docker-compose.yml ps |
| Path | Purpose |
|---|---|
.env | Environment-specific production configuration and secrets. |
storage/logs/laravel.log | Application exceptions and operational messages. |
storage/app/installed.lock | Prevents installer reuse. |
storage/app/license.json | Signed domain license receipt. |
storage/app/playhub-*.json | Admin-managed settings persisted by each settings module. |
uploads/ | Local media and live replay outputs when local storage is active. |
gifts/, stickers/ | Local contribution catalog images. |
lang/ | Bundled and customized PHP language packs. |
livekit/runtime/ | Generated Compose, YAML, keys, certificates, status, and logs. |
build/ | Vite production frontend assets served to browsers. |
Use the support channel on the CodeCanyon item page Or the Direct Support portal. A reproducible report with sanitized logs can be diagnosed much faster than a screenshot without server context.
Never send passwords, database credentials, Redis passwords, full .env, LiveKit secrets, stream keys, payment keys, private certificates, purchase codes, or the signed license receipt in a public ticket.
PlayHub requires a valid CodeCanyon or KNL (Kontackt Direct License) purchase code during installation. Activation is tied to the installation domain and must follow the applicable Envato license. Do not redistribute the source package or share a purchase code.