From b0f7a35ee5251631db04d4a53ce68f325f858a07 Mon Sep 17 00:00:00 2001 From: Biswasindhu Mandal Date: Sun, 5 Jul 2026 21:27:28 +0530 Subject: [PATCH 1/5] Update: monolithic to moduler conversion --- .vscode/settings.json | 4 +- build.js | 85 --- package-lock.json | 560 +++++++++++++++++- package.json | 8 +- favicon.ico => public/favicon.ico | Bin index.html => public/index.html | 2 +- rollup.config.js | 93 +++ src/script/config.js | 58 ++ src/script/index.js | 65 ++ src/script/media.js | 37 ++ .../media.js => src/script/ottMediaPlayer.js | 229 +------ src/script/utils.js | 239 ++++++++ {style => src/style}/media.css | 0 13 files changed, 1059 insertions(+), 321 deletions(-) delete mode 100644 build.js rename favicon.ico => public/favicon.ico (100%) rename index.html => public/index.html (99%) create mode 100644 rollup.config.js create mode 100644 src/script/config.js create mode 100644 src/script/index.js create mode 100644 src/script/media.js rename script/media.js => src/script/ottMediaPlayer.js (80%) create mode 100644 src/script/utils.js rename {style => src/style}/media.css (100%) diff --git a/.vscode/settings.json b/.vscode/settings.json index a01c137..bb81c58 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -10,8 +10,8 @@ "explorer.fileNesting.expand": false, "explorer.fileNesting.patterns": { "README.md": "*.md, .gitignore, *.ico, LICENSE", - "package.json": "*.json, .nvmrc, .node-version, .yarnrc, .yarnrc.yml, .yarnrc.yaml", - "index.html": "*.js" + "package.json": "*.json, .nvmrc, .node-version, .yarnrc, .yarnrc.yml, .yarnrc.yaml, rollup.config.js, rollup.config.mjs, rollup.config.cjs, rollup.config.ts, tsconfig.json, tsconfig.*.json", + "index.html": "*.js, *.css, *.ico" }, "cSpell.words": [] } \ No newline at end of file diff --git a/build.js b/build.js deleted file mode 100644 index b9c0f31..0000000 --- a/build.js +++ /dev/null @@ -1,85 +0,0 @@ -#!/usr/bin/env node - -const fs = require('fs'); -const path = require('path'); -const { execSync } = require('child_process'); - -// Create build directory -const buildDir = 'dist'; -if (!fs.existsSync(buildDir)) { - fs.mkdirSync(buildDir); - console.log('✅ Created build directory'); -} - -// Copy favicon -try { - fs.copyFileSync('favicon.ico', path.join(buildDir, 'favicon.ico')); - console.log('✅ Copied favicon.ico'); -} catch (error) { - console.error('❌ Error copying favicon.ico:', error.message); -} - -// Copy data directory -try { - fs.cpSync('data', path.join(buildDir, 'data'), { recursive: true, force: true }); - console.log('✅ Copied data directory'); -} catch (error) { - console.error('❌ Error copying data directory:', error.message); -} - -// Minify CSS -try { - execSync('npx cleancss -o dist/style/media.min.css style/media.css', { stdio: 'inherit' }); - console.log('✅ Minified CSS'); -} catch (error) { - console.error('❌ Error minifying CSS:', error.message); -} - -// Minify JavaScript -try { - // Create script directory if it doesn't exist - const scriptDir = path.join(buildDir, 'script'); - if (!fs.existsSync(scriptDir)) { - fs.mkdirSync(scriptDir, { recursive: true }); - } - execSync('npx uglifyjs script/media.js -o dist/script/media.min.js --compress --mangle', { stdio: 'inherit' }); - console.log('✅ Minified JavaScript'); - - // Obfuscate the minified JavaScript - execSync('npx javascript-obfuscator dist/script/media.min.js --output dist/script/media.min.js --compact true --control-flow-flattening true', { stdio: 'inherit' }); - console.log('✅ Obfuscated JavaScript'); -} catch (error) { - console.error('❌ Error minifying/obfuscating JavaScript:', error.message); - // Fallback: copy original JS file if minification fails - try { - fs.copyFileSync('script/media.js', path.join(buildDir, 'script', 'media.js')); - console.log('✅ Copied original JavaScript file as fallback'); - } catch (fallbackError) { - console.error('❌ Error copying fallback JavaScript file:', fallbackError.message); - } -} - -// Update HTML to reference minified files -try { - let htmlContent = fs.readFileSync('index.html', 'utf8'); - - // Update CSS reference - htmlContent = htmlContent.replace( - 'style/media.css', - 'style/media.min.css' - ); - - // Update JS reference - htmlContent = htmlContent.replace( - 'script/media.js', - 'script/media.min.js' - ); - - fs.writeFileSync(path.join(buildDir, 'index.html'), htmlContent); - console.log('✅ Created and updated index.html with minified references'); -} catch (error) { - console.error('❌ Error updating HTML references:', error.message); -} - -console.log('\n🎉 Build completed successfully!'); -console.log('📁 Build output available in: ./dist/'); diff --git a/package-lock.json b/package-lock.json index e6f3cec..e631432 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,9 +12,11 @@ "http-server": "^0.12.1" }, "devDependencies": { + "@rollup/plugin-node-resolve": "^16.0.3", "clean-css-cli": "^5.6.3", "javascript-obfuscator": "^5.1.0", "nodemon": "^3.1.10", + "rollup": "^4.62.2", "uglify-js": "^3.19.3" } }, @@ -75,6 +77,424 @@ "node": ">=4.0" } }, + "node_modules/@rollup/plugin-node-resolve": { + "version": "16.0.3", + "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-16.0.3.tgz", + "integrity": "sha512-lUYM3UBGuM93CnMPG1YocWu7X802BrNF3jW2zny5gQyLQgRFJhV1Sq0Zi74+dh/6NBx1DxFC4b4GXg9wUCG5Qg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@rollup/pluginutils": "^5.0.1", + "@types/resolve": "1.20.2", + "deepmerge": "^4.2.2", + "is-module": "^1.0.0", + "resolve": "^1.22.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^2.78.0||^3.0.0||^4.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, + "node_modules/@rollup/pluginutils": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.4.0.tgz", + "integrity": "sha512-MfPp06CjRLfXQ3wY0R8vJDYBy/MvVcc9OulEfR0B8Iv9ko+GCNaRZ+EpJYFl27LhKsZK0o420sYCRHCjfCgeUg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "estree-walker": "^2.0.2", + "picomatch": "^4.0.2" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, + "node_modules/@rollup/pluginutils/node_modules/picomatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.5.tgz", + "integrity": "sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.62.2.tgz", + "integrity": "sha512-6o7ZLZK+BeenkZCFNDXqpbjw9bD6nuWonvS/lwQJp7NoVVxm6p3qE7qQ5jGuBjiFsgvqjD8mZAU5oWxTmbOeOg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.62.2.tgz", + "integrity": "sha512-BaH7BllCACHoH1LguOU56UItGfUWjujlO65kS9LAodViaN4bwIKd7oeW/ZHJ/4ljr/7MIiENnNy3HJ0zXv8Zkw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.62.2.tgz", + "integrity": "sha512-v39RCCvj4He82I9sFmk+M1VZ0PLM9sfsLVikjfx2hYBNALhrrOR2D3JjQA6AhlaSOgcR+RzrKY7e1+bT6SUO/A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.62.2.tgz", + "integrity": "sha512-yl0y2vq3S3lHeuXhEdss6TWfKW8vkujImO12tn4ZkG/4oghr09LvdYm2RElVjokTQiUvDUGXLGsYeLqUMCKpGA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.62.2.tgz", + "integrity": "sha512-tT4pvt4qXD+vEoezupCWi+a1F0vvDiksiHc+PxRlYTOH1I6/X4id9jPxTP+Fg+545euaFT1jJVs4CEdHZAU1vw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.62.2.tgz", + "integrity": "sha512-6nU5F2wCW+qvCBhTn1pdIU3bzsIoF7EUwsCDRxilWGprQR6yd508YnH9+OKFCwpfS8pjZqDUmnCAr7exax0XCg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.62.2.tgz", + "integrity": "sha512-n1GJHPOvpIfhi3TmrCeh6S6URt9BFCt0KQE3qvexyGCTAKpR4Lg+eWvNZEqu7epxwus/8ElT3hacYEucm49SZg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.62.2.tgz", + "integrity": "sha512-JqgflS8wEB+UXV/vS1RpRbifGBeN4D5lz8D8oOFbFZw4vedvdOgCFAjfBmIMdW3yL10XpQQ0Ambepw6MXrhOnA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.62.2.tgz", + "integrity": "sha512-wnFJkogWvN4jm/hQRF2UBaeUmk20j5+DmHvoyWii2b8HJDyvz1MF2OU/6ynXt2KR63rbZLWkFpoytpdc/yBuSA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.62.2.tgz", + "integrity": "sha512-HVu2bp0zhvJ8xHEV9+UUs7S90VadmBSY3LcIMvozbPo4AuMGDWlz3ymHLHZPX4hR67TKTt8Qp5PJ5RBg/i+RMQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-gnu": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.62.2.tgz", + "integrity": "sha512-mQqqAV8QaoSgr9I2fKDLY2BAVvmKjWoGiu/cSYQonsLvtqwEn1E4QYfnCOcp5zoEqNhsDYin1s6jx/VJmrxlZg==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-musl": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.62.2.tgz", + "integrity": "sha512-IxKLoxCQ2IWi6bT2akyDUBGsOImDKB+sPp4EsTmwFQ/fMwpCKm8uLSSgP/Kx/QYUgKis6SEZ5/Nlhup0DIA0PQ==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-gnu": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.62.2.tgz", + "integrity": "sha512-Mk5ha2RQSgyFfmYYLkBpPnUk8D8FriBxesO1u9O75X0mHgXL1UQcH5Itl2lurWL2tj0RxV9b9tJgipac0hRY9A==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-musl": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.62.2.tgz", + "integrity": "sha512-CjvEnqJL/0/TQ3TXX3OPIJ/kmBellrWd4heXUmHeJlTnmwjKpSJzoehLaL6Xk0ZnMHBu9dZuFADNOrtjF4v+2w==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.62.2.tgz", + "integrity": "sha512-1SiZbzwdkaDURsew/tSOrooKiYy7EQGT6m8ufavAi9NEyQb/6VuIxFXAL1fqa4iZe3g4NbNk4P7J32z2tw5Mgg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.62.2.tgz", + "integrity": "sha512-nQts12zJ3NQRoE6uYljOH89v7szzLDvG2JD/vsX+vGXU8w/At1GowTZ5/7qeFQ8m7L55rpR8Okugnuo5bgjy2Q==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.62.2.tgz", + "integrity": "sha512-E9/ll019jhPIJgpzfZoIkBGhcz+kKNgVWYRY0zr9srBdPPFVpvOKW8VaJKUbeK+eZXyQF9ltME+Kk6affeaPgg==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.62.2.tgz", + "integrity": "sha512-5BqxR/pshjey51iliyzTD5Xi3EN0aLmQ2lZ3lvefVV9c82BvrLo2/6OT55iifpWBufs6kdwWbuOKS841DrmK9A==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.62.2.tgz", + "integrity": "sha512-uNN83XxQrRAh/w0/pmAfibcwyb6YWt4gP+dpnQKPVJshAloQ785ii8CT8ZCIxkGg9opVsvAlGhFitSm6D1Jjpg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-openbsd-x64": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.62.2.tgz", + "integrity": "sha512-srjEIxSH3LRnJN6THczDHWQplqEMFiAJrTab0msUryh9kwNpkICf3Ea6q6MN/2cZwRFUNx5w+h6Hpi4QuHS6Zg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ] + }, + "node_modules/@rollup/rollup-openharmony-arm64": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.62.2.tgz", + "integrity": "sha512-8hOJnxgbyObnCm5AlRA3A931xX19xq80RjVTKgJOvEKWqJruP/Uf12IbAOaDjjEXYRewwHLfmF0YRIdK3OwKWA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.62.2.tgz", + "integrity": "sha512-mmF4AY1i0hG/bLWUctUq59gtmgaSIRa3cu/A3JFRp/sCNEme2bgDEiDS22P9FbnJB8NJNF4jPJiSP5RHQpUTDg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.62.2.tgz", + "integrity": "sha512-DZgkknc6jhHrk46V25vbAM0zZkyP0nSDkJB8/dRkLTxv470dOmWDqGoEJl/9A0dFfS7yE3REOwNDxpHwSLSt0Q==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-gnu": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.62.2.tgz", + "integrity": "sha512-T6xr6ucWSFto+VGajA8YH26LdpHRuP4YLHEKAtCWvJDOlnmWcDZVCI2Jmjr+IFHDlt2zRaTAKE4tfjTaWLgJBg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.62.2.tgz", + "integrity": "sha512-BfzEnDJOt9T8M989/lA37EcJgat01wLRnoi5dQf3QzOH7jzpqTAzdDbVfRljVr5r+jzKqpbHeyOfAaXxAd0PAA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@types/estree": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz", + "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/minimatch": { "version": "3.0.5", "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.5.tgz", @@ -82,6 +502,13 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/resolve": { + "version": "1.20.2", + "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.20.2.tgz", + "integrity": "sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/validator": { "version": "13.15.10", "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.15.10.tgz", @@ -617,6 +1044,16 @@ "dev": true, "license": "MIT" }, + "node_modules/deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/define-data-property": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", @@ -809,6 +1246,13 @@ "node": ">=4.0" } }, + "node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "dev": true, + "license": "MIT" + }, "node_modules/esutils": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", @@ -1082,9 +1526,9 @@ } }, "node_modules/hasown": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", - "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.4.tgz", + "integrity": "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==", "license": "MIT", "dependencies": { "function-bind": "^1.1.2" @@ -1228,6 +1672,22 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-core-module": { + "version": "2.16.2", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.2.tgz", + "integrity": "sha512-evOr8xfXKxE6qSR0hSXL2r3sd7ALj8+7jQEUvPYcm5sgZFdJ+AYzT6yNmJenvIYQBgIGwfwz08sL8zoL7yq2BA==", + "dev": true, + "license": "MIT", + "dependencies": { + "hasown": "^2.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", @@ -1271,6 +1731,13 @@ "node": ">=0.10.0" } }, + "node_modules/is-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz", + "integrity": "sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==", + "dev": true, + "license": "MIT" + }, "node_modules/is-nan": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/is-nan/-/is-nan-1.3.2.tgz", @@ -1682,6 +2149,13 @@ "node": ">=0.10.0" } }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true, + "license": "MIT" + }, "node_modules/picomatch": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", @@ -1795,6 +2269,73 @@ "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", "license": "MIT" }, + "node_modules/resolve": { + "version": "1.22.12", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.12.tgz", + "integrity": "sha512-TyeJ1zif53BPfHootBGwPRYT1RUt6oGWsaQr8UyZW/eAm9bKoijtvruSDEmZHm92CwS9nj7/fWttqPCgzep8CA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "is-core-module": "^2.16.1", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/rollup": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.62.2.tgz", + "integrity": "sha512-RFnrW4lhXA3s3eqHDZvN654g8OTjzRfqpIRJYczCGB6HzphckVAi/Qh4tbPUbRuDi7s1Llv8g/NspLkttY3gTA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "1.0.9" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.62.2", + "@rollup/rollup-android-arm64": "4.62.2", + "@rollup/rollup-darwin-arm64": "4.62.2", + "@rollup/rollup-darwin-x64": "4.62.2", + "@rollup/rollup-freebsd-arm64": "4.62.2", + "@rollup/rollup-freebsd-x64": "4.62.2", + "@rollup/rollup-linux-arm-gnueabihf": "4.62.2", + "@rollup/rollup-linux-arm-musleabihf": "4.62.2", + "@rollup/rollup-linux-arm64-gnu": "4.62.2", + "@rollup/rollup-linux-arm64-musl": "4.62.2", + "@rollup/rollup-linux-loong64-gnu": "4.62.2", + "@rollup/rollup-linux-loong64-musl": "4.62.2", + "@rollup/rollup-linux-ppc64-gnu": "4.62.2", + "@rollup/rollup-linux-ppc64-musl": "4.62.2", + "@rollup/rollup-linux-riscv64-gnu": "4.62.2", + "@rollup/rollup-linux-riscv64-musl": "4.62.2", + "@rollup/rollup-linux-s390x-gnu": "4.62.2", + "@rollup/rollup-linux-x64-gnu": "4.62.2", + "@rollup/rollup-linux-x64-musl": "4.62.2", + "@rollup/rollup-openbsd-x64": "4.62.2", + "@rollup/rollup-openharmony-arm64": "4.62.2", + "@rollup/rollup-win32-arm64-msvc": "4.62.2", + "@rollup/rollup-win32-ia32-msvc": "4.62.2", + "@rollup/rollup-win32-x64-gnu": "4.62.2", + "@rollup/rollup-win32-x64-msvc": "4.62.2", + "fsevents": "~2.3.2" + } + }, "node_modules/safe-regex-test": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz", @@ -2003,6 +2544,19 @@ "node": ">=4" } }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/tagged-tag": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/tagged-tag/-/tagged-tag-1.0.0.tgz", diff --git a/package.json b/package.json index 2adaf08..af47d33 100644 --- a/package.json +++ b/package.json @@ -1,14 +1,14 @@ { "name": "mediaplayer", - "version": "1.0.0", + "version": "2.0.0", "description": "create a custom media player using native html", "main": "http-server -p 54322 -o", "scripts": { "clean": "node -e \"const fs=require('fs'); try { fs.rmSync('dist', {recursive: true, force: true}); } catch(e) {}\"", - "build": "node build.js", + "build": "rollup -c", "server": "http-server dist -p 54322 -o -d", "start": "npm run build && npm run server", - "watch": "nodemon --exec npm run build" + "watch": "rollup -c -w" }, "repository": { "type": "git", @@ -20,9 +20,11 @@ "http-server": "^0.12.1" }, "devDependencies": { + "@rollup/plugin-node-resolve": "^16.0.3", "clean-css-cli": "^5.6.3", "javascript-obfuscator": "^5.1.0", "nodemon": "^3.1.10", + "rollup": "^4.62.2", "uglify-js": "^3.19.3" } } diff --git a/favicon.ico b/public/favicon.ico similarity index 100% rename from favicon.ico rename to public/favicon.ico diff --git a/index.html b/public/index.html similarity index 99% rename from index.html rename to public/index.html index 2436f00..0e69758 100644 --- a/index.html +++ b/public/index.html @@ -134,7 +134,7 @@

OTT Player

- + \ No newline at end of file diff --git a/rollup.config.js b/rollup.config.js new file mode 100644 index 0000000..a7308d5 --- /dev/null +++ b/rollup.config.js @@ -0,0 +1,93 @@ +const fs = require('fs'); +const { execSync } = require('child_process'); +const { nodeResolve } = require('@rollup/plugin-node-resolve'); + +function cleanDist() { + return { + name: 'clean-dist', + buildStart() { + fs.rmSync('dist', { recursive: true, force: true }); + }, + }; +} + +function minifyJavaScript() { + return { + name: 'minify-javascript', + renderChunk(code) { + const uglify = require('uglify-js'); + const result = uglify.minify(code); + + if (result.error) { + throw result.error; + } + + return { + code: result.code, + map: null, + }; + }, + }; +} + +function emitStaticFiles() { + return { + name: 'emit-static-files', + generateBundle() { + const html = fs + .readFileSync('public/index.html', 'utf8') + .replace( + /<\/script>/, + '', + ) + .replace( + //, + '', + ); + + this.emitFile({ + type: 'asset', + fileName: 'index.html', + source: html, + }); + + this.emitFile({ + type: 'asset', + fileName: 'style/media.min.css', + source: execSync('npx cleancss src/style/media.css', { encoding: 'utf8' }), + }); + + if (fs.existsSync('public/favicon.ico')) { + this.emitFile({ + type: 'asset', + fileName: 'favicon.ico', + source: fs.readFileSync('public/favicon.ico'), + }); + } + + if (fs.existsSync('data')) { + for (const fileName of fs.readdirSync('data')) { + if (!fileName.toLowerCase().endsWith('.mp4')) { + continue; + } + + this.emitFile({ + type: 'asset', + fileName: `data/${fileName}`, + source: fs.readFileSync(`data/${fileName}`), + }); + } + } + }, + }; +} + +module.exports = { + input: 'src/script/index.js', + output: { + file: 'dist/index.min.js', + format: 'iife', + name: 'OTTPlayerApp', + }, + plugins: [cleanDist(), nodeResolve(), minifyJavaScript(), emitStaticFiles()], +}; \ No newline at end of file diff --git a/src/script/config.js b/src/script/config.js new file mode 100644 index 0000000..274a6f2 --- /dev/null +++ b/src/script/config.js @@ -0,0 +1,58 @@ +window.OTT_PLAYER_CONFIG = Object.freeze({ + ui: { + inputModes: { + file: "file", + url: "url", + directory: "directory", + }, + labels: { + emptyDirectory: "No Directory", + mediaDropdownDefault: "Select a media file...", + }, + mediaTypePrefixes: ["video/", "audio/"], + }, + elements: { + videoPlayer: "media-video-player", + controlsContainer: "media-media-controls", + dragHandle: "dragHandle", + headerVideoUrlInput: "headerVideoUrlInput", + inputs: { + inputModeDropdown: "inputModeDropdown", + fileInputRow: "fileInputRow", + urlInputRow: "urlInputRow", + directoryInputRow: "directoryInputRow", + navButtonsRow: "navButtonsRow", + fileInput: "fName", + directoryInput: "directoryInput", + mediaDropdown: "mediaDropdown", + directoryName: "directoryName", + }, + playback: { + startPos: "startPos", + seekBar: "player-seekbar", + endPos: "endPos", + resetPlayback: "reset", + playbackRate: "playbackRate", + backwordPlayback: "backword", + playPauseBtn: "playPause", + forwardPlayback: "forward", + fullScreenBtn: "fullScreen", + pipModeBtn: "pipMode", + rotationBtn: "screenRotation", + theaterModeBtn: "theaterMode", + volumeBar: "volumeBar", + volumeValue: "volumeValue", + volumeBtn: "volume", + videoMode: "videoMode", + }, + trim: { + trimStartBtn: "setTrimStart", + trimEndBtn: "setTrimEnd", + playTrimmedBtn: "playTrimmed", + trimStartInput: "trimStartInput", + trimEndInput: "trimEndInput", + isRepeateChkBox: "enableAutoLoop", + repeateTrimBtn: "repeatTrim", + }, + }, +}); \ No newline at end of file diff --git a/src/script/index.js b/src/script/index.js new file mode 100644 index 0000000..a91a879 --- /dev/null +++ b/src/script/index.js @@ -0,0 +1,65 @@ +import "./config.js"; +import { enableMobileDraggableControls } from "./utils.js"; +import { OTTMediaPlayer } from "./ottMediaPlayer.js"; + +// Auto-instantiate player and setup helpers on DOMContentLoaded +document.addEventListener("DOMContentLoaded", function () { + const config = window.OTT_PLAYER_CONFIG || {}; + const ids = (config.elements || {}); + const playbackIds = (ids.playback || {}); + const trimIds = (ids.trim || {}); + const getById = (id) => document.getElementById(id); + + const playerConfig = { + startPos: getById(playbackIds.startPos), + seekBar: getById(playbackIds.seekBar), + endPos: getById(playbackIds.endPos), + + resetPlayback: getById(playbackIds.resetPlayback), + playbackRate: getById(playbackIds.playbackRate), + backwordPlayback: getById(playbackIds.backwordPlayback), + playPauseBtn: getById(playbackIds.playPauseBtn), + forwardPlayback: getById(playbackIds.forwardPlayback), + fullScreenBtn: getById(playbackIds.fullScreenBtn), + pipModeBtn: getById(playbackIds.pipModeBtn), + rotationBtn: getById(playbackIds.rotationBtn), + theaterModeBtn: getById(playbackIds.theaterModeBtn), + + volumeBar: getById(playbackIds.volumeBar), + volumeValue: getById(playbackIds.volumeValue), + volumeBtn: getById(playbackIds.volumeBtn), + + videoMode: getById(playbackIds.videoMode), + }; + + const trimFeature = { + trimStartBtn: getById(trimIds.trimStartBtn), + trimEndBtn: getById(trimIds.trimEndBtn), + playTrimmedBtn: getById(trimIds.playTrimmedBtn), + trimStartInput: getById(trimIds.trimStartInput), + trimEndInput: getById(trimIds.trimEndInput), + isRepeateChkBox: getById(trimIds.isRepeateChkBox), + repeateTrimBtn: getById(trimIds.repeateTrimBtn), + }; + + const player = new OTTMediaPlayer( + getById(ids.videoPlayer), + playerConfig, + { trimFeature }, + ); + + OTTMediaPlayer.makeControlsDraggable(ids.controlsContainer, ids.dragHandle); + + // Attach playFromHeaderUrl to global for button usage + window.playFromHeaderUrl = function () { + OTTMediaPlayer.playFromHeaderUrl( + ids.headerVideoUrlInput, + ids.videoPlayer, + ); + }; + + enableMobileDraggableControls(); + + // Preserve debug access to the current player instance. + window.__ottPlayerInstance = player; +}); diff --git a/src/script/media.js b/src/script/media.js new file mode 100644 index 0000000..4a62b17 --- /dev/null +++ b/src/script/media.js @@ -0,0 +1,37 @@ +/* + * Legacy compatibility entry point. + * + * The player source has been split into: + * - script/config.js + * - script/utils.js + * - script/ottMediaPlayer.js + * - script/index.js + * + * Keep this file to support older HTML pages still referencing script/media.js. + */ +(function () { + if ( + window.OTTMediaPlayer && + window.enableMobileDraggableControls && + window.OTT_PLAYER_CONFIG + ) { + return; + } + + var head = document.head || document.getElementsByTagName("head")[0]; + var scripts = [ + "script/config.js", + "script/utils.js", + "script/ottMediaPlayer.js", + "script/index.js", + ]; + + scripts.forEach(function (src) { + var existing = document.querySelector('script[src="' + src + '"]'); + if (existing) return; + + var script = document.createElement("script"); + script.src = src; + head.appendChild(script); + }); +})(); diff --git a/script/media.js b/src/script/ottMediaPlayer.js similarity index 80% rename from script/media.js rename to src/script/ottMediaPlayer.js index 45a488d..867e27d 100644 --- a/script/media.js +++ b/src/script/ottMediaPlayer.js @@ -1,4 +1,4 @@ -class OTTMediaPlayer { +export class OTTMediaPlayer { constructor(videoElement, controls, playerFeatures) { this.config = { fwdTime: 10, @@ -849,229 +849,4 @@ class OTTMediaPlayer { } } -// Toggle input mode dropdown visibility -function toggleInputModeDropdown() { - var mode = document.getElementById("inputModeDropdown").value; - document.getElementById("fileInputRow").style.display = mode === "file" ? "" : "none"; - document.getElementById("urlInputRow").style.display = mode === "url" ? "" : "none"; - document.getElementById("directoryInputRow").style.display = mode === "directory" ? "" : "none"; - document.getElementById("navButtonsRow").style.display = "none"; // Hide nav buttons when not in directory mode -} - -// Choose local file from file input -function chooseLocalFile() { - const fileInput = document.getElementById("fName"); - const video = document.getElementById("media-video-player"); - if (fileInput.files && fileInput.files[0]) { - const fileURL = URL.createObjectURL(fileInput.files[0]); - video.pause(); - video.src = fileURL; - video.name = fileInput.files[0].name; - video.load(); - video.play(); - } -} - -// Load media files from selected directory -function loadDirectoryFiles() { - const directoryInput = document.getElementById("directoryInput"); - const mediaDropdown = document.getElementById("mediaDropdown"); - const directoryName = document.getElementById("directoryName"); - mediaDropdown.innerHTML = ""; - const defaultOption = document.createElement("option"); - defaultOption.textContent = "Select a media file..."; - defaultOption.value = ""; - mediaDropdown.appendChild(defaultOption); - - if (directoryInput.files && directoryInput.files.length > 0) { - const dirName = directoryInput.files[0].webkitRelativePath.split("/")[0]; - directoryName.textContent = `${dirName}(${directoryInput.files.length})`; - Array.from(directoryInput.files) - .filter( - (file) => - file.type.startsWith("video/") || file.type.startsWith("audio/"), - ) - .forEach((file) => { - const option = document.createElement("option"); - option.value = URL.createObjectURL(file); - option.textContent = file.name; - option.dataset.file = file; // Store file reference - mediaDropdown.appendChild(option); - }); - mediaDropdown.hidden = false; - document.getElementById("navButtonsRow").style.display = ""; // Show nav buttons when media files are loaded - // Automatically select and play the first media file - if (mediaDropdown.options.length > 1) { - mediaDropdown.selectedIndex = 1; - playSelectedMedia(); - } - } else { - directoryName.textContent = "No Directory"; - mediaDropdown.hidden = true; - document.getElementById("navButtonsRow").style.display = "none"; // Hide nav buttons when no files - } -} - -// Play selected media from dropdown -function playSelectedMedia() { - const mediaDropdown = document.getElementById("mediaDropdown"); - const selectedValue = mediaDropdown.value; - if (selectedValue) { - const video = document.getElementById("media-video-player"); - video.pause(); - video.src = selectedValue; - video.name = mediaDropdown.options[mediaDropdown.selectedIndex].textContent; - video.load(); - video.play(); - } -} - -// Navigate to previous media in directory -function playPreviousMedia() { - const mediaDropdown = document.getElementById("mediaDropdown"); - if (mediaDropdown.selectedIndex > 1) { - // Index 0 is default, 1 is first file - mediaDropdown.selectedIndex--; - playSelectedMedia(); - } else if (mediaDropdown.selectedIndex === 1) { - mediaDropdown.selectedIndex = mediaDropdown.options.length - 1; - playSelectedMedia(); - } -} - -// Navigate to next media in directory -function playNextMedia() { - const mediaDropdown = document.getElementById("mediaDropdown"); - if (mediaDropdown.selectedIndex < mediaDropdown.options.length - 1) { - mediaDropdown.selectedIndex++; - playSelectedMedia(); - } else if (mediaDropdown.selectedIndex === mediaDropdown.options.length - 1) { - mediaDropdown.selectedIndex = 1; - playSelectedMedia(); - } -} - -// Attach to global for HTML usage -window.toggleInputModeDropdown = toggleInputModeDropdown; -window.chooseLocalFile = chooseLocalFile; -window.loadDirectoryFiles = loadDirectoryFiles; -window.playSelectedMedia = playSelectedMedia; -window.playPreviousMedia = playPreviousMedia; -window.playNextMedia = playNextMedia; - -// Auto-instantiate player and setup helpers on DOMContentLoaded -document.addEventListener("DOMContentLoaded", function () { - const playerConfig = { - startPos: document.getElementById("startPos"), - seekBar: document.getElementById("player-seekbar"), - endPos: document.getElementById("endPos"), - - resetPlayback: document.getElementById("reset"), - playbackRate: document.getElementById("playbackRate"), - backwordPlayback: document.getElementById("backword"), - playPauseBtn: document.getElementById("playPause"), - forwardPlayback: document.getElementById("forward"), - fullScreenBtn: document.getElementById("fullScreen"), - pipModeBtn: document.getElementById("pipMode"), - rotationBtn: document.getElementById("screenRotation"), - theaterModeBtn: document.getElementById("theaterMode"), - - volumeBar: document.getElementById("volumeBar"), - volumeValue: document.getElementById("volumeValue"), - volumeBtn: document.getElementById("volume"), - - videoMode: document.getElementById("videoMode"), - }; - - const trimFeature = { - trimStartBtn: document.getElementById("setTrimStart"), - trimEndBtn: document.getElementById("setTrimEnd"), - playTrimmedBtn: document.getElementById("playTrimmed"), - trimStartInput: document.getElementById("trimStartInput"), - trimEndInput: document.getElementById("trimEndInput"), - isRepeateChkBox: document.getElementById("enableAutoLoop"), - repeateTrimBtn: document.getElementById("repeatTrim"), - }; - - const player = new OTTMediaPlayer( - document.getElementById("media-video-player"), - playerConfig, - { trimFeature }, - ); - - OTTMediaPlayer.makeControlsDraggable("media-media-controls", "dragHandle"); - // Attach playFromHeaderUrl to global for button usage - window.playFromHeaderUrl = function () { - OTTMediaPlayer.playFromHeaderUrl( - "headerVideoUrlInput", - "media-video-player", - ); - }; - enableMobileDraggableControls(); -}); - -// Make player-controls draggable on mobile and desktop, with focus fix -function enableMobileDraggableControls() { - const controls = document.getElementById("media-media-controls"); - const handle = document.getElementById("dragHandle"); - let isDragging = false, - startX, - startY, - origX, - origY; - - function setPosition(x, y) { - controls.style.left = x + "px"; - controls.style.top = y + "px"; - controls.style.position = "fixed"; - controls.style.zIndex = 1000; - controls.style.transition = "none"; - controls.focus(); // Ensure focus after move - } - - // Desktop - handle.addEventListener("mousedown", function (e) { - isDragging = true; - startX = e.clientX; - startY = e.clientY; - const rect = controls.getBoundingClientRect(); - origX = rect.left; - origY = rect.top; - setPosition(origX, origY); - controls.setAttribute("tabindex", "-1"); // Make focusable if not already - controls.focus(); - }); - document.addEventListener("mousemove", function (e) { - if (!isDragging) return; - let dx = e.clientX - startX; - let dy = e.clientY - startY; - setPosition(origX + dx, origY + dy); - }); - document.addEventListener("mouseup", function () { - isDragging = false; - }); - - // Mobile (touch) - handle.addEventListener("touchstart", function (e) { - isDragging = true; - const touch = e.touches[0]; - startX = touch.clientX; - startY = touch.clientY; - const rect = controls.getBoundingClientRect(); - origX = rect.left; - origY = rect.top; - setPosition(origX, origY); - controls.setAttribute("tabindex", "-1"); - controls.focus(); - }); - document.addEventListener("touchmove", function (e) { - if (!isDragging) return; - const touch = e.touches[0]; - let dx = touch.clientX - startX; - let dy = touch.clientY - startY; - setPosition(origX + dx, origY + dy); - }); - document.addEventListener("touchend", function () { - isDragging = false; - }); -} +window.OTTMediaPlayer = OTTMediaPlayer; diff --git a/src/script/utils.js b/src/script/utils.js new file mode 100644 index 0000000..baec382 --- /dev/null +++ b/src/script/utils.js @@ -0,0 +1,239 @@ +export function getOttElements() { + const config = window.OTT_PLAYER_CONFIG || {}; + const elements = config.elements || {}; + const inputDefaults = { + inputModeDropdown: "inputModeDropdown", + fileInputRow: "fileInputRow", + urlInputRow: "urlInputRow", + directoryInputRow: "directoryInputRow", + navButtonsRow: "navButtonsRow", + fileInput: "fName", + directoryInput: "directoryInput", + mediaDropdown: "mediaDropdown", + directoryName: "directoryName", + }; + + return { + videoPlayer: elements.videoPlayer || "media-video-player", + controlsContainer: elements.controlsContainer || "media-media-controls", + dragHandle: elements.dragHandle || "dragHandle", + inputs: { + ...inputDefaults, + ...(elements.inputs || {}), + }, + }; +} + +export function getOttUiConfig() { + const config = window.OTT_PLAYER_CONFIG || {}; + const ui = config.ui || {}; + + return { + inputModes: { + file: "file", + url: "url", + directory: "directory", + ...(ui.inputModes || {}), + }, + labels: { + emptyDirectory: "No Directory", + mediaDropdownDefault: "Select a media file...", + ...(ui.labels || {}), + }, + mediaTypePrefixes: Array.isArray(ui.mediaTypePrefixes) + ? ui.mediaTypePrefixes + : ["video/", "audio/"], + }; +} + +// Toggle input mode dropdown visibility +export function toggleInputModeDropdown() { + const { inputs } = getOttElements(); + const { inputModes } = getOttUiConfig(); + var mode = document.getElementById(inputs.inputModeDropdown).value; + document.getElementById(inputs.fileInputRow).style.display = + mode === inputModes.file ? "" : "none"; + document.getElementById(inputs.urlInputRow).style.display = + mode === inputModes.url ? "" : "none"; + document.getElementById(inputs.directoryInputRow).style.display = + mode === inputModes.directory ? "" : "none"; + document.getElementById(inputs.navButtonsRow).style.display = "none"; // Hide nav buttons when not in directory mode +} + +// Choose local file from file input +export function chooseLocalFile() { + const elements = getOttElements(); + const fileInput = document.getElementById(elements.inputs.fileInput); + const video = document.getElementById(elements.videoPlayer); + if (fileInput.files && fileInput.files[0]) { + const fileURL = URL.createObjectURL(fileInput.files[0]); + video.pause(); + video.src = fileURL; + video.name = fileInput.files[0].name; + video.load(); + video.play(); + } +} + +// Load media files from selected directory +export function loadDirectoryFiles() { + const { inputs } = getOttElements(); + const { labels, mediaTypePrefixes } = getOttUiConfig(); + const directoryInput = document.getElementById(inputs.directoryInput); + const mediaDropdown = document.getElementById(inputs.mediaDropdown); + const directoryName = document.getElementById(inputs.directoryName); + mediaDropdown.innerHTML = ""; + const defaultOption = document.createElement("option"); + defaultOption.textContent = labels.mediaDropdownDefault; + defaultOption.value = ""; + mediaDropdown.appendChild(defaultOption); + + if (directoryInput.files && directoryInput.files.length > 0) { + const dirName = directoryInput.files[0].webkitRelativePath.split("/")[0]; + directoryName.textContent = `${dirName}(${directoryInput.files.length})`; + Array.from(directoryInput.files) + .filter( + (file) => + mediaTypePrefixes.some((typePrefix) => + file.type.startsWith(typePrefix), + ), + ) + .forEach((file) => { + const option = document.createElement("option"); + option.value = URL.createObjectURL(file); + option.textContent = file.name; + option.dataset.file = file; // Store file reference + mediaDropdown.appendChild(option); + }); + mediaDropdown.hidden = false; + document.getElementById(inputs.navButtonsRow).style.display = ""; // Show nav buttons when media files are loaded + // Automatically select and play the first media file + if (mediaDropdown.options.length > 1) { + mediaDropdown.selectedIndex = 1; + playSelectedMedia(); + } + } else { + directoryName.textContent = labels.emptyDirectory; + mediaDropdown.hidden = true; + document.getElementById(inputs.navButtonsRow).style.display = "none"; // Hide nav buttons when no files + } +} + +// Play selected media from dropdown +export function playSelectedMedia() { + const elements = getOttElements(); + const mediaDropdown = document.getElementById(elements.inputs.mediaDropdown); + const selectedValue = mediaDropdown.value; + if (selectedValue) { + const video = document.getElementById(elements.videoPlayer); + video.pause(); + video.src = selectedValue; + video.name = mediaDropdown.options[mediaDropdown.selectedIndex].textContent; + video.load(); + video.play(); + } +} + +// Navigate to previous media in directory +export function playPreviousMedia() { + const mediaDropdown = document.getElementById( + getOttElements().inputs.mediaDropdown, + ); + if (mediaDropdown.selectedIndex > 1) { + // Index 0 is default, 1 is first file + mediaDropdown.selectedIndex--; + playSelectedMedia(); + } else if (mediaDropdown.selectedIndex === 1) { + mediaDropdown.selectedIndex = mediaDropdown.options.length - 1; + playSelectedMedia(); + } +} + +// Navigate to next media in directory +export function playNextMedia() { + const mediaDropdown = document.getElementById( + getOttElements().inputs.mediaDropdown, + ); + if (mediaDropdown.selectedIndex < mediaDropdown.options.length - 1) { + mediaDropdown.selectedIndex++; + playSelectedMedia(); + } else if (mediaDropdown.selectedIndex === mediaDropdown.options.length - 1) { + mediaDropdown.selectedIndex = 1; + playSelectedMedia(); + } +} + +// Make player-controls draggable on mobile and desktop, with focus fix +export function enableMobileDraggableControls() { + const elements = getOttElements(); + const controls = document.getElementById(elements.controlsContainer); + const handle = document.getElementById(elements.dragHandle); + let isDragging = false, + startX, + startY, + origX, + origY; + + function setPosition(x, y) { + controls.style.left = x + "px"; + controls.style.top = y + "px"; + controls.style.position = "fixed"; + controls.style.zIndex = 1000; + controls.style.transition = "none"; + controls.focus(); // Ensure focus after move + } + + // Desktop + handle.addEventListener("mousedown", function (e) { + isDragging = true; + startX = e.clientX; + startY = e.clientY; + const rect = controls.getBoundingClientRect(); + origX = rect.left; + origY = rect.top; + setPosition(origX, origY); + controls.setAttribute("tabindex", "-1"); // Make focusable if not already + controls.focus(); + }); + document.addEventListener("mousemove", function (e) { + if (!isDragging) return; + let dx = e.clientX - startX; + let dy = e.clientY - startY; + setPosition(origX + dx, origY + dy); + }); + document.addEventListener("mouseup", function () { + isDragging = false; + }); + + // Mobile (touch) + handle.addEventListener("touchstart", function (e) { + isDragging = true; + const touch = e.touches[0]; + startX = touch.clientX; + startY = touch.clientY; + const rect = controls.getBoundingClientRect(); + origX = rect.left; + origY = rect.top; + setPosition(origX, origY); + controls.setAttribute("tabindex", "-1"); + controls.focus(); + }); + document.addEventListener("touchmove", function (e) { + if (!isDragging) return; + const touch = e.touches[0]; + let dx = touch.clientX - startX; + let dy = touch.clientY - startY; + setPosition(origX + dx, origY + dy); + }); + document.addEventListener("touchend", function () { + isDragging = false; + }); +} + +window.toggleInputModeDropdown = toggleInputModeDropdown; +window.chooseLocalFile = chooseLocalFile; +window.loadDirectoryFiles = loadDirectoryFiles; +window.playSelectedMedia = playSelectedMedia; +window.playPreviousMedia = playPreviousMedia; +window.playNextMedia = playNextMedia; +window.enableMobileDraggableControls = enableMobileDraggableControls; diff --git a/style/media.css b/src/style/media.css similarity index 100% rename from style/media.css rename to src/style/media.css From 3421dc9635736289c3b359f82b92cbadc0ddc52a Mon Sep 17 00:00:00 2001 From: Biswasindhu Mandal Date: Sun, 5 Jul 2026 21:32:51 +0530 Subject: [PATCH 2/5] Update v24 version --- .node-version | 2 +- .nvmrc | 2 +- package-lock.json | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.node-version b/.node-version index 5b54067..51105aa 100644 --- a/.node-version +++ b/.node-version @@ -1 +1 @@ -22.16.0 +24.0.0 diff --git a/.nvmrc b/.nvmrc index 2bd5a0a..a45fd52 100644 --- a/.nvmrc +++ b/.nvmrc @@ -1 +1 @@ -22 +24 diff --git a/package-lock.json b/package-lock.json index e631432..93f22ee 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "mediaplayer", - "version": "1.0.0", + "version": "2.0.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "mediaplayer", - "version": "1.0.0", + "version": "2.0.0", "license": "MIT", "dependencies": { "http-server": "^0.12.1" From d8d18e896b00c4f4e9258d83c0050c8b193f1129 Mon Sep 17 00:00:00 2001 From: Biswasindhu Mandal Date: Sun, 5 Jul 2026 21:42:10 +0530 Subject: [PATCH 3/5] update docs --- .vscode/settings.json | 1 + src/script/index.js | 13 +++++++++++++ src/script/media.js | 11 ++++------- 3 files changed, 18 insertions(+), 7 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index bb81c58..57ade51 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -11,6 +11,7 @@ "explorer.fileNesting.patterns": { "README.md": "*.md, .gitignore, *.ico, LICENSE", "package.json": "*.json, .nvmrc, .node-version, .yarnrc, .yarnrc.yml, .yarnrc.yaml, rollup.config.js, rollup.config.mjs, rollup.config.cjs, rollup.config.ts, tsconfig.json, tsconfig.*.json", + "index.js": "*.js", "index.html": "*.js, *.css, *.ico" }, "cSpell.words": [] diff --git a/src/script/index.js b/src/script/index.js index a91a879..f4e1512 100644 --- a/src/script/index.js +++ b/src/script/index.js @@ -1,3 +1,16 @@ +/* + * Primary application entry point. + * + * Current source layout: + * - src/script/config.js + * - src/script/utils.js + * - src/script/ottMediaPlayer.js + * - src/script/index.js (this file) + * + * Build output is bundled to dist/index.min.js. + * For backward compatibility, older pages may still include script/media.js, + * which dynamically loads the same script/* modules in order. + */ import "./config.js"; import { enableMobileDraggableControls } from "./utils.js"; import { OTTMediaPlayer } from "./ottMediaPlayer.js"; diff --git a/src/script/media.js b/src/script/media.js index 4a62b17..6eab1ee 100644 --- a/src/script/media.js +++ b/src/script/media.js @@ -1,13 +1,10 @@ /* - * Legacy compatibility entry point. + * Legacy compatibility loader shim. * - * The player source has been split into: - * - script/config.js - * - script/utils.js - * - script/ottMediaPlayer.js - * - script/index.js + * This file supports older pages that still include script/media.js by + * dynamically loading modular script/* files in order. * - * Keep this file to support older HTML pages still referencing script/media.js. + * Primary application entry is src/script/index.js. */ (function () { if ( From 0dc9658317fd1b235a1e11ee1ba036ce50fb7246 Mon Sep 17 00:00:00 2001 From: Biswasindhu Mandal Date: Sun, 5 Jul 2026 21:50:45 +0530 Subject: [PATCH 4/5] Update modulerased structure --- src/script/index.js | 22 +++++++-- src/script/media.js | 34 ------------- src/script/ottMediaPlayer.js | 66 +++++-------------------- src/script/utils.js | 95 +++++++++++++++++++++++++++++++++--- 4 files changed, 118 insertions(+), 99 deletions(-) delete mode 100644 src/script/media.js diff --git a/src/script/index.js b/src/script/index.js index f4e1512..9308f8f 100644 --- a/src/script/index.js +++ b/src/script/index.js @@ -8,13 +8,29 @@ * - src/script/index.js (this file) * * Build output is bundled to dist/index.min.js. - * For backward compatibility, older pages may still include script/media.js, - * which dynamically loads the same script/* modules in order. */ import "./config.js"; -import { enableMobileDraggableControls } from "./utils.js"; +import { + chooseLocalFile, + enableMobileDraggableControls, + loadDirectoryFiles, + playNextMedia, + playPreviousMedia, + playSelectedMedia, + toggleInputModeDropdown, +} from "./utils.js"; import { OTTMediaPlayer } from "./ottMediaPlayer.js"; +// Legacy inline handlers from HTML are bound here so this file remains the single entry point. +window.toggleInputModeDropdown = toggleInputModeDropdown; +window.chooseLocalFile = chooseLocalFile; +window.loadDirectoryFiles = loadDirectoryFiles; +window.playSelectedMedia = playSelectedMedia; +window.playPreviousMedia = playPreviousMedia; +window.playNextMedia = playNextMedia; +window.enableMobileDraggableControls = enableMobileDraggableControls; +window.__ottPlayerEntryLoaded = true; + // Auto-instantiate player and setup helpers on DOMContentLoaded document.addEventListener("DOMContentLoaded", function () { const config = window.OTT_PLAYER_CONFIG || {}; diff --git a/src/script/media.js b/src/script/media.js deleted file mode 100644 index 6eab1ee..0000000 --- a/src/script/media.js +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Legacy compatibility loader shim. - * - * This file supports older pages that still include script/media.js by - * dynamically loading modular script/* files in order. - * - * Primary application entry is src/script/index.js. - */ -(function () { - if ( - window.OTTMediaPlayer && - window.enableMobileDraggableControls && - window.OTT_PLAYER_CONFIG - ) { - return; - } - - var head = document.head || document.getElementsByTagName("head")[0]; - var scripts = [ - "script/config.js", - "script/utils.js", - "script/ottMediaPlayer.js", - "script/index.js", - ]; - - scripts.forEach(function (src) { - var existing = document.querySelector('script[src="' + src + '"]'); - if (existing) return; - - var script = document.createElement("script"); - script.src = src; - head.appendChild(script); - }); -})(); diff --git a/src/script/ottMediaPlayer.js b/src/script/ottMediaPlayer.js index 867e27d..102731a 100644 --- a/src/script/ottMediaPlayer.js +++ b/src/script/ottMediaPlayer.js @@ -1,3 +1,9 @@ +import { + getFfmpegScriptList, + playNextMedia, + playPreviousMedia, +} from "./utils.js"; + export class OTTMediaPlayer { constructor(videoElement, controls, playerFeatures) { this.config = { @@ -781,61 +787,11 @@ export class OTTMediaPlayer { : Math.min(videoResolution.width, cropVideo.HD.height), }; - const scriptList = { - break0: "------ Basic Video Information & Transformation --------", - videoResolution: `${videoResolution.width} x ${videoResolution.height} ${isHighResolution ? "✅" : "🚫"}`, - storeMediaInfo: `ffprobe -v quiet -print_format json -show_format -show_streams "{INPUTFILE}" > "trim/mediaInfo.json"`, - reEncode_video_and_Audio: `ffmpeg -i "{INPUTFILE}" -c:v libx264 -crf 23 -preset medium -c:a aac -b:a 192k "${object.INPUTFILE.replace(/\.[\w\d]+$/gi, "")}.mp4"`, - break1: "--------Full Video Audio-------------", - // Trim Video with range in second - trimeVideo_sec: `ffmpeg -i "{INPUTFILE}" -ss {STARTTIME} -t {TRIMDURATION} -c:v libx264 -crf 23 -preset fast -c:a aac -b:a 128k "{OUTPUTFILE}_{SCRIPTKEY}.mp4"`, - trimVideoWithoutAudio_sec: `ffmpeg -i "{INPUTFILE}" -ss {STARTTIME} -t {TRIMDURATION} -c:v libx264 -crf 23 -preset fast -an "{OUTPUTFILE}_{SCRIPTKEY}.mp4"`, - trimAudioOnlyFromVideo_sec: `ffmpeg -i "{INPUTFILE}" -ss {STARTTIME} -t {TRIMDURATION} -q:a 0 -map a "{OUTPUTFILE}_{SCRIPTKEY}.mp3"`, - rotateVideoClockWise90: `ffmpeg -i "{INPUTFILE}" -vf "transpose=1" "{OUTPUTFILE}_{SCRIPTKEY}_clock90.mp4"`, - rotateVideoAntiClockWise90: `ffmpeg -i "{INPUTFILE}" -vf "transpose=1,transpose=1,transpose=1" "{OUTPUTFILE}_{SCRIPTKEY}_anticlock90.mp4"`, - - break2: "\n--------Video Crop Center | Left | Right-------------", - cropVideo_left: `ffmpeg -i "{INPUTFILE}" -ss {STARTTIME} -t {TRIMDURATION} -vf "crop={CROP_WIDTH}:{CROP_HEIGHT}:(({VIDEO_WIDTH}-{CROP_WIDTH}*3)/2 + {CROP_WIDTH}*0):({VIDEO_HEIGHT}-1920)/2" -c:v libx264 -crf 23 -preset fast -c:a aac -b:a 128k "{OUTPUTFILE}_{SCRIPTKEY}.mp4"`, - cropVideo_center_OLD: `ffmpeg -i "{INPUTFILE}" -ss {STARTTIME} -t {TRIMDURATION} -vf "crop={CROP_WIDTH}:{CROP_HEIGHT}:(({VIDEO_WIDTH}-{CROP_WIDTH}*3)/2 + {CROP_WIDTH}*1):({VIDEO_HEIGHT}-1920)/2" -c:v libx264 -crf 23 -preset fast -c:a aac -b:a 128k "{OUTPUTFILE}_{SCRIPTKEY}.mp4"`, - cropVideo_center: `ffmpeg -i "{INPUTFILE}" -ss {STARTTIME} -t {TRIMDURATION} -vf "crop={CROP_WIDTH}:{CROP_HEIGHT}:(({VIDEO_WIDTH}-{CROP_WIDTH})/2):(({VIDEO_HEIGHT}-{CROP_HEIGHT})/2)" -c:v libx264 -crf 23 -preset fast -c:a aac -b:a 128k "{OUTPUTFILE}_{SCRIPTKEY}.mp4"`, - cropVideo_right: `ffmpeg -i "{INPUTFILE}" -ss {STARTTIME} -t {TRIMDURATION} -vf "crop={CROP_WIDTH}:{CROP_HEIGHT}:(({VIDEO_WIDTH}-{CROP_WIDTH}*3)/2 + {CROP_WIDTH}*2):({VIDEO_HEIGHT}-1920)/2" -c:v libx264 -crf 23 -preset fast -c:a aac -b:a 128k "{OUTPUTFILE}_{SCRIPTKEY}.mp4"`, - - break3: - "\n--------Reverse Corped Video Center | Left | Right-------------", - cropVideo_left_reverse: `ffmpeg -i "{OUTPUTFILE}_{SCRIPTKEY-REV}.mp4" -vf reverse -af areverse -preset fast -c:v libx264 -c:a aac -b:a 128k "{OUTPUTFILE}_{SCRIPTKEY}.mp4"`, - cropVideo_center_reverse: `ffmpeg -i "{OUTPUTFILE}_{SCRIPTKEY-REV}.mp4" -vf reverse -af areverse -preset fast -c:v libx264 -c:a aac -b:a 128k "{OUTPUTFILE}_{SCRIPTKEY}.mp4"`, - cropVideo_right_reverse: `ffmpeg -i "{OUTPUTFILE}_{SCRIPTKEY-REV}.mp4" -vf reverse -af areverse -preset fast -c:v libx264 -c:a aac -b:a 128k "{OUTPUTFILE}_{SCRIPTKEY}.mp4"`, - - break4: - "\n--------Video Crop Extrime Left/Right | Middle of Left-Center/Right-Center-------------", - cropVideo_extrime_left: `ffmpeg -i "{INPUTFILE}" -ss {STARTTIME} -t {TRIMDURATION} -vf "crop={CROP_WIDTH}:{CROP_HEIGHT}:0:({VIDEO_HEIGHT}-1920)/2" -c:v libx264 -crf 23 -preset fast -c:a aac -b:a 128k "{OUTPUTFILE}_{SCRIPTKEY}.mp4"`, - cropVideo_left_center_mid: `ffmpeg -i "{INPUTFILE}" -ss {STARTTIME} -t {TRIMDURATION} -vf "crop={CROP_WIDTH}:{CROP_HEIGHT}:(({VIDEO_WIDTH}-{CROP_WIDTH}*3)/2 + ({CROP_WIDTH}*(0+1)/2)):({VIDEO_HEIGHT}-1920)/2" -c:v libx264 -crf 23 -preset fast -c:a aac -b:a 128k "{OUTPUTFILE}_{SCRIPTKEY}.mp4"`, - cropVideo_center_right_mid: `ffmpeg -i "{INPUTFILE}" -ss {STARTTIME} -t {TRIMDURATION} -vf "crop={CROP_WIDTH}:{CROP_HEIGHT}:(({VIDEO_WIDTH}-{CROP_WIDTH}*3)/2 + ({CROP_WIDTH}*(1+2)/2)):({VIDEO_HEIGHT}-1920)/2" -c:v libx264 -crf 23 -preset fast -c:a aac -b:a 128k "{OUTPUTFILE}_{SCRIPTKEY}.mp4"`, - cropVideo_extrime_right: `ffmpeg -i "{INPUTFILE}" -ss {STARTTIME} -t {TRIMDURATION} -vf "crop={CROP_WIDTH}:{CROP_HEIGHT}:({VIDEO_WIDTH}-{CROP_WIDTH}):({VIDEO_HEIGHT}-1920)/2" -c:v libx264 -crf 23 -preset fast -c:a aac -b:a 128k "{OUTPUTFILE}_{SCRIPTKEY}.mp4"`, - - break5: - "\n--------Reverse Corped Video Extrime Left/Right | Middle of Left-Center/Right-Center-------------", - cropVideo_extrime_left_reverse: `ffmpeg -i "{OUTPUTFILE}_{SCRIPTKEY-REV}.mp4" -vf reverse -af areverse -preset fast -c:v libx264 -c:a aac -b:a 128k "{OUTPUTFILE}_{SCRIPTKEY}.mp4"`, - cropVideo_left_center_mid_reverse: `ffmpeg -i "{OUTPUTFILE}_{SCRIPTKEY-REV}.mp4" -vf reverse -af areverse -preset fast -c:v libx264 -c:a aac -b:a 128k "{OUTPUTFILE}_{SCRIPTKEY}.mp4"`, - cropVideo_center_right_mid_reverse: `ffmpeg -i "{OUTPUTFILE}_{SCRIPTKEY-REV}.mp4" -vf reverse -af areverse -preset fast -c:v libx264 -c:a aac -b:a 128k "{OUTPUTFILE}_{SCRIPTKEY}.mp4"`, - cropVideo_extrime_right_reverse: `ffmpeg -i "{OUTPUTFILE}_{SCRIPTKEY-REV}.mp4" -vf reverse -af areverse -preset fast -c:v libx264 -c:a aac -b:a 128k "{OUTPUTFILE}_{SCRIPTKEY}.mp4"`, - - break6: "--------Merge Clips-------------", - mergedCropVideo: - "ffmpeg -f concat -safe 0 -i mergevideolist.txt -c copy {SCRIPTKEY}.mp4", - mergedCropVideo_no_Audio: - 'ffmpeg -i "mergedCropVideo.mp4" -an {SCRIPTKEY}.mp4', - trimAudioFromVideo: - 'ffmpeg -i "{INPUTFILE}" -ss {STARTTIME} -t {TRIMDURATION} -c copy "{SCRIPTKEY}.mp3"', - mergedCropAudios: - "ffmpeg -f concat -safe 0 -i mergevideolist.txt -c copy {SCRIPTKEY}.mp3", - mergedAudio_And_Video: - "ffmpeg -i mergedCropVideo_no_Audio.mp4 -i trimAudioFromVideo.mp3 -c:v copy -c:a aac -shortest {SCRIPTKEY}.mp4", - mergedAudio_And_Video_90deg: - 'ffmpeg -i "mergedAudio_And_Video.mp4" -vf "transpose=1" "{SCRIPTKEY}.mp4"', - mergedAudio_And_Video_270deg: - 'ffmpeg -i "mergedAudio_And_Video.mp4" -vf "transpose=1,transpose=1,transpose=1" "{SCRIPTKEY}.mp4"', - }; + const scriptList = getFfmpegScriptList({ + videoResolution, + isHighResolution, + inputFileName: object.INPUTFILE, + }); console.clear(); Object.keys(scriptList).forEach((script) => diff --git a/src/script/utils.js b/src/script/utils.js index baec382..6468efc 100644 --- a/src/script/utils.js +++ b/src/script/utils.js @@ -230,10 +230,91 @@ export function enableMobileDraggableControls() { }); } -window.toggleInputModeDropdown = toggleInputModeDropdown; -window.chooseLocalFile = chooseLocalFile; -window.loadDirectoryFiles = loadDirectoryFiles; -window.playSelectedMedia = playSelectedMedia; -window.playPreviousMedia = playPreviousMedia; -window.playNextMedia = playNextMedia; -window.enableMobileDraggableControls = enableMobileDraggableControls; +/** + * Creates the ffmpeg command template dictionary used by trim/export helpers. + * + * @param {{videoResolution:{width:number,height:number},isHighResolution:boolean,inputFileName:string}} params + * @returns {Record} + */ +export function getFfmpegScriptList({ + videoResolution, + isHighResolution, + inputFileName, +}) { + return { + break0: "------ Basic Video Information & Transformation --------", + videoResolution: `${videoResolution.width} x ${videoResolution.height} ${isHighResolution ? "✅" : "🚫"}`, + storeMediaInfo: + 'ffprobe -v quiet -print_format json -show_format -show_streams "{INPUTFILE}" > "trim/mediaInfo.json"', + reEncode_video_and_Audio: `ffmpeg -i "{INPUTFILE}" -c:v libx264 -crf 23 -preset medium -c:a aac -b:a 192k "${inputFileName.replace(/\.[\w\d]+$/gi, "")}.mp4"`, + break1: "--------Full Video Audio-------------", + // Trim Video with range in second + trimeVideo_sec: + 'ffmpeg -i "{INPUTFILE}" -ss {STARTTIME} -t {TRIMDURATION} -c:v libx264 -crf 23 -preset fast -c:a aac -b:a 128k "{OUTPUTFILE}_{SCRIPTKEY}.mp4"', + trimVideoWithoutAudio_sec: + 'ffmpeg -i "{INPUTFILE}" -ss {STARTTIME} -t {TRIMDURATION} -c:v libx264 -crf 23 -preset fast -an "{OUTPUTFILE}_{SCRIPTKEY}.mp4"', + trimAudioOnlyFromVideo_sec: + 'ffmpeg -i "{INPUTFILE}" -ss {STARTTIME} -t {TRIMDURATION} -q:a 0 -map a "{OUTPUTFILE}_{SCRIPTKEY}.mp3"', + rotateVideoClockWise90: + 'ffmpeg -i "{INPUTFILE}" -vf "transpose=1" "{OUTPUTFILE}_{SCRIPTKEY}_clock90.mp4"', + rotateVideoAntiClockWise90: + 'ffmpeg -i "{INPUTFILE}" -vf "transpose=1,transpose=1,transpose=1" "{OUTPUTFILE}_{SCRIPTKEY}_anticlock90.mp4"', + + break2: "\n--------Video Crop Center | Left | Right-------------", + cropVideo_left: + 'ffmpeg -i "{INPUTFILE}" -ss {STARTTIME} -t {TRIMDURATION} -vf "crop={CROP_WIDTH}:{CROP_HEIGHT}:(({VIDEO_WIDTH}-{CROP_WIDTH}*3)/2 + {CROP_WIDTH}*0):({VIDEO_HEIGHT}-1920)/2" -c:v libx264 -crf 23 -preset fast -c:a aac -b:a 128k "{OUTPUTFILE}_{SCRIPTKEY}.mp4"', + cropVideo_center_OLD: + 'ffmpeg -i "{INPUTFILE}" -ss {STARTTIME} -t {TRIMDURATION} -vf "crop={CROP_WIDTH}:{CROP_HEIGHT}:(({VIDEO_WIDTH}-{CROP_WIDTH}*3)/2 + {CROP_WIDTH}*1):({VIDEO_HEIGHT}-1920)/2" -c:v libx264 -crf 23 -preset fast -c:a aac -b:a 128k "{OUTPUTFILE}_{SCRIPTKEY}.mp4"', + cropVideo_center: + 'ffmpeg -i "{INPUTFILE}" -ss {STARTTIME} -t {TRIMDURATION} -vf "crop={CROP_WIDTH}:{CROP_HEIGHT}:(({VIDEO_WIDTH}-{CROP_WIDTH})/2):(({VIDEO_HEIGHT}-{CROP_HEIGHT})/2)" -c:v libx264 -crf 23 -preset fast -c:a aac -b:a 128k "{OUTPUTFILE}_{SCRIPTKEY}.mp4"', + cropVideo_right: + 'ffmpeg -i "{INPUTFILE}" -ss {STARTTIME} -t {TRIMDURATION} -vf "crop={CROP_WIDTH}:{CROP_HEIGHT}:(({VIDEO_WIDTH}-{CROP_WIDTH}*3)/2 + {CROP_WIDTH}*2):({VIDEO_HEIGHT}-1920)/2" -c:v libx264 -crf 23 -preset fast -c:a aac -b:a 128k "{OUTPUTFILE}_{SCRIPTKEY}.mp4"', + + break3: + "\n--------Reverse Corped Video Center | Left | Right-------------", + cropVideo_left_reverse: + 'ffmpeg -i "{OUTPUTFILE}_{SCRIPTKEY-REV}.mp4" -vf reverse -af areverse -preset fast -c:v libx264 -c:a aac -b:a 128k "{OUTPUTFILE}_{SCRIPTKEY}.mp4"', + cropVideo_center_reverse: + 'ffmpeg -i "{OUTPUTFILE}_{SCRIPTKEY-REV}.mp4" -vf reverse -af areverse -preset fast -c:v libx264 -c:a aac -b:a 128k "{OUTPUTFILE}_{SCRIPTKEY}.mp4"', + cropVideo_right_reverse: + 'ffmpeg -i "{OUTPUTFILE}_{SCRIPTKEY-REV}.mp4" -vf reverse -af areverse -preset fast -c:v libx264 -c:a aac -b:a 128k "{OUTPUTFILE}_{SCRIPTKEY}.mp4"', + + break4: + "\n--------Video Crop Extrime Left/Right | Middle of Left-Center/Right-Center-------------", + cropVideo_extrime_left: + 'ffmpeg -i "{INPUTFILE}" -ss {STARTTIME} -t {TRIMDURATION} -vf "crop={CROP_WIDTH}:{CROP_HEIGHT}:0:({VIDEO_HEIGHT}-1920)/2" -c:v libx264 -crf 23 -preset fast -c:a aac -b:a 128k "{OUTPUTFILE}_{SCRIPTKEY}.mp4"', + cropVideo_left_center_mid: + 'ffmpeg -i "{INPUTFILE}" -ss {STARTTIME} -t {TRIMDURATION} -vf "crop={CROP_WIDTH}:{CROP_HEIGHT}:(({VIDEO_WIDTH}-{CROP_WIDTH}*3)/2 + ({CROP_WIDTH}*(0+1)/2)):({VIDEO_HEIGHT}-1920)/2" -c:v libx264 -crf 23 -preset fast -c:a aac -b:a 128k "{OUTPUTFILE}_{SCRIPTKEY}.mp4"', + cropVideo_center_right_mid: + 'ffmpeg -i "{INPUTFILE}" -ss {STARTTIME} -t {TRIMDURATION} -vf "crop={CROP_WIDTH}:{CROP_HEIGHT}:(({VIDEO_WIDTH}-{CROP_WIDTH}*3)/2 + ({CROP_WIDTH}*(1+2)/2)):({VIDEO_HEIGHT}-1920)/2" -c:v libx264 -crf 23 -preset fast -c:a aac -b:a 128k "{OUTPUTFILE}_{SCRIPTKEY}.mp4"', + cropVideo_extrime_right: + 'ffmpeg -i "{INPUTFILE}" -ss {STARTTIME} -t {TRIMDURATION} -vf "crop={CROP_WIDTH}:{CROP_HEIGHT}:({VIDEO_WIDTH}-{CROP_WIDTH}):({VIDEO_HEIGHT}-1920)/2" -c:v libx264 -crf 23 -preset fast -c:a aac -b:a 128k "{OUTPUTFILE}_{SCRIPTKEY}.mp4"', + + break5: + "\n--------Reverse Corped Video Extrime Left/Right | Middle of Left-Center/Right-Center-------------", + cropVideo_extrime_left_reverse: + 'ffmpeg -i "{OUTPUTFILE}_{SCRIPTKEY-REV}.mp4" -vf reverse -af areverse -preset fast -c:v libx264 -c:a aac -b:a 128k "{OUTPUTFILE}_{SCRIPTKEY}.mp4"', + cropVideo_left_center_mid_reverse: + 'ffmpeg -i "{OUTPUTFILE}_{SCRIPTKEY-REV}.mp4" -vf reverse -af areverse -preset fast -c:v libx264 -c:a aac -b:a 128k "{OUTPUTFILE}_{SCRIPTKEY}.mp4"', + cropVideo_center_right_mid_reverse: + 'ffmpeg -i "{OUTPUTFILE}_{SCRIPTKEY-REV}.mp4" -vf reverse -af areverse -preset fast -c:v libx264 -c:a aac -b:a 128k "{OUTPUTFILE}_{SCRIPTKEY}.mp4"', + cropVideo_extrime_right_reverse: + 'ffmpeg -i "{OUTPUTFILE}_{SCRIPTKEY-REV}.mp4" -vf reverse -af areverse -preset fast -c:v libx264 -c:a aac -b:a 128k "{OUTPUTFILE}_{SCRIPTKEY}.mp4"', + + break6: "--------Merge Clips-------------", + mergedCropVideo: + "ffmpeg -f concat -safe 0 -i mergevideolist.txt -c copy {SCRIPTKEY}.mp4", + mergedCropVideo_no_Audio: 'ffmpeg -i "mergedCropVideo.mp4" -an {SCRIPTKEY}.mp4', + trimAudioFromVideo: + 'ffmpeg -i "{INPUTFILE}" -ss {STARTTIME} -t {TRIMDURATION} -c copy "{SCRIPTKEY}.mp3"', + mergedCropAudios: + "ffmpeg -f concat -safe 0 -i mergevideolist.txt -c copy {SCRIPTKEY}.mp3", + mergedAudio_And_Video: + "ffmpeg -i mergedCropVideo_no_Audio.mp4 -i trimAudioFromVideo.mp3 -c:v copy -c:a aac -shortest {SCRIPTKEY}.mp4", + mergedAudio_And_Video_90deg: + 'ffmpeg -i "mergedAudio_And_Video.mp4" -vf "transpose=1" "{SCRIPTKEY}.mp4"', + mergedAudio_And_Video_270deg: + 'ffmpeg -i "mergedAudio_And_Video.mp4" -vf "transpose=1,transpose=1,transpose=1" "{SCRIPTKEY}.mp4"', + }; +} + From 4a8f7d5180222b1f796ddb65df108f50ecdd80f4 Mon Sep 17 00:00:00 2001 From: Biswasindhu Mandal Date: Sun, 5 Jul 2026 21:58:45 +0530 Subject: [PATCH 5/5] Fixed: ci/cd pipeline issue --- .github/workflows/ci-cd.yml | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml index 558dba2..e03b8ee 100644 --- a/.github/workflows/ci-cd.yml +++ b/.github/workflows/ci-cd.yml @@ -2,9 +2,9 @@ name: CI/CD Pipeline on: push: - branches: [ main, master, develop ] + branches: [ main, master, develop, monolithic_to_moduler ] pull_request: - branches: [ main, master, develop ] + branches: [ main, master, develop, monolithic_to_moduler ] workflow_dispatch: permissions: @@ -41,9 +41,7 @@ jobs: ls -la dist/ test -f dist/index.html test -f dist/style/media.min.css - test -f dist/script/media.min.js - test -f dist/favicon.ico - test -f dist/data/sample.mp4 + test -f dist/index.min.js echo "✅ Build validation passed" - name: Setup GitHub Pages