diff --git a/package.json b/package.json index 36bcb1d..74876bd 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "vset", "productName": "VSET", - "version": "4.2.2", + "version": "4.3.6", "description": "VSET", "author": "NangInShell", "main": "./out/main/index.js", diff --git a/src/renderer/src/utils/getConfig.ts b/resources/json/.gitkeeper similarity index 100% rename from src/renderer/src/utils/getConfig.ts rename to resources/json/.gitkeeper diff --git a/resources/vpyfiles/.gitkeeper b/resources/vpyfiles/.gitkeeper new file mode 100644 index 0000000..e69de29 diff --git a/src/main/getCorePath.ts b/src/main/getCorePath.ts index b26dcff..c0e5025 100644 --- a/src/main/getCorePath.ts +++ b/src/main/getCorePath.ts @@ -41,8 +41,8 @@ export function getExtraSRModelPath(): string { * 暂时存放在 config_json.outputfolder 目录下 * @param config_json */ -export function getGenSettingsPath(config_json): string { - return path.join(config_json.outputfolder, 'setting.json') +export function getGenSettingsPath(): string { + return path.join(app.getAppPath(), 'resources', 'json', 'setting.json') } /** @@ -51,6 +51,6 @@ export function getGenSettingsPath(config_json): string { * @param config_json * @param base_name 生成的 vpy 文件名(不含扩展名) */ -export function getGenVpyPath(config_json, base_name: string): string { - return path.join(config_json.outputfolder, `${base_name}.vpy`) +export function getGenVpyPath(base_name: string): string { + return path.join(app.getAppPath(), 'resources', 'vpyfiles', `${base_name}.vpy`) } diff --git a/src/main/index.ts b/src/main/index.ts index 7467352..c5ee57e 100644 --- a/src/main/index.ts +++ b/src/main/index.ts @@ -8,7 +8,7 @@ import { getGenSettingsPath } from './getCorePath' import { getCpuInfo, getGpuInfo } from './getSystemInfo' import { openDirectory } from './openDirectory' import { preview, previewFrame } from './previewOutput' -import { runCommand } from './runCommand' +import { PauseCommand, runCommand } from './runCommand' function createWindow(): BrowserWindow { const mainWindow = new BrowserWindow({ @@ -19,7 +19,7 @@ function createWindow(): BrowserWindow { show: false, autoHideMenuBar: true, icon: nativeImage.createFromPath(appIcon), - title: 'VSET 4.2.2', + title: 'VSET 4.3.6', webPreferences: { preload: path.join(__dirname, '../preload/index.js'), sandbox: false, @@ -29,6 +29,8 @@ function createWindow(): BrowserWindow { // ipcMain ipcMain.on('execute-command', runCommand) + ipcMain.on('pause', PauseCommand) + ipcMain.on('preview', preview) ipcMain.on('preview-frame', previewFrame) @@ -36,7 +38,7 @@ function createWindow(): BrowserWindow { ipcMain.on('stop-all-processes', killAllProcesses) ipcMain.on('generate-json', (_, data) => { - const filePath = getGenSettingsPath(data) + const filePath = getGenSettingsPath() writeFileSync(filePath, JSON.stringify(data, null, 2)) }) diff --git a/src/main/previewOutput.ts b/src/main/previewOutput.ts index 8ad8e03..eadb2b9 100644 --- a/src/main/previewOutput.ts +++ b/src/main/previewOutput.ts @@ -5,24 +5,15 @@ import path from 'node:path' import iconv from 'iconv-lite' import { addProcess, removeProcess } from './childProcessManager' import { getExecPath, getGenVpyPath } from './getCorePath' -import { generate_vpy } from './runCommand' -export async function preview(event, config_json): Promise { +export async function preview(event, video, vpyContent): Promise { const vspipePath = getExecPath().vspipe - const videos = config_json.fileList - if (videos?.length === 0) { - event.sender.send('ffmpeg-finish') - return - } - const video = videos[0] - const baseName = path.basename(video, path.extname(video)) - const vpyPath = getGenVpyPath(config_json, baseName) + const vpyPath = getGenVpyPath(baseName) // ========== 生成 vpy 文件 ========== - const vpyFile = generate_vpy(config_json, video) - writeFileSync(vpyPath, vpyFile) + writeFileSync(vpyPath, vpyContent.replace('__VIDEO_PATH__', video)) let info: { width: string diff --git a/src/main/runCommand.ts b/src/main/runCommand.ts index d4bd958..8019ada 100644 --- a/src/main/runCommand.ts +++ b/src/main/runCommand.ts @@ -5,515 +5,45 @@ import path from 'node:path' import { promisify } from 'node:util' import iconv from 'iconv-lite' import { addProcess, removeProcess } from './childProcessManager' -import { getExecPath, getExtraSRModelPath, getGenVpyPath } from './getCorePath' +import { getCorePath, getExecPath, getGenVpyPath } from './getCorePath' const exec = promisify(execCallback) +function splitArgs(str): string[] { + return str + .match(/"[^"]+"|\S+/g) // 匹配带引号的或普通的 + .map(s => s.replace(/^"|"$/g, '')) // 去掉首尾引号 +} -export function generate_cmd(config_json, vipipePath, vpyPath, ffmpegPath, video, hasAudio, hasSubtitle): string { - let cmd = `"${vipipePath}"` + ` "-c" "y4m" "${vpyPath}" "-" | "${ - ffmpegPath}" "-hide_banner" "-y" "-i" "pipe:" "-i" "${video}"` - + ` "-map" "0:v:0" ` - if (hasAudio) { - cmd += '"-map" "1:a" ' - } - - cmd += `"-c:v" "${config_json.encoderValue}" ` +// 中断循环 +let shouldStop = false - if (hasSubtitle && config_json.isSavesubtitle === true) { - cmd += '"-map" "1:s" "-c:s" "copy" ' - } +export function requestStop(): void { + shouldStop = true +} - if (config_json.encoderValue === 'libx265') { - cmd += '"-pix_fmt" "yuv420p10le" "-profile:v" "main10" "-vtag" "hvc1" ' - } - if (config_json.encoderValue === 'libx264') { - cmd += '"-pix_fmt" "yuv420p" "-profile:v" "main" ' - } - if (config_json.encoderValue === 'libaom-av1') { - cmd += '"-pix_fmt" "yuv420p10le" ' - } - if (config_json.encoderValue === 'h264_nvenc') { - cmd += '"-pix_fmt" "yuv420p" ' - } - if (config_json.encoderValue === 'hevc_nvenc') { - cmd += '"-pix_fmt" "p010le" "-profile:v" "main10" "-vtag" "hvc1" ' - } - if (config_json.encoderValue === 'av1_nvenc') { - cmd += '"-pix_fmt" "p010le" ' - } - if (config_json.encoderValue === 'libsvtav1') { - cmd += '"-pix_fmt" "yuv420p10le" ' - } - if (config_json.encoderValue === 'libsvtav1') { - cmd += `-preset ` + `"${config_json.cpusvtav1_qualityValue}" ` - } - else { - cmd += `-preset ` + `"${config_json.qualityValue}" ` - } - if (config_json.isUseCrf === true) { - if (config_json.encoderValue.includes('nvenc')) { - cmd += `"-cq" ` + `"${config_json.crfValue}" ` - } - else { - cmd += `"-crf" ` + `"${config_json.crfValue}" ` - } - } - else { - cmd += `"-b:v" ` + `"${config_json.bitValue}M" ` - } - if (hasAudio === true) { - if (config_json.isSaveAudio === true) { +function generate_cmd(taskconfig, hasAudio, hasSubtitle): string { + let cmd = '' + if (hasAudio) { + cmd += '"-map" "1:a" ' + if (taskconfig.isSaveAudio === true) { cmd += '"-c:a" "copy" ' } else { - cmd += `"-c:a" ` + `"${config_json.AudioContainer.toLowerCase()}" ` + cmd += `"-c:a" ` + `"${taskconfig.AudioContainer.toLowerCase()}" ` } } - - // 最终cmd命令 - cmd += `"${config_json.outputfolder}/${path.parse(path.basename(video)).name}_enhance` + `.${config_json.videoContainer.toLowerCase()}"` - return cmd -} - -export function generate_vpy(config_json, videoName): string { - let vpyContent = '' - - vpyContent += 'import vapoursynth as vs\n' - vpyContent += 'core = vs.core\n' - vpyContent += `res = core.lsmas.LWLibavSource(r"${videoName}")\n` - vpyContent += 'from vsmlrt import CUGAN,RealESRGAN,Waifu2x,RIFE,ArtCNN,SwinIR,Backend\n' - vpyContent += 'import vsmlrt\n' - - // 前置缩放(需要在此改进色彩控制) - if (config_json.UseResize_BeforeEnhance === true) { - vpyContent - += `res = core.resize.Bicubic(clip=res,width=${config_json.ResizeWidth_BeforeEnhance - },height=${config_json.ResizeHeight_BeforeEnhance},format=vs.YUV420P16)\n` - } - else { - vpyContent += 'res = core.resize.Bicubic(clip=res,format=vs.YUV420P16)\n' - } - - vpyContent += `res = core.std.Crop(clip=res,left=${config_json.ReduceLeft_BeforeEnhance - }, right=${config_json.ReduceRight_BeforeEnhance - }, top=${config_json.ReduceOn_BeforeEnhance - }, bottom=${config_json.ReduceDown_BeforeEnhance})\n` - - // 超分 - if (config_json.useSR === true) { - vpyContent += 'res = core.resize.Bicubic(clip=res,range=1,matrix_in_s="709",format=vs.RGB48)\n' - vpyContent += 'res=core.fmtc.bitdepth(res, bits=32)\n' - - // 超分设备 - if (config_json.SRMethodValue === 'Real_cugan') { - if (config_json.RealcuganInferenceValue === 'Cuda') { - vpyContent += 'device_sr=Backend.ORT_CUDA()\n' - } - if (config_json.RealcuganInferenceValue === 'TensorRt') { - vpyContent += 'device_sr=Backend.TRT_RTX()\n' - vpyContent += `device_sr.use_cuda_graph = ${ - config_json.Sr_cudagraph.charAt(0).toUpperCase() + config_json.Sr_cudagraph.slice(1) - }\n` - } - if (config_json.RealcuganInferenceValue === 'TensorRt_RTX') { - vpyContent += 'device_sr=Backend.MIGX()\n' - } - if (config_json.RealcuganInferenceValue === 'NCNN') { - vpyContent += 'device_sr=Backend.NCNN_VK()\n' - } - if (config_json.RealcuganInferenceValue === 'DML') { - vpyContent += 'device_sr=Backend.ORT_DML()\n' - } - if (config_json.RealcuganInferenceValue === 'MIGX') { - vpyContent += 'device_sr=Backend.MIGX()\n' - } - } - if (config_json.SRMethodValue === 'Real_esrgan') { - if (config_json.RealesrganInferenceValue === 'Cuda') { - vpyContent += 'device_sr=Backend.ORT_CUDA()\n' - } - if (config_json.RealesrganInferenceValue === 'TensorRt') { - vpyContent += 'device_sr=Backend.TRT()\n' - vpyContent += `device_sr.use_cuda_graph = ${ - config_json.Sr_cudagraph.charAt(0).toUpperCase() + config_json.Sr_cudagraph.slice(1) - }\n` - } - if (config_json.RealesrganInferenceValue === 'TensorRt_RTX') { - vpyContent += 'device_sr=Backend.TRT_RTX()\n' - } - if (config_json.RealesrganInferenceValue === 'NCNN') { - vpyContent += 'device_sr=Backend.NCNN_VK()\n' - } - if (config_json.RealesrganInferenceValue === 'DML') { - vpyContent += 'device_sr=Backend.ORT_DML()\n' - } - if (config_json.RealesrganInferenceValue === 'MIGX') { - vpyContent += 'device_sr=Backend.MIGX()\n' - } - } - if (config_json.SRMethodValue === 'Waifu2x') { - if (config_json.Waifu2xInferenceValue === 'Cuda') { - vpyContent += 'device_sr=Backend.ORT_CUDA()\n' - } - if (config_json.Waifu2xInferenceValue === 'TensorRt') { - vpyContent += 'device_sr=Backend.TRT()\n' - vpyContent += `device_sr.use_cuda_graph = ${ - config_json.Sr_cudagraph.charAt(0).toUpperCase() + config_json.Sr_cudagraph.slice(1) - }\n` - } - if (config_json.Waifu2xInferenceValue === 'TensorRt_RTX') { - vpyContent += 'device_sr=Backend.TRT_RTX()\n' - } - if (config_json.Waifu2xInferenceValue === 'NCNN') { - vpyContent += 'device_sr=Backend.NCNN_VK()\n' - } - if (config_json.Waifu2xInferenceValue === 'DML') { - vpyContent += 'device_sr=Backend.ORT_DML()\n' - } - if (config_json.Waifu2xInferenceValue === 'MIGX') { - vpyContent += 'device_sr=Backend.MIGX()\n' - } - } - if (config_json.SRMethodValue === 'SR_ExtraModel') { - if (config_json.SR_ExtraModelInferenceValue === 'Cuda') { - vpyContent += 'device_sr=Backend.ORT_CUDA()\n' - } - if (config_json.SR_ExtraModelInferenceValue === 'TensorRt') { - vpyContent += 'device_sr=Backend.TRT()\n' - vpyContent += `device_sr.use_cuda_graph = ${ - config_json.Sr_cudagraph.charAt(0).toUpperCase() + config_json.Sr_cudagraph.slice(1) - }\n` - } - if (config_json.SR_ExtraModelInferenceValue === 'NCNN') { - vpyContent += 'device_sr=Backend.NCNN_VK()\n' - } - if (config_json.SR_ExtraModelInferenceValue === 'DML') { - vpyContent += 'device_sr=Backend.ORT_DML()\n' - } - if (config_json.SR_ExtraModelInferenceValue === 'MIGX') { - vpyContent += 'device_sr=Backend.MIGX()\n' - } - } - - vpyContent += 'device_sr.device_id=0\n' - vpyContent += 'device_sr.fp16=True\n' - vpyContent += `device_sr.num_streams=${config_json.Sr_numstreams}\n` - - if (config_json.SRMethodValue === 'Real_cugan') { - const model_switch = { - 'pro-conservative-up2x': [0, 2, 2], - 'pro-conservative-up3x': [0, 3, 2], - 'pro-denoise3x-up2x': [3, 2, 2], - 'pro-denoise3x-up3x': [3, 3, 2], - 'pro-no-denoise3x-up2x': [-1, 2, 2], - 'pro-no-denoise3x-up3x': [-1, 3, 2], - 'up2x-latest-conservative': [0, 2, 1], - 'up2x-latest-denoise1x': [1, 2, 1], - 'up2x-latest-denoise2x': [2, 2, 1], - 'up2x-latest-denoise3x': [3, 2, 1], - 'up2x-latest-no-denoise': [-1, 2, 1], - 'up3x-latest-conservative': [0, 3, 1], - 'up3x-latest-denoise3x': [3, 3, 1], - 'up3x-latest-no-denoise': [-1, 3, 1], - 'up4x-latest-conservative': [0, 4, 1], - 'up4x-latest-denoise3x': [3, 4, 1], - 'up4x-latest-no-denoise': [-1, 4, 1], - } - const [noise, scale, version] = model_switch[config_json.RealcuganModelValue] || [0, 2, 2] - vpyContent += `res = CUGAN(res, noise=${noise}, scale=${scale}, tiles=${config_json.RealcuganTileValue}, version=${version}, alpha=${config_json.RealcuganAlphaValue}, backend=device_sr)\n` - } - - if (config_json.SRMethodValue === 'Real_esrgan') { - const model_switch = { - 'animevideov3': 0, - 'animevideo-xsx2': 1, - 'animevideo-xsx4': 2, - 'animejanaiV2L1': 5005, - 'animejanaiV2L2': 5006, - 'animejanaiV2L3': 5007, - 'animejanaiV3_HD_L1': 5008, - 'animejanaiV3_HD_L2': 5009, - 'animejanaiV3_HD_L3': 5010, - 'Ani4Kv2_G6i2_Compact ': 7000, - 'Ani4Kv2_G6i2_UltraCompact ': 7001, - 'AniScale_x2': 7010, - 'AniScale2_Refiner_x1': 7011, - 'AniScale2S_Compact_x2': 7012, - 'AniSD_AC_Compact_x2': 7013, - 'AniSD_Compact_x2': 7014, - 'AniSD_DB_Compact_x1': 7015, - 'AniSD_PS_Compact_x2': 7016, - } - const model = model_switch[config_json.RealesrganModelValue] || 0 - vpyContent += `res = RealESRGAN(res, scale=${config_json.RealesrganScaleValue},tiles=${ - config_json.RealesrganTileValue},model=${model}, backend=device_sr)\n` - } - - // if (config_json.SRMethodValue=='ArtCNN'){ - // const model_switch = { - // 'ArtCNN_C4F32': 0, - // 'ArtCNN_C4F32_DS': 1, - // 'ArtCNN_C16F64': 2, - // 'ArtCNN_C16F64_DS' :3 , - // 'ArtCNN_C4F32_Chroma' : 4, - // 'ArtCNN_C16F64_Chroma' : 5, - // 'ArtCNN_R16F96' : 6, - // 'ArtCNN_R8F64' : 7, - // 'ArtCNN_R8F64_DS' : 8, - // 'ArtCNN_R8F64_Chroma ' : 9, - // 'ArtCNN_C4F16 ' : 10, - // 'ArtCNN_C4F16_DS ' : 11, - // }; - // const model = model_switch[config_json.ArtCNNModelValue] || 0; - // vpyContent +='res = core.resize.Bicubic(clip=res, matrix_s="709", format=vs.YUV444PS)\n' - - // vpyContent +='res = ArtCNN(res, tiles=' + - // config_json.ArtCNNTileValue + ', model=' + model + ', backend=device_sr)\n' - // } - - if (config_json.SRMethodValue === 'Waifu2x') { - const model_switch = { - 'anime_style_art_rgb_noise0': [1, 0, 1], - 'anime_style_art_rgb_noise1': [1, 1, 1], - 'anime_style_art_rgb_noise2': [1, 2, 1], - 'anime_style_art_rgb_noise3': [1, 3, 1], - 'anime_style_art_rgb_scale2.0x': [1, -1, 2], - - 'photo_noise0': [2, 0, 1], - 'photo_noise1': [2, 1, 1], - 'photo_noise2': [2, 2, 1], - 'photo_noise3': [2, 3, 1], - 'photo_scale2.0x': [2, -1, 2], - - 'upconv_7_anime_style_art_rgb_noise0_scale2.0x': [3, 0, 2], - 'upconv_7_anime_style_art_rgb_noise1_scale2.0x': [3, 1, 2], - 'upconv_7_anime_style_art_rgb_noise2_scale2.0x': [3, 2, 2], - 'upconv_7_anime_style_art_rgb_noise3_scale2.0x': [3, 3, 2], - 'upconv_7_anime_style_art_rgb_scale2.0x': [3, -1, 2], - - 'upconv_7_photo_noise0_scale2.0x': [4, 0, 2], - 'upconv_7_photo_noise1_scale2.0x': [4, 1, 2], - 'upconv_7_photo_noise2_scale2.0x': [4, 2, 2], - 'upconv_7_photo_noise3_scale2.0x': [4, 3, 2], - 'upconv_7_photo_scale2.0x_': [4, -1, 2], - - 'upresnet10_noise0_scale2.0x': [5, 0, 2], - 'upresnet10_noise1_scale2.0x': [5, 1, 2], - 'upresnet10_noise2_scale2.0x': [5, 2, 2], - 'upresnet10_noise3_scale2.0x': [5, 3, 2], - 'upresnet10_scale2.0x': [5, -1, 2], - - 'cunet_noise0': [6, 0, 1], - 'cunet_noise1': [6, 1, 1], - 'cunet_noise2': [6, 2, 1], - 'cunet_noise3': [6, 3, 1], - 'cunet_noise0_scale2.0x': [6, 0, 2], - 'cunet_noise1_scale2.0x': [6, 1, 2], - 'cunet_noise2_scale2.0x': [6, 2, 2], - 'cunet_noise3_scale2.0x': [6, 3, 2], - 'cunet_scale2.0x': [6, -1, 2], - - 'swin_unet_art_noise0': [7, 0, 1], - 'swin_unet_art_noise0_scale2x': [7, 0, 2], - 'swin_unet_art_noise0_scale4x': [7, 0, 4], - 'swin_unet_art_noise1': [7, 1, 1], - 'swin_unet_art_noise1_scale2x': [7, 1, 2], - 'swin_unet_art_noise1_scale4x': [7, 1, 4], - 'swin_unet_art_noise2': [7, 2, 1], - 'swin_unet_art_noise2_scale2x': [7, 2, 2], - 'swin_unet_art_noise2_scale4x': [7, 2, 4], - 'swin_unet_art_noise3': [7, 3, 1], - 'swin_unet_art_noise3_scale2x': [7, 3, 2], - 'swin_unet_art_noise3_scale4x': [7, 3, 4], - 'swin_unet_art_scale2x': [7, -1, 2], - 'swin_unet_art_scale4x': [7, -1, 4], - - 'swin_unet_photo_noise0_scale4x': [8, 0, 4], - 'swin_unet_photo_noise1_scale4x': [8, 1, 4], - 'swin_unet_photo_noise2_scale4x': [8, 2, 4], - 'swin_unet_photo_noise3_scale4x': [8, 3, 4], - 'swin_unet_photo_scale4x': [8, -1, 4], - - 'swin_unet_photo_v2_noise0_scale4x': [9, 0, 4], - 'swin_unet_photo_v2_noise1_scale4x': [9, 1, 4], - 'swin_unet_photo_v2_noise2_scale4x': [9, 2, 4], - 'swin_unet_photo_v2_noise3_scale4x': [9, 3, 4], - 'swin_unet_photo_v2_scale4x': [9, -1, 4], - - 'swin_unet_art_scan_noise0_scale4x': [10, 0, 4], - 'swin_unet_art_scan_noise1_scale4x': [10, 1, 4], - 'swin_unet_art_scan_noise2_scale4x': [10, 2, 4], - 'swin_unet_art_scan_noise3_scale4x': [10, 3, 4], - 'swin_unet_art_scan_scale4x': [10, -1, 4], - } - const [model, noise, scale] = model_switch[config_json.Waifu2xModelValue] || [1, 0, 1] - vpyContent += `res = Waifu2x(res, noise=${noise}, scale=${scale}, tiles=${config_json.Waifu2xTileValue}, model=${model}, backend=device_sr)\n` - } - - // if (config_json.SRMethodValue=='SwinIR'){ - // const model_switch = { - // 'lightweightSR_DIV2K_s64w8_SwinIR_S_x2': 0, - // 'lightweightSR_DIV2K_s64w8_SwinIR_S_x3': 1, - // 'lightweightSR_DIV2K_s64w8_SwinIR_S_x4': 2, - // 'realSR_BSRGAN_DFOWMFC_s64w8_SwinIR_L_x4_GAN': 3, - // 'realSR_BSRGAN_DFOWMFC_s64w8_SwinIR_L_x4_PSNR': 5, - // 'classicalSR_DF2K_s64w8_SwinIR_M_x2': 6, - // 'classicalSR_DF2K_s64w8_SwinIR_M_x3': 7, - // 'classicalSR_DF2K_s64w8_SwinIR_M_x4': 8, - // 'classicalSR_DF2K_s64w8_SwinIR_M_x8': 9, - // 'realSR_BSRGAN_DFO_s64w8_SwinIR_M_x2_GAN': 10, - // 'realSR_BSRGAN_DFO_s64w8_SwinIR_M_x2_PSNR': 11, - // 'realSR_BSRGAN_DFO_s64w8_SwinIR_M_x4_GAN': 12, - // 'realSR_BSRGAN_DFO_s64w8_SwinIR_M_x4_PSNR': 13, - // // 'grayDN_DFWB_s128w8_SwinIR_M_noise15': 14, - // // 'grayDN_DFWB_s128w8_SwinIR_M_noise25': 15, - // // 'grayDN_DFWB_s128w8_SwinIR_M_noise50': 16, - // 'colorDN_DFWB_s128w8_SwinIR_M_noise15': 17, - // 'colorDN_DFWB_s128w8_SwinIR_M_noise25': 18, - // 'colorDN_DFWB_s128w8_SwinIR_M_noise50': 19, - // 'CAR_DFWB_s126w7_SwinIR_M_jpeg10': 20, - // 'CAR_DFWB_s126w7_SwinIR_M_jpeg20': 21, - // 'CAR_DFWB_s126w7_SwinIR_M_jpeg30': 22, - // 'CAR_DFWB_s126w7_SwinIR_M_jpeg40': 23, - // 'colorCAR_DFWB_s126w7_SwinIR_M_jpeg10': 24, - // 'colorCAR_DFWB_s126w7_SwinIR_M_jpeg20': 25, - // 'colorCAR_DFWB_s126w7_SwinIR_M_jpeg30': 26, - // 'colorCAR_DFWB_s126w7_SwinIR_M_jpeg40': 27 - // }; - // const model = model_switch[config_json.SwinIRModelValue] || 0; - // vpyContent +='res = SwinIR(res, tiles=' + - // config_json.SwinIRTileValue + ', model=' + model + ', backend=device_sr)\n' - // } - - if (config_json.SRMethodValue === 'SR_ExtraModel') { - const model_switch = { - AniSD_DC_SPAN_x2: 'AniSD_DC_SPAN_x2', - } - - const model = `${getExtraSRModelPath()}/${model_switch[config_json.SR_ExtraModelValue] || 'AniSD_DC_SPAN_x2'}` - - vpyContent += `res = vsmlrt.inference(res, network_path="${model}", backend=device_sr)\n` - } - } - - // 补帧 - if (config_json.useVfi === true) { - vpyContent += 'res = core.resize.Bicubic(clip=res,range=1,matrix_in_s="709",format=vs.RGB48)\n' - vpyContent += 'res=core.fmtc.bitdepth(res, bits=32)\n' - - if (config_json.VfiMethodValue === 'Rife') { - if (config_json.RifeInferenceValue === 'Cuda') { - vpyContent += 'device_vfi=Backend.ORT_CUDA()\n' - } - if (config_json.RifeInferenceValue === 'TensorRt') { - vpyContent += 'device_vfi=Backend.TRT()\n' - vpyContent += `device_vfi.use_cuda_graph = ${ - config_json.Vfi_cudagraph.charAt(0).toUpperCase() + config_json.Vfi_cudagraph.slice(1) - }\n` - } - if (config_json.RifeInferenceValue === 'TensorRt_RTX') { - vpyContent += 'device_vfi=Backend.TRT_RTX()\n' - } - if (config_json.RifeInferenceValue === 'NCNN') { - vpyContent += 'device_vfi=Backend.NCNN_VK()\n' - } - if (config_json.RifeInferenceValue === 'DML') { - vpyContent += 'device_vfi=Backend.ORT_DML()\n' - } - if (config_json.RifeInferenceValue === 'MIGX') { - vpyContent += 'device_vfi=Backend.MIGX()\n' - } - } - - vpyContent += 'device_vfi.device_id=0\n' - vpyContent += 'device_vfi.fp16=True\n' - vpyContent += `device_sr.num_streams=${config_json.Vfi_numstreams}\n` - vpyContent += 'from fractions import Fraction\n' - - if (config_json.VfiMethodValue === 'Rife') { - const model_switch = { - v4_0: 40, - v4_2: 42, - v4_3: 43, - v4_4: 44, - v4_5: 45, - v4_6: 46, - v4_7: 47, - v4_8: 48, - v4_9: 49, - v4_10: 410, - v4_11: 411, - v4_12: 412, - v4_12_lite: 4121, - v4_13: 413, - v4_13_lite: 4131, - v4_14: 414, - v4_14_lite: 4141, - v4_15: 415, - v4_15_lite: 4151, - v4_16_lite: 4161, - v4_17: 417, - v4_17_lite: 4171, - v4_18: 418, - v4_19: 419, - v4_20: 420, - v4_21: 421, - v4_22: 422, - v4_22_lite: 4221, - v4_23: 423, - v4_24: 424, - v4_25: 425, - v4_25_lite: 4251, - v4_25_heavy: 4252, - v4_26: 426, - v4_26_heavy: 4262, - } - const model = model_switch[config_json.RifeModelValue] || 40 - const EnsembleBool = config_json.RifeEnsembleValue ? 'True' : 'False' - vpyContent += `res = core.misc.SCDetect(res,threshold=${config_json.RifeDetectionValue})\n` - - vpyContent += 'res_height = (32 - res.height % 32) % 32\n' - vpyContent += 'res_width = (32 - res.width % 32) % 32\n' - vpyContent += 'res = core.std.AddBorders(clip=res, right=res_width, bottom=res_height)\n' - - vpyContent += `res = RIFE(res, scale=${config_json.RifeScaleValue},model=${model},ensemble=${EnsembleBool - },multi=Fraction(${config_json.RifeMultiValue},res.fps)` + `, backend=device_vfi)\n` - - vpyContent += 'res = core.std.Crop(clip=res, right=res_width, bottom=res_height)\n' - } - } - - // 后置缩放(需要在此改进色彩控制) - if (config_json.UseResize_AfterEnhance === true) { - vpyContent - += `res = core.resize.Bicubic(clip=res,width=${config_json.ResizeWidth_AfterEnhance - },height=${config_json.ResizeHeight_AfterEnhance},matrix_s="709", format=vs.YUV420P16)\n` - } - else { - vpyContent += 'res = core.resize.Bicubic(clip=res, matrix_s="709", format=vs.YUV420P16)\n' + if (hasSubtitle && taskconfig.isSavesubtitle === true) { + cmd += '"-map" "1:s" "-c:s" "copy" ' } - - vpyContent += `res = core.std.Crop(clip=res,left=${config_json.ReduceLeft_AfterEnhance - }, right=${config_json.ReduceRight_AfterEnhance - }, top=${config_json.ReduceOn_AfterEnhance - }, bottom=${config_json.ReduceDown_AfterEnhance})\n` - vpyContent += 'res.set_output()\n' - return vpyContent -} - -// 中断循环 -let shouldStop = false - -export function requestStop(): void { - shouldStop = true + return cmd } -export async function runCommand(event, config_json): Promise { +export async function runCommand(event, vpyContent, taskConfig, ffmpegCMD): Promise { const vspipePath = getExecPath().vspipe const ffmpegPath = getExecPath().ffmpeg const ffprobePath = getExecPath().ffprobe - const videos = config_json.fileList + const videos = Array.isArray(taskConfig.fileList) ? taskConfig.fileList : [] shouldStop = false @@ -526,7 +56,7 @@ export async function runCommand(event, config_json): Promise { try { // 生成唯一 vpy 路径 const baseName = path.basename(video, path.extname(video)) - const vpyPath = getGenVpyPath(config_json, baseName) + const vpyPath = getGenVpyPath(baseName) // ========== 1. 获取输入视频信息 ========== const ffprobeCommand = `"${ffprobePath}" -v error -show_streams -of json "${video}"` @@ -553,8 +83,7 @@ export async function runCommand(event, config_json): Promise { event.sender.send('ffmpeg-output', `是否含有字幕: ${subtitleText}\n`) } // ========== 2. 生成 vpy 文件 ========== - const vpyFile = generate_vpy(config_json, video) - writeFileSync(vpyPath, vpyFile) + writeFileSync(vpyPath, vpyContent.replace('__VIDEO_PATH__', video)) // ========== 3. 获取输出视频信息 ========== let info: { @@ -614,13 +143,30 @@ export async function runCommand(event, config_json): Promise { }) // ========== 4. 构建渲染命令 ========== - const cmd = generate_cmd(config_json, vspipePath, vpyPath, ffmpegPath, video, hasAudio, hasSubtitle) - event.sender.send('ffmpeg-output', `Executing command: ${cmd}\n`) + const vspipeArgs = ffmpegCMD[0].replace('__VPY_PATH__', vpyPath) + const ffmpegMajorArgs = ffmpegCMD[1] + const ffmpegMinorArgs = ffmpegCMD[2] + const ffmpeg_audio_sub_Args = generate_cmd(taskConfig, hasAudio, hasSubtitle) + + const ffmpegArgs = ffmpegMajorArgs.replace('__VIDEO_PATH__', video) + ffmpeg_audio_sub_Args + ffmpegMinorArgs.replace('__VIDEO_NAME__', path.join(taskConfig.outputfolder, `${baseName}_enchance.`) + taskConfig.videoContainer.toLowerCase()) + + const full_cmd = `${`"${vspipePath}" ${vspipeArgs}`} | "${ffmpegPath}" ${ffmpegArgs}` + event.sender.send('ffmpeg-output', `Executing command: ${full_cmd}\n`) // ========== 5. 渲染并监听输出 ========== await new Promise((resolve, reject) => { - const renderProcess = spawn(cmd, { shell: true }) + const renderProcess = spawn(ffmpegPath, splitArgs(ffmpegArgs), { shell: false }) + const vspipeProc = spawn(vspipePath, splitArgs(vspipeArgs), { shell: false }) + + event.sender.send('vspipePID', vspipeProc.pid) + event.sender.send('ffmpegPID', renderProcess.pid) + event.sender.send('ffmpeg-output', `vspipePID:${vspipeProc.pid} || ffmpegPID:${renderProcess.pid} \n`) + + vspipeProc.stdout.pipe(renderProcess.stdin) + addProcess(renderProcess) + addProcess(vspipeProc) + renderProcess.stdout.on('data', (data) => { event.sender.send('ffmpeg-output', data.toString()) }) @@ -655,9 +201,8 @@ export async function runCommand(event, config_json): Promise { }) renderProcess.on('close', () => { - removeProcess(renderProcess) + // removeProcess(renderProcess) event.sender.send('ffmpeg-output', 'finish\n') - resolve() }) @@ -673,3 +218,14 @@ export async function runCommand(event, config_json): Promise { } event.sender.send('ffmpeg-finish') } + +export async function PauseCommand(event, data: { isPause: boolean, vspipePID: number }): Promise { + const pssuspendPath = path.join(getCorePath(), 'pssuspend.exe') + const { isPause, vspipePID } = data + const action = isPause ? '' : '-r' + + const vspipeProc = spawn(pssuspendPath, ['-accepteula', action, vspipePID.toString()], { shell: true }) + vspipeProc.on('close', () => { + event.sender.send('ffmpeg-output', `${isPause ? '暂停' : '恢复'}完成\n`) + }) +} diff --git a/src/renderer/index.html b/src/renderer/index.html index e1bfe5c..d697473 100644 --- a/src/renderer/index.html +++ b/src/renderer/index.html @@ -2,7 +2,7 @@ - VSET 4.2.2 + VSET 4.3.6 -import useOutputconfigStore from '@renderer/store/OutputStote' +import useOutputconfigStore from '@renderer/store/OutputStore' import { storeToRefs } from 'pinia' -import { computed } from 'vue' + +import { + AmfH264_options, + AmfH265_options, + AudioContainer_options, + CpuAv1_options, + CpuH264_options, + CpuH265_options, + CpusvtAv1_options, + Encoder_options, + NvencAv1_options, + NvencH264_options, + NvencH265_options, + QSVH264_options, + QSVH265_options, + VideoContainer_options, +} from '../store/OutputMethod' const OutputConfigStore = useOutputconfigStore() const { bitValue, crfValue, + cqValue, + qbValue, encoderValue, - qualityValue, + + Libx265QualityValue, + Libx264QualityValue, + Libaomav1QualityValue, + Libsvtav1QualityValue, + HevcnvencQualityValue, + H264nvencQualityValue, + Av1nvencQualityValue, + HevcamfQualityValue, + H264amfQualityValue, + HevcqsvQualityValue, + H264qsvQualityValue, + videoContainer, AudioContainer, isUseCrf, isSaveAudio, - isSavesubtitle, - encoder_options, - CpuH265_options, - CpuH264_options, - CpuAv1_options, + isSaveSubtitle, - cpusvtav1_qualityValue, - CpusvtAv1_options, - - NvencH265_options, - NvencH264_options, - NvencAv1_options, - - VideoContainer_options, - AudioContainer_options, outputfolder, + isUseCustomParams, + CustomParams, } = storeToRefs(OutputConfigStore) -const qualityPresets = computed(() => { - switch (encoderValue.value) { - case 'libx265': - return CpuH265_options.value - case 'libx264': - return CpuH264_options.value - case 'libaom-av1': - return CpuAv1_options.value - case 'hevc_nvenc': - return NvencH265_options.value - case 'h264_nvenc': - return NvencH264_options.value - case 'av1_nvenc': - return NvencAv1_options.value - default: - return [] - } -}) - -function changeSelect(value: string) { - qualityValue.value = 'slow' - encoderValue.value = value -} - async function selectDirectory() { outputfolder.value = await window.electron.ipcRenderer.invoke('open-folder-dialog', ['openDirectory']) } @@ -70,10 +65,9 @@ async function selectDirectory() { placeholder="Select" size="large" style="width: 240px" - @change="changeSelect" > -
- 质量预设 +
+ 质量预设(libx265) - + + +
+ +
+ 质量预设(libx264) + + + +
+ +
+ 质量预设(libaom-av1) + +
- 质量预设 + 质量预设(libsvtav1)
-
- 质量控制参数 - - - 码率 - - - CRF - - +
+ 质量预设(hevc_nvenc) + + +
-
- 码率(M) - +
+ 质量预设(h264_nvenc) + + + +
+ +
+ 质量预设(av1_nvenc) + + +
-
+ +
+ 质量预设(hevc_amf) + + + +
+ +
+ 质量预设(h264_amf) + + + +
+ +
+ 质量预设(h265_qsv) + + + +
+ +
+ 质量预设(h264_qsv) + + + +
+ + + +
CRF
+
+ CQ + +
+ +
+ QP + +
+ +
+ 码率(M) + +
+
视频容器 字幕处理 - + 保留 @@ -199,6 +308,43 @@ async function selectDirectory() {
+ +
+ + 自定义 + + + + 自定义视频压制参数 +
+ +
+
+ +
+
+ + + +
@@ -225,8 +371,13 @@ async function selectDirectory() { } .flex-container { - display: flex; - flex-direction: column; /* 设置为垂直排列 */ - gap: 15px; /* 可选项,用于设置组件之间的间隔 */ - } + display: flex; + flex-direction: column; /* 设置为垂直排列 */ + gap: 15px; /* 可选项,用于设置组件之间的间隔 */ +} + +.flex-container-extra { + display: flex; + justify-content: flex-end; /* 水平方向靠右 */ +} diff --git a/src/renderer/src/components/PreviewPage.vue b/src/renderer/src/components/PreviewPage.vue index ffbf089..81f6d4d 100644 --- a/src/renderer/src/components/PreviewPage.vue +++ b/src/renderer/src/components/PreviewPage.vue @@ -1,13 +1,10 @@ + + + + diff --git a/src/renderer/src/components/RendingPage.vue b/src/renderer/src/components/RendingPage.vue deleted file mode 100644 index 1fef57f..0000000 --- a/src/renderer/src/components/RendingPage.vue +++ /dev/null @@ -1,295 +0,0 @@ - - - - - diff --git a/src/renderer/src/main.d.ts b/src/renderer/src/main.d.ts new file mode 100644 index 0000000..0400d3b --- /dev/null +++ b/src/renderer/src/main.d.ts @@ -0,0 +1 @@ +import 'element-plus/dist/index.css' diff --git a/src/renderer/src/main.js b/src/renderer/src/main.js new file mode 100644 index 0000000..09f7ddd --- /dev/null +++ b/src/renderer/src/main.js @@ -0,0 +1,17 @@ +import ElementPlus from 'element-plus' +import naive from 'naive-ui' +import { createPinia } from 'pinia' +import piniaPluginPersistedstate from 'pinia-plugin-persistedstate' +import { createApp } from 'vue' +import App from './App.vue' +import router from './router/index' +import 'element-plus/dist/index.css' + +const app = createApp(App) +const pinia = createPinia() +pinia.use(piniaPluginPersistedstate) +app.use(naive) +app.use(pinia) +app.use(ElementPlus) +app.use(router) +app.mount('#app') diff --git a/src/renderer/src/router/index.ts b/src/renderer/src/router/index.ts index 035bf0b..07cddea 100644 --- a/src/renderer/src/router/index.ts +++ b/src/renderer/src/router/index.ts @@ -6,7 +6,7 @@ import HomePage from '../components/HomePage.vue' import InputPage from '../components/InputPage.vue' import OutputPage from '../components/OutputPage.vue' import PreviewPage from '../components/PreviewPage.vue' -import RendingPage from '../components/RendingPage.vue' +import RenderPage from '../components/RenderPage.vue' const routes: Array = [ { @@ -42,7 +42,7 @@ const routes: Array = [ { path: '/rending', name: 'RendingPage', - component: RendingPage, + component: RenderPage, }, { path: '/preview', diff --git a/src/renderer/src/store/AppStore.ts b/src/renderer/src/store/AppStore.ts index b9266ec..b80966f 100644 --- a/src/renderer/src/store/AppStore.ts +++ b/src/renderer/src/store/AppStore.ts @@ -4,10 +4,22 @@ import { defineStore } from 'pinia' export const useAppStore = defineStore('app', { state: () => ({ isRunning: false, + isPause: true, + vspipePID: 0, + ffmpegPID: 0, }), actions: { setRunning(val: boolean) { this.isRunning = val }, + sePauste(val: boolean) { + this.isPause = val + }, + setVspipePID(val: number) { + this.vspipePID = val + }, + setFfmpegPID(val: number) { + this.ffmpegPID = val + }, }, }) diff --git a/src/renderer/src/store/InputStore.ts b/src/renderer/src/store/InputStore.ts index d3f3a57..053eeee 100644 --- a/src/renderer/src/store/InputStore.ts +++ b/src/renderer/src/store/InputStore.ts @@ -7,7 +7,7 @@ export interface FileWithPath extends File { } export default defineStore('inputConfig', () => { - const fileList = ref([]) + const fileList = ref<{ path: string }[]>([]) return { fileList, diff --git a/src/renderer/src/store/OutputMethod.ts b/src/renderer/src/store/OutputMethod.ts new file mode 100644 index 0000000..21858db --- /dev/null +++ b/src/renderer/src/store/OutputMethod.ts @@ -0,0 +1,504 @@ +const Encoder_options = [ + { value: 'libx265', label: 'CPU_H265' }, + { value: 'libx264', label: 'CPU_H264' }, + { value: 'libaom-av1', label: 'CPU_Av1' }, + { value: 'libsvtav1', label: 'CPU_svtAv1' }, + + { value: 'hevc_nvenc', label: 'NVENC_H265' }, + { value: 'h264_nvenc', label: 'NVENC_H264' }, + { value: 'av1_nvenc', label: 'NVENC_Av1' }, + + { value: 'hevc_amf', label: 'AMF_H265' }, + { value: 'h264_amf', label: 'AMF_H264' }, + +] + +const CpuH265_options = [ + { + value: 'veryslow', + label: 'veryslow', + }, + { + value: 'slower', + label: 'slower', + }, + { + value: 'slow', + label: 'slow', + }, + { + value: 'medium', + label: 'medium', + }, + { + value: 'fast', + label: 'fast', + }, + { + value: 'faster', + label: 'faster', + }, + { + value: 'veryfast', + label: 'veryfast', + }, +] + +const CpuH264_options = [ + { + value: 'veryslow', + label: 'veryslow', + }, + { + value: 'slower', + label: 'slower', + }, + { + value: 'slow', + label: 'slow', + }, + { + value: 'medium', + label: 'medium', + }, + { + value: 'fast', + label: 'fast', + }, + { + value: 'faster', + label: 'faster', + }, + { + value: 'veryfast', + label: 'veryfast', + }, +] + +const CpuAv1_options = [ + { + value: '0', + label: '0', + }, + { + value: '1', + label: '1', + }, + { + value: '2', + label: '2', + }, + { + value: '3', + label: '3', + }, + { + value: '4', + label: '4', + }, + { + value: '5', + label: '5', + }, + { + value: '6', + label: '6', + }, + { + value: '7', + label: '7', + }, + { + value: '8', + label: '8', + }, +] + +const CpusvtAv1_options = [ + { + value: '0', + label: '0', + }, + { + value: '1', + label: '1', + }, + { + value: '2', + label: '2', + }, + { + value: '3', + label: '3', + }, + { + value: '4', + label: '4', + }, + { + value: '5', + label: '5', + }, + { + value: '6', + label: '6', + }, + { + value: '7', + label: '7', + }, + { + value: '8', + label: '8', + }, + { + value: '9', + label: '9', + }, + { + value: '10', + label: '10', + }, + { + value: '11', + label: '11', + }, + { + value: '12', + label: '12', + }, + { + value: '13', + label: '13', + }, +] + +const NvencH265_options = [ + { + value: 'slow', + label: 'slow', + }, + { + value: 'medium', + label: 'medium', + }, + { + value: 'fast', + label: 'fast', + }, + { + value: 'hp', + label: 'hp', + }, + { + value: 'hq', + label: 'hq', + }, + { + value: 'bd', + label: 'bd', + }, + { + value: 'll', + label: 'll', + }, + { + value: 'llhq', + label: 'llhq', + }, + { + value: 'llhp', + label: 'llhp', + }, + { + value: 'p1', + label: 'p1', + }, + { + value: 'p2', + label: 'p2', + }, + { + value: 'p3', + label: 'p3', + }, + { + value: 'p4', + label: 'p4', + }, + { + value: 'p5', + label: 'p5', + }, + { + value: 'p6', + label: 'p6', + }, + { + value: 'p7', + label: 'p7', + }, + +] + +const NvencH264_options = [ + { + value: 'slow', + label: 'slow', + }, + { + value: 'medium', + label: 'medium', + }, + { + value: 'fast', + label: 'fast', + }, + { + value: 'hp', + label: 'hp', + }, + { + value: 'hq', + label: 'hq', + }, + { + value: 'bd', + label: 'bd', + }, + { + value: 'll', + label: 'll', + }, + { + value: 'llhq', + label: 'llhq', + }, + { + value: 'llhp', + label: 'llhp', + }, + { + value: 'p1', + label: 'p1', + }, + { + value: 'p2', + label: 'p2', + }, + { + value: 'p3', + label: 'p3', + }, + { + value: 'p4', + label: 'p4', + }, + { + value: 'p5', + label: 'p5', + }, + { + value: 'p6', + label: 'p6', + }, + { + value: 'p7', + label: 'p7', + }, +] + +const NvencAv1_options = [ + { + value: 'slow', + label: 'slow', + }, + { + value: 'medium', + label: 'medium', + }, + { + value: 'fast', + label: 'fast', + }, + { + value: 'p1', + label: 'p1', + }, + { + value: 'p2', + label: 'p2', + }, + { + value: 'p3', + label: 'p3', + }, + { + value: 'p4', + label: 'p4', + }, + { + value: 'p5', + label: 'p5', + }, + { + value: 'p6', + label: 'p6', + }, + { + value: 'p7', + label: 'p7', + }, +] + +const AmfH265_options = [ + { + value: '0', + label: '0', + }, + { + value: '1', + label: '1', + }, + { + value: '2', + label: '2', + }, + { + value: '3', + label: '3', + }, + { + value: '4', + label: '4', + }, + { + value: '5', + label: '5', + }, + { + value: '6', + label: '6', + }, + { + value: '7', + label: '7', + }, + { + value: '8', + label: '8', + }, + { + value: '9', + label: '9', + }, + { + value: '10', + label: '10', + }, +] + +const AmfH264_options = [ + { + value: '0', + label: '0', + }, + { + value: '1', + label: '1', + }, + { + value: '2', + label: '2', + }, +] + +const QSVH265_options = [ + { + value: 'veryslow', + label: 'veryslow', + }, + { + value: 'slower', + label: 'slower', + }, + { + value: 'slow', + label: 'slow', + }, + { + value: 'medium', + label: 'medium', + }, + { + value: 'fast', + label: 'fast', + }, + { + value: 'faster', + label: 'faster', + }, + { + value: 'veryfast', + label: 'veryfast', + }, +] + +const QSVH264_options = [ + { + value: 'veryslow', + label: 'veryslow', + }, + { + value: 'slower', + label: 'slower', + }, + { + value: 'slow', + label: 'slow', + }, + { + value: 'medium', + label: 'medium', + }, + { + value: 'fast', + label: 'fast', + }, + { + value: 'faster', + label: 'faster', + }, + { + value: 'veryfast', + label: 'veryfast', + }, +] + +const VideoContainer_options = [ + { + value: 'mp4', + label: 'MP4', + }, + { + value: 'mkv', + label: 'MKV', + }, + { + value: 'mov', + label: 'MOV', + }, +] + +const AudioContainer_options = [ + { + value: 'aac', + label: 'AAC', + }, + { + value: 'flac', + label: 'FLAC', + }, +] + +export { AmfH264_options, AmfH265_options, AudioContainer_options, CpuAv1_options, CpuH264_options, CpuH265_options, CpusvtAv1_options, Encoder_options, NvencAv1_options, NvencH264_options, NvencH265_options, QSVH264_options, QSVH265_options, VideoContainer_options } diff --git a/src/renderer/src/store/OutputStore.ts b/src/renderer/src/store/OutputStore.ts new file mode 100644 index 0000000..fdd385b --- /dev/null +++ b/src/renderer/src/store/OutputStore.ts @@ -0,0 +1,67 @@ +import { defineStore } from 'pinia' +import { ref } from 'vue' + +export default defineStore('outputconfig', () => { + const bitValue = ref(20) + const crfValue = ref(16) + const cqValue = ref(25) + const qbValue = ref(25) + + const encoderValue = ref('libx265') + + const Libx265QualityValue = ref('medium') + const Libx264QualityValue = ref('medium') + const Libaomav1QualityValue = ref('4') + const Libsvtav1QualityValue = ref('5') + const HevcnvencQualityValue = ref('medium') + const H264nvencQualityValue = ref('medium') + const Av1nvencQualityValue = ref('medium') + const HevcamfQualityValue = ref('5') + const H264amfQualityValue = ref('0') + const HevcqsvQualityValue = ref('medium') + const H264qsvQualityValue = ref('medium') + + const videoContainer = ref('MP4') + const AudioContainer = ref('AAC') + + const isUseCrf = ref(true) + const isSaveAudio = ref(false) + const isSaveSubtitle = ref(false) + + const outputfolder = ref('') + const isUseCustomParams = ref(false) + const CustomParams = ref('') + + return { + bitValue, + crfValue, + cqValue, + qbValue, + encoderValue, + + Libx265QualityValue, + Libx264QualityValue, + Libaomav1QualityValue, + Libsvtav1QualityValue, + HevcnvencQualityValue, + H264nvencQualityValue, + Av1nvencQualityValue, + HevcamfQualityValue, + H264amfQualityValue, + HevcqsvQualityValue, + H264qsvQualityValue, + + videoContainer, + AudioContainer, + isUseCrf, + + isSaveAudio, + isSaveSubtitle, + + outputfolder, + isUseCustomParams, + CustomParams, + } +}, { + persist: true, +}) diff --git a/src/renderer/src/store/OutputStote.ts b/src/renderer/src/store/OutputStote.ts deleted file mode 100644 index c25a424..0000000 --- a/src/renderer/src/store/OutputStote.ts +++ /dev/null @@ -1,327 +0,0 @@ -import { defineStore } from 'pinia' -import { ref } from 'vue' - -const defaultEncoderOptions = [ - { value: 'libx265', label: 'CPU_H265' }, - { value: 'libx264', label: 'CPU_H264' }, - { value: 'libaom-av1', label: 'CPU_Av1' }, - { value: 'libsvtav1', label: 'CPU_svtAv1' }, - { value: 'hevc_nvenc', label: 'NVENC_H265' }, - { value: 'h264_nvenc', label: 'NVENC_H264' }, - { value: 'av1_nvenc', label: 'NVENC_Av1' }, -] - -export default defineStore('outputconfig', () => { - const bitValue = ref(20) - const crfValue = ref(16) - - const encoderValue = ref('libx265') - const qualityValue = ref('slow') - const videoContainer = ref('MP4') - const AudioContainer = ref('AAC') - - const cpusvtav1_qualityValue = ref('3') - - const isUseCrf = ref(true) - const isSaveAudio = ref(false) - const isSavesubtitle = ref(false) - - const outputfolder = ref('') - const encoder_options = ref([...defaultEncoderOptions]) - - const CpuH265_options = ref([ - { - value: 'veryslow', - label: 'veryslow', - }, - { - value: 'slower', - label: 'slower', - }, - { - value: 'slow', - label: 'slow', - }, - { - value: 'medium', - label: 'medium', - }, - { - value: 'fast', - label: 'fast', - }, - { - value: 'faster', - label: 'faster', - }, - { - value: 'veryfast', - label: 'veryfast', - }, - ]) - - const CpuH264_options = CpuH265_options - const CpuAv1_options = CpuH265_options - - const CpusvtAv1_options = ref([ - { - value: '0', - label: '0', - }, - { - value: '1', - label: '1', - }, - { - value: '2', - label: '2', - }, - { - value: '3', - label: '3', - }, - { - value: '4', - label: '4', - }, - { - value: '5', - label: '5', - }, - { - value: '6', - label: '6', - }, - { - value: '7', - label: '7', - }, - { - value: '8', - label: '8', - }, - { - value: '9', - label: '9', - }, - { - value: '10', - label: '10', - }, - { - value: '11', - label: '11', - }, - { - value: '12', - label: '12', - }, - { - value: '13', - label: '13', - }, - ]) - - const NvencH265_options = ref([ - { - value: 'slow', - label: 'slow', - }, - { - value: 'medium', - label: 'medium', - }, - { - value: 'fast', - label: 'fast', - }, - { - value: 'hp', - label: 'hp', - }, - { - value: 'hq', - label: 'hq', - }, - { - value: 'bd', - label: 'bd', - }, - { - value: 'll', - label: 'll', - }, - { - value: 'llhq', - label: 'llhq', - }, - { - value: 'llhp', - label: 'llhp', - }, - { - value: 'p1', - label: 'p1', - }, - { - value: 'p2', - label: 'p2', - }, - { - value: 'p3', - label: 'p3', - }, - { - value: 'p4', - label: 'p4', - }, - { - value: 'p5', - label: 'p5', - }, - { - value: 'p6', - label: 'p6', - }, - { - value: 'p7', - label: 'p7', - }, - - ]) - - const NvencH264_options = ref([ - { - value: 'slow', - label: 'slow', - }, - { - value: 'medium', - label: 'medium', - }, - { - value: 'fast', - label: 'fast', - }, - { - value: 'hp', - label: 'hp', - }, - { - value: 'hq', - label: 'hq', - }, - { - value: 'bd', - label: 'bd', - }, - { - value: 'll', - label: 'll', - }, - { - value: 'llhq', - label: 'llhq', - }, - { - value: 'llhp', - label: 'llhp', - }, - ]) - - const NvencAv1_options = ref([ - { - value: 'slow', - label: 'slow', - }, - { - value: 'medium', - label: 'medium', - }, - { - value: 'fast', - label: 'fast', - }, - { - value: 'hp', - label: 'hp', - }, - { - value: 'hq', - label: 'hq', - }, - ]) - - const VideoContainer_options = ref([ - { - value: 'mp4', - label: 'MP4', - }, - { - value: 'mkv', - label: 'MKV', - }, - { - value: 'mov', - label: 'MOV', - }, - ]) - - const AudioContainer_options = ref([ - { - value: 'aac', - label: 'AAC', - }, - { - value: 'flac', - label: 'FLAC', - }, - ]) - - return { - bitValue, - crfValue, - encoderValue, - qualityValue, - - cpusvtav1_qualityValue, - CpusvtAv1_options, - - videoContainer, - AudioContainer, - isUseCrf, - - isSaveAudio, - isSavesubtitle, - encoder_options, - CpuH265_options, - CpuH264_options, - - CpuAv1_options, - NvencH265_options, - NvencH264_options, - NvencAv1_options, - - VideoContainer_options, - AudioContainer_options, - - outputfolder, - } -}, { - persist: { - afterRestore: (ctx) => { - // 1. 确保 encoderValue 有默认值 - if (!ctx.store.encoderValue) { - ctx.store.encoderValue = 'libx265' - } - - // 2. 合并 encoder_options 默认值 - const existingValues = new Set(ctx.store.encoder_options.map(e => e.value)) - defaultEncoderOptions.forEach((opt) => { - if (!existingValues.has(opt.value)) { - ctx.store.encoder_options.push(opt) - } - }) - }, - }, -} as any) diff --git a/src/renderer/src/type/config.ts b/src/renderer/src/type/config.ts index 81370df..b82b913 100644 --- a/src/renderer/src/type/config.ts +++ b/src/renderer/src/type/config.ts @@ -1,63 +1,8 @@ -// interface ConfigType { -// fileList: fileListNames, -// useSR: useSR.value, -// SRMethodValue: SRMethodValue.value, -// RealcuganTileValue: RealcuganTileValue.value, -// RealcuganInferenceValue: RealcuganInferenceValue.value, -// RealcuganModelValue: RealcuganModelValue.value, -// RealcuganAlphaValue: RealcuganAlphaValue.value, -// RealesrganInferenceValue: RealesrganInferenceValue.value, -// RealesrganModelValue: RealesrganModelValue.value, -// RealesrganTileValue: RealesrganTileValue.value, -// RealesrganScaleValue: RealesrganScaleValue.value, -// // ArtCNNInferenceValue: ArtCNNInferenceValue.value, -// // ArtCNNModelValue: ArtCNNModelValue.value, -// // ArtCNNTileValue: ArtCNNTileValue.value, -// Waifu2xInferenceValue: Waifu2xInferenceValue.value, -// Waifu2xModelValue: Waifu2xModelValue.value, -// Waifu2xTileValue: Waifu2xTileValue.value, -// SwinIRInferenceValue: SwinIRInferenceValue.value, -// SwinIRModelValue: SwinIRModelValue.value, -// SwinIRTileValue: SwinIRTileValue.value, -// SR_ExtraModelValue: SR_ExtraModelValue.value, -// SR_ExtraModelInferenceValue: SR_ExtraModelInferenceValue.value, -// Sr_numstreams: Sr_numstreams.value, -// Sr_cudagraph: Sr_cudagraph.value, -// -// useVfi: useVfi.value, -// VfiMethodValue: VfiMethodValue.value, -// RifeInferenceValue: RifeInferenceValue.value, -// RifeModelValue: RifeModelValue.value, -// RifeScaleValue: RifeScaleValue.value, -// RifeMultiValue: RifeMultiValue.value, -// RifeEnsembleValue: RifeEnsembleValue.value, -// RifeDetectionValue: RifeDetectionValue.value, -// Vfi_numstreams: Vfi_numstreams.value, -// Vfi_cudagraph: Vfi_cudagraph.value, -// -// UseResize_BeforeEnhance: UseResize_BeforeEnhance.value, -// UseResize_AfterEnhance: UseResize_AfterEnhance.value, -// ResizeWidth_BeforeEnhance: ResizeWidth_BeforeEnhance.value, -// ResizeHeight_BeforeEnhance: ResizeHeight_BeforeEnhance.value, -// ResizeWidth_AfterEnhance: ResizeWidth_AfterEnhance.value, -// ResizeHeight_AfterEnhance: ResizeHeight_AfterEnhance.value, -// ReduceLeft_BeforeEnhance: ReduceLeft_BeforeEnhance.value, -// ReduceRight_BeforeEnhance: ReduceRight_BeforeEnhance.value, -// ReduceOn_BeforeEnhance: ReduceOn_BeforeEnhance.value, -// ReduceDown_BeforeEnhance: ReduceDown_BeforeEnhance.value, -// ReduceLeft_AfterEnhance: ReduceLeft_AfterEnhance.value, -// ReduceRight_AfterEnhance: ReduceRight_AfterEnhance.value, -// ReduceOn_AfterEnhance: ReduceOn_AfterEnhance.value, -// ReduceDown_AfterEnhance: ReduceDown_AfterEnhance.value, -// -// bitValue: bitValue.value, -// crfValue: crfValue.value, -// encoderValue: encoderValue.value, -// qualityValue: qualityValue.value, -// videoContainer: videoContainer.value, -// AudioContainer: AudioContainer.value, -// isUseCrf: isUseCrf.value, -// isSaveAudio: isSaveAudio.value, -// isSavesubtitle: isSavesubtitle.value, -// outputfolder: outputfolder.value, -// } +export interface JsonData { + fileList: string[] + AudioContainer: string + isSaveAudio: boolean + isSaveSubtitle: boolean + videoContainer: string + outputfolder: string +} diff --git a/src/renderer/src/utils/checkSetting.ts b/src/renderer/src/utils/checkSetting.ts new file mode 100644 index 0000000..3160c90 --- /dev/null +++ b/src/renderer/src/utils/checkSetting.ts @@ -0,0 +1,44 @@ +import useOutputconfigStore from '@renderer/store/OutputStore' +import useVfisettingconfigStore from '@renderer/store/VfiSettingsStore' +import { storeToRefs } from 'pinia' + +export function CheckSetting(): boolean { + const VfiSettingStore = useVfisettingconfigStore() + const OutputConfigStore = useOutputconfigStore() + + const { + useVfi, + RifeModelValue, + RifeScaleValue, + RifeEnsembleValue, + } = storeToRefs(VfiSettingStore) + const { + outputfolder, + } = storeToRefs(OutputConfigStore) + + if (!outputfolder.value) { + return false// 终止后续执行 + } + + if (useVfi.value === true) { + // ensemble参数判断 + if (RifeEnsembleValue.value === true) { + if (RifeModelValue.value === 'v4_21' || RifeModelValue.value === 'v4_22' || RifeModelValue.value === 'v4_22_lite' || RifeModelValue.value === 'v4_23' + || RifeModelValue.value === 'v4_25' || RifeModelValue.value === 'v4_25_lite' || RifeModelValue.value === 'v4_25_heavy' || RifeModelValue.value === 'v4_26' + || RifeModelValue.value === 'v4_26_heavy') { + return false// 终止后续执行 + } + if (RifeScaleValue.value !== 1.0) { + return false// 终止后续执行 + } + } + // 光流参数判断 + if (RifeScaleValue.value !== 1) { + if (RifeModelValue.value !== 'v4_0' && RifeModelValue.value !== 'v4_2' && RifeModelValue.value !== 'v4_3' + && RifeModelValue.value !== 'v4_4' && RifeModelValue.value !== 'v4_5' && RifeModelValue.value !== 'v4_6') { + return false// 终止后续执行} + } + } + } + return true +} diff --git a/src/renderer/src/utils/getFfmpegConfig.ts b/src/renderer/src/utils/getFfmpegConfig.ts new file mode 100644 index 0000000..8f32b0c --- /dev/null +++ b/src/renderer/src/utils/getFfmpegConfig.ts @@ -0,0 +1,177 @@ +// 引入 store +import useOutputconfigStore from '@renderer/store/OutputStore' +import { storeToRefs } from 'pinia' + +// ✅ 生成 JSON 数据的函数 +export function buildFfmpegCMD(): string[] { + // Output + const OutputConfigStore = useOutputconfigStore() + const { + bitValue, + crfValue, + cqValue, + qbValue, + encoderValue, + Libx265QualityValue, + Libx264QualityValue, + Libaomav1QualityValue, + Libsvtav1QualityValue, + HevcnvencQualityValue, + H264nvencQualityValue, + Av1nvencQualityValue, + HevcamfQualityValue, + H264amfQualityValue, + HevcqsvQualityValue, + H264qsvQualityValue, + isUseCrf, + isUseCustomParams, + CustomParams, + } = storeToRefs(OutputConfigStore) + + // ✅ 返回 JSON 对象 + let cmd_major = '' + let cmd_minor = '' + + if (isUseCustomParams.value !== true) { + cmd_major + += `"-hide_banner" "-y" "-i" "pipe:" "-i" "__VIDEO_PATH__"` + + ` "-map" "0:v:0" ` + cmd_minor += `"-c:v" "${encoderValue.value}" ` + if (encoderValue.value === 'libx265') { + cmd_minor + += `"-pix_fmt" "yuv420p10le" "-profile:v" "main10" "-vtag" "hvc1" ` + + `"-preset" "${ + Libx265QualityValue.value + }" ` + if (isUseCrf.value === true) { + cmd_minor += `"-crf" "${crfValue.value}" ` + } + else { + cmd_minor += `"-b:v" "${bitValue.value}M" ` + } + } + + if (encoderValue.value === 'libx264') { + cmd_minor + += `"-pix_fmt" "yuv420p" "-profile:v" "main" ` + + `"-preset" "${ + Libx264QualityValue.value + }" ` + if (isUseCrf.value === true) { + cmd_minor += `"-crf" "${crfValue.value}" ` + } + else { + cmd_minor += `"-b:v" "${bitValue.value}M" ` + } + } + + if (encoderValue.value === 'libaom-av1') { + cmd_minor += `"-pix_fmt" "yuv420p10le" ` + `"-cpu-used" "${Libaomav1QualityValue.value}" ` + if (isUseCrf.value === true) { + cmd_minor += `"-crf" "${crfValue.value}" ` + } + else { + cmd_minor += `"-b:v" "${bitValue.value}M" ` + } + } + + if (encoderValue.value === 'libsvtav1') { + cmd_minor += `"-pix_fmt" "yuv420p10le" ` + `"-preset" "${Libsvtav1QualityValue.value}" ` + if (isUseCrf.value === true) { + cmd_minor += `"-crf" "${crfValue.value}" ` + } + else { + cmd_minor += `"-b:v" "${bitValue.value}M" ` + } + } + + if (encoderValue.value === 'h264_nvenc') { + cmd_minor + += `"-pix_fmt" "yuv420p" ` + + `"-preset" "${ + H264nvencQualityValue.value + }" ` + + `"-cq" "${ + cqValue.value + }" ` + } + + if (encoderValue.value === 'hevc_nvenc') { + cmd_minor + += `"-pix_fmt" "p010le" "-profile:v" "main10" "-vtag" "hvc1" ` + + `"-preset" "${ + HevcnvencQualityValue.value + }" ` + + `"-cq" "${ + cqValue.value + }" ` + } + + if (encoderValue.value === 'av1_nvenc') { + cmd_minor + += `"-pix_fmt" "p010le" ` + + `"-preset" "${ + Av1nvencQualityValue.value + }" ` + + `"-qp" "${ + qbValue.value + }" ` + } + + if (encoderValue.value === 'hevc_amf') { + cmd_minor + += `"-pix_fmt" "yuv420p" ` + + `"-quality" "${ + HevcamfQualityValue.value + }" ` + + `"-qp" "${ + qbValue.value + }" ` + } + + if (encoderValue.value === 'h264_amf') { + cmd_minor + += `"-pix_fmt" "yuv420p" ` + + `"-quality" "${ + H264amfQualityValue.value + }" ` + + `"-qp" "${ + qbValue.value + }" ` + } + + if (encoderValue.value === 'h265_qsv') { + cmd_minor + += `"-pix_fmt" "p010le" "-profile:v" "main10" ` + + `"-preset" "${ + HevcqsvQualityValue.value + }" ` + + `"-qp" "${ + qbValue.value + }" ` + } + + if (encoderValue.value === 'h264_qsv') { + cmd_minor + += `"-pix_fmt" "nv12" ` + + `"-preset" "${ + H264qsvQualityValue.value + }" ` + + `"-qp" "${ + qbValue.value + }" ` + } + } + + else { + cmd_major += `"-hide_banner" "-y" "-i" "pipe:" "-i" "__VIDEO_PATH__" ` + cmd_minor + += `${CustomParams.value.trim().split(/\s+/).filter(Boolean).map(p => `"${p}"`).join(' ') + } ` + } + + cmd_minor += `"__VIDEO_NAME__"` + + const vspipecmd = `"-c" "y4m" "__VPY_PATH__" "-"` + return [vspipecmd, cmd_major, cmd_minor] +} diff --git a/src/renderer/src/utils/getTaskConfig.ts b/src/renderer/src/utils/getTaskConfig.ts new file mode 100644 index 0000000..0bc6641 --- /dev/null +++ b/src/renderer/src/utils/getTaskConfig.ts @@ -0,0 +1,35 @@ +import type { JsonData } from '@renderer/type/config' + +// 引入 store +import useInputconfigStore from '@renderer/store/InputStore' +import useOutputconfigStore from '@renderer/store/OutputStore' + +import { storeToRefs } from 'pinia' + +// ✅ 生成 JSON 数据的函数 +export function buildJsonData(): JsonData { + // Input + const InputConfigStore = useInputconfigStore() + const { fileList } = storeToRefs(InputConfigStore) + const fileListNames = fileList.value.map(file => (file.path).replace(/\\/g, '/')) + + // Output + const OutputConfigStore = useOutputconfigStore() + const { + AudioContainer, + isSaveAudio, + isSaveSubtitle, + outputfolder, + videoContainer, + } = storeToRefs(OutputConfigStore) + + // ✅ 返回 JSON 对象 + return { + fileList: fileListNames, + AudioContainer: AudioContainer.value, + isSaveAudio: isSaveAudio.value, + isSaveSubtitle: isSaveSubtitle.value, + outputfolder: String(outputfolder.value), + videoContainer: videoContainer.value, + } +} diff --git a/src/renderer/src/utils/getVpyConfig.ts b/src/renderer/src/utils/getVpyConfig.ts new file mode 100644 index 0000000..b7e0f29 --- /dev/null +++ b/src/renderer/src/utils/getVpyConfig.ts @@ -0,0 +1,434 @@ +import path from 'node:path' + +import useFilterconfigStore from '@renderer/store/FilterStore' +import useSrsettingconfigStore from '@renderer/store/SrSettingsStore' +import useVfisettingconfigStore from '@renderer/store/VfiSettingsStore' + +import { storeToRefs } from 'pinia' + +// ✅ 生成 JSON 数据的函数 +export function buildVpyContent(): string { + // SR + const SrSettingStore = useSrsettingconfigStore() + const { + useSR, + SRMethodValue, + RealcuganTileValue, + RealcuganInferenceValue, + RealcuganModelValue, + RealcuganAlphaValue, + RealesrganInferenceValue, + RealesrganModelValue, + RealesrganTileValue, + RealesrganScaleValue, + Waifu2xInferenceValue, + Waifu2xModelValue, + Waifu2xTileValue, + SR_ExtraModelValue, + SR_ExtraModelInferenceValue, + Sr_numstreams, + Sr_cudagraph, + } = storeToRefs(SrSettingStore) + + // VFI + const VfiSettingStore = useVfisettingconfigStore() + const { + useVfi, + VfiMethodValue, + RifeInferenceValue, + RifeModelValue, + RifeScaleValue, + RifeMultiValue, + RifeEnsembleValue, + RifeDetectionValue, + Vfi_numstreams, + Vfi_cudagraph, + } = storeToRefs(VfiSettingStore) + + // Filter + const FilterConfigStore = useFilterconfigStore() + const { + UseResize_BeforeEnhance, + UseResize_AfterEnhance, + ResizeWidth_BeforeEnhance, + ResizeHeight_BeforeEnhance, + ResizeWidth_AfterEnhance, + ResizeHeight_AfterEnhance, + ReduceLeft_BeforeEnhance, + ReduceRight_BeforeEnhance, + ReduceOn_BeforeEnhance, + ReduceDown_BeforeEnhance, + ReduceLeft_AfterEnhance, + ReduceRight_AfterEnhance, + ReduceOn_AfterEnhance, + ReduceDown_AfterEnhance, + } = storeToRefs(FilterConfigStore) + + // ✅ 返回 JSON 对象 + let vpyContent = '' + + vpyContent += 'import vapoursynth as vs\n' + vpyContent += 'core = vs.core\n' + vpyContent += `res = core.lsmas.LWLibavSource(r"__VIDEO_PATH__")\n` + vpyContent += 'from vsmlrt import CUGAN,RealESRGAN,Waifu2x,RIFE,Backend\n' + vpyContent += 'import vsmlrt\n' + + // 前置缩放(需要在此改进色彩控制) + if (UseResize_BeforeEnhance.value === true) { + vpyContent + += `res = core.resize.Bicubic(clip=res,width=${ResizeWidth_BeforeEnhance.value + },height=${ResizeHeight_BeforeEnhance.value},format=vs.YUV420P16)\n` + } + else { + vpyContent += 'res = core.resize.Bicubic(clip=res,format=vs.YUV420P16)\n' + } + + vpyContent += `res = core.std.Crop(clip=res,left=${ReduceLeft_BeforeEnhance.value + }, right=${ReduceRight_BeforeEnhance.value + }, top=${ReduceOn_BeforeEnhance.value + }, bottom=${ReduceDown_BeforeEnhance.value})\n` + + // 超分 + if (useSR.value === true) { + vpyContent += 'res = core.resize.Bicubic(clip=res,range=1,matrix_in_s="709",format=vs.RGB48)\n' + vpyContent += 'res=core.fmtc.bitdepth(res, bits=32)\n' + + // 超分设备 + if (SRMethodValue.value === 'Real_cugan') { + if (RealcuganInferenceValue.value === 'Cuda') { + vpyContent += 'device_sr=Backend.ORT_CUDA()\n' + } + if (RealcuganInferenceValue.value === 'TensorRt') { + vpyContent += 'device_sr=Backend.TRT()\n' + vpyContent += `device_sr.use_cuda_graph = ${String(Sr_cudagraph.value)[0].toUpperCase() + String(Sr_cudagraph.value).slice(1)}\n` + } + if (RealcuganInferenceValue.value === 'NCNN') { + vpyContent += 'device_sr=Backend.NCNN_VK()\n' + } + if (RealcuganInferenceValue.value === 'DML') { + vpyContent += 'device_sr=Backend.ORT_DML()\n' + } + if (RealcuganInferenceValue.value === 'MIGX') { + vpyContent += 'device_sr=Backend.MIGX()\n' + } + } + if (SRMethodValue.value === 'Real_esrgan') { + if (RealesrganInferenceValue.value === 'Cuda') { + vpyContent += 'device_sr=Backend.ORT_CUDA()\n' + } + if (RealesrganInferenceValue.value === 'TensorRt') { + vpyContent += 'device_sr=Backend.TRT()\n' + vpyContent += `device_sr.use_cuda_graph = ${String(Sr_cudagraph.value)[0].toUpperCase() + String(Sr_cudagraph.value).slice(1)}\n` + } + if (RealesrganInferenceValue.value === 'TensorRt_RTX') { + vpyContent += 'device_sr=Backend.TRT_RTX()\n' + } + if (RealesrganInferenceValue.value === 'NCNN') { + vpyContent += 'device_sr=Backend.NCNN_VK()\n' + } + if (RealesrganInferenceValue.value === 'DML') { + vpyContent += 'device_sr=Backend.ORT_DML()\n' + } + if (RealesrganInferenceValue.value === 'MIGX') { + vpyContent += 'device_sr=Backend.MIGX()\n' + } + } + if (SRMethodValue.value === 'Waifu2x') { + if (Waifu2xInferenceValue.value === 'Cuda') { + vpyContent += 'device_sr=Backend.ORT_CUDA()\n' + } + if (Waifu2xInferenceValue.value === 'TensorRt') { + vpyContent += 'device_sr=Backend.TRT()\n' + vpyContent += `device_sr.use_cuda_graph = ${String(Sr_cudagraph.value)[0].toUpperCase() + String(Sr_cudagraph.value).slice(1)}\n` + } + if (Waifu2xInferenceValue.value === 'TensorRt_RTX') { + vpyContent += 'device_sr=Backend.TRT_RTX()\n' + } + if (Waifu2xInferenceValue.value === 'NCNN') { + vpyContent += 'device_sr=Backend.NCNN_VK()\n' + } + if (Waifu2xInferenceValue.value === 'DML') { + vpyContent += 'device_sr=Backend.ORT_DML()\n' + } + if (Waifu2xInferenceValue.value === 'MIGX') { + vpyContent += 'device_sr=Backend.MIGX()\n' + } + } + if (SRMethodValue.value === 'SR_ExtraModel') { + if (SR_ExtraModelInferenceValue.value === 'Cuda') { + vpyContent += 'device_sr=Backend.ORT_CUDA()\n' + } + if (SR_ExtraModelInferenceValue.value === 'TensorRt') { + vpyContent += 'device_sr=Backend.TRT()\n' + vpyContent += `device_sr.use_cuda_graph = ${String(Sr_cudagraph.value)[0].toUpperCase() + String(Sr_cudagraph.value).slice(1)}\n` + } + if (SR_ExtraModelInferenceValue.value === 'NCNN') { + vpyContent += 'device_sr=Backend.NCNN_VK()\n' + } + if (SR_ExtraModelInferenceValue.value === 'DML') { + vpyContent += 'device_sr=Backend.ORT_DML()\n' + } + if (SR_ExtraModelInferenceValue.value === 'MIGX') { + vpyContent += 'device_sr=Backend.MIGX()\n' + } + } + + vpyContent += 'device_sr.device_id=0\n' + vpyContent += 'device_sr.fp16=True\n' + vpyContent += `device_sr.num_streams=${Sr_numstreams.value}\n` + + if (SRMethodValue.value === 'Real_cugan') { + const model_switch = { + 'pro-conservative-up2x': [0, 2, 2], + 'pro-conservative-up3x': [0, 3, 2], + 'pro-denoise3x-up2x': [3, 2, 2], + 'pro-denoise3x-up3x': [3, 3, 2], + 'pro-no-denoise3x-up2x': [-1, 2, 2], + 'pro-no-denoise3x-up3x': [-1, 3, 2], + 'up2x-latest-conservative': [0, 2, 1], + 'up2x-latest-denoise1x': [1, 2, 1], + 'up2x-latest-denoise2x': [2, 2, 1], + 'up2x-latest-denoise3x': [3, 2, 1], + 'up2x-latest-no-denoise': [-1, 2, 1], + 'up3x-latest-conservative': [0, 3, 1], + 'up3x-latest-denoise3x': [3, 3, 1], + 'up3x-latest-no-denoise': [-1, 3, 1], + 'up4x-latest-conservative': [0, 4, 1], + 'up4x-latest-denoise3x': [3, 4, 1], + 'up4x-latest-no-denoise': [-1, 4, 1], + } + const [noise, scale, version] = model_switch[RealcuganModelValue.value] || [0, 2, 2] + vpyContent += `res = CUGAN(res, noise=${noise}, scale=${scale}, tiles=${RealcuganTileValue.value}, version=${version}, alpha=${RealcuganAlphaValue.value}, backend=device_sr)\n` + } + + if (SRMethodValue.value === 'Real_esrgan') { + const model_switch = { + 'animevideov3': 0, + 'animevideo-xsx2': 1, + 'animevideo-xsx4': 2, + 'animejanaiV2L1': 5005, + 'animejanaiV2L2': 5006, + 'animejanaiV2L3': 5007, + 'animejanaiV3_HD_L1': 5008, + 'animejanaiV3_HD_L2': 5009, + 'animejanaiV3_HD_L3': 5010, + 'Ani4Kv2_G6i2_Compact ': 7000, + 'Ani4Kv2_G6i2_UltraCompact ': 7001, + 'AniScale_x2': 7010, + 'AniScale2_Refiner_x1': 7011, + 'AniScale2S_Compact_x2': 7012, + 'AniSD_AC_Compact_x2': 7013, + 'AniSD_Compact_x2': 7014, + 'AniSD_DB_Compact_x1': 7015, + 'AniSD_PS_Compact_x2': 7016, + } + const model = model_switch[RealesrganModelValue.value] || 0 + vpyContent += `res = RealESRGAN(res, scale=${RealesrganScaleValue.value},tiles=${ + RealesrganTileValue.value},model=${model}, backend=device_sr)\n` + } + + if (SRMethodValue.value === 'Waifu2x') { + const model_switch = { + 'anime_style_art_rgb_noise0': [1, 0, 1], + 'anime_style_art_rgb_noise1': [1, 1, 1], + 'anime_style_art_rgb_noise2': [1, 2, 1], + 'anime_style_art_rgb_noise3': [1, 3, 1], + 'anime_style_art_rgb_scale2.0x': [1, -1, 2], + + 'photo_noise0': [2, 0, 1], + 'photo_noise1': [2, 1, 1], + 'photo_noise2': [2, 2, 1], + 'photo_noise3': [2, 3, 1], + 'photo_scale2.0x': [2, -1, 2], + + 'upconv_7_anime_style_art_rgb_noise0_scale2.0x': [3, 0, 2], + 'upconv_7_anime_style_art_rgb_noise1_scale2.0x': [3, 1, 2], + 'upconv_7_anime_style_art_rgb_noise2_scale2.0x': [3, 2, 2], + 'upconv_7_anime_style_art_rgb_noise3_scale2.0x': [3, 3, 2], + 'upconv_7_anime_style_art_rgb_scale2.0x': [3, -1, 2], + + 'upconv_7_photo_noise0_scale2.0x': [4, 0, 2], + 'upconv_7_photo_noise1_scale2.0x': [4, 1, 2], + 'upconv_7_photo_noise2_scale2.0x': [4, 2, 2], + 'upconv_7_photo_noise3_scale2.0x': [4, 3, 2], + 'upconv_7_photo_scale2.0x_': [4, -1, 2], + + 'upresnet10_noise0_scale2.0x': [5, 0, 2], + 'upresnet10_noise1_scale2.0x': [5, 1, 2], + 'upresnet10_noise2_scale2.0x': [5, 2, 2], + 'upresnet10_noise3_scale2.0x': [5, 3, 2], + 'upresnet10_scale2.0x': [5, -1, 2], + + 'cunet_noise0': [6, 0, 1], + 'cunet_noise1': [6, 1, 1], + 'cunet_noise2': [6, 2, 1], + 'cunet_noise3': [6, 3, 1], + 'cunet_noise0_scale2.0x': [6, 0, 2], + 'cunet_noise1_scale2.0x': [6, 1, 2], + 'cunet_noise2_scale2.0x': [6, 2, 2], + 'cunet_noise3_scale2.0x': [6, 3, 2], + 'cunet_scale2.0x': [6, -1, 2], + + 'swin_unet_art_noise0': [7, 0, 1], + 'swin_unet_art_noise0_scale2x': [7, 0, 2], + 'swin_unet_art_noise0_scale4x': [7, 0, 4], + 'swin_unet_art_noise1': [7, 1, 1], + 'swin_unet_art_noise1_scale2x': [7, 1, 2], + 'swin_unet_art_noise1_scale4x': [7, 1, 4], + 'swin_unet_art_noise2': [7, 2, 1], + 'swin_unet_art_noise2_scale2x': [7, 2, 2], + 'swin_unet_art_noise2_scale4x': [7, 2, 4], + 'swin_unet_art_noise3': [7, 3, 1], + 'swin_unet_art_noise3_scale2x': [7, 3, 2], + 'swin_unet_art_noise3_scale4x': [7, 3, 4], + 'swin_unet_art_scale2x': [7, -1, 2], + 'swin_unet_art_scale4x': [7, -1, 4], + + 'swin_unet_photo_noise0_scale4x': [8, 0, 4], + 'swin_unet_photo_noise1_scale4x': [8, 1, 4], + 'swin_unet_photo_noise2_scale4x': [8, 2, 4], + 'swin_unet_photo_noise3_scale4x': [8, 3, 4], + 'swin_unet_photo_scale4x': [8, -1, 4], + + 'swin_unet_photo_v2_noise0_scale4x': [9, 0, 4], + 'swin_unet_photo_v2_noise1_scale4x': [9, 1, 4], + 'swin_unet_photo_v2_noise2_scale4x': [9, 2, 4], + 'swin_unet_photo_v2_noise3_scale4x': [9, 3, 4], + 'swin_unet_photo_v2_scale4x': [9, -1, 4], + + 'swin_unet_art_scan_noise0_scale4x': [10, 0, 4], + 'swin_unet_art_scan_noise1_scale4x': [10, 1, 4], + 'swin_unet_art_scan_noise2_scale4x': [10, 2, 4], + 'swin_unet_art_scan_noise3_scale4x': [10, 3, 4], + 'swin_unet_art_scan_scale4x': [10, -1, 4], + } + const [model, noise, scale] = model_switch[Waifu2xModelValue.value] || [1, 0, 1] + vpyContent += `res = Waifu2x(res, noise=${noise}, scale=${scale}, tiles=${Waifu2xTileValue.value}, model=${model}, backend=device_sr)\n` + } + + if (SRMethodValue.value === 'SR_ExtraModel') { + const model_switch = { + AniSD_DC_SPAN_x2: 'AniSD_DC_SPAN_x2.onnx', + } + const exeDir = path.dirname(process.execPath) + + const model = (path.join( + exeDir, + 'package', + 'vs-coreplugins', + 'models', + 'VSET_ExtraSrModel', + model_switch[SR_ExtraModelValue.value] || 'AniSD_DC_SPAN_x2.onnx', + )).replace(/\\/g, '/') + + vpyContent += `res = vsmlrt.inference(res, network_path="${model}", backend=device_sr)\n` + } + } + + // 补帧 + if (useVfi.value === true) { + vpyContent += 'res = core.resize.Bicubic(clip=res,range=1,matrix_in_s="709",format=vs.RGB48)\n' + vpyContent += 'res=core.fmtc.bitdepth(res, bits=32)\n' + + if (VfiMethodValue.value === 'Rife') { + if (RifeInferenceValue.value === 'Cuda') { + vpyContent += 'device_vfi=Backend.ORT_CUDA()\n' + } + if (RifeInferenceValue.value === 'TensorRt') { + vpyContent += 'device_vfi=Backend.TRT()\n' + vpyContent += `device_vfi.use_cuda_graph = ${String(Vfi_cudagraph.value)[0].toUpperCase() + String(Vfi_cudagraph.value).slice(1)}\n` + } + if (RifeInferenceValue.value === 'NCNN') { + vpyContent += 'device_vfi=Backend.NCNN_VK()\n' + } + if (RifeInferenceValue.value === 'DML') { + vpyContent += 'device_vfi=Backend.ORT_DML()\n' + } + if (RifeInferenceValue.value === 'MIGX') { + vpyContent += 'device_vfi=Backend.MIGX()\n' + } + } + + vpyContent += 'device_vfi.device_id=0\n' + vpyContent += 'device_vfi.fp16=True\n' + vpyContent += `device_vfi.num_streams=${Vfi_numstreams.value}\n` + vpyContent += 'from fractions import Fraction\n' + + if (VfiMethodValue.value === 'Rife') { + const model_switch = { + v4_0: 40, + v4_2: 42, + v4_3: 43, + v4_4: 44, + v4_5: 45, + v4_6: 46, + v4_7: 47, + v4_8: 48, + v4_9: 49, + v4_10: 410, + v4_11: 411, + v4_12: 412, + v4_12_lite: 4121, + v4_13: 413, + v4_13_lite: 4131, + v4_14: 414, + v4_14_lite: 4141, + v4_15: 415, + v4_15_lite: 4151, + v4_16_lite: 4161, + v4_17: 417, + v4_17_lite: 4171, + v4_18: 418, + v4_19: 419, + v4_20: 420, + v4_21: 421, + v4_22: 422, + v4_22_lite: 4221, + v4_23: 423, + v4_24: 424, + v4_25: 425, + v4_25_lite: 4251, + v4_25_heavy: 4252, + v4_26: 426, + v4_26_heavy: 4262, + } + const model = model_switch[RifeModelValue.value] || 40 + const EnsembleBool = RifeEnsembleValue.value ? 'True' : 'False' + vpyContent += `res = core.misc.SCDetect(res,threshold=${RifeDetectionValue.value})\n` + let tilesize_requirement = 32 + if (RifeModelValue.value === 'v4_25_lite') { + tilesize_requirement = 128 + } + if (RifeModelValue.value === 'v4_25_heavy' || RifeModelValue.value === 'v4_26_heavy' + || RifeModelValue.value === 'v4_26') { + tilesize_requirement = 64 + } + vpyContent += `Borders=${tilesize_requirement} / ${RifeScaleValue}\n` + vpyContent += 'res_height = (Borders - res.height % Borders) \n' + vpyContent += 'res_width = (Borders - res.width % Borders) \n' + vpyContent += 'res = core.std.AddBorders(clip=res, right=res_width, bottom=res_height)\n' + + vpyContent += `res = RIFE(res, scale=${RifeScaleValue.value},model=${model},ensemble=${EnsembleBool + },multi=Fraction(${RifeMultiValue.value},res.fps)` + `, backend=device_vfi)\n` + + vpyContent += 'res = core.std.Crop(clip=res, right=res_width, bottom=res_height)\n' + } + } + + // 后置缩放(需要在此改进色彩控制) + if (UseResize_AfterEnhance.value === true) { + vpyContent + += `res = core.resize.Bicubic(clip=res,width=${ResizeWidth_AfterEnhance.value + },height=${ResizeHeight_AfterEnhance.value},matrix_s="709", format=vs.YUV420P16)\n` + } + else { + vpyContent += 'res = core.resize.Bicubic(clip=res, matrix_s="709", format=vs.YUV420P16)\n' + } + + vpyContent += `res = core.std.Crop(clip=res,left=${ReduceLeft_AfterEnhance.value + }, right=${ReduceRight_AfterEnhance.value + }, top=${ReduceOn_AfterEnhance.value + }, bottom=${ReduceDown_AfterEnhance.value})\n` + vpyContent += 'res.set_output()\n' + return vpyContent +} diff --git a/tsconfig.json b/tsconfig.json index 6668d7c..fb5ae2e 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,4 +1,7 @@ { + "compilerOptions": { + "declaration": false + }, "references": [{ "path": "./tsconfig.node.json" }, { "path": "./tsconfig.web.json" }], "files": [] }