mirror of
https://github.com/Zaarrg/stremio-community-v5.git
synced 2026-05-11 12:40:37 +00:00
animejanai support
- Adjusted mpv config path to protable_config to support animejanai - Adjusted readme to the new path - Fixed installer not removing webengine cached data - Added build scripts for animejanai and anime4k - Now Anime4k is included by default in stremio - For Animejanai it must be provided as release after making the custom build using the build script
This commit is contained in:
parent
63fc8f21cb
commit
8296fe342d
9 changed files with 584 additions and 466 deletions
26
README.md
26
README.md
|
|
@ -61,10 +61,10 @@ Enhance your Stremio experience by customizing the MPV player settings. Below ar
|
|||
|
||||
- 📁 **`mpv.conf` Location**
|
||||
- The ``mpv.conf`` file can be found in the following location:
|
||||
- **Installation Path:** ``%localAppData%\Programs\LNV\Stremio-5\mpv.conf``
|
||||
- **Shaders Folder:** Located within the installation directory ``..\Stremio-5\shaders``.
|
||||
- **Installation Path:** ``%localAppData%\Programs\LNV\Stremio-5\portable_config\mpv.conf``
|
||||
- **Shaders Folder:** Located within the installation directory ``..\Stremio-5\portable_config\shaders``.
|
||||
|
||||
> **⏳ Note:** Any other configuration files can be just dropped into ``%localAppData%\Programs\LNV\Stremio-5\`` as this is the mpv ``config-dir`` like ``input.conf``
|
||||
> **⏳ Note:** Any other configuration files can be just dropped into ``%localAppData%\Programs\LNV\Stremio-5\portable_config`` as this is the mpv ``config-dir`` like ``input.conf``
|
||||
|
||||
- **🎹 Usage example in `input.conf` using Anime4k:**
|
||||
```shell
|
||||
|
|
@ -80,6 +80,26 @@ Enhance your Stremio experience by customizing the MPV player settings. Below ar
|
|||
```
|
||||
> **⏳ Note:** Some keys might not work as key presses are converted from js event.codes to literal values for mpv
|
||||
|
||||
## 🔍 **Mpv Upscalers**
|
||||
|
||||
- 🎥 **Anime4k**
|
||||
- ✅ Included by default.
|
||||
- 🔢 Use `CTRL+1` - `CTRL+6` to enable shaders.
|
||||
- ❌ Use `CTRL+0` to disable.
|
||||
|
||||
- 🎨 **AnimeJaNai**
|
||||
- ❌ Not included by default.
|
||||
- 📥 Download from the **Stremio-Desktop-v5** [release tab](https://github.com/Zaarrg/stremio-desktop-v5) the adjusted version for Stremio.
|
||||
- 🛠️ **Changes made:**
|
||||
- Removed `mpvnet.exe` as Stremio is used as the player.
|
||||
- Adjusted `mpv.conf` to work with Stremio.
|
||||
- Adjusted `input.conf` to work with Stremio.
|
||||
|
||||
- 🚀 **Nvidia RTX and Intel VSR Scaling**
|
||||
- 🔜 Coming soon!
|
||||
|
||||
|
||||
|
||||
## 📚 **Guide / Docs**
|
||||
If you want to build this app yourself, check the “docs” folder in this repository for setup instructions and additional information.
|
||||
|
||||
|
|
|
|||
197
build/build_anime4k.js
Normal file
197
build/build_anime4k.js
Normal file
|
|
@ -0,0 +1,197 @@
|
|||
#!/usr/bin/env node
|
||||
|
||||
/**
|
||||
* build_anime4k.js
|
||||
*
|
||||
* This script performs the following: (Needed for deploy_windows to include Anime4k in installer)
|
||||
* 1. Determines the latest Anime4K version from bloc97/Anime4K releases.
|
||||
* 2. Downloads the corresponding GLSL_Windows_High-end.zip from Tama47/Anime4K.
|
||||
* 3. Auto-detects 7z.exe on the system.
|
||||
* 4. Saves the downloaded zip as anime4k-High-end.zip in utils/mpv.
|
||||
* 5. Extracts the zip into the anime4k folder.
|
||||
* 6. Cleans up temporary files.
|
||||
*
|
||||
* Usage:
|
||||
* node build_anime4k.js
|
||||
*/
|
||||
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const https = require('https');
|
||||
const { execSync } = require('child_process');
|
||||
const os = require('os');
|
||||
|
||||
// Configuration
|
||||
const BLOC97_API_URL = 'https://api.github.com/repos/bloc97/Anime4K/releases/latest';
|
||||
const TEMP_DIR = path.join(os.tmpdir(), 'anime4k_build_temp');
|
||||
const OUTPUT_DIR = path.resolve(__dirname, '..', 'utils', 'mpv');
|
||||
const OUTPUT_ZIP_NAME = 'anime4k-High-end.zip';
|
||||
const EXTRACTION_DIR = path.join(OUTPUT_DIR, 'anime4k');
|
||||
|
||||
// Common 7z.exe installation paths on Windows
|
||||
const COMMON_7Z_PATHS = [
|
||||
path.join(process.env.PROGRAMFILES || 'C:\\Program Files', '7-Zip', '7z.exe'),
|
||||
path.join(process.env['PROGRAMFILES(X86)'] || 'C:\\Program Files (x86)', '7-Zip', '7z.exe'),
|
||||
path.join(process.env.LOCALAPPDATA || path.join(os.homedir(), 'AppData', 'Local'), '7-Zip', '7z.exe')
|
||||
];
|
||||
|
||||
// Maximum number of redirects to follow
|
||||
const MAX_REDIRECTS = 5;
|
||||
|
||||
// Helper Functions
|
||||
|
||||
function httpsGet(url, headers = {}, redirectCount = 0) {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (redirectCount > MAX_REDIRECTS) return reject(new Error('Too many redirects'));
|
||||
|
||||
const options = {
|
||||
headers: {
|
||||
'User-Agent': 'Node.js Script',
|
||||
...headers
|
||||
}
|
||||
};
|
||||
https.get(url, options, (res) => {
|
||||
if (res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {
|
||||
return resolve(httpsGet(res.headers.location, headers, redirectCount + 1));
|
||||
}
|
||||
if (res.statusCode !== 200) {
|
||||
res.resume();
|
||||
return reject(new Error(`Request Failed. Status Code: ${res.statusCode}`));
|
||||
}
|
||||
let data = '';
|
||||
res.setEncoding('utf8');
|
||||
res.on('data', chunk => data += chunk);
|
||||
res.on('end', () => resolve(data));
|
||||
}).on('error', e => reject(e));
|
||||
});
|
||||
}
|
||||
|
||||
function downloadFile(url, dest, headers = {}, redirectCount = 0) {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (redirectCount > MAX_REDIRECTS) return reject(new Error('Too many redirects'));
|
||||
|
||||
const options = {
|
||||
headers: {
|
||||
'User-Agent': 'Node.js Script',
|
||||
...headers
|
||||
}
|
||||
};
|
||||
|
||||
https.get(url, options, (res) => {
|
||||
if (res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {
|
||||
console.log(`Redirecting to ${res.headers.location}`);
|
||||
return resolve(downloadFile(res.headers.location, dest, headers, redirectCount + 1));
|
||||
}
|
||||
if (res.statusCode !== 200) {
|
||||
res.resume();
|
||||
return reject(new Error(`Failed to get '${url}' (${res.statusCode})`));
|
||||
}
|
||||
|
||||
const totalSize = parseInt(res.headers['content-length'], 10);
|
||||
let downloadedSize = 0;
|
||||
const file = fs.createWriteStream(dest);
|
||||
res.pipe(file);
|
||||
|
||||
res.on('data', chunk => {
|
||||
downloadedSize += chunk.length;
|
||||
if (totalSize) {
|
||||
const percent = ((downloadedSize / totalSize) * 100).toFixed(2);
|
||||
process.stdout.write(`Downloading... ${percent}%\r`);
|
||||
} else {
|
||||
process.stdout.write(`Downloading... ${downloadedSize} bytes\r`);
|
||||
}
|
||||
});
|
||||
|
||||
file.on('finish', () => {
|
||||
file.close(() => {
|
||||
process.stdout.write('\n');
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
|
||||
file.on('error', err => {
|
||||
fs.unlink(dest, () => reject(err));
|
||||
});
|
||||
}).on('error', err => reject(err));
|
||||
});
|
||||
}
|
||||
|
||||
function execCommand(command, cwd = process.cwd()) {
|
||||
try {
|
||||
execSync(command, { stdio: 'inherit', cwd });
|
||||
} catch (error) {
|
||||
throw new Error(`Command failed: ${command}\n${error.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
function commandExists(command) {
|
||||
try {
|
||||
execSync(`where ${command}`, { stdio: 'ignore' });
|
||||
return true;
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function find7zExecutable() {
|
||||
if (commandExists('7z')) {
|
||||
console.log('Found 7z.exe in PATH.');
|
||||
return '7z';
|
||||
}
|
||||
for (const potentialPath of COMMON_7Z_PATHS) {
|
||||
if (fs.existsSync(potentialPath)) {
|
||||
console.log(`Found 7z.exe at: ${potentialPath}`);
|
||||
return `"${potentialPath}"`;
|
||||
}
|
||||
}
|
||||
throw new Error('7z.exe not found. Please install 7-Zip.');
|
||||
}
|
||||
|
||||
// Main Build Function
|
||||
(async function buildAnime4K() {
|
||||
try {
|
||||
console.log('=== Build Anime4K Script Started ===');
|
||||
|
||||
const sevenZipPath = find7zExecutable();
|
||||
|
||||
if (fs.existsSync(TEMP_DIR)) fs.rmSync(TEMP_DIR, { recursive: true, force: true });
|
||||
fs.mkdirSync(TEMP_DIR, { recursive: true });
|
||||
console.log(`Created temporary directory at ${TEMP_DIR}`);
|
||||
|
||||
console.log('Fetching latest Anime4K version information...');
|
||||
const releaseData = await httpsGet(BLOC97_API_URL);
|
||||
const releaseJson = JSON.parse(releaseData);
|
||||
const version = releaseJson.tag_name;
|
||||
console.log(`Latest version: ${version}`);
|
||||
|
||||
const downloadUrl = `https://github.com/Tama47/Anime4K/releases/download/${version}/GLSL_Windows_High-end.zip`;
|
||||
const downloadedFilePath = path.join(TEMP_DIR, 'GLSL_Windows_High-end.zip');
|
||||
|
||||
console.log(`Downloading GLSL_Windows_High-end.zip for version ${version}...`);
|
||||
await downloadFile(downloadUrl, downloadedFilePath);
|
||||
console.log(`Downloaded to ${downloadedFilePath}`);
|
||||
|
||||
// Ensure output directory exists
|
||||
fs.mkdirSync(OUTPUT_DIR, { recursive: true });
|
||||
|
||||
const outputZipPath = path.join(OUTPUT_DIR, OUTPUT_ZIP_NAME);
|
||||
fs.copyFileSync(downloadedFilePath, outputZipPath);
|
||||
console.log(`Saved zip as ${outputZipPath}`);
|
||||
|
||||
// Extract the zip to the anime4k folder
|
||||
fs.mkdirSync(EXTRACTION_DIR, { recursive: true });
|
||||
console.log(`Extracting ${outputZipPath} to ${EXTRACTION_DIR}...`);
|
||||
execCommand(`${sevenZipPath} x "${outputZipPath}" -o"${EXTRACTION_DIR}" -y`);
|
||||
console.log('Extraction complete.');
|
||||
|
||||
// Cleanup
|
||||
console.log(`Cleaning up temporary files at ${TEMP_DIR}...`);
|
||||
fs.rmSync(TEMP_DIR, { recursive: true, force: true });
|
||||
console.log('Cleanup complete.');
|
||||
|
||||
console.log('=== Build Anime4K Script Completed Successfully ===');
|
||||
} catch (error) {
|
||||
console.error('Error during build:', error.message);
|
||||
process.exit(1);
|
||||
}
|
||||
})();
|
||||
353
build/build_animejanai.js
Normal file
353
build/build_animejanai.js
Normal file
|
|
@ -0,0 +1,353 @@
|
|||
#!/usr/bin/env node
|
||||
|
||||
/**
|
||||
* build_animejanai.js
|
||||
*
|
||||
* This script performs the following:
|
||||
* 1. Downloads the latest 'full-package' .7z release from Animejanai GitHub.
|
||||
* 2. Extracts the archive.
|
||||
* 3. Deletes specified files and folders.
|
||||
* 4. Modifies configuration files as per stremio requirements.
|
||||
* 5. Repackages the modified files into a new .7z archive with maximum compression.
|
||||
* 6. Places the final archive in utils/mpv.
|
||||
* 7. Cleans up temporary files.
|
||||
*
|
||||
* Usage:
|
||||
* node build_animejanai.js
|
||||
*/
|
||||
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const https = require('https');
|
||||
const { execSync } = require('child_process');
|
||||
const os = require('os');
|
||||
|
||||
// Configuration
|
||||
const GITHUB_API_URL = 'https://api.github.com/repos/the-database/mpv-upscale-2x_animejanai/releases/latest';
|
||||
const TEMP_DIR = path.join(os.tmpdir(), 'animejanai_build_temp');
|
||||
const OUTPUT_DIR = path.resolve(__dirname, '..', 'utils', 'mpv');
|
||||
const OUTPUT_FILENAME_TEMPLATE = 'stremio-animejanai-{version}.7z';
|
||||
|
||||
// Files and directories to delete
|
||||
const FILES_TO_DELETE = [
|
||||
'libmpv-2.dll',
|
||||
'libmpvnet.pdb',
|
||||
'MediaInfo.dll',
|
||||
'mpvnet.com',
|
||||
'mpvnet.dll.config',
|
||||
'mpvnet.exe',
|
||||
'mpvnet.pdb',
|
||||
'NGettext.Wpf.pdb'
|
||||
];
|
||||
|
||||
const FOLDERS_TO_DELETE = [
|
||||
'Locale'
|
||||
];
|
||||
|
||||
// Configuration for input.conf replacement
|
||||
const NEW_INPUT_CONF_CONTENT = `
|
||||
Ctrl+E show-text "Launching AnimeJaNaiConfEditor..."; run "~~\\..\\animejanai\\AnimeJaNaiConfEditor.exe" #menu: AnimeJaNai > Launch AnimeJaNaiConfEditor
|
||||
Ctrl+J script-binding "show_animejanai_stats" #menu: AnimeJaNai > Toggle AnimeJaNai Stats
|
||||
|
||||
) show-text "2x_AnimeJaNai_V3 Off"; apply-profile upscale-off;
|
||||
Ctrl+0 show-text "2x_AnimeJaNai_V3 Off"; apply-profile upscale-off;
|
||||
SHIFT+1 show-text "2x_AnimeJaNai_V3 Quality"; apply-profile upscale-on-quality;
|
||||
SHIFT+2 show-text "2x_AnimeJaNai_V3 Balanced"; apply-profile upscale-on-balanced;
|
||||
SHIFT+3 show-text "2x_AnimeJaNai_V3 Performance"; apply-profile upscale-on-performance;
|
||||
Ctrl+1 show-text "2x_AnimeJaNai_V3 Custom Profile 1"; apply-profile upscale-on-1;
|
||||
Ctrl+2 show-text "2x_AnimeJaNai_V3 Custom Profile 2"; apply-profile upscale-on-2;
|
||||
Ctrl+3 show-text "2x_AnimeJaNai_V3 Custom Profile 3"; apply-profile upscale-on-3;
|
||||
Ctrl+4 show-text "2x_AnimeJaNai_V3 Custom Profile 4"; apply-profile upscale-on-4;
|
||||
Ctrl+5 show-text "2x_AnimeJaNai_V3 Custom Profile 5"; apply-profile upscale-on-5;
|
||||
Ctrl+6 show-text "2x_AnimeJaNai_V3 Custom Profile 6"; apply-profile upscale-on-6;
|
||||
Ctrl+7 show-text "2x_AnimeJaNai_V3 Custom Profile 7"; apply-profile upscale-on-7;
|
||||
Ctrl+8 show-text "2x_AnimeJaNai_V3 Custom Profile 8"; apply-profile upscale-on-8;
|
||||
Ctrl+9 show-text "2x_AnimeJaNai_V3 Custom Profile 9"; apply-profile upscale-on-9;
|
||||
`;
|
||||
|
||||
// Lines to delete from mpv.conf
|
||||
const LINES_TO_DELETE_IN_MPV_CONF = [
|
||||
'save-position-on-quit=yes',
|
||||
'watch-later-options=start',
|
||||
'reset-on-next-file=pause'
|
||||
];
|
||||
|
||||
// Common 7z.exe installation paths on Windows
|
||||
const COMMON_7Z_PATHS = [
|
||||
path.join(process.env.PROGRAMFILES || 'C:\\Program Files', '7-Zip', '7z.exe'),
|
||||
path.join(process.env['PROGRAMFILES(X86)'] || 'C:\\Program Files (x86)', '7-Zip', '7z.exe'),
|
||||
path.join(process.env.LOCALAPPDATA || path.join(os.homedir(), 'AppData', 'Local'), '7-Zip', '7z.exe')
|
||||
];
|
||||
|
||||
// Maximum number of redirects to follow
|
||||
const MAX_REDIRECTS = 5;
|
||||
|
||||
// Function to make HTTPS GET requests with GitHub API headers
|
||||
function httpsGet(url, headers = {}, redirectCount = 0) {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (redirectCount > MAX_REDIRECTS) {
|
||||
return reject(new Error('Too many redirects'));
|
||||
}
|
||||
|
||||
const options = {
|
||||
headers: {
|
||||
'User-Agent': 'Node.js Script',
|
||||
...headers
|
||||
}
|
||||
};
|
||||
https.get(url, options, (res) => {
|
||||
if (res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {
|
||||
// Handle redirects
|
||||
resolve(httpsGet(res.headers.location, headers, redirectCount + 1));
|
||||
return;
|
||||
}
|
||||
if (res.statusCode !== 200) {
|
||||
reject(new Error(`Request Failed. Status Code: ${res.statusCode}`));
|
||||
res.resume(); // Consume response data to free up memory
|
||||
return;
|
||||
}
|
||||
let data = '';
|
||||
res.setEncoding('utf8');
|
||||
res.on('data', (chunk) => data += chunk);
|
||||
res.on('end', () => resolve(data));
|
||||
}).on('error', (e) => reject(e));
|
||||
});
|
||||
}
|
||||
|
||||
// Function to download a file from a URL, handling redirects and showing progress
|
||||
function downloadFile(url, dest, headers = {}, redirectCount = 0) {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (redirectCount > MAX_REDIRECTS) {
|
||||
return reject(new Error('Too many redirects'));
|
||||
}
|
||||
|
||||
const options = {
|
||||
headers: {
|
||||
'User-Agent': 'Node.js Script',
|
||||
...headers
|
||||
}
|
||||
};
|
||||
|
||||
https.get(url, options, (res) => {
|
||||
if (res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {
|
||||
// Handle redirects
|
||||
console.log(`Redirecting to ${res.headers.location}`);
|
||||
downloadFile(res.headers.location, dest, headers, redirectCount + 1).then(resolve).catch(reject);
|
||||
return;
|
||||
}
|
||||
|
||||
if (res.statusCode !== 200) {
|
||||
reject(new Error(`Failed to get '${url}' (${res.statusCode})`));
|
||||
res.resume();
|
||||
return;
|
||||
}
|
||||
|
||||
const totalSize = parseInt(res.headers['content-length'], 10);
|
||||
let downloadedSize = 0;
|
||||
|
||||
const file = fs.createWriteStream(dest);
|
||||
res.pipe(file);
|
||||
|
||||
res.on('data', (chunk) => {
|
||||
downloadedSize += chunk.length;
|
||||
if (totalSize) {
|
||||
const percent = ((downloadedSize / totalSize) * 100).toFixed(2);
|
||||
process.stdout.write(`Downloading... ${percent}%\r`);
|
||||
} else {
|
||||
process.stdout.write(`Downloading... ${downloadedSize} bytes\r`);
|
||||
}
|
||||
});
|
||||
|
||||
file.on('finish', () => {
|
||||
file.close(() => {
|
||||
process.stdout.write('\n');
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
|
||||
file.on('error', (err) => {
|
||||
fs.unlink(dest, () => reject(err));
|
||||
});
|
||||
}).on('error', (err) => {
|
||||
reject(err);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Function to execute a shell command synchronously
|
||||
function execCommand(command, cwd = process.cwd()) {
|
||||
try {
|
||||
execSync(command, { stdio: 'inherit', cwd });
|
||||
} catch (error) {
|
||||
throw new Error(`Command failed: ${command}\n${error.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
// Function to check if a command exists
|
||||
function commandExists(command) {
|
||||
try {
|
||||
execSync(`where ${command}`, { stdio: 'ignore' });
|
||||
return true;
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Function to find 7z.exe in common installation paths
|
||||
function find7zExecutable() {
|
||||
// First, check if 7z is in PATH
|
||||
if (commandExists('7z')) {
|
||||
console.log('Found 7z.exe in PATH.');
|
||||
return '7z';
|
||||
}
|
||||
|
||||
// Search in common installation directories
|
||||
for (const potentialPath of COMMON_7Z_PATHS) {
|
||||
if (fs.existsSync(potentialPath)) {
|
||||
console.log(`Found 7z.exe at: ${potentialPath}`);
|
||||
return `"${potentialPath}"`; // Quote the path in case it contains spaces
|
||||
}
|
||||
}
|
||||
|
||||
// If not found, throw an error
|
||||
throw new Error('7z.exe not found. Please install 7-Zip and ensure 7z.exe is in your PATH or installed in a common directory.');
|
||||
}
|
||||
|
||||
// Main Build Function
|
||||
(async function buildAnimeJanai() {
|
||||
try {
|
||||
console.log('=== Build AnimeJaNai Script Started ===');
|
||||
|
||||
// Locate 7z.exe
|
||||
const sevenZipPath = find7zExecutable();
|
||||
|
||||
// Create temporary directory
|
||||
if (fs.existsSync(TEMP_DIR)) {
|
||||
fs.rmSync(TEMP_DIR, { recursive: true, force: true });
|
||||
}
|
||||
fs.mkdirSync(TEMP_DIR, { recursive: true });
|
||||
console.log(`Created temporary directory at ${TEMP_DIR}`);
|
||||
|
||||
// Step 1: Fetch latest release info from GitHub
|
||||
console.log('Fetching latest release information from GitHub...');
|
||||
const releaseData = await httpsGet(GITHUB_API_URL);
|
||||
const releaseJson = JSON.parse(releaseData);
|
||||
const version = releaseJson.tag_name || 'latest';
|
||||
console.log(`Latest version: ${version}`);
|
||||
|
||||
// Step 2: Find the 'full-package' .7z asset
|
||||
const assets = releaseJson.assets;
|
||||
const fullPackageAsset = assets.find(asset => asset.name.includes('full-package') && asset.name.endsWith('.7z'));
|
||||
|
||||
if (!fullPackageAsset) {
|
||||
throw new Error("No 'full-package' .7z asset found in the latest release.");
|
||||
}
|
||||
|
||||
const downloadUrl = fullPackageAsset.browser_download_url;
|
||||
const assetName = fullPackageAsset.name;
|
||||
const downloadedFilePath = path.join(TEMP_DIR, assetName);
|
||||
|
||||
console.log(`Downloading asset: ${assetName}`);
|
||||
await downloadFile(downloadUrl, downloadedFilePath);
|
||||
console.log(`Downloaded to ${downloadedFilePath}`);
|
||||
|
||||
// Step 3: Extract the .7z archive
|
||||
const extractDir = path.join(TEMP_DIR, 'extracted');
|
||||
fs.mkdirSync(extractDir, { recursive: true });
|
||||
console.log(`Extracting ${downloadedFilePath} to ${extractDir}...`);
|
||||
execCommand(`${sevenZipPath} x "${downloadedFilePath}" -o"${extractDir}" -y`, TEMP_DIR);
|
||||
console.log('Extraction complete.');
|
||||
|
||||
// Step 4: Identify the root directory inside the extracted folder
|
||||
const extractedItems = fs.readdirSync(extractDir);
|
||||
let rootDir = extractDir;
|
||||
|
||||
if (extractedItems.length === 1 && fs.lstatSync(path.join(extractDir, extractedItems[0])).isDirectory()) {
|
||||
rootDir = path.join(extractDir, extractedItems[0]);
|
||||
console.log(`Detected root directory: ${rootDir}`);
|
||||
} else {
|
||||
console.log('No single root directory detected. Proceeding with extracted contents.');
|
||||
}
|
||||
|
||||
// Step 5: Delete specified files
|
||||
console.log('Deleting specified files...');
|
||||
FILES_TO_DELETE.forEach(file => {
|
||||
const filePath = path.join(rootDir, file);
|
||||
if (fs.existsSync(filePath)) {
|
||||
fs.unlinkSync(filePath);
|
||||
console.log(`Deleted file: ${filePath}`);
|
||||
} else {
|
||||
console.log(`File not found (skipped): ${filePath}`);
|
||||
}
|
||||
});
|
||||
|
||||
// Step 6: Delete specified folders
|
||||
console.log('Deleting specified folders...');
|
||||
FOLDERS_TO_DELETE.forEach(folder => {
|
||||
const folderPath = path.join(rootDir, folder);
|
||||
if (fs.existsSync(folderPath)) {
|
||||
fs.rmSync(folderPath, { recursive: true, force: true });
|
||||
console.log(`Deleted folder: ${folderPath}`);
|
||||
} else {
|
||||
console.log(`Folder not found (skipped): ${folderPath}`);
|
||||
}
|
||||
});
|
||||
|
||||
// Step 7: Modify portable_config/input.conf
|
||||
const portableConfigDir = path.join(rootDir, 'portable_config');
|
||||
const inputConfPath = path.join(portableConfigDir, 'input.conf');
|
||||
|
||||
if (fs.existsSync(inputConfPath)) {
|
||||
fs.writeFileSync(inputConfPath, NEW_INPUT_CONF_CONTENT, 'utf8');
|
||||
console.log(`Modified input.conf at ${inputConfPath}`);
|
||||
} else {
|
||||
console.warn(`input.conf not found at ${inputConfPath}. Skipping modification.`);
|
||||
}
|
||||
|
||||
// Step 8: Modify mpv.conf
|
||||
const mpvConfPath = path.join(portableConfigDir, 'mpv.conf'); // Corrected path
|
||||
|
||||
if (fs.existsSync(mpvConfPath)) {
|
||||
let mpvConfContent = fs.readFileSync(mpvConfPath, 'utf8');
|
||||
|
||||
// Replace vo={something} with vo=libmpv
|
||||
mpvConfContent = mpvConfContent.replace(/^vo=.*/m, 'vo=libmpv');
|
||||
|
||||
// Remove specified lines
|
||||
LINES_TO_DELETE_IN_MPV_CONF.forEach(line => {
|
||||
const regex = new RegExp(`^${line}$`, 'm');
|
||||
mpvConfContent = mpvConfContent.replace(regex, '');
|
||||
});
|
||||
|
||||
// Write the modified content back
|
||||
fs.writeFileSync(mpvConfPath, mpvConfContent, 'utf8');
|
||||
console.log(`Modified mpv.conf at ${mpvConfPath}`);
|
||||
} else {
|
||||
console.warn(`mpv.conf not found at ${mpvConfPath}. Skipping modification.`);
|
||||
}
|
||||
|
||||
// Step 9: Repack the modified files into a new .7z archive
|
||||
const outputVersion = version.startsWith('v') ? version.slice(1) : version;
|
||||
const outputFilename = OUTPUT_FILENAME_TEMPLATE.replace('{version}', outputVersion);
|
||||
const outputFilePath = path.join(OUTPUT_DIR, outputFilename);
|
||||
|
||||
// Ensure output directory exists
|
||||
fs.mkdirSync(OUTPUT_DIR, { recursive: true });
|
||||
|
||||
console.log(`Packing modified files into ${outputFilePath} with maximum compression...`);
|
||||
|
||||
// Change working directory to rootDir to ensure files are added directly
|
||||
execCommand(`${sevenZipPath} a -t7z "${outputFilePath}" * -mx=9`, rootDir);
|
||||
console.log(`Packaged archive created at ${outputFilePath}`);
|
||||
|
||||
// Step 10: Cleanup temporary directory
|
||||
console.log(`Cleaning up temporary files at ${TEMP_DIR}...`);
|
||||
fs.rmSync(TEMP_DIR, { recursive: true, force: true });
|
||||
console.log('Cleanup complete.');
|
||||
|
||||
console.log('=== Build AnimeJaNai Script Completed Successfully ===');
|
||||
} catch (error) {
|
||||
console.error('Error during build:', error.message);
|
||||
process.exit(1);
|
||||
}
|
||||
})();
|
||||
|
|
@ -29,7 +29,7 @@ const NODE_EXE = path.join(SOURCE_DIR, 'utils', 'windows', 'node.exe');
|
|||
const DS_FOLDER = path.join(SOURCE_DIR, 'utils', 'windows', 'DS');
|
||||
const STREMIO_RUNTIME_EXE = path.join(SOURCE_DIR, 'utils', 'windows', 'stremio-runtime.exe');
|
||||
const FFMPEG_FOLDER = path.join(SOURCE_DIR, 'utils', 'windows', 'ffmpeg');
|
||||
const MPV_FOLDER = path.join(SOURCE_DIR, 'utils', 'mpv');
|
||||
const MPV_FOLDER = path.join(SOURCE_DIR, 'utils', 'mpv', 'anime4k');
|
||||
|
||||
// Default Paths
|
||||
const DEFAULT_OPENSSL_BIN = 'C:\\Program Files\\OpenSSL-Win64\\bin';
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
#include <QObject>
|
||||
#include <QJsonObject>
|
||||
#include <QDir>
|
||||
|
||||
#include <QtGlobal>
|
||||
#include <QOpenGLContext>
|
||||
|
|
@ -142,8 +143,14 @@ void MpvObject::initialize_mpv() {
|
|||
// terminal=yes brings us all the terminal logs; on windows it's much better with winpty (https://github.com/mpv-player/mpv/blob/master/DOCS/compile-windows.md)
|
||||
mpv_set_option_string(mpv, "terminal", "yes");
|
||||
mpv_set_option_string(mpv, "msg-level", "all=v");
|
||||
// Set mpv.conf path to appDirPath. Can be used by users to apply mpv profiles using Conditional auto profiles with profile-cond property
|
||||
QString configPath = QCoreApplication::applicationDirPath();
|
||||
// Set mpv.conf path to appDirPath/portable_config. Can be used by users to apply mpv profiles using Conditional auto profiles with profile-cond property
|
||||
QString appDirPath = QCoreApplication::applicationDirPath();
|
||||
QString configPath = appDirPath + QDir::separator() + "portable_config";
|
||||
bool success = QDir().mkpath(configPath);
|
||||
if (!success) {
|
||||
qWarning("Failed to create portable_config directory.");
|
||||
}
|
||||
// Set the "config-dir" option for mpv
|
||||
mpv_set_option_string(mpv, "config-dir", configPath.toUtf8().constData());
|
||||
mpv_set_option_string(mpv, "config", "yes");
|
||||
|
||||
|
|
|
|||
|
|
@ -1,46 +0,0 @@
|
|||
[stremio-default]
|
||||
# Default Stremio Profile uncomment below line to customize / overwrite defaullt settings
|
||||
# profile-cond=width >= 1
|
||||
profile-desc=Stremio Profile
|
||||
# Shorten probe size and analyzeduration to reduce initial demux overhead. (Faster playback start)
|
||||
demuxer-lavf-probesize=524288
|
||||
demuxer-lavf-analyzeduration=0.5f
|
||||
# Increase max bytes/packets to allow for 60s cache-secs. Default 150mb/75mb
|
||||
demuxer-max-bytes=300000000
|
||||
demuxer-max-packets=150000000
|
||||
# Buffer / Cache Settings
|
||||
cache=yes
|
||||
cache-pause=no
|
||||
cache-secs=60 # Limited by demuxer-max-bytes
|
||||
# More threads for decoding
|
||||
vd-lavc-threads=0
|
||||
ad-lavc-threads=0
|
||||
|
||||
[stremio-anime]
|
||||
# Example profile following this guide https://kokomins.wordpress.com/2019/10/14/mpv-config-guide/#advanced-video-scaling-config
|
||||
profile-desc=Anime Profile
|
||||
# See mpv docs for conditional auto profiles https://mpv.io/manual/stable/#conditional-auto-profiles .To enable uncomment the line below:
|
||||
# profile-cond=filename ~= "(?i)anime|fansub|horriblesubs|ttga|lulu|ozr|thighs|mtbb|ember|lostyears|breeze|yuisubs|almighty|bigfoot|neohevc|cleo|judas|anime time|golumpa|legion|nokou|usagi|av1ary|yameii|metaljerk|gbr|sam|scy|salieri|anipakku|cbm|db|valenciano|suki desu|hakata ramen|trix|jacobswaggedup|sokudo"
|
||||
profile=gpu-hq
|
||||
# Deband filter. Always turn on for anime.
|
||||
deband=yes # Default values are 1:64:16:48
|
||||
|
||||
# Deband parameters configuration.
|
||||
deband-iterations=2 # Range 1-16.
|
||||
deband-threshold=35 # Range 0-4096.
|
||||
deband-range=20 # Range 1-64.
|
||||
deband-grain=5 # Range 0-4096.
|
||||
|
||||
dither-depth=auto
|
||||
|
||||
volume=100
|
||||
volume-max=100
|
||||
|
||||
demuxer-mkv-subtitle-preroll=yes
|
||||
sub-auto=fuzzy
|
||||
|
||||
# Source https://gist.github.com/igv/2364ffa6e81540f29cb7ab4c9bc05b6b
|
||||
glsl-shader="~~/shaders/SSimSuperResMitchell.glsl"
|
||||
scale=ewa_lanczossharp
|
||||
# Source https://github.com/awused/dotfiles/blob/master/mpv/.config/mpv/shaders/KrigBilateral.glsl
|
||||
glsl-shader="~~/shaders/KrigBilateral.glsl" # High quality chroma upscaler.
|
||||
|
|
@ -1,211 +0,0 @@
|
|||
// KrigBilateral by Shiandow
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 3.0 of the License, or (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library.
|
||||
|
||||
//!HOOK CHROMA
|
||||
//!BIND HOOKED
|
||||
//!BIND LUMA
|
||||
//!SAVE LOWRES_Y
|
||||
//!WIDTH LUMA.w
|
||||
//!WHEN CHROMA.w LUMA.w <
|
||||
//!DESC KrigBilateral Downscaling Y pass 1
|
||||
|
||||
#define lumaOffset (-vec2(0.0, 0.0)*LUMA_size*CHROMA_pt)
|
||||
|
||||
#define axis 1
|
||||
|
||||
#define Kernel(x) (1. - abs(x))
|
||||
|
||||
vec4 hook() {
|
||||
// Calculate bounds
|
||||
float low = ceil((LUMA_pos - 0.5*CHROMA_pt) * LUMA_size - lumaOffset - 0.5)[axis];
|
||||
float high = floor((LUMA_pos + 0.5*CHROMA_pt) * LUMA_size - lumaOffset - 0.5)[axis];
|
||||
|
||||
float W = 0.0;
|
||||
vec4 avg = vec4(0);
|
||||
vec2 pos = LUMA_pos;
|
||||
|
||||
for (float k = low; k <= high; k++) {
|
||||
pos[axis] = LUMA_pt[axis] * (k - lumaOffset[axis] + 0.5);
|
||||
float rel = (pos[axis] - LUMA_pos[axis])*CHROMA_size[axis];
|
||||
float w = Kernel(rel);
|
||||
|
||||
vec4 y = textureLod(LUMA_raw, pos, 0.0).xxxx * LUMA_mul;
|
||||
y.y *= y.y;
|
||||
avg += w * y;
|
||||
W += w;
|
||||
}
|
||||
avg /= W;
|
||||
avg.y = abs(avg.y - pow(avg.x, 2.0));
|
||||
return avg;
|
||||
}
|
||||
|
||||
//!HOOK CHROMA
|
||||
//!BIND HOOKED
|
||||
//!BIND LOWRES_Y
|
||||
//!SAVE LOWRES_Y
|
||||
//!WHEN CHROMA.w LUMA.w <
|
||||
//!DESC KrigBilateral Downscaling Y pass 2
|
||||
|
||||
#define lumaOffset (-vec2(0.0, 0.0)*LOWRES_Y_size*CHROMA_pt)
|
||||
|
||||
#define axis 0
|
||||
|
||||
#define Kernel(x) (1. - abs(x))
|
||||
|
||||
vec4 hook() {
|
||||
// Calculate bounds
|
||||
float low = ceil((LOWRES_Y_pos - 0.5*CHROMA_pt) * LOWRES_Y_size - lumaOffset - 0.5)[axis];
|
||||
float high = floor((LOWRES_Y_pos + 0.5*CHROMA_pt) * LOWRES_Y_size - lumaOffset - 0.5)[axis];
|
||||
|
||||
float W = 0.0;
|
||||
vec4 avg = vec4(0);
|
||||
vec2 pos = LOWRES_Y_pos;
|
||||
|
||||
for (float k = low; k <= high; k++) {
|
||||
pos[axis] = LOWRES_Y_pt[axis] * (k - lumaOffset[axis] + 0.5);
|
||||
float rel = (pos[axis] - LOWRES_Y_pos[axis])*CHROMA_size[axis];
|
||||
float w = Kernel(rel);
|
||||
|
||||
vec4 y = textureLod(LOWRES_Y_raw, pos, 0.0).xxxx * LOWRES_Y_mul;
|
||||
y.y *= y.y;
|
||||
avg += w * y;
|
||||
W += w;
|
||||
}
|
||||
avg /= W;
|
||||
avg.y = abs(avg.y - pow(avg.x, 2.0)) + LOWRES_Y_texOff(0).y;
|
||||
return avg;
|
||||
}
|
||||
|
||||
//!HOOK CHROMA
|
||||
//!BIND HOOKED
|
||||
//!BIND LUMA
|
||||
//!BIND LOWRES_Y
|
||||
//!WIDTH LUMA.w
|
||||
//!HEIGHT LUMA.h
|
||||
//!WHEN CHROMA.w LUMA.w <
|
||||
//!OFFSET ALIGN
|
||||
//!DESC KrigBilateral Upscaling UV
|
||||
|
||||
// -- Convenience --
|
||||
#define sqr(x) dot(x,x)
|
||||
#define bitnoise 1.0/(2.0*255.0)
|
||||
#define noise 0.05//5.0*bitnoise
|
||||
#define chromaOffset vec2(0.0, 0.0)
|
||||
|
||||
// -- Window Size --
|
||||
#define taps 3
|
||||
#define even (float(taps) - 2.0 * floor(float(taps) / 2.0) == 0.0)
|
||||
#define minX int(1.0-ceil(float(taps)/2.0))
|
||||
#define maxX int(floor(float(taps)/2.0))
|
||||
|
||||
#define Kernel(x) (cos(acos(-1.0)*(x)/float(taps))) // Hann kernel
|
||||
|
||||
// -- Input processing --
|
||||
#define GetY(coord) LOWRES_Y_tex(LOWRES_Y_pt*(pos+coord+vec2(0.5))).xy
|
||||
#define GetUV(coord) CHROMA_tex(CHROMA_pt*(pos+coord+vec2(0.5))).xy
|
||||
|
||||
#define N (taps*taps - 1)
|
||||
|
||||
#define M(i,j) Mx[min(i,j)*N + max(i,j) - min(i,j)*(min(i,j)+1)/2]
|
||||
|
||||
#define C(i,j) (inversesqrt(1.0 + (X[i].y + X[j].y)/localVar) * exp(-0.5*(sqr(X[i].x - X[j].x)/(localVar + X[i].y + X[j].y) + sqr((coords[i] - coords[j])/radius))) + (X[i].x - y) * (X[j].x - y) / localVar)
|
||||
#define c(i) (inversesqrt(1.0 + X[i].y/localVar) * exp(-0.5*(sqr(X[i].x - y)/(localVar + X[i].y) + sqr((coords[i] - offset)/radius))))
|
||||
|
||||
vec4 hook() {
|
||||
vec2 pos = CHROMA_pos * HOOKED_size - chromaOffset - vec2(0.5);
|
||||
vec2 offset = pos - (even ? floor(pos) : round(pos));
|
||||
pos -= offset;
|
||||
|
||||
vec2 coords[N+1];
|
||||
vec4 X[N+1];
|
||||
float y = LUMA_texOff(0).x;
|
||||
vec4 total = vec4(0);
|
||||
|
||||
coords[0] = vec2(-1,-1); coords[1] = vec2(-1, 0); coords[2] = vec2(-1, 1);
|
||||
coords[3] = vec2( 0,-1); coords[4] = vec2( 0, 1); coords[5] = vec2( 1,-1);
|
||||
coords[6] = vec2( 1, 0); coords[7] = vec2( 1, 1); coords[8] = vec2( 0, 0);
|
||||
|
||||
for (int i=0; i<N+1; i++) {
|
||||
X[i] = vec4(GetY(coords[i]), GetUV(coords[i]));
|
||||
vec2 w = clamp(1.5 - abs(coords[i] - offset), 0.0, 1.0);
|
||||
total += w.x*w.y*vec4(X[i].x, pow(X[i].x, 2.0), X[i].y, 1.0);
|
||||
}
|
||||
total.xyz /= total.w;
|
||||
float localVar = sqr(noise) + abs(total.y - pow(total.x, 2.0)) + total.z;
|
||||
float radius = 1.0;
|
||||
|
||||
float Mx[N*(N+1)/2];
|
||||
float b[N];
|
||||
vec4 interp = X[N];
|
||||
|
||||
b[0] = c(0) - c(N) - C(0,N) + C(N,N); M(0, 0) = C(0,0) - C(0,N) - C(0,N) + C(N,N); M(0, 1) = C(0,1) - C(1,N) - C(0,N) + C(N,N); M(0, 2) = C(0,2) - C(2,N) - C(0,N) + C(N,N); M(0, 3) = C(0,3) - C(3,N) - C(0,N) + C(N,N); M(0, 4) = C(0,4) - C(4,N) - C(0,N) + C(N,N); M(0, 5) = C(0,5) - C(5,N) - C(0,N) + C(N,N); M(0, 6) = C(0,6) - C(6,N) - C(0,N) + C(N,N); M(0, 7) = C(0,7) - C(7,N) - C(0,N) + C(N,N);
|
||||
b[1] = c(1) - c(N) - C(1,N) + C(N,N); M(1, 1) = C(1,1) - C(1,N) - C(1,N) + C(N,N); M(1, 2) = C(1,2) - C(2,N) - C(1,N) + C(N,N); M(1, 3) = C(1,3) - C(3,N) - C(1,N) + C(N,N); M(1, 4) = C(1,4) - C(4,N) - C(1,N) + C(N,N); M(1, 5) = C(1,5) - C(5,N) - C(1,N) + C(N,N); M(1, 6) = C(1,6) - C(6,N) - C(1,N) + C(N,N); M(1, 7) = C(1,7) - C(7,N) - C(1,N) + C(N,N);
|
||||
b[2] = c(2) - c(N) - C(2,N) + C(N,N); M(2, 2) = C(2,2) - C(2,N) - C(2,N) + C(N,N); M(2, 3) = C(2,3) - C(3,N) - C(2,N) + C(N,N); M(2, 4) = C(2,4) - C(4,N) - C(2,N) + C(N,N); M(2, 5) = C(2,5) - C(5,N) - C(2,N) + C(N,N); M(2, 6) = C(2,6) - C(6,N) - C(2,N) + C(N,N); M(2, 7) = C(2,7) - C(7,N) - C(2,N) + C(N,N);
|
||||
b[3] = c(3) - c(N) - C(3,N) + C(N,N); M(3, 3) = C(3,3) - C(3,N) - C(3,N) + C(N,N); M(3, 4) = C(3,4) - C(4,N) - C(3,N) + C(N,N); M(3, 5) = C(3,5) - C(5,N) - C(3,N) + C(N,N); M(3, 6) = C(3,6) - C(6,N) - C(3,N) + C(N,N); M(3, 7) = C(3,7) - C(7,N) - C(3,N) + C(N,N);
|
||||
b[4] = c(4) - c(N) - C(4,N) + C(N,N); M(4, 4) = C(4,4) - C(4,N) - C(4,N) + C(N,N); M(4, 5) = C(4,5) - C(5,N) - C(4,N) + C(N,N); M(4, 6) = C(4,6) - C(6,N) - C(4,N) + C(N,N); M(4, 7) = C(4,7) - C(7,N) - C(4,N) + C(N,N);
|
||||
b[5] = c(5) - c(N) - C(5,N) + C(N,N); M(5, 5) = C(5,5) - C(5,N) - C(5,N) + C(N,N); M(5, 6) = C(5,6) - C(6,N) - C(5,N) + C(N,N); M(5, 7) = C(5,7) - C(7,N) - C(5,N) + C(N,N);
|
||||
b[6] = c(6) - c(N) - C(6,N) + C(N,N); M(6, 6) = C(6,6) - C(6,N) - C(6,N) + C(N,N); M(6, 7) = C(6,7) - C(7,N) - C(6,N) + C(N,N);
|
||||
b[7] = c(7) - c(N) - C(7,N) + C(N,N); M(7, 7) = C(7,7) - C(7,N) - C(7,N) + C(N,N);
|
||||
|
||||
b[1] -= b[0] * M(1, 0) / M(0, 0); M(1, 1) -= M(0, 1) * M(1, 0) / M(0, 0); M(1, 2) -= M(0, 2) * M(1, 0) / M(0, 0); M(1, 3) -= M(0, 3) * M(1, 0) / M(0, 0); M(1, 4) -= M(0, 4) * M(1, 0) / M(0, 0); M(1, 5) -= M(0, 5) * M(1, 0) / M(0, 0); M(1, 6) -= M(0, 6) * M(1, 0) / M(0, 0); M(1, 7) -= M(0, 7) * M(1, 0) / M(0, 0);
|
||||
b[2] -= b[0] * M(2, 0) / M(0, 0); M(2, 2) -= M(0, 2) * M(2, 0) / M(0, 0); M(2, 3) -= M(0, 3) * M(2, 0) / M(0, 0); M(2, 4) -= M(0, 4) * M(2, 0) / M(0, 0); M(2, 5) -= M(0, 5) * M(2, 0) / M(0, 0); M(2, 6) -= M(0, 6) * M(2, 0) / M(0, 0); M(2, 7) -= M(0, 7) * M(2, 0) / M(0, 0);
|
||||
b[3] -= b[0] * M(3, 0) / M(0, 0); M(3, 3) -= M(0, 3) * M(3, 0) / M(0, 0); M(3, 4) -= M(0, 4) * M(3, 0) / M(0, 0); M(3, 5) -= M(0, 5) * M(3, 0) / M(0, 0); M(3, 6) -= M(0, 6) * M(3, 0) / M(0, 0); M(3, 7) -= M(0, 7) * M(3, 0) / M(0, 0);
|
||||
b[4] -= b[0] * M(4, 0) / M(0, 0); M(4, 4) -= M(0, 4) * M(4, 0) / M(0, 0); M(4, 5) -= M(0, 5) * M(4, 0) / M(0, 0); M(4, 6) -= M(0, 6) * M(4, 0) / M(0, 0); M(4, 7) -= M(0, 7) * M(4, 0) / M(0, 0);
|
||||
b[5] -= b[0] * M(5, 0) / M(0, 0); M(5, 5) -= M(0, 5) * M(5, 0) / M(0, 0); M(5, 6) -= M(0, 6) * M(5, 0) / M(0, 0); M(5, 7) -= M(0, 7) * M(5, 0) / M(0, 0);
|
||||
b[6] -= b[0] * M(6, 0) / M(0, 0); M(6, 6) -= M(0, 6) * M(6, 0) / M(0, 0); M(6, 7) -= M(0, 7) * M(6, 0) / M(0, 0);
|
||||
b[7] -= b[0] * M(7, 0) / M(0, 0); M(7, 7) -= M(0, 7) * M(7, 0) / M(0, 0);
|
||||
|
||||
b[2] -= b[1] * M(2, 1) / M(1, 1); M(2, 2) -= M(1, 2) * M(2, 1) / M(1, 1); M(2, 3) -= M(1, 3) * M(2, 1) / M(1, 1); M(2, 4) -= M(1, 4) * M(2, 1) / M(1, 1); M(2, 5) -= M(1, 5) * M(2, 1) / M(1, 1); M(2, 6) -= M(1, 6) * M(2, 1) / M(1, 1); M(2, 7) -= M(1, 7) * M(2, 1) / M(1, 1);
|
||||
b[3] -= b[1] * M(3, 1) / M(1, 1); M(3, 3) -= M(1, 3) * M(3, 1) / M(1, 1); M(3, 4) -= M(1, 4) * M(3, 1) / M(1, 1); M(3, 5) -= M(1, 5) * M(3, 1) / M(1, 1); M(3, 6) -= M(1, 6) * M(3, 1) / M(1, 1); M(3, 7) -= M(1, 7) * M(3, 1) / M(1, 1);
|
||||
b[4] -= b[1] * M(4, 1) / M(1, 1); M(4, 4) -= M(1, 4) * M(4, 1) / M(1, 1); M(4, 5) -= M(1, 5) * M(4, 1) / M(1, 1); M(4, 6) -= M(1, 6) * M(4, 1) / M(1, 1); M(4, 7) -= M(1, 7) * M(4, 1) / M(1, 1);
|
||||
b[5] -= b[1] * M(5, 1) / M(1, 1); M(5, 5) -= M(1, 5) * M(5, 1) / M(1, 1); M(5, 6) -= M(1, 6) * M(5, 1) / M(1, 1); M(5, 7) -= M(1, 7) * M(5, 1) / M(1, 1);
|
||||
b[6] -= b[1] * M(6, 1) / M(1, 1); M(6, 6) -= M(1, 6) * M(6, 1) / M(1, 1); M(6, 7) -= M(1, 7) * M(6, 1) / M(1, 1);
|
||||
b[7] -= b[1] * M(7, 1) / M(1, 1); M(7, 7) -= M(1, 7) * M(7, 1) / M(1, 1);
|
||||
|
||||
b[3] -= b[2] * M(3, 2) / M(2, 2); M(3, 3) -= M(2, 3) * M(3, 2) / M(2, 2); M(3, 4) -= M(2, 4) * M(3, 2) / M(2, 2); M(3, 5) -= M(2, 5) * M(3, 2) / M(2, 2); M(3, 6) -= M(2, 6) * M(3, 2) / M(2, 2); M(3, 7) -= M(2, 7) * M(3, 2) / M(2, 2);
|
||||
b[4] -= b[2] * M(4, 2) / M(2, 2); M(4, 4) -= M(2, 4) * M(4, 2) / M(2, 2); M(4, 5) -= M(2, 5) * M(4, 2) / M(2, 2); M(4, 6) -= M(2, 6) * M(4, 2) / M(2, 2); M(4, 7) -= M(2, 7) * M(4, 2) / M(2, 2);
|
||||
b[5] -= b[2] * M(5, 2) / M(2, 2); M(5, 5) -= M(2, 5) * M(5, 2) / M(2, 2); M(5, 6) -= M(2, 6) * M(5, 2) / M(2, 2); M(5, 7) -= M(2, 7) * M(5, 2) / M(2, 2);
|
||||
b[6] -= b[2] * M(6, 2) / M(2, 2); M(6, 6) -= M(2, 6) * M(6, 2) / M(2, 2); M(6, 7) -= M(2, 7) * M(6, 2) / M(2, 2);
|
||||
b[7] -= b[2] * M(7, 2) / M(2, 2); M(7, 7) -= M(2, 7) * M(7, 2) / M(2, 2);
|
||||
|
||||
b[4] -= b[3] * M(4, 3) / M(3, 3); M(4, 4) -= M(3, 4) * M(4, 3) / M(3, 3); M(4, 5) -= M(3, 5) * M(4, 3) / M(3, 3); M(4, 6) -= M(3, 6) * M(4, 3) / M(3, 3); M(4, 7) -= M(3, 7) * M(4, 3) / M(3, 3);
|
||||
b[5] -= b[3] * M(5, 3) / M(3, 3); M(5, 5) -= M(3, 5) * M(5, 3) / M(3, 3); M(5, 6) -= M(3, 6) * M(5, 3) / M(3, 3); M(5, 7) -= M(3, 7) * M(5, 3) / M(3, 3);
|
||||
b[6] -= b[3] * M(6, 3) / M(3, 3); M(6, 6) -= M(3, 6) * M(6, 3) / M(3, 3); M(6, 7) -= M(3, 7) * M(6, 3) / M(3, 3);
|
||||
b[7] -= b[3] * M(7, 3) / M(3, 3); M(7, 7) -= M(3, 7) * M(7, 3) / M(3, 3);
|
||||
|
||||
b[5] -= b[4] * M(5, 4) / M(4, 4); M(5, 5) -= M(4, 5) * M(5, 4) / M(4, 4); M(5, 6) -= M(4, 6) * M(5, 4) / M(4, 4); M(5, 7) -= M(4, 7) * M(5, 4) / M(4, 4);
|
||||
b[6] -= b[4] * M(6, 4) / M(4, 4); M(6, 6) -= M(4, 6) * M(6, 4) / M(4, 4); M(6, 7) -= M(4, 7) * M(6, 4) / M(4, 4);
|
||||
b[7] -= b[4] * M(7, 4) / M(4, 4); M(7, 7) -= M(4, 7) * M(7, 4) / M(4, 4);
|
||||
|
||||
b[6] -= b[5] * M(6, 5) / M(5, 5); M(6, 6) -= M(5, 6) * M(6, 5) / M(5, 5); M(6, 7) -= M(5, 7) * M(6, 5) / M(5, 5);
|
||||
b[7] -= b[5] * M(7, 5) / M(5, 5); M(7, 7) -= M(5, 7) * M(7, 5) / M(5, 5);
|
||||
|
||||
b[7] -= b[6] * M(7, 6) / M(6, 6); M(7, 7) -= M(6, 7) * M(7, 6) / M(6, 6);
|
||||
|
||||
for (int i=0; i<N; i++) {
|
||||
if(i > 6) b[N-1-i] -= M(N-1-i, 1) * b[1];
|
||||
if(i > 5) b[N-1-i] -= M(N-1-i, 2) * b[2];
|
||||
if(i > 4) b[N-1-i] -= M(N-1-i, 3) * b[3];
|
||||
if(i > 3) b[N-1-i] -= M(N-1-i, 4) * b[4];
|
||||
if(i > 2) b[N-1-i] -= M(N-1-i, 5) * b[5];
|
||||
if(i > 1) b[N-1-i] -= M(N-1-i, 6) * b[6];
|
||||
if(i > 0) b[N-1-i] -= M(N-1-i, 7) * b[7];
|
||||
|
||||
b[N-1-i] /= M(N-1-i, N-1-i);
|
||||
interp += b[N-1-i] * (X[N-1-i] - X[N]);
|
||||
}
|
||||
|
||||
return interp.zwxx;
|
||||
}
|
||||
|
|
@ -1,203 +0,0 @@
|
|||
// SSimSuperRes by Shiandow
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 3.0 of the License, or (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library.
|
||||
|
||||
//!HOOK POSTKERNEL
|
||||
//!BIND HOOKED
|
||||
//!SAVE LOWRES
|
||||
//!HEIGHT NATIVE_CROPPED.h
|
||||
//!WHEN NATIVE_CROPPED.h OUTPUT.h <
|
||||
//!COMPONENTS 4
|
||||
//!DESC SSSR Downscaling I
|
||||
|
||||
#define axis 1
|
||||
|
||||
#define offset vec2(0,0)
|
||||
|
||||
#define MN(B,C,x) (x < 1.0 ? ((2.-1.5*B-(C))*x + (-3.+2.*B+C))*x*x + (1.-(B)/3.) : (((-(B)/6.-(C))*x + (B+5.*C))*x + (-2.*B-8.*C))*x+((4./3.)*B+4.*C))
|
||||
#define Kernel(x) MN(0.334, 0.333, abs(x))
|
||||
#define taps 2.0
|
||||
|
||||
#define Luma(rgb) dot(rgb*rgb, vec3(0.2126, 0.7152, 0.0722))
|
||||
|
||||
vec4 hook() {
|
||||
float low = ceil((HOOKED_pos - taps/input_size) * HOOKED_size - offset - 0.5)[axis];
|
||||
float high = floor((HOOKED_pos + taps/input_size) * HOOKED_size - offset - 0.5)[axis];
|
||||
|
||||
float W = 0.0;
|
||||
vec4 avg = vec4(0);
|
||||
vec2 pos = HOOKED_pos;
|
||||
vec4 tex;
|
||||
|
||||
for (float k = low; k <= high; k++) {
|
||||
pos[axis] = HOOKED_pt[axis] * (k - offset[axis] + 0.5);
|
||||
float rel = (pos[axis] - HOOKED_pos[axis])*input_size[axis];
|
||||
float w = Kernel(rel);
|
||||
|
||||
tex.rgb = textureLod(HOOKED_raw, pos, 0.0).rgb * HOOKED_mul;
|
||||
tex.a = Luma(tex.rgb);
|
||||
avg += w * tex;
|
||||
W += w;
|
||||
}
|
||||
avg /= W;
|
||||
|
||||
return vec4(avg.rgb, max(abs(avg.a - Luma(avg.rgb)), 5e-7));
|
||||
}
|
||||
|
||||
//!HOOK POSTKERNEL
|
||||
//!BIND LOWRES
|
||||
//!SAVE LOWRES
|
||||
//!WIDTH NATIVE_CROPPED.w
|
||||
//!HEIGHT NATIVE_CROPPED.h
|
||||
//!WHEN NATIVE_CROPPED.w OUTPUT.w <
|
||||
//!COMPONENTS 4
|
||||
//!DESC SSSR Downscaling II
|
||||
|
||||
#define axis 0
|
||||
|
||||
#define offset vec2(0,0)
|
||||
|
||||
#define MN(B,C,x) (x < 1.0 ? ((2.-1.5*B-(C))*x + (-3.+2.*B+C))*x*x + (1.-(B)/3.) : (((-(B)/6.-(C))*x + (B+5.*C))*x + (-2.*B-8.*C))*x+((4./3.)*B+4.*C))
|
||||
#define Kernel(x) MN(0.334, 0.333, abs(x))
|
||||
#define taps 2.0
|
||||
|
||||
#define Luma(rgb) dot(rgb*rgb, vec3(0.2126, 0.7152, 0.0722))
|
||||
|
||||
vec4 hook() {
|
||||
float low = ceil((LOWRES_pos - taps/input_size) * LOWRES_size - offset - 0.5)[axis];
|
||||
float high = floor((LOWRES_pos + taps/input_size) * LOWRES_size - offset - 0.5)[axis];
|
||||
|
||||
float W = 0.0;
|
||||
vec4 avg = vec4(0);
|
||||
vec2 pos = LOWRES_pos;
|
||||
vec4 tex;
|
||||
|
||||
for (float k = low; k <= high; k++) {
|
||||
pos[axis] = LOWRES_pt[axis] * (k - offset[axis] + 0.5);
|
||||
float rel = (pos[axis] - LOWRES_pos[axis])*input_size[axis];
|
||||
float w = Kernel(rel);
|
||||
|
||||
tex.rgb = textureLod(LOWRES_raw, pos, 0.0).rgb * LOWRES_mul;
|
||||
tex.a = Luma(tex.rgb);
|
||||
avg += w * tex;
|
||||
W += w;
|
||||
}
|
||||
avg /= W;
|
||||
|
||||
return vec4(avg.rgb, max(abs(avg.a - Luma(avg.rgb)), 5e-7) + LOWRES_texOff(0).a);
|
||||
}
|
||||
|
||||
//!HOOK POSTKERNEL
|
||||
//!BIND PREKERNEL
|
||||
//!BIND LOWRES
|
||||
//!SAVE var
|
||||
//!WIDTH NATIVE_CROPPED.w
|
||||
//!HEIGHT NATIVE_CROPPED.h
|
||||
//!WHEN NATIVE_CROPPED.h OUTPUT.h <
|
||||
//!COMPONENTS 2
|
||||
//!DESC SSSR var
|
||||
|
||||
#define spread 1.0 / 4.0
|
||||
|
||||
#define GetL(x,y) PREKERNEL_tex(PREKERNEL_pt * (PREKERNEL_pos * input_size + tex_offset + vec2(x,y))).rgb
|
||||
#define GetH(x,y) LOWRES_texOff(vec2(x,y)).rgb
|
||||
|
||||
#define Luma(rgb) dot(rgb*rgb, vec3(0.2126, 0.7152, 0.0722))
|
||||
#define diff(x,y) vec2(Luma((GetL(x,y) - meanL)), Luma((GetH(x,y) - meanH)))
|
||||
|
||||
vec4 hook() {
|
||||
vec3 meanL = GetL(0,0);
|
||||
vec3 meanH = GetH(0,0);
|
||||
for (int X=-1; X<=1; X+=2) {
|
||||
meanL += GetL(X,0) * spread;
|
||||
meanH += GetH(X,0) * spread;
|
||||
}
|
||||
for (int Y=-1; Y<=1; Y+=2) {
|
||||
meanL += GetL(0,Y) * spread;
|
||||
meanH += GetH(0,Y) * spread;
|
||||
}
|
||||
meanL /= (1.0 + 4.0*spread);
|
||||
meanH /= (1.0 + 4.0*spread);
|
||||
|
||||
vec2 var = diff(0,0);
|
||||
for (int X=-1; X<=1; X+=2)
|
||||
var += diff(X,0) * spread;
|
||||
|
||||
for (int Y=-1; Y<=1; Y+=2)
|
||||
var += diff(0,Y) * spread;
|
||||
|
||||
return vec4(max(var / (1.0 + 4.0*spread), vec2(1e-6)), 0, 0);
|
||||
}
|
||||
|
||||
//!HOOK POSTKERNEL
|
||||
//!BIND HOOKED
|
||||
//!BIND PREKERNEL
|
||||
//!BIND LOWRES
|
||||
//!BIND var
|
||||
//!WHEN NATIVE_CROPPED.h OUTPUT.h <
|
||||
//!DESC SSSR final pass
|
||||
|
||||
#define oversharp 0.5
|
||||
|
||||
// -- Window Size --
|
||||
#define taps 3.0
|
||||
#define even (taps - 2.0 * floor(taps / 2.0) == 0.0)
|
||||
#define minX int(1.0-ceil(taps/2.0))
|
||||
#define maxX int(floor(taps/2.0))
|
||||
|
||||
#define Kernel(x) cos(acos(-1.0)*(x)/taps) // Hann kernel
|
||||
|
||||
// -- Input processing --
|
||||
#define var(x,y) var_tex(var_pt * (pos + vec2(x,y) + 0.5)).rg
|
||||
#define GetL(x,y) PREKERNEL_tex(PREKERNEL_pt * (pos + tex_offset + vec2(x,y) + 0.5)).rgb
|
||||
#define GetH(x,y) LOWRES_tex(LOWRES_pt * (pos + vec2(x,y) + 0.5))
|
||||
|
||||
#define Luma(rgb) dot(rgb*rgb, vec3(0.2126, 0.7152, 0.0722))
|
||||
|
||||
vec4 hook() {
|
||||
vec4 c0 = HOOKED_texOff(0);
|
||||
|
||||
vec2 pos = HOOKED_pos * LOWRES_size - vec2(0.5);
|
||||
vec2 offset = pos - (even ? floor(pos) : round(pos));
|
||||
pos -= offset;
|
||||
|
||||
vec2 mVar = vec2(0.0);
|
||||
for (int X=-1; X<=1; X++)
|
||||
for (int Y=-1; Y<=1; Y++) {
|
||||
vec2 w = clamp(1.5 - abs(vec2(X,Y)), 0.0, 1.0);
|
||||
mVar += w.r * w.g * vec2(GetH(X,Y).a, 1.0);
|
||||
}
|
||||
mVar.r /= mVar.g;
|
||||
|
||||
// Calculate faithfulness force
|
||||
float weightSum = 0.0;
|
||||
vec3 diff = vec3(0);
|
||||
|
||||
for (int X = minX; X <= maxX; X++)
|
||||
for (int Y = minX; Y <= maxX; Y++)
|
||||
{
|
||||
float R = (-1.0 - oversharp) * sqrt(var(X,Y).r / (var(X,Y).g + mVar.r));
|
||||
|
||||
vec2 krnl = Kernel(vec2(X,Y) - offset);
|
||||
float weight = krnl.r * krnl.g / (Luma((c0.rgb - GetH(X,Y).rgb)) + GetH(X,Y).a);
|
||||
|
||||
diff += weight * (GetL(X,Y) + GetH(X,Y).rgb * R + (-1.0 - R) * (c0.rgb));
|
||||
weightSum += weight;
|
||||
}
|
||||
diff /= weightSum;
|
||||
|
||||
c0.rgb = ((c0.rgb) + diff);
|
||||
|
||||
return c0;
|
||||
}
|
||||
|
|
@ -309,6 +309,7 @@ Section "uninstall"
|
|||
IfErrors 0 KeepUserData
|
||||
notsilent:
|
||||
RMDir /r "$LOCALAPPDATA\${COMPANY_NAME}"
|
||||
RMDir /r "$APPDATA\${COMPANY_NAME}"
|
||||
RMDir /r "$APPDATA\${DATA_FOLDER}"
|
||||
KeepUserData:
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue