{"id":1952,"date":"2026-08-21T04:33:27","date_gmt":"2026-08-21T04:33:27","guid":{"rendered":"https:\/\/documentation.iqonic.design\/streamit-laravel\/?p=1952"},"modified":"2026-08-21T11:43:46","modified_gmt":"2026-08-21T11:43:46","slug":"how-transcoding-works","status":"publish","type":"post","link":"https:\/\/documentation.iqonic.design\/streamit-laravel\/how-transcoding-works\/","title":{"rendered":"How Transcoding works?"},"content":{"rendered":"<div class=\"nolwrap\">\n<hr class=\"wp-block-separator has-alpha-channel-opacity\" \/>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"user-content-1-overview\">1. Overview<\/h2>\n\n\n\n<p>Transcoding converts a raw video file uploaded to an episode into a multi-quality streaming format (HLS) that plays smoothly on any device and network speed, without the viewer downloading the full file first.<\/p>\n\n\n\n<p>Everything runs on your own server \u2014 there is no third-party transcoding service, subscription, or API key involved. The Short Drama add-on ships with its own processing pipeline built on FFmpeg, so once it&#8217;s configured, transcoding happens automatically every time an admin uploads a local video file.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\" \/>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"user-content-2-key-highlights\">2. Key Highlights<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Automatic, no manual encoding.<\/strong>&nbsp;Admins upload a video; the server generates a ready-to-stream package in the background.<\/li>\n\n\n\n<li><strong>Multiple quality levels.<\/strong>&nbsp;Every episode is encoded into 480p, 720p, and 1080p renditions, so the player can switch quality based on the viewer&#8217;s connection.<\/li>\n\n\n\n<li><strong>Vertical video done right.<\/strong>&nbsp;Portrait (9:16) short-drama footage is detected automatically and encoded at the correct orientation, instead of being stretched or letterboxed into landscape.<\/li>\n\n\n\n<li><strong>Wide device compatibility.<\/strong>&nbsp;Output is normalized to a color format every phone, browser, and smart TV can hardware-decode, avoiding black-screen playback failures some source files would otherwise cause.<\/li>\n\n\n\n<li><strong>Server-aware processing.<\/strong>&nbsp;The pipeline checks how much CPU the server actually has (including on shared\/containerized hosting) and paces itself \u2014 small servers process one video at a time instead of overloading.<\/li>\n\n\n\n<li><strong>Never blocks the admin panel.<\/strong>&nbsp;Encoding runs as a background job. Admins can keep working while a video processes; the episode goes live automatically once it&#8217;s ready.<\/li>\n\n\n\n<li><strong>Graceful fallback.<\/strong>&nbsp;If a viewer opens an episode while it&#8217;s still processing, the original uploaded file is served directly so it&#8217;s still watchable, then automatically upgraded to the full adaptive stream once processing finishes.<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\" \/>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"user-content-3-how-it-works\">3. How It Works<\/h2>\n\n\n\n<p>1. <strong>Upload.<\/strong>&nbsp;An admin uploads a video file to an episode and enables transcoding.<\/p>\n\n\n\n<p>2. <strong>Analyze.<\/strong>&nbsp;The server inspects the source file \u2014 resolution, orientation (portrait\/landscape), and any audio or subtitle tracks embedded in the file.<\/p>\n\n\n\n<p>3. <strong>Encode.<\/strong>&nbsp;FFmpeg produces three quality renditions of the video (480p \/ 720p \/ 1080p), each split into small streaming segments.<\/p>\n\n\n\n<p>4. <strong>Package.<\/strong>&nbsp;If multi-language audio or subtitles are enabled, those are processed and linked in as separate selectable tracks.<\/p>\n\n\n\n<p>5. <strong>Generate previews.<\/strong>&nbsp;Poster images, thumbnails, and (if enabled) scrub-bar preview images are extracted from the video.<\/p>\n\n\n\n<p>6. <strong>Build the playlist.<\/strong>&nbsp;All renditions and tracks are compiled into a single streaming playlist file (<code>master.m3u8<\/code>) that the player reads to know which qualities and tracks are available.<\/p>\n\n\n\n<p>7. <strong>Publish.<\/strong>&nbsp;The episode is automatically marked active and becomes playable \u2014 no manual &#8220;publish&#8221; step required.<\/p>\n\n\n\n<p>While processing is underway, the episode stays hidden from viewers; a status indicator in the admin panel shows progress until it completes.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\" \/>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"user-content-4-setup--server-configuration\">4. Setup &amp; Server Configuration<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"user-content-41-admin-workflow\">4.1 Admin workflow<\/h3>\n\n\n\n<p>1. Go to&nbsp;<strong>Short Drama \u2192 Episodes \u2192 Create<\/strong>&nbsp;(or edit an existing episode).<\/p>\n\n\n\n<p>2. Set&nbsp;<strong>Upload Type<\/strong>&nbsp;to&nbsp;<strong>Local<\/strong>, and select the video file.<\/p>\n\n\n\n<p>3. Under&nbsp;<strong>Processing Options<\/strong>, enable:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Enable transcoding (HLS)<\/strong>&nbsp;\u2014 generates the 480p \/ 720p \/ 1080p stream.<\/li>\n\n\n\n<li><strong>Enable multi-audio<\/strong>&nbsp;\u2014 auto-detects and includes embedded audio tracks.<\/li>\n\n\n\n<li><strong>Enable subtitle support<\/strong>&nbsp;\u2014 auto-detects and includes embedded subtitle tracks.<\/li>\n<\/ul>\n\n\n\n<p>4. Save the episode.<code>[Screenshot: Episode \u2192 Processing options panel with transcoding toggle enabled]<\/code><\/p>\n\n\n\n<p>5. The episode shows a&nbsp;<strong>Processing<\/strong>&nbsp;status badge. Leave it \u2014 no further action is needed.<code>[Screenshot: Episode list showing a processing status badge]<\/code><\/p>\n\n\n\n<p>6. Once the badge changes to&nbsp;<strong>Completed<\/strong>, the episode is live and streamable.<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><\/li>\n<\/ol>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"user-content-42-server-requirements\">4.2 Server requirements<\/h3>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th class=\"has-text-align-left\" data-align=\"left\">Requirement<\/th><th class=\"has-text-align-left\" data-align=\"left\">Recommendation<\/th><\/tr><\/thead><tbody><tr><td>OS<\/td><td>Ubuntu 20.04\/22.04 LTS (or any Linux distribution FFmpeg supports)<\/td><\/tr><tr><td>FFmpeg<\/td><td>Version 4.3 or newer (available system-wide on standard PATH)<\/td><\/tr><tr><td>CPU<\/td><td>4+ cores minimum; 8+ cores recommended for a production launch<\/td><\/tr><tr><td>RAM<\/td><td>8 GB minimum; 16 GB+ recommended<\/td><\/tr><tr><td>Disk<\/td><td>Fast SSD\/NVMe for temporary processing files<\/td><\/tr><tr><td>PHP<\/td><td>8.2+, with&nbsp;<code>pdo<\/code>,&nbsp;<code>mbstring<\/code>,&nbsp;<code>openssl<\/code>,&nbsp;<code>json<\/code>,&nbsp;<code>fileinfo<\/code>,&nbsp;<code>xml<\/code>,&nbsp;<code>curl<\/code>,&nbsp;<code>zip<\/code>,&nbsp;<code>gd<\/code><\/td><\/tr><tr><td>Queue<\/td><td>A persistent queue driver \u2014&nbsp;<code>database<\/code>&nbsp;or&nbsp;<code>redis<\/code>&nbsp;(never&nbsp;<code>sync<\/code>)<\/td><\/tr><tr><td>Process manager<\/td><td>Supervisor (or systemd) to keep the queue worker running continuously<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>Transcoding is CPU-intensive. For higher traffic launches, run the queue worker on a separate server from the one serving web traffic.<\/p>\n<\/blockquote>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"user-content-43-installing-ffmpeg\">4.3 Installing FFmpeg<\/h3>\n\n\n\n<p>Install FFmpeg so that&nbsp;<code>ffmpeg<\/code>&nbsp;and&nbsp;<code>ffprobe<\/code>&nbsp;are available on your server&#8217;s standard system&nbsp;<code>PATH<\/code>:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">sudo apt update<br>sudo apt install ffmpeg<br>ffmpeg -version<br>ffprobe -version<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"user-content-44-environment-configuration\">4.4 Environment configuration<\/h3>\n\n\n\n<p>Add the following to your project&#8217;s&nbsp;<code>.env<\/code>&nbsp;file:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">QUEUE_CONNECTION=database<br>SHORT_DRAMA_PROCESSING_QUEUE=default<\/pre>\n\n\n\n<p>Run the queue worker (this is what actually performs the encoding):<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">php artisan queue:work --queue=default --timeout=3600 --tries=3<\/pre>\n\n\n\n<pre class=\"wp-block-preformatted\">sudo apt install supervisor<br>sudo supervisorctl reread<br>sudo supervisorctl update<br>sudo supervisorctl start short-drama-worker:*<\/pre>\n\n\n\n<p>After changing&nbsp;<code>.env<\/code>, restart the worker and clear the cached config:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">php artisan config:clear<br>sudo supervisorctl <br>restart short-drama-worker:*<\/pre>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p><strong>Built-in Fallback Worker:<\/strong>&nbsp;If no persistent queue worker is active, the add-on briefly spawns a temporary background worker on dispatch. This is intended for local testing only \u2014 disable it in production once Supervisor is active by setting&nbsp;<code>SHORT_DRAMA_AUTO_WORKER=false<\/code>.<\/p>\n<\/blockquote>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"user-content-45-verifying-the-setup\">4.5 Verifying the setup<\/h3>\n\n\n\n<p>A built-in check command confirms FFmpeg, storage, and the queue are all working:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">bashphp artisan short-drama:verify-local-env --hls-smoke --queue-smoke<\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\" \/>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"user-content-5-configuration-settings\">5. Configuration Settings<\/h2>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th class=\"has-text-align-left\" data-align=\"left\">Setting (<code>.env<\/code>&nbsp;key)<\/th><th class=\"has-text-align-left\" data-align=\"left\">Default<\/th><th class=\"has-text-align-left\" data-align=\"left\">Description<\/th><\/tr><\/thead><tbody><tr><td><code>SHORT_DRAMA_PROCESSING_QUEUE<\/code><\/td><td><code>default<\/code><\/td><td>Queue name on which transcoding jobs run.<\/td><\/tr><tr><td><code>FFMPEG_THREADS<\/code><\/td><td>auto<\/td><td>CPU threads dedicated per encode job. Left unset, it auto-detects based on available CPU cores.<\/td><\/tr><tr><td><code>SHORT_DRAMA_MAX_CONCURRENT<\/code><\/td><td>auto<\/td><td>How many episodes may transcode at the same time. Left unset, smaller hosts are limited to 1 at a time to prevent CPU starvation.<\/td><\/tr><tr><td><code>SHORT_DRAMA_SLOT_RETRY_DELAY<\/code><\/td><td><code>30<\/code>&nbsp;(seconds)<\/td><td>How long a queued job waits before retrying when all processing slots are busy.<\/td><\/tr><tr><td><code>SHORT_DRAMA_RETRY_WINDOW_HOURS<\/code><\/td><td><code>24<\/code><\/td><td>How long a job keeps retrying for a free processing slot before giving up.<\/td><\/tr><tr><td><code>SHORT_DRAMA_AUTO_WORKER<\/code><\/td><td><code>true<\/code><\/td><td>Auto-starts a temporary worker if none is running. Set to&nbsp;<code>false<\/code>&nbsp;once Supervisor manages a permanent worker.<\/td><\/tr><tr><td><code>SHORT_DRAMA_RAW_SOURCE_FALLBACK<\/code><\/td><td><code>true<\/code><\/td><td>Serves the original upload directly if a viewer opens the episode before transcoding finishes.<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>Quality levels and target bitrates are set in the module configuration:<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th class=\"has-text-align-left\" data-align=\"left\">Quality<\/th><th class=\"has-text-align-left\" data-align=\"left\">Target Bitrate<\/th><th class=\"has-text-align-left\" data-align=\"left\">Resolution &amp; FPS<\/th><\/tr><\/thead><tbody><tr><td><strong>480p<\/strong><\/td><td>1000 Kbps<\/td><td>854&#215;480 @ 24fps<\/td><\/tr><tr><td><strong>720p<\/strong><\/td><td>2500 Kbps<\/td><td>1280&#215;720 @ 24fps<\/td><\/tr><tr><td><strong>1080p<\/strong><\/td><td>4500 Kbps<\/td><td>1920&#215;1080 @ 24fps<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\" \/>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"user-content-6-limitations--notes\">6. Limitations &amp; Notes<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Requires a VPS or dedicated server with FFmpeg and a persistent queue worker. Not supported on shared hosting<\/li>\n\n\n\n<li>Transcoding only applies to&nbsp;<strong>locally uploaded<\/strong>&nbsp;video files. Episodes set to&nbsp;<strong>URL<\/strong>&nbsp;upload type stream directly from the source you provide and are not re-encoded.<\/li>\n\n\n\n<li>Storage grows roughly 3x the size of the original file once all quality levels are generated \u2014 plan disk space (or object storage) accordingly.<\/li>\n\n\n\n<li>The queue&nbsp;<strong>must<\/strong>&nbsp;use a persistent driver (<code>database<\/code>&nbsp;or&nbsp;<code>redis<\/code>). Using&nbsp;<code>sync<\/code>&nbsp;will make the admin panel hang while a video encodes.<\/li>\n\n\n\n<li>Long or large uploads need a queue timeout of at least&nbsp;<code>3600<\/code>&nbsp;seconds (<code>--timeout=3600<\/code>).<\/li>\n\n\n\n<li>This module produces HLS streams (<code>.m3u8<\/code>&nbsp;\/&nbsp;<code>.ts<\/code>). It does not generate DASH (<code>.mpd<\/code>) manifests.<\/li>\n\n\n\n<li>FFmpeg process management and queue logic are fully integrated; no separate subscriptions or paid external API keys are required.<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\" \/>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"user-content-conclusion\">Conclusion<\/h2>\n\n\n\n<p>Transcoding turns any uploaded video into a smooth, adaptive-quality stream automatically, on infrastructure you control. Once FFmpeg is installed on your server and a persistent queue worker is configured, admins simply upload local video files and enable transcoding \u2014 the system takes care of encoding, packaging, and publishing seamless HLS streams for your viewers.<\/p>\n<\/div>","protected":false},"excerpt":{"rendered":"<p>1. Overview Transcoding converts a raw video file uploaded to an episode into a multi-quality streaming format (HLS) that plays smoothly on any device and network speed, without the viewer downloading the full file first. Everything runs on your own server \u2014 there is no third-party transcoding service, subscription, or API key involved. The Short [&hellip;]<\/p>\n","protected":false},"author":11,"featured_media":0,"parent":1880,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-1952","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"featured_image_src":null,"author_info":{"display_name":"laraveladminiq","author_link":"https:\/\/documentation.iqonic.design\/streamit-laravel\/author\/laraveladminiq\/"},"children":[],"_links":{"self":[{"href":"https:\/\/documentation.iqonic.design\/streamit-laravel\/wp-json\/wp\/v2\/posts\/1952","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/documentation.iqonic.design\/streamit-laravel\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/documentation.iqonic.design\/streamit-laravel\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/documentation.iqonic.design\/streamit-laravel\/wp-json\/wp\/v2\/users\/11"}],"replies":[{"embeddable":true,"href":"https:\/\/documentation.iqonic.design\/streamit-laravel\/wp-json\/wp\/v2\/comments?post=1952"}],"version-history":[{"count":3,"href":"https:\/\/documentation.iqonic.design\/streamit-laravel\/wp-json\/wp\/v2\/posts\/1952\/revisions"}],"predecessor-version":[{"id":1977,"href":"https:\/\/documentation.iqonic.design\/streamit-laravel\/wp-json\/wp\/v2\/posts\/1952\/revisions\/1977"}],"up":[{"embeddable":true,"href":"https:\/\/documentation.iqonic.design\/streamit-laravel\/wp-json\/wp\/v2\/posts\/1880"}],"wp:attachment":[{"href":"https:\/\/documentation.iqonic.design\/streamit-laravel\/wp-json\/wp\/v2\/media?parent=1952"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/documentation.iqonic.design\/streamit-laravel\/wp-json\/wp\/v2\/categories?post=1952"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/documentation.iqonic.design\/streamit-laravel\/wp-json\/wp\/v2\/tags?post=1952"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}