Files
ArtPlayer/docs/document/assets/en_plugin_auto-thumbnail.md.B4xf1kbN.js

22 lines
17 KiB
JavaScript
Raw Permalink Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import{_ as e,o as i,c as n,ak as s,j as t}from"./chunks/framework.xxfEszSJ.js";const k=JSON.parse('{"title":"Automatic Thumbnails","description":"","frontmatter":{},"headers":[],"relativePath":"en/plugin/auto-thumbnail.md","filePath":"en/plugin/auto-thumbnail.md","lastUpdated":1789498635000}'),r={name:"en/plugin/auto-thumbnail.md"};function l(p,a,d,o,h,c){return i(),n("div",null,a[0]||(a[0]=[s(`<h1 id="automatic-thumbnails" tabindex="-1">Automatic Thumbnails <a class="header-anchor" href="#automatic-thumbnails" aria-label="Permalink to &quot;Automatic Thumbnails&quot;">​</a></h1><p><a href="./../../plugin/auto-thumbnail.html">简体中文</a></p><p>Read frames with a separate video element, progressively create a JPEG sprite sheet in the browser, and update the player&#39;s progress-bar thumbnails. This page describes the unreleased refactor branch; the online example and unpinned npm/CDN packages are not the current candidate.</p><h2 id="installation-and-example" tabindex="-1">Installation and example <a class="header-anchor" href="#installation-and-example" aria-label="Permalink to &quot;Installation and example&quot;">​</a></h2><div class="language-sh vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">sh</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">yarn</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> add</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> artplayer</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> artplayer-plugin-auto-thumbnail</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br></div></div><div class="language-js vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> Artplayer </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &#39;artplayer&#39;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> artplayerPluginAutoThumbnail </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &#39;artplayer-plugin-auto-thumbnail&#39;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br></div></div><p>For script usage, load ArtPlayer before <code>dist/artplayer-plugin-auto-thumbnail.js</code>; the global is <code>artplayerPluginAutoThumbnail</code>. This preserves the <a href="https://artplayer.org/?libs=./uncompiled/artplayer-plugin-auto-thumbnail/index.js&amp;example=auto.thumbnail" target="_blank" rel="noreferrer">original online example</a>. The factory requires an options object; use <code>{}</code> for defaults.</p>`,7),t("div",{className:"run-code","data-libs":"./uncompiled/artplayer-plugin-auto-thumbnail/index.js"},"▶ Run Code",-1),s(`<div class="language-js vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// npm i artplayer-plugin-auto-thumbnail</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// import artplayerPluginAutoThumbnail from &#39;artplayer-plugin-auto-thumbnail&#39;;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> art</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> Artplayer</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">({</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> container: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&#39;.artplayer-app&#39;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> url: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&#39;/assets/sample/video.mp4&#39;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> plugins: [</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> artplayerPluginAutoThumbnail</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">({</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> //</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }),</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> ],</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">})</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br></div></div><h2 id="options-and-generation" tabindex="-1">Options and generation <a class="header-anchor" href="#options-and-generation" aria-label="Permalink to &quot;Options and generation&quot;">​</a></h2><table tabindex="0"><thead><tr><th>Field</th><th>Type</th><th>Default</th><th>Meaning</th></tr></thead><tbody><tr><td><code>url</code></td><td><code>string</code></td><td>Current <code>art.option.url</code></td><td>Media read by the separate decoder; an explicit nonempty URL takes precedence</td></tr><tr><td><code>width</code></td><td><code>number</code></td><td><code>160</code></td><td>Width of each thumbnail cell in pixels</td></tr><tr><td><code>number</code></td><td><code>number</code></td><td><code>100</code></td><td>Target sample count; normally use a positive integer</td></tr><tr><td><code>scale</code></td><td><code>number</code></td><td><code>1</code></td><td>Preview display scale passed to the player; does not reduce the generated canvas size</td></tr><tr><td><code>height</code></td><td><code>number</code></td><td>Derived from video aspect ratio</td><td>Historical ignored option accepted by the precise runtime type</td></tr></tbody></table><p>Defaults preserve <code>value || default</code> behavior: <code>width: 0</code>, for example, uses 160. After fallback, width and number must convert to finite positive values. Historical JavaScript numeric strings and fractional counts are retained, but typed examples use numbers and positive integer counts. Height is <code>Math.floor(width * videoHeight / videoWidth)</code>, with ten columns per row. Media needs finite positive duration and dimensions; infinite-duration live streams do not qualify.</p><p>Sampling uses <code>duration * index / number</code>, starting at index 0 and excluding the media endpoint. Duration and sheet dimensions are captured at the separate video&#39;s metadata event. Each drawn cell is followed by encoding the whole JPEG and publishing a new <code>art.thumbnails</code> configuration. Later cells can therefore remain empty while generation is in progress.</p><p>Larger width and count increase canvas allocation, decoding and repeated encoding cost. Dimension checks are not a browser memory budget. Choose values appropriate for the media and device, or use prebuilt <a href="./vtt-thumbnail.html">VTT thumbnails</a>.</p><h2 id="registration-source-changes-and-cleanup" tabindex="-1">Registration, source changes and cleanup <a class="header-anchor" href="#registration-source-changes-and-cleanup" aria-label="Permalink to &quot;Registration, source changes and cleanup&quot;">​</a></h2><p>The factory returns an asynchronous registrar whose result contains only <code>name: &#39;artplayerPluginAutoThumbnail&#39;</code>. Its Promise resolves after installing player subscriptions, before extraction. It does not confirm that media was read successfully. There are no public progress, extraction-completion, update, stop or destroy methods.</p><p>Each <code>video:loadedmetadata</code> event starts extraction and rereads the original options object, so later mutations affect the next run. Installation does not replay metadata events that already occurred. <code>restart</code> cancels the old job; a subsequent metadata event starts another. Old frame or encoding callbacks cannot overwrite the newer job.</p><p>Metadata acquisition, each frame wait and each JPEG encoding operation have separate 30-second limits, not one total extraction deadline. Media, canvas and encoding failures clean up the current job, report through <code>console.warn</code> and retain the last usable preview. They cannot reject an already-resolved registration Promise.</p><p>Completion or cancellation releases the separate video and canvas. The final image URL remains until a usable replacement is installed or the player is destroyed. Only generated URLs are revoked; application-owned thumbnail URLs are not. Destroy also removes subscriptions. Directly invoking a retained registrar after player destruction returns the same name without allocating a decoder; it does not override core <code>plugins.add()</code> destruction checks.</p><h2 id="media-access-and-browser-limits" tabindex="-1">Media access and browser limits <a class="header-anchor" href="#media-access-and-browser-limits" aria-label="Permalink to &quot;Media access and browser limits&quot;">​</a></h2><p>The separate video uses <code>crossOrigin = &#39;anonymous&#39;</code>, is muted, and is never explicitly played. Media must support native browser loading and Canvas pixel access, including appropriate server CORS headers. Player custom loaders, SDKs, request headers and proxies are not installed into this decoder; supply a directly readable media <code>url</code> when necessary.</p><p>The hidden video is attached to the document with a rendered box; it is not an additional visible player. Actual decoding and first-frame correctness remain browser-dependent. The current Windows WebKit first-frame issue is still unresolved. Types, navigation and other browser results do not close it or establish physical Safari/mobile support.</p><h2 id="compatible-typescript-entries" tabindex="-1">Compatible TypeScript entries <a class="header-anchor" href="#compatible-typescript-entries" aria-label="Permalink to &quot;Compatible TypeScript entries&quot;">​</a></h2><p>The root and <code>/legacy</code> preserve npm 1.1.0 synchronous result declarations and required options; the root Option does not contain height. For the actual Promise, historical height input or <code>.default</code> self-alias types, use <code>/runtime</code>, which loads the same implementation:</p><div class="language-ts vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">ts</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> type</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> Artplayer </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &#39;artplayer&#39;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> autoThumbnail </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &#39;artplayer-plugin-auto-thumbnail/runtime&#39;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> type</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { Option, Result } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &#39;artplayer-plugin-auto-thumbnail/runtime&#39;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> options</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">:</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> Option</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { width: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">160</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, number: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">100</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, scale: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> };</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">async</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> function</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> registerThumbnails</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">art</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">:</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> Artplayer</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">)</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">:</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> Promise</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">&lt;</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">Result</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">&gt; {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> await</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> autoThumbnail</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(options)(art); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Registration only, not extraction completion.</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">}</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br></div></div><p>Runtime exports <code>Option</code>, <code>Result</code>, <code>Factory</code> and <code>RuntimeFactory</code>. Factory is a plain asynchronous factory; RuntimeFactory adds the writable <code>.default</code> self-alias. CommonJS runtime supports direct and <code>.default(...)</code> calls. Earlier 1.0.x <code>export =</code> and height declarations differ from 1.1.0; use the runtime <code>import = require</code> form when migrating those imports. Root NodeNext namespace behavior remains unchanged; use runtime for an accurate callable default import. Classic Node10 default imports need <code>esModuleInterop</code>.</p>`,18)]))}const m=e(r,[["render",l]]);export{k as __pageData,m as default};