mirror of
https://github.com/zhw2590582/ArtPlayer.git
synced 2026-10-23 22:01:20 -08:00
feat: batch video upscaling with folder upload, directory save, and result comparison (#1051)
* feat: support batch video upscaling with folder upload and directory save - Add multi-file selection and entire folder upload (webkitdirectory) - Support drag & drop of both files and folders via FileSystemEntry API - Add save directory picker using File System Access API (showDirectoryPicker) - Process videos sequentially with per-file progress and status tracking - Add right-side result list with click-to-compare functionality - Add per-video duration and total batch duration display - Add retry button for failed items with error detail display - Remove auto-play on comparison viewer load - Fix worker error handling: handle "error" command to reject stale promises - Fix event listener accumulation in video comparison (AbortController) - Fix XSS risk by escaping HTML in all innerHTML injections - Fix URL revocation timing in download to prevent large file truncation - Extract writeToSaveDirectory and truncateName helpers to reduce duplication - Add Usage Guide panel explaining single/multiple/folder upload options Files changed: docs/upscaler/index.html (+1110/-181) docs/upscaler/upscaler.js (+110) * fix: prevent auto-play and resource consumption during upscaling - Set preload="metadata" on preview and comparison video elements - Explicitly pause preview video after setting src in showVideoPreview - Remove preview video seek sync from batch processing progress callbacks (was causing continuous decode during upscaling, wasting GPU resources) - Remove preview video seek sync from retry progress callback - All videos now require manual play; no background resource usage * fix: improve upscaled video quality with higher bitrate and codec support - Raise base bitrate from 2.5 Mbps (25e5) to 8 Mbps (8e6) for standard and firefox processors, preventing quality loss when source videos have high bitrates (e.g. 720p @ 16.7 Mbps was producing 1440p @ 10 Mbps, smaller than the original file) - Double the bitrate for mediabunny processor (X.n1 * 2) to account for the 4x pixel increase from 2x upscaling - Add H.264 Level 5.1 (avc1.640033) and Level 5.2 (avc1.640034) codecs to the fallback lists, since Level 4.0 (avc1.640028, ~24.6 Mbps) cannot support the higher bitrates for 1440p+ outputs - Add latencyMode: "quality" to VideoEncoder configs for both standard and firefox processors, prioritizing encoding quality over latency (suitable for offline processing) * feat: add video data comparison panel for original vs upscaled metrics - Add a comparison data table below the file info bar showing 6 metrics: Resolution, File Size, Duration, Est. Bitrate, Pixels, Process Time - Display per-metric change percentage with color-coded indicators: green (↑) for improvements, red (↓) for regressions, gray for neutral - Estimated bitrate calculated from file size × 8 / video duration - Table renders after both original and upscaled video metadata loads - Auto-hide panel on reset * fix: make video data comparison panel full-width and responsive - Move comparison data table from inside the left column to the full-width area below the left/right layout, so it is no longer constrained by the comparison viewer column width - Remove table-fixed colgroup and overflow-x-auto that caused horizontal scrolling on smaller screens - Table now uses w-full auto-layout, displaying all 4 columns (Metric, Original, Upscaled, Change) without requiring horizontal scrolling --------- Co-authored-by: rionzhao <rionzhao@tencent.com>
This commit is contained in:
commit
0896841d23
538 files changed
+379715
No files matched your search
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1 @@
|
||||
(globalThis.webpackChunkfree_video_upscaler=globalThis.webpackChunkfree_video_upscaler||[]).push([[869],{41:(t,e)=>{var i,r,s=(i=new Date,r=4,{setLogLevel:function(t){r=t==this.debug?1:t==this.info?2:t==this.warn?3:(this.error,4)},debug:function(t,e){void 0===console.debug&&(console.debug=console.log),1>=r&&console.debug("["+s.getDurationString(new Date-i,1e3)+"]","["+t+"]",e)},log:function(t,e){this.debug(t.msg)},info:function(t,e){2>=r&&console.info("["+s.getDurationString(new Date-i,1e3)+"]","["+t+"]",e)},warn:function(t,e){3>=r&&console.warn("["+s.getDurationString(new Date-i,1e3)+"]","["+t+"]",e)},error:function(t,e){4>=r&&console.error("["+s.getDurationString(new Date-i,1e3)+"]","["+t+"]",e)}});s.getDurationString=function(t,e){var i;function r(t,e){for(var i=(""+t).split(".");i[0].length<e;)i[0]="0"+i[0];return i.join(".")}t<0?(i=!0,t=-t):i=!1;var s=t/(e||1),a=Math.floor(s/3600);s-=3600*a;var n=Math.floor(s/60),o=1e3*(s-=60*n);return o-=1e3*(s=Math.floor(s)),o=Math.floor(o),(i?"-":"")+a+":"+r(n,2)+":"+r(s,2)+"."+r(o,3)},s.printRanges=function(t){var e=t.length;if(e>0){for(var i="",r=0;r<e;r++)r>0&&(i+=","),i+="["+s.getDurationString(t.start(r))+","+s.getDurationString(t.end(r))+"]";return i}return"(empty)"},e.Log=s;var a=function(t){if(!(t instanceof ArrayBuffer))throw"Needs an array buffer";this.buffer=t,this.dataview=new DataView(t),this.position=0};a.prototype.getPosition=function(){return this.position},a.prototype.getEndPosition=function(){return this.buffer.byteLength},a.prototype.getLength=function(){return this.buffer.byteLength},a.prototype.seek=function(t){var e=Math.max(0,Math.min(this.buffer.byteLength,t));return this.position=isNaN(e)||!isFinite(e)?0:e,!0},a.prototype.isEos=function(){return this.getPosition()>=this.getEndPosition()},a.prototype.readAnyInt=function(t,e){var i=0;if(this.position+t<=this.buffer.byteLength){switch(t){case 1:i=e?this.dataview.getInt8(this.position):this.dataview.getUint8(this.position);break;case 2:i=e?this.dataview.getInt16(this.position):this.dataview.getUint16(this.position);break;case 3:if(e)throw"No method for reading signed 24 bits values";i=this.dataview.getUint8(this.position)<<16,i|=this.dataview.getUint8(this.position+1)<<8,i|=this.dataview.getUint8(this.position+2);break;case 4:i=e?this.dataview.getInt32(this.position):this.dataview.getUint32(this.position);break;case 8:if(e)throw"No method for reading signed 64 bits values";i=this.dataview.getUint32(this.position)<<32,i|=this.dataview.getUint32(this.position+4);break;default:throw"readInt method not implemented for size: "+t}return this.position+=t,i}throw"Not enough bytes in buffer"},a.prototype.readUint8=function(){return this.readAnyInt(1,!1)},a.prototype.readUint16=function(){return this.readAnyInt(2,!1)},a.prototype.readUint24=function(){return this.readAnyInt(3,!1)},a.prototype.readUint32=function(){return this.readAnyInt(4,!1)},a.prototype.readUint64=function(){return this.readAnyInt(8,!1)},a.prototype.readString=function(t){if(this.position+t<=this.buffer.byteLength){for(var e="",i=0;i<t;i++)e+=String.fromCharCode(this.readUint8());return e}throw"Not enough bytes in buffer"},a.prototype.readCString=function(){for(var t=[];;){var e=this.readUint8();if(0===e)break;t.push(e)}return String.fromCharCode.apply(null,t)},a.prototype.readInt8=function(){return this.readAnyInt(1,!0)},a.prototype.readInt16=function(){return this.readAnyInt(2,!0)},a.prototype.readInt32=function(){return this.readAnyInt(4,!0)},a.prototype.readInt64=function(){return this.readAnyInt(8,!1)},a.prototype.readUint8Array=function(t){for(var e=new Uint8Array(t),i=0;i<t;i++)e[i]=this.readUint8();return e},a.prototype.readInt16Array=function(t){for(var e=new Int16Array(t),i=0;i<t;i++)e[i]=this.readInt16();return e},a.prototype.readUint16Array=function(t){for(var e=new Int16Array(t),i=0;i<t;i++)e[i]=this.readUint16();return e},a.prototype.readUint32Array=function(t){for(var e=new Uint32Array(t),i=0;i<t;i++)e[i]=this.readUint32();return e},a.prototype.readInt32Array=function(t){for(var e=new Int32Array(t),i=0;i<t;i++)e[i]=this.readInt32();return e},e.MP4BoxStream=a;var n=function(t,e,i){this._byteOffset=e||0,t instanceof ArrayBuffer?this.buffer=t:"object"==typeof t?(this.dataView=t,e&&(this._byteOffset+=e)):this.buffer=new ArrayBuffer(t||0),this.position=0,this.endianness=null==i?n.LITTLE_ENDIAN:i};n.prototype={},n.prototype.getPosition=function(){return this.position},n.prototype._realloc=function(t){if(this._dynamicSize){var e=this._byteOffset+this.position+t,i=this._buffer.byteLength;if(e<=i)e>this._byteLength&&(this._byteLength=e);else{for(i<1&&(i=1);e>i;)i*=2;var r=new ArrayBuffer(i),s=new Uint8Array(this._buffer);new Uint8Array(r,0,s.length).set(s),this.buffer=r,this._byteLength=e}}},n.prototype._trimAlloc=function(){if(this._byteLength!=this._buffer.byteLength){var t=new ArrayBuffer(this._byteLength),e=new Uint8Array(t),i=new Uint8Array(this._buffer,0,e.length);e.set(i),this.buffer=t}},n.BIG_ENDIAN=!1,n.LITTLE_ENDIAN=!0,Line truncated
|
||||
Reference in new issue
Block a user