Replace original code with .NET 5

This commit is contained in:
Dankrushen
2021-02-08 15:48:44 -05:00
parent 8a1c7d3295
commit e990ec0505
104 changed files with 86 additions and 25425 deletions

View File

@@ -10,34 +10,39 @@ echo.
set "ver=16" set "ver=16"
set /p ver="Enter the version number: " set /p ver="Enter the version number: "
cd ..\Code\bin\x64\Release cd ..
dotnet publish -c Release -o "Release/Build" "Code5"
cd Release
rmdir /s/q FlowframesApp%ver% rmdir /s/q FlowframesApp%ver%
mkdir "FlowframesApp%ver%" mkdir "FlowframesApp%ver%"
mkdir "FlowframesApp%ver%/FlowframesData" mkdir "FlowframesApp%ver%/FlowframesData"
mkdir "FlowframesApp%ver%/FlowframesData/pkgs" mkdir "FlowframesApp%ver%/FlowframesData/pkgs"
rem xcopy "../../../../pkgs" "FlowframesApp%ver%/FlowframesData\pkgs\" /E rem xcopy "../pkgs" "FlowframesApp%ver%/FlowframesData\pkgs\" /E
xcopy "../../../../pkgs/av" "FlowframesApp%ver%/FlowframesData\pkgs\av" /E /I xcopy "../pkgs/av" "FlowframesApp%ver%/FlowframesData\pkgs\av" /E /I
xcopy "../../../../pkgs/dain-ncnn" "FlowframesApp%ver%/FlowframesData\pkgs\dain-ncnn" /E /I xcopy "../pkgs/dain-ncnn" "FlowframesApp%ver%/FlowframesData\pkgs\dain-ncnn" /E /I
xcopy "../../../../pkgs/licenses" "FlowframesApp%ver%/FlowframesData\pkgs\licenses" /E /I xcopy "../pkgs/licenses" "FlowframesApp%ver%/FlowframesData\pkgs\licenses" /E /I
xcopy "../../../../pkgs/rife-cuda" "FlowframesApp%ver%/FlowframesData\pkgs\rife-cuda" /E /I xcopy "../pkgs/rife-cuda" "FlowframesApp%ver%/FlowframesData\pkgs\rife-cuda" /E /I
xcopy "../../../../pkgs/rife-ncnn" "FlowframesApp%ver%/FlowframesData\pkgs\rife-ncnn" /E /I xcopy "../pkgs/rife-ncnn" "FlowframesApp%ver%/FlowframesData\pkgs\rife-ncnn" /E /I
echo %ver% >> "FlowframesApp%ver%/FlowframesData/ver.ini" echo %ver% >> "FlowframesApp%ver%/FlowframesData/ver.ini"
xcopy Flowframes.exe "FlowframesApp%ver%" xcopy /E "Build" "FlowframesApp%ver%"
cd ../../../../Build cd ..\Build5
rmdir /s/q ..\Code\bin\x64\Release\FlowframesApp%ver%\FlowframesData\logs rmdir /s/q ..\Release\FlowframesApp%ver%\FlowframesData\logs
del ..\Code\bin\x64\Release\FlowframesApp%ver%\FlowframesData\config.ini del ..\Release\FlowframesApp%ver%\FlowframesData\config.ini
7za.exe a FF-%ver%-Slim.7z -m0=flzma2 -mx5 "..\Code\bin\x64\Release\FlowframesApp%ver%" del FF-%ver%-Slim.7z
7za.exe a FF-%ver%-Slim.7z -m0=flzma2 -mx5 "..\Release\FlowframesApp%ver%"
rmdir /s/q ..\Code\bin\x64\Release\FlowframesApp%ver% rmdir /s/q ..\Release\FlowframesApp%ver%
rem pause rem pause

View File

@@ -10,41 +10,48 @@ echo.
set "ver=16" set "ver=16"
set /p ver="Enter the version number: " set /p ver="Enter the version number: "
cd ..\Code\bin\x64\Release cd ..
dotnet publish -c Release -o "Release/Build" "Code5"
cd Release
rmdir /s/q FlowframesApp%ver% rmdir /s/q FlowframesApp%ver%
mkdir "FlowframesApp%ver%" mkdir "FlowframesApp%ver%"
mkdir "FlowframesApp%ver%/FlowframesData" mkdir "FlowframesApp%ver%/FlowframesData"
mkdir "FlowframesApp%ver%/FlowframesData/pkgs" mkdir "FlowframesApp%ver%/FlowframesData/pkgs"
rem xcopy "../../../../pkgs" "FlowframesApp%ver%/FlowframesData\pkgs\" /E rem xcopy "../pkgs" "FlowframesApp%ver%/FlowframesData\pkgs\" /E
xcopy "../../../../pkgs/av" "FlowframesApp%ver%/FlowframesData\pkgs\av" /E /I xcopy "../pkgs/av" "FlowframesApp%ver%/FlowframesData\pkgs\av" /E /I
xcopy "../../../../pkgs/dain-ncnn" "FlowframesApp%ver%/FlowframesData\pkgs\dain-ncnn" /E /I xcopy "../pkgs/dain-ncnn" "FlowframesApp%ver%/FlowframesData\pkgs\dain-ncnn" /E /I
xcopy "../../../../pkgs/licenses" "FlowframesApp%ver%/FlowframesData\pkgs\licenses" /E /I xcopy "../pkgs/licenses" "FlowframesApp%ver%/FlowframesData\pkgs\licenses" /E /I
xcopy "../../../../pkgs/rife-cuda" "FlowframesApp%ver%/FlowframesData\pkgs\rife-cuda" /E /I xcopy "../pkgs/rife-cuda" "FlowframesApp%ver%/FlowframesData\pkgs\rife-cuda" /E /I
xcopy "../../../../pkgs/rife-ncnn" "FlowframesApp%ver%/FlowframesData\pkgs\rife-ncnn" /E /I xcopy "../pkgs/rife-ncnn" "FlowframesApp%ver%/FlowframesData\pkgs\rife-ncnn" /E /I
echo %ver% >> "FlowframesApp%ver%/FlowframesData/ver.ini" echo %ver% >> "FlowframesApp%ver%/FlowframesData/ver.ini"
xcopy Flowframes.exe "FlowframesApp%ver%" xcopy /E "Build" "FlowframesApp%ver%"
cd ../../../../Build cd ..\Build5
rmdir /s/q ..\Code\bin\x64\Release\FlowframesApp%ver%\FlowframesData\logs rmdir /s/q ..\Release\FlowframesApp%ver%\FlowframesData\logs
del ..\Code\bin\x64\Release\FlowframesApp%ver%\FlowframesData\config.ini del ..\Release\FlowframesApp%ver%\FlowframesData\config.ini
7za.exe a FF-%ver%-Slim.7z -m0=flzma2 -mx5 "..\Code\bin\x64\Release\FlowframesApp%ver%" del FF-%ver%-Slim.7z
7za.exe a FF-%ver%-Slim.7z -m0=flzma2 -mx5 "..\Release\FlowframesApp%ver%"
xcopy "../pkgs/py-tu" "..\Code\bin\x64\Release\FlowframesApp%ver%\FlowframesData\pkgs\py-tu" /E /I xcopy "../pkgs/py-tu" "..\Release\FlowframesApp%ver%\FlowframesData\pkgs\py-tu" /E /I
7za.exe a FF-%ver%-Full.7z -m0=flzma2 -mx7 "..\Code\bin\x64\Release\FlowframesApp%ver%" del FF-%ver%-Full.7z
7za.exe a FF-%ver%-Full.7z -m0=flzma2 -mx7 "..\Release\FlowframesApp%ver%"
rmdir /s/q ..\Code\bin\x64\Release\FlowframesApp%ver%\FlowframesData\pkgs\py-tu rmdir /s/q ..\Release\FlowframesApp%ver%\FlowframesData\pkgs\py-tu
xcopy "../pkgs/py-amp" "..\Code\bin\x64\Release\FlowframesApp%ver%\FlowframesData\pkgs\py-amp" /E /I xcopy "../pkgs/py-amp" "..\Release\FlowframesApp%ver%\FlowframesData\pkgs\py-amp" /E /I
7za.exe a FF-%ver%-Full-RTX3000.7z -m0=flzma2 -mx7 "..\Code\bin\x64\Release\FlowframesApp%ver%" del FF-%ver%-Full-RTX3000.7z
7za.exe a FF-%ver%-Full-RTX3000.7z -m0=flzma2 -mx7 "..\Release\FlowframesApp%ver%"
rmdir /s/q ..\Code\bin\x64\Release\FlowframesApp%ver% rmdir /s/q ..\Release\FlowframesApp%ver%
rem pause rem pause

Binary file not shown.

Binary file not shown.

View File

@@ -1,48 +0,0 @@
@echo off
echo ===============================
echo == NMKD'S FLOWFRAMES BUILDER ==
echo ===============================
echo.
echo This script makes a build ready for distribution by creating three 7z archives, without python, with pytorch for Turing, and with pytorch for Ampere.
echo.
set "ver=16"
set /p ver="Enter the version number: "
cd ..
dotnet publish -c Release -o "Release/Build" "Code5"
cd Release
rmdir /s/q FlowframesApp%ver%
mkdir "FlowframesApp%ver%"
mkdir "FlowframesApp%ver%/FlowframesData"
mkdir "FlowframesApp%ver%/FlowframesData/pkgs"
rem xcopy "../pkgs" "FlowframesApp%ver%/FlowframesData\pkgs\" /E
xcopy "../pkgs/av" "FlowframesApp%ver%/FlowframesData\pkgs\av" /E /I
xcopy "../pkgs/dain-ncnn" "FlowframesApp%ver%/FlowframesData\pkgs\dain-ncnn" /E /I
xcopy "../pkgs/licenses" "FlowframesApp%ver%/FlowframesData\pkgs\licenses" /E /I
xcopy "../pkgs/rife-cuda" "FlowframesApp%ver%/FlowframesData\pkgs\rife-cuda" /E /I
xcopy "../pkgs/rife-ncnn" "FlowframesApp%ver%/FlowframesData\pkgs\rife-ncnn" /E /I
echo %ver% >> "FlowframesApp%ver%/FlowframesData/ver.ini"
xcopy /E "Build" "FlowframesApp%ver%"
cd ..\Build5
rmdir /s/q ..\Release\FlowframesApp%ver%\FlowframesData\logs
del ..\Release\FlowframesApp%ver%\FlowframesData\config.ini
del FF-%ver%-Slim.7z
7za.exe a FF-%ver%-Slim.7z -m0=flzma2 -mx5 "..\Release\FlowframesApp%ver%"
rmdir /s/q ..\Release\FlowframesApp%ver%
rem pause

View File

@@ -1,57 +0,0 @@
@echo off
echo ===============================
echo == NMKD'S FLOWFRAMES BUILDER ==
echo ===============================
echo.
echo This script makes a build ready for distribution by creating three 7z archives, without python, with pytorch for Turing, and with pytorch for Ampere.
echo.
set "ver=16"
set /p ver="Enter the version number: "
cd ..
dotnet publish -c Release -o "Release/Build" "Code5"
cd Release
rmdir /s/q FlowframesApp%ver%
mkdir "FlowframesApp%ver%"
mkdir "FlowframesApp%ver%/FlowframesData"
mkdir "FlowframesApp%ver%/FlowframesData/pkgs"
rem xcopy "../pkgs" "FlowframesApp%ver%/FlowframesData\pkgs\" /E
xcopy "../pkgs/av" "FlowframesApp%ver%/FlowframesData\pkgs\av" /E /I
xcopy "../pkgs/dain-ncnn" "FlowframesApp%ver%/FlowframesData\pkgs\dain-ncnn" /E /I
xcopy "../pkgs/licenses" "FlowframesApp%ver%/FlowframesData\pkgs\licenses" /E /I
xcopy "../pkgs/rife-cuda" "FlowframesApp%ver%/FlowframesData\pkgs\rife-cuda" /E /I
xcopy "../pkgs/rife-ncnn" "FlowframesApp%ver%/FlowframesData\pkgs\rife-ncnn" /E /I
echo %ver% >> "FlowframesApp%ver%/FlowframesData/ver.ini"
xcopy /E "Build" "FlowframesApp%ver%"
cd ..\Build5
rmdir /s/q ..\Release\FlowframesApp%ver%\FlowframesData\logs
del ..\Release\FlowframesApp%ver%\FlowframesData\config.ini
del FF-%ver%-Slim.7z
7za.exe a FF-%ver%-Slim.7z -m0=flzma2 -mx5 "..\Release\FlowframesApp%ver%"
xcopy "../pkgs/py-tu" "..\Release\FlowframesApp%ver%\FlowframesData\pkgs\py-tu" /E /I
del FF-%ver%-Full.7z
7za.exe a FF-%ver%-Full.7z -m0=flzma2 -mx7 "..\Release\FlowframesApp%ver%"
rmdir /s/q ..\Release\FlowframesApp%ver%\FlowframesData\pkgs\py-tu
xcopy "../pkgs/py-amp" "..\Release\FlowframesApp%ver%\FlowframesData\pkgs\py-amp" /E /I
del FF-%ver%-Full-RTX3000.7z
7za.exe a FF-%ver%-Full-RTX3000.7z -m0=flzma2 -mx7 "..\Release\FlowframesApp%ver%"
rmdir /s/q ..\Release\FlowframesApp%ver%
rem pause

View File

@@ -1,17 +0,0 @@
1) Download...
- FF-Slim if you have an AMD/Intel GPU, or if you have an Nvidia GPU and Pytorch already installed
- FF-Full if you have an Nvidia Turing (RTX 2000) or older GPU
- FF-Full-RTX3000 if you have an Nvidia Ampere (RTX 3000) GPU. Also compatible with older GPUs, but has bigger filesize.
2) Extract the 7z file using 7zip or any other program that supports it
3) Run Flowframes.exe
If you updated from an older version, you can optionally copy "FlowframesData/config.ini" to your new installation if you want to keep your settings.
You can delete your old installation after updating.
IT IS NOT RECOMMENDED TO OVERWRITE YOUR OLD INSTALLATION!
Instead, delete it first or install the new one to a different/empty folder.

View File

@@ -1,30 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" />
</startup>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Syncfusion.Licensing" publicKeyToken="632609b4d040f6b4" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-18.2460.0.56" newVersion="18.2460.0.56" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Numerics.Vectors" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.1.4.0" newVersion="4.1.4.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Security.Principal.Windows" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.1.0" newVersion="4.0.1.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Runtime.CompilerServices.Unsafe" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.6.0" newVersion="4.0.6.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Buffers" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.3.0" newVersion="4.0.3.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>

View File

@@ -1,369 +1,50 @@
<?xml version="1.0" encoding="utf-8"?> <Project Sdk="Microsoft.NET.Sdk">
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="packages\Costura.Fody.4.1.0\build\Costura.Fody.props" Condition="Exists('packages\Costura.Fody.4.1.0\build\Costura.Fody.props')" />
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup> <PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{389E42DD-A163-49D7-9E0A-AE41090A07B3}</ProjectGuid>
<OutputType>WinExe</OutputType> <OutputType>WinExe</OutputType>
<RootNamespace>Flowframes</RootNamespace> <TargetFramework>net5.0-windows</TargetFramework>
<AssemblyName>Flowframes</AssemblyName> <UseWindowsForms>true</UseWindowsForms>
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment> <RuntimeIdentifier>win7-x64</RuntimeIdentifier>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects> <PublishTrimmed>true</PublishTrimmed>
<Deterministic>true</Deterministic>
<NuGetPackageImportStamp> <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
</NuGetPackageImportStamp> <GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
<IsWebBootstrapper>false</IsWebBootstrapper> <GenerateAssemblyTitleAttribute>false</GenerateAssemblyTitleAttribute>
<PublishUrl>publish\</PublishUrl> <GenerateAssemblyVersionAttribute>false</GenerateAssemblyVersionAttribute>
<Install>true</Install>
<InstallFrom>Disk</InstallFrom>
<UpdateEnabled>false</UpdateEnabled>
<UpdateMode>Foreground</UpdateMode>
<UpdateInterval>7</UpdateInterval>
<UpdateIntervalUnits>Days</UpdateIntervalUnits>
<UpdatePeriodically>false</UpdatePeriodically>
<UpdateRequired>false</UpdateRequired>
<MapFileExtensions>true</MapFileExtensions>
<ApplicationRevision>0</ApplicationRevision>
<ApplicationVersion>1.0.0.%2a</ApplicationVersion>
<UseApplicationTrust>false</UseApplicationTrust>
<BootstrapperEnabled>true</BootstrapperEnabled>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>x64</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup>
<ApplicationIcon>flowframesIcoNew.ico</ApplicationIcon> <ApplicationIcon>flowframesIcoNew.ico</ApplicationIcon>
</PropertyGroup> </PropertyGroup>
<PropertyGroup>
<StartupObject />
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x64\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>x64</PlatformTarget>
<LangVersion>7.3</LangVersion>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<Prefer32Bit>true</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
<OutputPath>bin\x64\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x64</PlatformTarget>
<LangVersion>7.3</LangVersion>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<Prefer32Bit>true</Prefer32Bit>
</PropertyGroup>
<ItemGroup> <ItemGroup>
<Reference Include="7z.NET, Version=1.0.3.0, Culture=neutral, processorArchitecture=MSIL"> <PackageReference Include="CircularProgressBar" Version="2.8.0.16" />
<HintPath>packages\7z.NET.1.0.3\lib\net463\7z.NET.dll</HintPath> <PackageReference Include="Crc32.NET" Version="1.2.0" />
</Reference> <PackageReference Include="CyotekTabList" Version="2.2.0" />
<Reference Include="CircularProgressBar, Version=2.8.0.16, Culture=neutral, PublicKeyToken=310fd07b25df79b3, processorArchitecture=MSIL"> <PackageReference Include="diskdetector-net" Version="0.3.2" />
<HintPath>packages\CircularProgressBar.2.8.0.16\lib\net40\CircularProgressBar.dll</HintPath> <PackageReference Include="HTAlt.Standart" Version="0.1.6" />
</Reference> <PackageReference Include="HTAlt.WinForms" Version="0.1.6" />
<Reference Include="Costura, Version=4.1.0.0, Culture=neutral, PublicKeyToken=9919ef960d84173d, processorArchitecture=MSIL"> <PackageReference Include="Magick.NET-Q16-AnyCPU" Version="7.23.1" />
<HintPath>packages\Costura.Fody.4.1.0\lib\net40\Costura.dll</HintPath> <PackageReference Include="Magick.NET.Core" Version="6.1.0" />
</Reference> <PackageReference Include="NvAPIWrapper.Net" Version="0.8.1.101" />
<Reference Include="Crc32.NET, Version=1.0.0.0, Culture=neutral, PublicKeyToken=dc0b95cf99bf4e99, processorArchitecture=MSIL"> <PackageReference Include="Standart.Hash.xxHash" Version="3.1.0" />
<HintPath>packages\Crc32.NET.1.2.0\lib\net20\Crc32.NET.dll</HintPath> <PackageReference Include="System.Management" Version="5.0.0" />
</Reference> <PackageReference Include="WindowsAPICodePack-Core" Version="1.1.2" />
<Reference Include="CustomMarshalers" /> <PackageReference Include="WindowsAPICodePack-Shell" Version="1.1.1" />
<Reference Include="Cyotek.Windows.Forms.TabList, Version=2.0.0.0, Culture=neutral, PublicKeyToken=58daa28b0b2de221, processorArchitecture=MSIL"> <PackageReference Include="WinFormAnimation" Version="1.6.0.4" />
<HintPath>packages\CyotekTabList.2.0.0\lib\net35\Cyotek.Windows.Forms.TabList.dll</HintPath>
</Reference>
<Reference Include="DiskDetector, Version=0.3.2.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>packages\diskdetector-net.0.3.2\lib\netstandard2.0\DiskDetector.dll</HintPath>
</Reference>
<Reference Include="HTAlt WinForms, Version=0.1.6.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>packages\HTAlt.WinForms.0.1.6\lib\net461\HTAlt WinForms.dll</HintPath>
</Reference>
<Reference Include="HTAlt.Standart, Version=0.1.6.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>packages\HTAlt.Standart.0.1.6\lib\netstandard2.0\HTAlt.Standart.dll</HintPath>
</Reference>
<Reference Include="Magick.NET-Q16-AnyCPU, Version=7.21.1.0, Culture=neutral, PublicKeyToken=2004825badfa91ec, processorArchitecture=MSIL">
<HintPath>packages\Magick.NET-Q16-AnyCPU.7.21.1\lib\net40\Magick.NET-Q16-AnyCPU.dll</HintPath>
</Reference>
<Reference Include="Magick.NET.Core, Version=4.1.0.0, Culture=neutral, PublicKeyToken=2004825badfa91ec, processorArchitecture=MSIL">
<HintPath>packages\Magick.NET.Core.4.1.0\lib\net40\Magick.NET.Core.dll</HintPath>
</Reference>
<Reference Include="Microsoft.VisualBasic" />
<Reference Include="Microsoft.WindowsAPICodePack, Version=1.1.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>packages\WindowsAPICodePack-Core.1.1.1\lib\Microsoft.WindowsAPICodePack.dll</HintPath>
</Reference>
<Reference Include="Microsoft.WindowsAPICodePack.Shell, Version=1.1.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>packages\WindowsAPICodePack-Shell.1.1.1\lib\Microsoft.WindowsAPICodePack.Shell.dll</HintPath>
</Reference>
<Reference Include="NvAPIWrapper, Version=0.8.0.98, Culture=neutral, PublicKeyToken=310fd07b25df79b3, processorArchitecture=MSIL">
<HintPath>packages\NvAPIWrapper.Net.0.8.0.98\lib\net45\NvAPIWrapper.dll</HintPath>
</Reference>
<Reference Include="PagedControl, Version=2.2.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>packages\PagedControl.2.2.0\lib\net35\PagedControl.dll</HintPath>
</Reference>
<Reference Include="PresentationCore" />
<Reference Include="PresentationFramework" />
<Reference Include="Standart.Hash.xxHash, Version=3.1.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>packages\Standart.Hash.xxHash.3.1.0\lib\netstandard2.0\Standart.Hash.xxHash.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Buffers, Version=4.0.3.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>packages\System.Buffers.4.5.1\lib\net461\System.Buffers.dll</HintPath>
</Reference>
<Reference Include="System.Core" />
<Reference Include="System.Data.HashFunction.Core, Version=2.0.0.0, Culture=neutral, PublicKeyToken=80c9288e394c1322, processorArchitecture=MSIL">
<HintPath>packages\System.Data.HashFunction.Core.2.0.0\lib\net45\System.Data.HashFunction.Core.dll</HintPath>
</Reference>
<Reference Include="System.Data.HashFunction.Interfaces, Version=2.0.0.0, Culture=neutral, PublicKeyToken=80c9288e394c1322, processorArchitecture=MSIL">
<HintPath>packages\System.Data.HashFunction.Interfaces.2.0.0\lib\net45\System.Data.HashFunction.Interfaces.dll</HintPath>
</Reference>
<Reference Include="System.Design" />
<Reference Include="System.Drawing.Common, Version=4.0.0.1, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>packages\System.Drawing.Common.5.0.0\lib\net461\System.Drawing.Common.dll</HintPath>
</Reference>
<Reference Include="System.Management" />
<Reference Include="System.Memory, Version=4.0.1.1, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>packages\System.Memory.4.5.4\lib\net461\System.Memory.dll</HintPath>
</Reference>
<Reference Include="System.Numerics" />
<Reference Include="System.Numerics.Vectors, Version=4.1.4.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll</HintPath>
</Reference>
<Reference Include="System.Runtime.CompilerServices.Unsafe, Version=4.0.6.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>packages\System.Runtime.CompilerServices.Unsafe.4.7.1\lib\net461\System.Runtime.CompilerServices.Unsafe.dll</HintPath>
</Reference>
<Reference Include="System.Security.Claims, Version=4.0.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>packages\System.Security.Claims.4.3.0\lib\net46\System.Security.Claims.dll</HintPath>
<Private>True</Private>
<Private>True</Private>
</Reference>
<Reference Include="System.Security.Principal.Windows, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>packages\System.Security.Principal.Windows.4.3.0\lib\net46\System.Security.Principal.Windows.dll</HintPath>
</Reference>
<Reference Include="System.Threading.Tasks.Extensions, Version=4.2.0.1, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>packages\System.Threading.Tasks.Extensions.4.5.3\lib\netstandard2.0\System.Threading.Tasks.Extensions.dll</HintPath>
</Reference>
<Reference Include="System.Xaml" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Deployment" />
<Reference Include="System.Drawing" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml" />
<Reference Include="TabControl, Version=2.1.2.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>packages\TabControl.2.1.2\lib\net35\TabControl.dll</HintPath>
</Reference>
<Reference Include="Win32Interop.Dwmapi, Version=1.0.1.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>packages\Win32Interop.Dwmapi.1.0.1\lib\Win32Interop.Dwmapi.dll</HintPath>
</Reference>
<Reference Include="Win32Interop.Gdi32, Version=1.0.1.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>packages\Win32Interop.Gdi32.1.0.1\lib\Win32Interop.Gdi32.dll</HintPath>
</Reference>
<Reference Include="Win32Interop.Kernel32, Version=1.0.1.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>packages\Win32Interop.Kernel32.1.0.1\lib\Win32Interop.Kernel32.dll</HintPath>
</Reference>
<Reference Include="Win32Interop.User32, Version=1.0.1.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>packages\Win32Interop.User32.1.0.1\lib\Win32Interop.User32.dll</HintPath>
</Reference>
<Reference Include="Win32Interop.Uxtheme, Version=1.0.1.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>packages\Win32Interop.Uxtheme.1.0.1\lib\Win32Interop.Uxtheme.dll</HintPath>
</Reference>
<Reference Include="WindowsBase" />
<Reference Include="WindowsFormsIntegration" />
<Reference Include="WinFormAnimation, Version=1.6.0.4, Culture=neutral, PublicKeyToken=310fd07b25df79b3, processorArchitecture=MSIL">
<HintPath>packages\WinFormAnimation.1.6.0.4\lib\net40\WinFormAnimation.dll</HintPath>
</Reference>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="Data\AI.cs" /> <Compile Update="Properties\Settings.Designer.cs">
<Compile Include="Data\InterpSettings.cs" /> <DesignTimeSharedInput>True</DesignTimeSharedInput>
<Compile Include="Data\Networks.cs" />
<Compile Include="Data\Padding.cs" />
<Compile Include="Data\ResumeState.cs" />
<Compile Include="Data\SubtitleTrack.cs" />
<Compile Include="Forms\BatchForm.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="Forms\BatchForm.Designer.cs">
<DependentUpon>BatchForm.cs</DependentUpon>
</Compile>
<Compile Include="Forms\BigPreviewForm.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="Forms\BigPreviewForm.Designer.cs">
<DependentUpon>BigPreviewForm.cs</DependentUpon>
</Compile>
<Compile Include="Forms\SettingsForm.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="Forms\SettingsForm.Designer.cs">
<DependentUpon>SettingsForm.cs</DependentUpon>
</Compile>
<Compile Include="Forms\UpdaterForm.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="Forms\UpdaterForm.Designer.cs">
<DependentUpon>UpdaterForm.cs</DependentUpon>
</Compile>
<Compile Include="IO\ConfigParser.cs" />
<Compile Include="Data\FlowPackage.cs" />
<Compile Include="IO\ModelDownloader.cs" />
<Compile Include="Data\Packages.cs" />
<Compile Include="IO\PkgUtils.cs" />
<Compile Include="Main\AutoEncode.cs" />
<Compile Include="Main\BatchProcessing.cs" />
<Compile Include="Main\CreateVideo.cs" />
<Compile Include="Main\InterpolateSteps.cs" />
<Compile Include="Main\InterpolateUtils.cs" />
<Compile Include="Main\FrameOrder.cs" />
<Compile Include="Main\ResumeUtils.cs" />
<Compile Include="Media\AvProcess.cs" />
<Compile Include="Media\FfmpegAlpha.cs" />
<Compile Include="Media\FfmpegAudioAndMetadata.cs" />
<Compile Include="Media\FfmpegCommands.cs" />
<Compile Include="Media\FfmpegEncode.cs" />
<Compile Include="Media\FfmpegExtract.cs" />
<Compile Include="Media\FFmpegUtils.cs" />
<Compile Include="MiscUtils\Benchmarker.cs" />
<Compile Include="OS\AiProcess.cs" />
<Compile Include="ExtensionMethods.cs" />
<Compile Include="Form1.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="Form1.Designer.cs">
<DependentUpon>Form1.cs</DependentUpon>
</Compile>
<Compile Include="Main\Interpolate.cs" />
<Compile Include="IO\CfgStrings.cs" />
<Compile Include="IO\Config.cs" />
<Compile Include="IO\IOUtils.cs" />
<Compile Include="Data\Paths.cs" />
<Compile Include="IO\Logger.cs" />
<Compile Include="Magick\Converter.cs" />
<Compile Include="Magick\Dedupe.cs" />
<Compile Include="OS\NvApi.cs" />
<Compile Include="OS\OSUtils.cs" />
<Compile Include="OS\Python.cs" />
<Compile Include="OS\Updater.cs" />
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="MiscUtils\FormatUtils.cs" />
<Compile Include="UI\GetWebInfo.cs" />
<Compile Include="UI\MainUiFunctions.cs" />
<Compile Include="UI\UIUtils.cs" />
<Compile Include="UI\UtilsTab.cs" />
<EmbeddedResource Include="Form1.resx">
<DependentUpon>Form1.cs</DependentUpon>
<SubType>Designer</SubType>
</EmbeddedResource>
<EmbeddedResource Include="Forms\BatchForm.resx">
<DependentUpon>BatchForm.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Forms\BigPreviewForm.resx">
<DependentUpon>BigPreviewForm.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Forms\SettingsForm.resx">
<DependentUpon>SettingsForm.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Forms\UpdaterForm.resx">
<DependentUpon>UpdaterForm.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
<SubType>Designer</SubType>
</EmbeddedResource>
<Compile Include="Properties\Resources.Designer.cs">
<AutoGen>True</AutoGen> <AutoGen>True</AutoGen>
<DependentUpon>Resources.resx</DependentUpon> <DependentUpon>Settings.settings</DependentUpon>
<DesignTime>True</DesignTime>
</Compile> </Compile>
<None Include="packages.config" /> </ItemGroup>
<None Include="Properties\Settings.settings">
<ItemGroup>
<None Update="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator> <Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>Settings.Designer.cs</LastGenOutput> <LastGenOutput>Settings.Designer.cs</LastGenOutput>
</None> </None>
<Compile Include="Properties\Settings.Designer.cs">
<AutoGen>True</AutoGen>
<DependentUpon>Settings.settings</DependentUpon>
<DesignTimeSharedInput>True</DesignTimeSharedInput>
</Compile>
</ItemGroup> </ItemGroup>
<ItemGroup>
<None Include="App.config" />
</ItemGroup>
<ItemGroup>
<BootstrapperPackage Include=".NETFramework,Version=v4.7.2">
<Visible>False</Visible>
<ProductName>Microsoft .NET Framework 4.7.2 %28x86 and x64%29</ProductName>
<Install>true</Install>
</BootstrapperPackage>
<BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
<Visible>False</Visible>
<ProductName>.NET Framework 3.5 SP1</ProductName>
<Install>false</Install>
</BootstrapperPackage>
</ItemGroup>
<ItemGroup>
<Content Include="FlowFramesFunkyLogo1.ico" />
<Content Include="FlowFramesFunkyLogo2.ico" />
<None Include="Resources\flowframesIcoNew-512px.png" />
<None Include="Resources\flowframesIcoNew.png" />
<None Include="Resources\questmark-72px-bordeer.png" />
<None Include="Resources\7za.exe" />
<None Include="Resources\baseline_fact_check_white_48dp.png" />
<None Include="Resources\discordIco.png" />
<None Include="Resources\paypal256px.png" />
<None Include="Resources\patreon256px.png" />
<None Include="Resources\baseline_settings_white_48dp.png" />
<None Include="Resources\baseline_image_white_48dp.png" />
<None Include="Resources\baseline_image_white_48dp-4x.png" />
<None Include="Resources\baseline_image_white_48dp-4x-25pcAlpha.png" />
<None Include="Resources\baseline_queue_white_48dp.png" />
<None Include="Resources\separatorTest1.png" />
<None Include="Resources\discordIcoColored.png" />
<None Include="Resources\patreon256pxColored.png" />
<None Include="Resources\baseline_create_white_18dp.png" />
<None Include="Resources\baseline_create_white_18dp-semiTransparent.png" />
<Content Include="flowframesIcoNew.ico" />
<None Include="Resources\baseline_system_update_alt_white_48dp.png" />
<None Include="Resources\baseline_system_update_alt_white_48dp1.png" />
</ItemGroup>
<ItemGroup />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('packages\Costura.Fody.4.1.0\build\Costura.Fody.props')" Text="$([System.String]::Format('$(ErrorText)', 'packages\Costura.Fody.4.1.0\build\Costura.Fody.props'))" />
<Error Condition="!Exists('packages\7z.NET.1.0.3\build\7z.NET.targets')" Text="$([System.String]::Format('$(ErrorText)', 'packages\7z.NET.1.0.3\build\7z.NET.targets'))" />
<Error Condition="!Exists('packages\Fody.6.3.0\build\Fody.targets')" Text="$([System.String]::Format('$(ErrorText)', 'packages\Fody.6.3.0\build\Fody.targets'))" />
</Target>
<Import Project="packages\7z.NET.1.0.3\build\7z.NET.targets" Condition="Exists('packages\7z.NET.1.0.3\build\7z.NET.targets')" />
<Import Project="packages\Fody.6.3.0\build\Fody.targets" Condition="Exists('packages\Fody.6.3.0\build\Fody.targets')" />
</Project> </Project>

View File

@@ -1,31 +1,25 @@
 
Microsoft Visual Studio Solution File, Format Version 12.00 Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16 # Visual Studio Version 16
VisualStudioVersion = 16.0.30413.136 VisualStudioVersion = 16.0.30907.101
MinimumVisualStudioVersion = 10.0.40219.1 MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Flowframes", "Flowframes.csproj", "{389E42DD-A163-49D7-9E0A-AE41090A07B3}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Flowframes", "Flowframes.csproj", "{A7E45FC0-5BE5-40FC-BCB6-48096F57AF73}"
EndProject EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU Debug|Any CPU = Debug|Any CPU
Debug|x64 = Debug|x64
Release|Any CPU = Release|Any CPU Release|Any CPU = Release|Any CPU
Release|x64 = Release|x64
EndGlobalSection EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution GlobalSection(ProjectConfigurationPlatforms) = postSolution
{389E42DD-A163-49D7-9E0A-AE41090A07B3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {A7E45FC0-5BE5-40FC-BCB6-48096F57AF73}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{389E42DD-A163-49D7-9E0A-AE41090A07B3}.Debug|Any CPU.Build.0 = Debug|Any CPU {A7E45FC0-5BE5-40FC-BCB6-48096F57AF73}.Debug|Any CPU.Build.0 = Debug|Any CPU
{389E42DD-A163-49D7-9E0A-AE41090A07B3}.Debug|x64.ActiveCfg = Debug|x64 {A7E45FC0-5BE5-40FC-BCB6-48096F57AF73}.Release|Any CPU.ActiveCfg = Release|Any CPU
{389E42DD-A163-49D7-9E0A-AE41090A07B3}.Debug|x64.Build.0 = Debug|x64 {A7E45FC0-5BE5-40FC-BCB6-48096F57AF73}.Release|Any CPU.Build.0 = Release|Any CPU
{389E42DD-A163-49D7-9E0A-AE41090A07B3}.Release|Any CPU.ActiveCfg = Release|Any CPU
{389E42DD-A163-49D7-9E0A-AE41090A07B3}.Release|Any CPU.Build.0 = Release|Any CPU
{389E42DD-A163-49D7-9E0A-AE41090A07B3}.Release|x64.ActiveCfg = Release|x64
{389E42DD-A163-49D7-9E0A-AE41090A07B3}.Release|x64.Build.0 = Release|x64
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE
EndGlobalSection EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {4622DEE4-C34E-4439-A743-7B534210FDFA} SolutionGuid = {62B981E7-6590-4960-BDF4-3439D25D3840}
EndGlobalSection EndGlobalSection
EndGlobal EndGlobal

View File

@@ -1,40 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="7z.NET" version="1.0.3" targetFramework="net472" />
<package id="CircularProgressBar" version="2.8.0.16" targetFramework="net472" />
<package id="Costura.Fody" version="4.1.0" targetFramework="net472" />
<package id="Crc32.NET" version="1.2.0" targetFramework="net472" />
<package id="CyotekTabList" version="2.0.0" targetFramework="net472" />
<package id="diskdetector-net" version="0.3.2" targetFramework="net472" />
<package id="Fody" version="6.3.0" targetFramework="net472" developmentDependency="true" />
<package id="HTAlt.Standart" version="0.1.6" targetFramework="net472" />
<package id="HTAlt.WinForms" version="0.1.6" targetFramework="net472" />
<package id="Magick.NET.Core" version="4.1.0" targetFramework="net472" />
<package id="Magick.NET-Q16-AnyCPU" version="7.21.1" targetFramework="net472" />
<package id="Microsoft-WindowsAPICodePack-Core" version="1.1.4" targetFramework="net472" />
<package id="Microsoft-WindowsAPICodePack-Shell" version="1.1.4" targetFramework="net472" />
<package id="NvAPIWrapper.Net" version="0.8.0.98" targetFramework="net472" />
<package id="PagedControl" version="2.2.0" targetFramework="net472" />
<package id="Standart.Hash.xxHash" version="3.1.0" targetFramework="net472" />
<package id="System.Buffers" version="4.5.1" targetFramework="net472" />
<package id="System.Data.HashFunction.Core" version="2.0.0" targetFramework="net472" />
<package id="System.Data.HashFunction.Interfaces" version="2.0.0" targetFramework="net472" />
<package id="System.Drawing.Common" version="5.0.0" targetFramework="net472" />
<package id="System.Management" version="5.0.0" targetFramework="net472" />
<package id="System.Memory" version="4.5.4" targetFramework="net472" />
<package id="System.Numerics.Vectors" version="4.5.0" targetFramework="net472" />
<package id="System.Runtime.CompilerServices.Unsafe" version="4.7.1" targetFramework="net472" />
<package id="System.Runtime.Numerics" version="4.3.0" targetFramework="net472" />
<package id="System.Security.Claims" version="4.3.0" targetFramework="net472" />
<package id="System.Security.Principal.Windows" version="4.3.0" targetFramework="net472" />
<package id="System.Threading.Tasks.Extensions" version="4.5.3" targetFramework="net472" />
<package id="TabControl" version="2.1.2" targetFramework="net472" />
<package id="Win32Interop.Dwmapi" version="1.0.1" targetFramework="net472" />
<package id="Win32Interop.Gdi32" version="1.0.1" targetFramework="net472" />
<package id="Win32Interop.Kernel32" version="1.0.1" targetFramework="net472" />
<package id="Win32Interop.User32" version="1.0.1" targetFramework="net472" />
<package id="Win32Interop.Uxtheme" version="1.0.1" targetFramework="net472" />
<package id="WindowsAPICodePack-Core" version="1.1.1" targetFramework="net472" />
<package id="WindowsAPICodePack-Shell" version="1.1.1" targetFramework="net472" />
<package id="WinFormAnimation" version="1.6.0.4" targetFramework="net472" />
</packages>

442
Code5/.gitignore vendored
View File

@@ -1,442 +0,0 @@
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
##
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
# User-specific files
*.rsuser
*.suo
*.user
*.userosscache
*.sln.docstates
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
# Mono auto generated files
mono_crash.*
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
[Aa][Rr][Mm]/
[Aa][Rr][Mm]64/
bld/
[Bb]in/
[Oo]bj/
[Ll]og/
[Ll]ogs/
# Visual Studio 2015/2017 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/
# Visual Studio 2017 auto generated files
Generated\ Files/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
# NUnit
*.VisualState.xml
TestResult.xml
nunit-*.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
# Benchmark Results
BenchmarkDotNet.Artifacts/
# .NET Core
project.lock.json
project.fragment.lock.json
artifacts/
# StyleCop
StyleCopReport.xml
# Files built by Visual Studio
*_i.c
*_p.c
*_h.h
*.ilk
*.meta
*.obj
*.iobj
*.pch
*.pdb
*.ipdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*_wpftmp.csproj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Chutzpah Test files
_Chutzpah*
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
*.VC.db
*.VC.VC.opendb
# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap
# Visual Studio Trace Files
*.e2e
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# AxoCover is a Code Coverage Tool
.axoCover/*
!.axoCover/settings.json
# Coverlet is a free, cross platform Code Coverage Tool
coverage*[.json, .xml, .info]
# Visual Studio code coverage results
*.coverage
*.coveragexml
# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*
# MightyMoose
*.mm.*
AutoTest.Net/
# Web workbench (sass)
.sass-cache/
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# Note: Comment the next line if you want to checkin your web deploy settings,
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj
# Microsoft Azure Web App publish settings. Comment the next line if you want to
# checkin your Azure Web App publish settings, but sensitive information contained
# in these scripts will be unencrypted
PublishScripts/
# NuGet Packages
*.nupkg
# NuGet Symbol Packages
*.snupkg
# The packages folder can be ignored because of Package Restore
**/[Pp]ackages/*
# except build/, which is used as an MSBuild target.
!**/[Pp]ackages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/[Pp]ackages/repositories.config
# NuGet v3's project.json files produces more ignorable files
*.nuget.props
*.nuget.targets
# Microsoft Azure Build Output
csx/
*.build.csdef
# Microsoft Azure Emulator
ecf/
rcf/
# Windows Store app package directories and files
AppPackages/
BundleArtifacts/
Package.StoreAssociation.xml
_pkginfo.txt
*.appx
*.appxbundle
*.appxupload
# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!?*.[Cc]ache/
# Others
ClientBin/
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.jfm
*.pfx
*.publishsettings
orleans.codegen.cs
# Including strong name files can present a security risk
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
#*.snk
# Since there are multiple workflows, uncomment next line to ignore bower_components
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
#bower_components/
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
ServiceFabricBackup/
*.rptproj.bak
# SQL Server files
*.mdf
*.ldf
*.ndf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
*.rptproj.rsuser
*- [Bb]ackup.rdl
*- [Bb]ackup ([0-9]).rdl
*- [Bb]ackup ([0-9][0-9]).rdl
# Microsoft Fakes
FakesAssemblies/
# GhostDoc plugin setting file
*.GhostDoc.xml
# Node.js Tools for Visual Studio
.ntvs_analysis.dat
node_modules/
# Visual Studio 6 build log
*.plg
# Visual Studio 6 workspace options file
*.opt
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
*.vbw
# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions
# Paket dependency manager
.paket/paket.exe
paket-files/
# FAKE - F# Make
.fake/
# CodeRush personal settings
.cr/personal
# Python Tools for Visual Studio (PTVS)
__pycache__/
*.pyc
# Cake - Uncomment if you are using it
# tools/**
# !tools/packages.config
# Tabs Studio
*.tss
# Telerik's JustMock configuration file
*.jmconfig
# BizTalk build output
*.btp.cs
*.btm.cs
*.odx.cs
*.xsd.cs
# OpenCover UI analysis results
OpenCover/
# Azure Stream Analytics local run output
ASALocalRun/
# MSBuild Binary and Structured Log
*.binlog
# NVidia Nsight GPU debugger configuration file
*.nvuser
# MFractors (Xamarin productivity tool) working folder
.mfractor/
# Local History for Visual Studio
.localhistory/
# BeatPulse healthcheck temp database
healthchecksdb
# Backup folder for Package Reference Convert tool in Visual Studio 2017
MigrationBackup/
# Ionide (cross platform F# VS Code tools) working folder
.ionide/
##
## Visual studio for Mac
##
# globs
Makefile.in
*.userprefs
*.usertasks
config.make
config.status
aclocal.m4
install-sh
autom4te.cache/
*.tar.gz
tarballs/
test-results/
# Mac bundle stuff
*.dmg
*.app
# content below from: https://github.com/github/gitignore/blob/master/Global/macOS.gitignore
# General
.DS_Store
.AppleDouble
.LSOverride
# Icon must end with two \r
Icon
# Thumbnails
._*
# Files that might appear in the root of a volume
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns
.com.apple.timemachine.donotpresent
# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk
# content below from: https://github.com/github/gitignore/blob/master/Global/Windows.gitignore
# Windows thumbnail cache files
Thumbs.db
ehthumbs.db
ehthumbs_vista.db
# Dump file
*.stackdump
# Folder config file
[Dd]esktop.ini
# Recycle Bin used on file shares
$RECYCLE.BIN/
# Windows Installer files
*.cab
*.msi
*.msix
*.msm
*.msp
# Windows shortcuts
*.lnk
# JetBrains Rider
.idea/
*.sln.iml
##
## Visual Studio Code
##
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json

View File

@@ -1,29 +0,0 @@
using Flowframes.IO;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Flowframes.Data
{
public struct AI
{
public string aiName;
public string aiNameShort;
public string friendlyName;
public string description;
public FlowPackage pkg;
public bool supportsAnyExp;
public AI(string aiNameArg, string friendlyNameArg, string descArg, FlowPackage pkgArg, bool supportsAnyExpArg)
{
aiName = aiNameArg;
aiNameShort = aiNameArg.Split(' ')[0].Split('_')[0];
friendlyName = friendlyNameArg;
description = descArg;
pkg = pkgArg;
supportsAnyExp = supportsAnyExpArg;
}
}
}

View File

@@ -1,24 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Flowframes.IO
{
public struct FlowPackage
{
public string friendlyName;
public string fileName;
public int downloadSizeMb;
public string desc;
public FlowPackage(string friendlyNameStr, string fileNameStr, int downloadSizeMbInt, string description)
{
friendlyName = friendlyNameStr;
fileName = fileNameStr;
downloadSizeMb = downloadSizeMbInt;
desc = description;
}
}
}

View File

@@ -1,214 +0,0 @@
using Flowframes.Media;
using Flowframes.Data;
using Flowframes.IO;
using Flowframes.Main;
using Flowframes.MiscUtils;
using Flowframes.UI;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
namespace Flowframes
{
public struct InterpSettings
{
public string inPath;
public string outPath;
public AI ai;
public float inFps;
public float outFps;
public float interpFactor;
public Interpolate.OutMode outMode;
public string model;
public string tempFolder;
public string framesFolder;
public string interpFolder;
public bool inputIsFrames;
public string outFilename;
public Size inputResolution;
public Size scaledResolution;
public bool alpha;
public bool stepByStep;
public InterpSettings(string inPathArg, string outPathArg, AI aiArg, float inFpsArg, int interpFactorArg, Interpolate.OutMode outModeArg, string modelArg)
{
inPath = inPathArg;
outPath = outPathArg;
ai = aiArg;
inFps = inFpsArg;
interpFactor = interpFactorArg;
outFps = inFpsArg * interpFactorArg;
outMode = outModeArg;
model = modelArg;
alpha = false;
stepByStep = false;
try
{
tempFolder = InterpolateUtils.GetTempFolderLoc(inPath, outPath);
framesFolder = Path.Combine(tempFolder, Paths.framesDir);
interpFolder = Path.Combine(tempFolder, Paths.interpDir);
inputIsFrames = IOUtils.IsPathDirectory(inPath);
outFilename = Path.Combine(outPath, Path.GetFileNameWithoutExtension(inPath) + IOUtils.GetExportSuffix(interpFactor, ai, model) + FFmpegUtils.GetExt(outMode));
}
catch
{
Logger.Log("Tried to create InterpSettings struct without an inpath. Can't set tempFolder, framesFolder and interpFolder.", true);
tempFolder = "";
framesFolder = "";
interpFolder = "";
inputIsFrames = false;
outFilename = "";
}
inputResolution = new Size(0, 0);
scaledResolution = new Size(0, 0);
}
public InterpSettings (string serializedData)
{
inPath = "";
outPath = "";
ai = Networks.networks[0];
inFps = 0;
interpFactor = 0;
outFps = 0;
outMode = Interpolate.OutMode.VidMp4;
model = "";
alpha = false;
stepByStep = false;
inputResolution = new Size(0, 0);
scaledResolution = new Size(0, 0);
Dictionary<string, string> entries = new Dictionary<string, string>();
foreach(string line in serializedData.SplitIntoLines())
{
if (line.Length < 3) continue;
string[] keyValuePair = line.Split('|');
entries.Add(keyValuePair[0], keyValuePair[1]);
}
foreach (KeyValuePair<string, string> entry in entries)
{
switch (entry.Key)
{
case "INPATH": inPath = entry.Value; break;
case "OUTPATH": outPath = entry.Value; break;
case "AI": ai = Networks.GetAi(entry.Value); break;
case "INFPS": inFps = float.Parse(entry.Value); break;
case "OUTFPS": outFps = float.Parse(entry.Value); break;
case "INTERPFACTOR": interpFactor = float.Parse(entry.Value); break;
case "OUTMODE": outMode = (Interpolate.OutMode)Enum.Parse(typeof(Interpolate.OutMode), entry.Value); break;
case "MODEL": model = entry.Value; break;
case "INPUTRES": inputResolution = FormatUtils.ParseSize(entry.Value); break;
case "OUTPUTRES": scaledResolution = FormatUtils.ParseSize(entry.Value); break;
case "ALPHA": alpha = bool.Parse(entry.Value); break;
case "STEPBYSTEP": stepByStep = bool.Parse(entry.Value); break;
}
}
try
{
tempFolder = InterpolateUtils.GetTempFolderLoc(inPath, outPath);
framesFolder = Path.Combine(tempFolder, Paths.framesDir);
interpFolder = Path.Combine(tempFolder, Paths.interpDir);
inputIsFrames = IOUtils.IsPathDirectory(inPath);
outFilename = Path.Combine(outPath, Path.GetFileNameWithoutExtension(inPath) + IOUtils.GetExportSuffix(interpFactor, ai, model) + FFmpegUtils.GetExt(outMode));
}
catch
{
Logger.Log("Tried to create InterpSettings struct without an inpath. Can't set tempFolder, framesFolder and interpFolder.", true);
tempFolder = "";
framesFolder = "";
interpFolder = "";
inputIsFrames = false;
outFilename = "";
}
}
public void UpdatePaths (string inPathArg, string outPathArg)
{
inPath = inPathArg;
outPath = outPathArg;
tempFolder = InterpolateUtils.GetTempFolderLoc(inPath, outPath);
framesFolder = Path.Combine(tempFolder, Paths.framesDir);
interpFolder = Path.Combine(tempFolder, Paths.interpDir);
inputIsFrames = IOUtils.IsPathDirectory(inPath);
outFilename = Path.Combine(outPath, Path.GetFileNameWithoutExtension(inPath) + IOUtils.GetExportSuffix(interpFactor, ai, model) + FFmpegUtils.GetExt(outMode));
}
public async Task<Size> GetInputRes()
{
await RefreshResolutions();
return inputResolution;
}
public async Task<Size> GetScaledRes()
{
await RefreshResolutions();
return scaledResolution;
}
async Task RefreshResolutions ()
{
if (inputResolution.IsEmpty || scaledResolution.IsEmpty)
{
inputResolution = await IOUtils.GetVideoOrFramesRes(inPath);
scaledResolution = InterpolateUtils.GetOutputResolution(inputResolution, false);
}
}
public int GetTargetFrameCount(string overrideInputDir = "", float overrideFactor = -1)
{
if (framesFolder == null || !Directory.Exists(framesFolder))
return 0;
string framesDir = (!string.IsNullOrWhiteSpace(overrideInputDir)) ? overrideInputDir : framesFolder;
int frames = IOUtils.GetAmountOfFiles(framesDir, false, "*.png");
float factor = (overrideFactor > 0) ? overrideFactor : interpFactor;
int targetFrameCount = ((frames * factor) - (interpFactor - 1)).RoundToInt();
return targetFrameCount;
}
public void RefreshAlpha ()
{
try
{
bool alphaEnabled = Config.GetBool("enableAlpha", false);
bool outputSupportsAlpha = (outMode == Interpolate.OutMode.ImgPng || outMode == Interpolate.OutMode.VidGif);
string ext = inputIsFrames ? Path.GetExtension(IOUtils.GetFilesSorted(inPath).First()).ToLower() : Path.GetExtension(inPath).ToLower();
alpha = (alphaEnabled && outputSupportsAlpha && (ext == ".gif" || ext == ".png" || ext == ".apng"));
}
catch (Exception e)
{
Logger.Log("RefreshAlpha Error: " + e.Message, true);
alpha = false;
}
}
public string Serialize ()
{
string s = $"INPATH|{inPath}\n";
s += $"OUTPATH|{outPath}\n";
s += $"AI|{ai.aiName}\n";
s += $"INFPS|{inFps.ToStringDot()}\n";
s += $"OUTFPS|{outFps.ToStringDot()}\n";
s += $"INTERPFACTOR|{interpFactor}\n";
s += $"OUTMODE|{outMode}\n";
s += $"MODEL|{model}\n";
s += $"INPUTRES|{inputResolution.Width}x{inputResolution.Height}\n";
s += $"OUTPUTRES|{scaledResolution.Width}x{scaledResolution.Height}\n";
s += $"ALPHA|{alpha}\n";
s += $"STEPBYSTEP|{stepByStep}\n";
return s;
}
}
}

View File

@@ -1,34 +0,0 @@
using Flowframes.IO;
using System;
using System.Collections.Generic;
namespace Flowframes.Data
{
class Networks
{
public static AI rifeCuda = new AI("RIFE_CUDA", "RIFE", "CUDA/Pytorch Implementation of RIFE", Packages.rifeCuda, true);
public static AI rifeNcnn = new AI("RIFE_NCNN", "RIFE (NCNN)", "Vulkan/NCNN Implementation of RIFE", Packages.rifeNcnn, false);
public static AI dainNcnn = new AI("DAIN_NCNN", "DAIN (NCNN)", "Vulkan/NCNN Implementation of DAIN", Packages.dainNcnn, true);
public static List<AI> networks = new List<AI>();
public static void Init ()
{
networks.Clear();
networks.Add(rifeCuda);
networks.Add(rifeNcnn);
networks.Add(dainNcnn);
}
public static AI GetAi (string aiName)
{
foreach(AI ai in networks)
{
if (ai.aiName == aiName)
return ai;
}
return networks[0];
}
}
}

View File

@@ -1,15 +0,0 @@

namespace Flowframes.IO
{
class Packages
{
public static FlowPackage dainNcnn = new FlowPackage("DAIN-NCNN (AMD/Nvidia)", "dain-ncnn.7z", 40, "NCNN/Vulkan implementation of DAIN. Very slow and VRAM-hungry.");
//public static FlowPackage cainNcnn = new FlowPackage("CAIN-NCNN (AMD/Nvidia)", "cain-ncnn.7z", 75, "NCNN/Vulkan implementation of CAIN. About 8x faster than DAIN and very lightweight on VRAM.");
public static FlowPackage rifeCuda = new FlowPackage("RIFE (Nvidia)", "rife-cuda.7z", 50, "Pytorch implementation of RIFE. Very fast (~2x CAIN, >16x DAIN) and not too VRAM-heavy.");
public static FlowPackage rifeNcnn = new FlowPackage("RIFE-NCNN (AMD/Nvidia) [EXPERIMENTAL]", "rife-ncnn.7z", 25, "NCNN/Vulkan implementation of RIFE. Similar speed and VRAM usage as CAIN, but can have better quality.");
//public static FlowPackage python = new FlowPackage("Python Runtime", "py.7z", 640, "Embedded Python runtime including Pytorch and all other dependencies. Install this if you don't have system Python.");
public static FlowPackage audioVideo = new FlowPackage("Audio/Video Tools (Required)", "av.7z", 10, "Utilities for extracting frames, analysing videos, encoding videos and GIFs.");
public static FlowPackage licenses = new FlowPackage("Licenses (Required)", "licenses.7z", 1, "License files for redistributed software.");
}
}

View File

@@ -1,15 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Flowframes.Data
{
class Padding
{
public const int inputFrames = 9;
public const int inputFramesRenamed = 8;
public const int interpFrames = 8;
}
}

View File

@@ -1,57 +0,0 @@
using System;
using System.Collections.Generic;
using System.IO;
namespace Flowframes.IO
{
class Paths
{
public const string framesDir = "frames";
public const string interpDir = "interp";
public const string chunksDir = "vchunks";
public const string resumeDir = "resumedata";
public const string scenesDir = "scenes";
public const string alphaSuffix = "-a";
public const string prevSuffix = "-previous";
public const string frameOrderPrefix = "frames";
public static string GetFrameOrderFilename(float factor)
{
return $"{frameOrderPrefix}-{factor.ToStringDot()}x.ini";
}
public static string GetFrameOrderFilenameChunk (int from, int to)
{
return $"{frameOrderPrefix}-chunk-{from}-{to}.ini";
}
public static string GetVerPath()
{
return Path.Combine(GetDataPath(), "ver.ini");
}
public static string GetDataPath ()
{
string path = Path.Combine(IOUtils.GetExeDir(), "FlowframesData");
Directory.CreateDirectory(path);
return path;
}
public static string GetPkgPath()
{
string path = Path.Combine(GetDataPath(), "pkgs");
Directory.CreateDirectory(path);
return path;
}
public static string GetLogPath()
{
string path = Path.Combine(GetDataPath(), "logs");
Directory.CreateDirectory(path);
return path;
}
}
}

View File

@@ -1,56 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Flowframes.Data
{
public struct ResumeState
{
public bool autoEncode;
public int interpolatedInputFrames;
public ResumeState (bool autoEncArg, int lastInterpInFrameArg)
{
autoEncode = autoEncArg;
interpolatedInputFrames = lastInterpInFrameArg;
}
public ResumeState(string serializedData)
{
autoEncode = false;
interpolatedInputFrames = 0;
Dictionary<string, string> entries = new Dictionary<string, string>();
foreach (string line in serializedData.SplitIntoLines())
{
if (line.Length < 3) continue;
string[] keyValuePair = line.Split('|');
entries.Add(keyValuePair[0], keyValuePair[1]);
}
foreach (KeyValuePair<string, string> entry in entries)
{
switch (entry.Key)
{
case "AUTOENC": autoEncode = bool.Parse(entry.Value); break;
case "INTERPOLATEDINPUTFRAMES": interpolatedInputFrames = entry.Value.GetInt(); break;
}
}
}
public override string ToString ()
{
string s = $"AUTOENC|{autoEncode}\n";
if (!autoEncode)
{
s += $"INTERPOLATEDINPUTFRAMES|{interpolatedInputFrames}";
}
return s;
}
}
}

View File

@@ -1,23 +0,0 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
namespace Flowframes.Data
{
class SubtitleTrack
{
public int streamIndex;
public string lang;
public string langFriendly;
public string encoding;
public SubtitleTrack (int streamNum, string langStr, string encodingStr)
{
streamIndex = streamNum;
lang = langStr;
langFriendly = CultureInfo.CurrentCulture.TextInfo.ToTitleCase(langStr.ToLower());
encoding = encodingStr.Trim();
}
}
}

View File

@@ -1,184 +0,0 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Flowframes
{
public static class ExtensionMethods
{
public static string TrimNumbers(this string s, bool allowDotComma = false)
{
if (!allowDotComma)
s = Regex.Replace(s, "[^0-9]", "");
else
s = Regex.Replace(s, "[^.,0-9]", "");
return s.Trim();
}
public static int GetInt(this TextBox textbox)
{
return GetInt(textbox.Text);
}
public static int GetInt(this ComboBox combobox)
{
return GetInt(combobox.Text);
}
public static int GetInt(this string str)
{
if (str.Length < 1 || str == null)
return 0;
try { return int.Parse(str.TrimNumbers()); }
catch (Exception e)
{
Logger.Log("Failed to parse \"" + str + "\" to int: " + e.Message, true);
return 0;
}
}
public static float GetFloat(this TextBox textbox)
{
return GetFloat(textbox.Text);
}
public static float GetFloat(this ComboBox combobox)
{
return GetFloat(combobox.Text);
}
public static float GetFloat(this string str)
{
if (str.Length < 1 || str == null)
return 0f;
string num = str.TrimNumbers(true).Replace(",", ".");
float value;
float.TryParse(num, NumberStyles.Any, CultureInfo.InvariantCulture, out value);
return value;
}
public static string Wrap(this string path, bool addSpaceFront = false, bool addSpaceEnd = false)
{
string s = "\"" + path + "\"";
if (addSpaceFront)
s = " " + s;
if (addSpaceEnd)
s = s + " ";
return s;
}
public static string GetParentDir(this string path)
{
return Directory.GetParent(path).FullName;
}
public static int RoundToInt(this float f)
{
return (int)Math.Round(f);
}
public static int Clamp(this int i, int min, int max)
{
if (i < min)
i = min;
if (i > max)
i = max;
return i;
}
public static string[] SplitIntoLines(this string str)
{
return Regex.Split(str, "\r\n|\r|\n");
}
public static string Trunc(this string inStr, int maxChars, bool addEllipsis = true)
{
string str = inStr.Length <= maxChars ? inStr : inStr.Substring(0, maxChars);
if(addEllipsis && inStr.Length > maxChars)
str += "…";
return str;
}
public static string StripBadChars(this string str)
{
string outStr = Regex.Replace(str, @"[^\u0020-\u007E]", string.Empty);
outStr = outStr.Remove("(").Remove(")").Remove("[").Remove("]").Remove("{").Remove("}").Remove("%").Remove("'").Remove("~");
return outStr;
}
public static string StripNumbers(this string str)
{
return new string(str.Where(c => c != '-' && (c < '0' || c > '9')).ToArray());
}
public static string Remove(this string str, string stringToRemove)
{
if (str == null || stringToRemove == null)
return str;
return str.Replace(stringToRemove, "");
}
public static string TrimWhitespaces(this string str)
{
if (str == null) return str;
var newString = new StringBuilder();
bool previousIsWhitespace = false;
for (int i = 0; i < str.Length; i++)
{
if (Char.IsWhiteSpace(str[i]))
{
if (previousIsWhitespace)
continue;
previousIsWhitespace = true;
}
else
{
previousIsWhitespace = false;
}
newString.Append(str[i]);
}
return newString.ToString();
}
public static string ReplaceLast (this string str, string stringToReplace, string replaceWith)
{
int place = str.LastIndexOf(stringToReplace);
if (place == -1)
return str;
return str.Remove(place, stringToReplace.Length).Insert(place, replaceWith);
}
public static string[] SplitBy (this string str, string splitBy)
{
return str.Split(new string[] { splitBy }, StringSplitOptions.None);
}
public static string RemoveComments (this string str)
{
return str.Split('#')[0].SplitBy("//")[0];
}
public static string FilenameSuffix(this string path, string suffix)
{
string filename = Path.ChangeExtension(path, null);
string ext = Path.GetExtension(path);
return filename + suffix + ext;
}
public static string ToStringDot (this float f, string format = "")
{
if(string.IsNullOrWhiteSpace(format))
return f.ToString().Replace(",", ".");
else
return f.ToString(format).Replace(",", ".");
}
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 196 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 196 KiB

View File

@@ -1,50 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net5.0-windows</TargetFramework>
<UseWindowsForms>true</UseWindowsForms>
<RuntimeIdentifier>win7-x64</RuntimeIdentifier>
<PublishTrimmed>true</PublishTrimmed>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
<GenerateAssemblyTitleAttribute>false</GenerateAssemblyTitleAttribute>
<GenerateAssemblyVersionAttribute>false</GenerateAssemblyVersionAttribute>
<ApplicationIcon>flowframesIcoNew.ico</ApplicationIcon>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="CircularProgressBar" Version="2.8.0.16" />
<PackageReference Include="Crc32.NET" Version="1.2.0" />
<PackageReference Include="CyotekTabList" Version="2.2.0" />
<PackageReference Include="diskdetector-net" Version="0.3.2" />
<PackageReference Include="HTAlt.Standart" Version="0.1.6" />
<PackageReference Include="HTAlt.WinForms" Version="0.1.6" />
<PackageReference Include="Magick.NET-Q16-AnyCPU" Version="7.23.1" />
<PackageReference Include="Magick.NET.Core" Version="6.1.0" />
<PackageReference Include="NvAPIWrapper.Net" Version="0.8.1.101" />
<PackageReference Include="Standart.Hash.xxHash" Version="3.1.0" />
<PackageReference Include="System.Management" Version="5.0.0" />
<PackageReference Include="WindowsAPICodePack-Core" Version="1.1.2" />
<PackageReference Include="WindowsAPICodePack-Shell" Version="1.1.1" />
<PackageReference Include="WinFormAnimation" Version="1.6.0.4" />
</ItemGroup>
<ItemGroup>
<Compile Update="Properties\Settings.Designer.cs">
<DesignTimeSharedInput>True</DesignTimeSharedInput>
<AutoGen>True</AutoGen>
<DependentUpon>Settings.settings</DependentUpon>
</Compile>
</ItemGroup>
<ItemGroup>
<None Update="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
</None>
</ItemGroup>
</Project>

View File

@@ -1,25 +0,0 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.30907.101
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Flowframes", "Flowframes.csproj", "{A7E45FC0-5BE5-40FC-BCB6-48096F57AF73}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{A7E45FC0-5BE5-40FC-BCB6-48096F57AF73}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A7E45FC0-5BE5-40FC-BCB6-48096F57AF73}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A7E45FC0-5BE5-40FC-BCB6-48096F57AF73}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A7E45FC0-5BE5-40FC-BCB6-48096F57AF73}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {62B981E7-6590-4960-BDF4-3439D25D3840}
EndGlobalSection
EndGlobal

View File

@@ -1,3 +0,0 @@
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
<Costura />
</Weavers>

View File

@@ -1,111 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. -->
<xs:element name="Weavers">
<xs:complexType>
<xs:all>
<xs:element name="Costura" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:all>
<xs:element minOccurs="0" maxOccurs="1" name="ExcludeAssemblies" type="xs:string">
<xs:annotation>
<xs:documentation>A list of assembly names to exclude from the default action of "embed all Copy Local references", delimited with line breaks</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element minOccurs="0" maxOccurs="1" name="IncludeAssemblies" type="xs:string">
<xs:annotation>
<xs:documentation>A list of assembly names to include from the default action of "embed all Copy Local references", delimited with line breaks.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element minOccurs="0" maxOccurs="1" name="Unmanaged32Assemblies" type="xs:string">
<xs:annotation>
<xs:documentation>A list of unmanaged 32 bit assembly names to include, delimited with line breaks.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element minOccurs="0" maxOccurs="1" name="Unmanaged64Assemblies" type="xs:string">
<xs:annotation>
<xs:documentation>A list of unmanaged 64 bit assembly names to include, delimited with line breaks.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element minOccurs="0" maxOccurs="1" name="PreloadOrder" type="xs:string">
<xs:annotation>
<xs:documentation>The order of preloaded assemblies, delimited with line breaks.</xs:documentation>
</xs:annotation>
</xs:element>
</xs:all>
<xs:attribute name="CreateTemporaryAssemblies" type="xs:boolean">
<xs:annotation>
<xs:documentation>This will copy embedded files to disk before loading them into memory. This is helpful for some scenarios that expected an assembly to be loaded from a physical file.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="IncludeDebugSymbols" type="xs:boolean">
<xs:annotation>
<xs:documentation>Controls if .pdbs for reference assemblies are also embedded.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="DisableCompression" type="xs:boolean">
<xs:annotation>
<xs:documentation>Embedded assemblies are compressed by default, and uncompressed when they are loaded. You can turn compression off with this option.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="DisableCleanup" type="xs:boolean">
<xs:annotation>
<xs:documentation>As part of Costura, embedded assemblies are no longer included as part of the build. This cleanup can be turned off.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="LoadAtModuleInit" type="xs:boolean">
<xs:annotation>
<xs:documentation>Costura by default will load as part of the module initialization. This flag disables that behavior. Make sure you call CosturaUtility.Initialize() somewhere in your code.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="IgnoreSatelliteAssemblies" type="xs:boolean">
<xs:annotation>
<xs:documentation>Costura will by default use assemblies with a name like 'resources.dll' as a satellite resource and prepend the output path. This flag disables that behavior.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="ExcludeAssemblies" type="xs:string">
<xs:annotation>
<xs:documentation>A list of assembly names to exclude from the default action of "embed all Copy Local references", delimited with |</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="IncludeAssemblies" type="xs:string">
<xs:annotation>
<xs:documentation>A list of assembly names to include from the default action of "embed all Copy Local references", delimited with |.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="Unmanaged32Assemblies" type="xs:string">
<xs:annotation>
<xs:documentation>A list of unmanaged 32 bit assembly names to include, delimited with |.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="Unmanaged64Assemblies" type="xs:string">
<xs:annotation>
<xs:documentation>A list of unmanaged 64 bit assembly names to include, delimited with |.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="PreloadOrder" type="xs:string">
<xs:annotation>
<xs:documentation>The order of preloaded assemblies, delimited with |.</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:complexType>
</xs:element>
</xs:all>
<xs:attribute name="VerifyAssembly" type="xs:boolean">
<xs:annotation>
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="VerifyIgnoreCodes" type="xs:string">
<xs:annotation>
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="GenerateXsd" type="xs:boolean">
<xs:annotation>
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:complexType>
</xs:element>
</xs:schema>

1415
Code5/Form1.Designer.cs generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,453 +0,0 @@
using Flowframes.Forms;
using Flowframes.IO;
using Flowframes.Magick;
using Flowframes.Main;
using Flowframes.OS;
using Flowframes.UI;
using Microsoft.WindowsAPICodePack.Dialogs;
using System;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Windows.Forms;
using HTAlt.WinForms;
using Flowframes.Data;
using Microsoft.WindowsAPICodePack.Taskbar;
using System.Threading.Tasks;
using Flowframes.MiscUtils;
namespace Flowframes
{
public partial class Form1 : Form
{
public bool initialized = false;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
CheckForIllegalCrossThreadCalls = false;
AutoScaleMode = AutoScaleMode.None;
Text = $"Flowframes {Updater.GetInstalledVer()}";
// Main Tab
UIUtils.InitCombox(interpFactorCombox, 0);
UIUtils.InitCombox(outModeCombox, 0);
UIUtils.InitCombox(aiModel, 2);
// Video Utils
UIUtils.InitCombox(utilsLoopTimesCombox, 0);
UIUtils.InitCombox(utilsSpeedCombox, 0);
UIUtils.InitCombox(utilsConvCrf, 0);
Program.mainForm = this;
Logger.textbox = logBox;
InitAis();
InterpolateUtils.preview = previewPicturebox;
UpdateStepByStepControls(true);
Initialized();
Checks();
}
void Checks()
{
try
{
GetWebInfo.LoadNews(newsLabel);
GetWebInfo.LoadPatronListCsv(patronsLabel);
Updater.AsyncUpdateCheck();
Python.CheckCompression();
}
catch (Exception e)
{
Logger.Log("Non-critical error while performing online checks. See logs for details.");
Logger.Log(e.Message + "\n" + e.StackTrace, true);
}
}
public HTTabControl GetMainTabControl() { return mainTabControl; }
public bool IsInFocus() { return (ActiveForm == this); }
public void SetTab(string tabName)
{
foreach (TabPage tab in mainTabControl.TabPages)
{
if (tab.Text.ToLower() == tabName.ToLower())
mainTabControl.SelectedTab = tab;
}
mainTabControl.Refresh();
mainTabControl.Update();
}
public InterpSettings GetCurrentSettings()
{
SetTab("interpolate");
return new InterpSettings(inputTbox.Text.Trim(), outputTbox.Text.Trim(), GetAi(), fpsInTbox.GetFloat(), interpFactorCombox.GetInt(), GetOutMode(), GetModel());
}
public void LoadBatchEntry(InterpSettings entry)
{
inputTbox.Text = entry.inPath;
outputTbox.Text = entry.outPath;
interpFactorCombox.Text = entry.interpFactor.ToString();
aiCombox.SelectedIndex = Networks.networks.IndexOf(entry.ai);
SetOutMode(entry.outMode);
}
public void SetStatus(string str)
{
Logger.Log(str, true);
statusLabel.Text = str;
}
public void SetProgress(int percent)
{
percent = percent.Clamp(0, 100);
TaskbarManager.Instance.SetProgressValue(percent, 100);
longProgBar.Value = percent;
longProgBar.Refresh();
}
public Size currInRes;
public float currInFps;
public int currInFrames;
public long currInDuration;
public void UpdateInputInfo ()
{
string str = $"Resolution: {(!currInRes.IsEmpty ? $"{currInRes.Width}x{currInRes.Height}" : "Unknown")} - ";
str += $"Framerate: {(currInFps > 0f ? $"{currInFps.ToStringDot()} FPS" : "Unknown")} - ";
str += $"Frame Count: {(currInFrames > 0 ? $"{currInFrames}" : "Unknown")} - ";
str += $"Duration: {(currInDuration > 0 ? $"{FormatUtils.MsToTimestamp(currInDuration)}" : "Unknown")}";
inputInfo.Text = str;
}
public void ResetInputInfo ()
{
currInRes = new Size();
currInFps = 0;
currInFrames = 0;
currInDuration = 0;
UpdateInputInfo();
}
void InitAis()
{
foreach (AI ai in Networks.networks)
aiCombox.Items.Add(ai.friendlyName + " - " + ai.description);
ConfigParser.LoadComboxIndex(aiCombox);
}
public void Initialized()
{
initialized = true;
runBtn.Enabled = true;
}
private void browseInputBtn_Click(object sender, EventArgs e)
{
CommonOpenFileDialog dialog = new CommonOpenFileDialog();
dialog.InitialDirectory = inputTbox.Text.Trim();
dialog.IsFolderPicker = true;
if (dialog.ShowDialog() == CommonFileDialogResult.Ok)
DragDropHandler(new string[] { dialog.FileName });
}
private void browseInputFileBtn_Click(object sender, EventArgs e)
{
CommonOpenFileDialog dialog = new CommonOpenFileDialog();
dialog.InitialDirectory = inputTbox.Text.Trim();
dialog.IsFolderPicker = false;
if (dialog.ShowDialog() == CommonFileDialogResult.Ok)
DragDropHandler(new string[] { dialog.FileName });
}
private void browseOutBtn_Click(object sender, EventArgs e)
{
CommonOpenFileDialog dialog = new CommonOpenFileDialog();
dialog.InitialDirectory = inputTbox.Text.Trim();
dialog.IsFolderPicker = true;
if (dialog.ShowDialog() == CommonFileDialogResult.Ok)
outputTbox.Text = dialog.FileName;
}
public void runBtn_Click(object sender, EventArgs e)
{
if (!BatchProcessing.busy) // Don't load values from gui if batch processing is used
Interpolate.current = GetCurrentSettings();
Interpolate.Start();
}
public string GetModel()
{
return aiModel.Text.Split('-')[0].Remove(" ").Remove(".");
}
Interpolate.OutMode GetOutMode()
{
Interpolate.OutMode outMode = Interpolate.OutMode.VidMp4;
if (outModeCombox.Text.ToLower().Contains("mkv")) outMode = Interpolate.OutMode.VidMkv;
if (outModeCombox.Text.ToLower().Contains("webm")) outMode = Interpolate.OutMode.VidWebm;
if (outModeCombox.Text.ToLower().Contains("prores")) outMode = Interpolate.OutMode.VidProRes;
if (outModeCombox.Text.ToLower().Contains("avi")) outMode = Interpolate.OutMode.VidAvi;
if (outModeCombox.Text.ToLower().Contains("gif")) outMode = Interpolate.OutMode.VidGif;
if (outModeCombox.Text.ToLower().Contains("image")) outMode = Interpolate.OutMode.ImgPng;
return outMode;
}
public void SetOutMode(Interpolate.OutMode mode)
{
int theIndex = 0;
for(int i = 0; i < outModeCombox.Items.Count; i++)
{
string currentItem = outModeCombox.Items[i].ToString().ToLower();
if (mode == Interpolate.OutMode.VidMkv && currentItem.Contains("mkv")) theIndex = i;
if (mode == Interpolate.OutMode.VidWebm && currentItem.Contains("webm")) theIndex = i;
if (mode == Interpolate.OutMode.VidProRes && currentItem.Contains("prores")) theIndex = i;
if (mode == Interpolate.OutMode.VidAvi && currentItem.Contains("avi")) theIndex = i;
if (mode == Interpolate.OutMode.VidGif && currentItem.Contains("gif")) theIndex = i;
if (mode == Interpolate.OutMode.ImgPng && currentItem.Contains("image")) theIndex = i;
}
outModeCombox.SelectedIndex = theIndex;
}
AI GetAi()
{
return Networks.networks[aiCombox.SelectedIndex];
}
void inputTbox_DragEnter(object sender, DragEventArgs e) { e.Effect = DragDropEffects.Copy; }
private void inputTbox_DragDrop(object sender, DragEventArgs e)
{
DragDropHandler((string[])e.Data.GetData(DataFormats.FileDrop));
}
void outputTbox_DragEnter(object sender, DragEventArgs e) { e.Effect = DragDropEffects.Copy; }
private void outputTbox_DragDrop(object sender, DragEventArgs e)
{
if (Program.busy) return;
string[] files = (string[])e.Data.GetData(DataFormats.FileDrop);
outputTbox.Text = files[0];
}
private void fpsInTbox_TextChanged(object sender, EventArgs e)
{
fpsInTbox.Text = fpsInTbox.Text.TrimNumbers(true);
UpdateOutputFPS();
}
public void UpdateOutputFPS()
{
float fpsOut = fpsInTbox.GetFloat() * interpFactorCombox.GetFloat();
fpsOutTbox.Text = fpsOut.ToString();
}
private void interpFactorCombox_SelectedIndexChanged(object sender, EventArgs e)
{
UpdateOutputFPS();
int guiInterpFactor = interpFactorCombox.GetInt();
if (!initialized)
return;
string aiName = GetAi().aiName.Replace("_", "-");
if (!Program.busy && guiInterpFactor > 2 && !GetAi().supportsAnyExp && Config.GetInt("autoEncMode") > 0 && !Logger.GetLastLine().Contains(aiName))
Logger.Log($"Warning: {aiName} doesn't natively support 4x/8x and will run multiple times for {guiInterpFactor}x. Auto-Encode will only work on the last run.");
}
public void SetWorking(bool state, bool allowCancel = true)
{
Logger.Log($"SetWorking({state})", true);
SetProgress(-1);
Control[] controlsToDisable = new Control[] { runBtn, runStepBtn, stepSelector, settingsBtn };
Control[] controlsToHide = new Control[] { runBtn, runStepBtn, stepSelector };
progressCircle.Visible = state;
cancelBtn.Visible = state;
foreach (Control c in controlsToDisable)
c.Enabled = !state;
foreach (Control c in controlsToHide)
c.Visible = !state;
cancelBtn.Enabled = allowCancel;
Program.busy = state;
Program.mainForm.UpdateStepByStepControls(false);
}
string lastAiComboxStr = "";
private void aiCombox_SelectedIndexChanged(object sender, EventArgs e)
{
if (string.IsNullOrWhiteSpace(aiCombox.Text) || aiCombox.Text == lastAiComboxStr) return;
lastAiComboxStr = aiCombox.Text;
aiModel = UIUtils.FillAiModelsCombox(aiModel, GetAi());
if(initialized)
ConfigParser.SaveComboxIndex(aiCombox);
interpFactorCombox_SelectedIndexChanged(null, null);
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
Logger.Log("Closing main form.", true);
}
private async void debugExtractFramesBtn_Click(object sender, EventArgs e)
{
await UtilsTab.ExtractVideo(inputTbox.Text.Trim(), utilsExtractAudioCbox.Checked);
}
private void licenseBtn_Click(object sender, EventArgs e)
{
Process.Start("explorer.exe", Path.Combine(Paths.GetPkgPath(), Path.GetFileNameWithoutExtension(Packages.licenses.fileName)));
}
private async void utilsLoopVidBtn_Click(object sender, EventArgs e)
{
await UtilsTab.LoopVideo(inputTbox.Text.Trim(), utilsLoopTimesCombox);
}
private async void utilsChangeSpeedBtn_Click(object sender, EventArgs e)
{
await UtilsTab.ChangeSpeed(inputTbox.Text.Trim(), utilsSpeedCombox);
}
private void Form1_DragEnter(object sender, DragEventArgs e) { e.Effect = DragDropEffects.Copy; }
private void Form1_DragDrop(object sender, DragEventArgs e)
{
DragDropHandler((string[])e.Data.GetData(DataFormats.FileDrop));
}
public void DragDropHandler(string[] files)
{
if (Program.busy) return;
if (files.Length > 1)
{
queueBtn_Click(null, null);
if (BatchProcessing.currentBatchForm != null)
BatchProcessing.currentBatchForm.LoadDroppedPaths(files);
}
else
{
SetTab("interpolation");
Logger.Log("Selected video/directory: " + Path.GetFileName(files[0]));
inputTbox.Text = files[0];
bool resume = (IOUtils.GetAmountOfFiles(Path.Combine(files[0], Paths.resumeDir), true) > 0);
ResumeUtils.resumeNextRun = resume;
if (resume)
ResumeUtils.LoadTempFolder(files[0]);
MainUiFunctions.InitInput(outputTbox, inputTbox, fpsInTbox);
}
}
private async void utilsConvertMp4Btn_Click(object sender, EventArgs e)
{
await UtilsTab.Convert(inputTbox.Text.Trim(), utilsConvCrf);
}
private void utilsDedupBtn_Click(object sender, EventArgs e)
{
UtilsTab.Dedupe(inputTbox.Text.Trim(), false);
}
private void utilsDedupTestBtn_Click(object sender, EventArgs e)
{
UtilsTab.Dedupe(inputTbox.Text.Trim(), true);
}
private void cancelBtn_Click(object sender, EventArgs e)
{
SetTab("interpolation");
Interpolate.Cancel();
}
private void discordBtn_Click(object sender, EventArgs e)
{
Process.Start("https://discord.gg/eJHD2NSJRe");
}
private void paypalBtn_Click(object sender, EventArgs e)
{
Process.Start("https://www.paypal.com/paypalme/nmkd/10");
}
private void patreonBtn_Click(object sender, EventArgs e)
{
Process.Start("https://patreon.com/n00mkrad");
}
private void settingsBtn_Click(object sender, EventArgs e)
{
new SettingsForm().ShowDialog();
}
private void queueBtn_Click(object sender, EventArgs e)
{
if (BatchProcessing.currentBatchForm != null)
{
BatchProcessing.currentBatchForm.WindowState = FormWindowState.Normal;
BatchProcessing.currentBatchForm.BringToFront();
}
else
{
new BatchForm().Show();
}
}
private void previewPicturebox_MouseClick(object sender, MouseEventArgs e)
{
if (InterpolateUtils.bigPreviewForm == null)
{
InterpolateUtils.bigPreviewForm = new BigPreviewForm();
InterpolateUtils.bigPreviewForm.Show();
InterpolateUtils.bigPreviewForm.SetImage(previewPicturebox.Image);
}
}
private async void updateBtn_Click(object sender, EventArgs e)
{
new UpdaterForm().ShowDialog();
}
private void welcomeLabel2_Click(object sender, EventArgs e)
{
SetTab("interpolation");
}
public void UpdateStepByStepControls(bool settingsMayHaveChanged)
{
if (settingsMayHaveChanged)
{
stepSelector.Items.Clear();
if (Config.GetBool("scnDetect"))
stepSelector.Items.AddRange(new string[] { "1) Extract Scene Changes", "2) Import/Extract Frames", "3) Run Interpolation", "4) Export", "5) Cleanup & Reset" });
else
stepSelector.Items.AddRange(new string[] { "1) Import/Extract Frames", "2) Run Interpolation", "3) Export", "4) Cleanup & Reset" });
stepSelector.SelectedIndex = 0;
}
bool stepByStep = Config.GetInt("processingMode") == 1;
runBtn.Visible = !stepByStep && !Program.busy;
}
private async void runStepBtn_Click(object sender, EventArgs e)
{
SetTab("interpolate");
await InterpolateSteps.Run(stepSelector.Text);
}
private void mainTabControl_SelectedIndexChanged(object sender, EventArgs e)
{
if (!initialized) return;
aiCombox_SelectedIndexChanged(null, null);
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,226 +0,0 @@
namespace Flowframes.Forms
{
partial class BatchForm
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(BatchForm));
this.titleLabel = new System.Windows.Forms.Label();
this.stopBtn = new System.Windows.Forms.Button();
this.runBtn = new System.Windows.Forms.Button();
this.addToQueue = new System.Windows.Forms.Button();
this.forceStopBtn = new System.Windows.Forms.Button();
this.clearBtn = new System.Windows.Forms.Button();
this.taskList = new System.Windows.Forms.ListBox();
this.clearSelectedBtn = new System.Windows.Forms.Button();
this.label1 = new System.Windows.Forms.Label();
this.panel1 = new System.Windows.Forms.Panel();
this.panel1.SuspendLayout();
this.SuspendLayout();
//
// titleLabel
//
this.titleLabel.AutoSize = true;
this.titleLabel.Font = new System.Drawing.Font("Yu Gothic UI", 21.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.titleLabel.ForeColor = System.Drawing.Color.White;
this.titleLabel.Location = new System.Drawing.Point(12, 9);
this.titleLabel.Margin = new System.Windows.Forms.Padding(3, 0, 3, 10);
this.titleLabel.Name = "titleLabel";
this.titleLabel.Size = new System.Drawing.Size(323, 40);
this.titleLabel.TabIndex = 1;
this.titleLabel.Text = "Batch Processing Queue";
//
// stopBtn
//
this.stopBtn.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.stopBtn.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(48)))), ((int)(((byte)(48)))), ((int)(((byte)(48)))));
this.stopBtn.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.stopBtn.ForeColor = System.Drawing.Color.White;
this.stopBtn.Location = new System.Drawing.Point(682, 351);
this.stopBtn.Name = "stopBtn";
this.stopBtn.Size = new System.Drawing.Size(250, 40);
this.stopBtn.TabIndex = 35;
this.stopBtn.Text = "Stop After Current Task";
this.stopBtn.UseVisualStyleBackColor = false;
this.stopBtn.Visible = false;
this.stopBtn.Click += new System.EventHandler(this.stopBtn_Click);
//
// runBtn
//
this.runBtn.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.runBtn.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(48)))), ((int)(((byte)(48)))), ((int)(((byte)(48)))));
this.runBtn.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.runBtn.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.runBtn.ForeColor = System.Drawing.Color.White;
this.runBtn.Location = new System.Drawing.Point(682, 443);
this.runBtn.Name = "runBtn";
this.runBtn.Size = new System.Drawing.Size(250, 40);
this.runBtn.TabIndex = 36;
this.runBtn.Text = "Start";
this.runBtn.UseVisualStyleBackColor = false;
this.runBtn.Click += new System.EventHandler(this.runBtn_Click);
//
// addToQueue
//
this.addToQueue.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.addToQueue.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(48)))), ((int)(((byte)(48)))), ((int)(((byte)(48)))));
this.addToQueue.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.addToQueue.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.addToQueue.ForeColor = System.Drawing.Color.White;
this.addToQueue.Location = new System.Drawing.Point(682, 65);
this.addToQueue.Name = "addToQueue";
this.addToQueue.Size = new System.Drawing.Size(250, 40);
this.addToQueue.TabIndex = 39;
this.addToQueue.Text = "Add Current Configuration To Queue";
this.addToQueue.UseVisualStyleBackColor = false;
this.addToQueue.Click += new System.EventHandler(this.addToQueue_Click);
//
// forceStopBtn
//
this.forceStopBtn.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.forceStopBtn.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(48)))), ((int)(((byte)(48)))), ((int)(((byte)(48)))));
this.forceStopBtn.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.forceStopBtn.ForeColor = System.Drawing.Color.White;
this.forceStopBtn.Location = new System.Drawing.Point(682, 397);
this.forceStopBtn.Name = "forceStopBtn";
this.forceStopBtn.Size = new System.Drawing.Size(250, 40);
this.forceStopBtn.TabIndex = 40;
this.forceStopBtn.Text = "Force Stop Now";
this.forceStopBtn.UseVisualStyleBackColor = false;
this.forceStopBtn.Visible = false;
this.forceStopBtn.Click += new System.EventHandler(this.forceStopBtn_Click);
//
// clearBtn
//
this.clearBtn.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.clearBtn.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(48)))), ((int)(((byte)(48)))), ((int)(((byte)(48)))));
this.clearBtn.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.clearBtn.ForeColor = System.Drawing.Color.White;
this.clearBtn.Location = new System.Drawing.Point(682, 157);
this.clearBtn.Name = "clearBtn";
this.clearBtn.Size = new System.Drawing.Size(250, 40);
this.clearBtn.TabIndex = 41;
this.clearBtn.Text = "Clear All Queue Entries";
this.clearBtn.UseVisualStyleBackColor = false;
this.clearBtn.Click += new System.EventHandler(this.clearBtn_Click);
//
// taskList
//
this.taskList.AllowDrop = true;
this.taskList.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(48)))), ((int)(((byte)(48)))), ((int)(((byte)(48)))));
this.taskList.Font = new System.Drawing.Font("Microsoft Sans Serif", 11.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.taskList.ForeColor = System.Drawing.Color.White;
this.taskList.FormattingEnabled = true;
this.taskList.ItemHeight = 18;
this.taskList.Location = new System.Drawing.Point(12, 65);
this.taskList.Name = "taskList";
this.taskList.Size = new System.Drawing.Size(664, 418);
this.taskList.TabIndex = 43;
this.taskList.SelectedIndexChanged += new System.EventHandler(this.taskList_SelectedIndexChanged);
this.taskList.DragDrop += new System.Windows.Forms.DragEventHandler(this.taskList_DragDrop);
this.taskList.DragEnter += new System.Windows.Forms.DragEventHandler(this.taskList_DragEnter);
//
// clearSelectedBtn
//
this.clearSelectedBtn.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.clearSelectedBtn.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(48)))), ((int)(((byte)(48)))), ((int)(((byte)(48)))));
this.clearSelectedBtn.Enabled = false;
this.clearSelectedBtn.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.clearSelectedBtn.ForeColor = System.Drawing.Color.White;
this.clearSelectedBtn.Location = new System.Drawing.Point(682, 111);
this.clearSelectedBtn.Name = "clearSelectedBtn";
this.clearSelectedBtn.Size = new System.Drawing.Size(250, 40);
this.clearSelectedBtn.TabIndex = 44;
this.clearSelectedBtn.Text = "Clear Selected Queue Entry";
this.clearSelectedBtn.UseVisualStyleBackColor = false;
this.clearSelectedBtn.Click += new System.EventHandler(this.clearSelectedBtn_Click);
//
// label1
//
this.label1.ForeColor = System.Drawing.Color.White;
this.label1.Location = new System.Drawing.Point(6, 6);
this.label1.Margin = new System.Windows.Forms.Padding(6);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(238, 111);
this.label1.TabIndex = 45;
this.label1.Text = "Tip:\r\nYou can also drag and drop multiple videos into the list.\r\nThey will be add" +
"ed to the queue using the interpolation settings set in the GUI.";
//
// panel1
//
this.panel1.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(40)))), ((int)(((byte)(40)))), ((int)(((byte)(40)))));
this.panel1.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.panel1.Controls.Add(this.label1);
this.panel1.Font = new System.Drawing.Font("Microsoft Sans Serif", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.panel1.Location = new System.Drawing.Point(682, 203);
this.panel1.Name = "panel1";
this.panel1.Size = new System.Drawing.Size(250, 142);
this.panel1.TabIndex = 46;
//
// BatchForm
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(32)))), ((int)(((byte)(32)))), ((int)(((byte)(32)))));
this.ClientSize = new System.Drawing.Size(944, 501);
this.Controls.Add(this.panel1);
this.Controls.Add(this.clearSelectedBtn);
this.Controls.Add(this.taskList);
this.Controls.Add(this.clearBtn);
this.Controls.Add(this.forceStopBtn);
this.Controls.Add(this.addToQueue);
this.Controls.Add(this.runBtn);
this.Controls.Add(this.stopBtn);
this.Controls.Add(this.titleLabel);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedToolWindow;
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
this.MaximizeBox = false;
this.Name = "BatchForm";
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
this.Text = "Batch Processing";
this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.BatchForm_FormClosing);
this.Load += new System.EventHandler(this.BatchForm_Load);
this.panel1.ResumeLayout(false);
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.Label titleLabel;
private System.Windows.Forms.Button stopBtn;
private System.Windows.Forms.Button runBtn;
private System.Windows.Forms.Button addToQueue;
private System.Windows.Forms.Button forceStopBtn;
private System.Windows.Forms.Button clearBtn;
private System.Windows.Forms.ListBox taskList;
private System.Windows.Forms.Button clearSelectedBtn;
private System.Windows.Forms.Label label1;
private System.Windows.Forms.Panel panel1;
}
}

View File

@@ -1,150 +0,0 @@
using Flowframes.IO;
using Flowframes.Main;
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Flowframes.Forms
{
public partial class BatchForm : Form
{
public BatchForm()
{
AutoScaleMode = AutoScaleMode.None;
InitializeComponent();
BatchProcessing.currentBatchForm = this;
}
private void addToQueue_Click(object sender, EventArgs e)
{
Program.batchQueue.Enqueue(Program.mainForm.GetCurrentSettings());
RefreshGui();
}
public void RefreshGui ()
{
taskList.Items.Clear();
string nl = Environment.NewLine;
for (int i = 0; i < Program.batchQueue.Count; i++)
{
InterpSettings entry = Program.batchQueue.ElementAt(i);
string niceOutMode = entry.outMode.ToString().ToUpper().Replace("VID", "").Replace("IMG", "");
string str = $"#{i}: {Path.GetFileName(entry.inPath).Trunc(45)} - {entry.inFps} FPS => {entry.interpFactor}x{nl} {entry.ai.aiNameShort} => {niceOutMode}";
taskList.Items.Add(str);
}
}
public void SetWorking (bool working)
{
runBtn.Enabled = !working;
addToQueue.Enabled = !working;
stopBtn.Visible = working;
forceStopBtn.Visible = working;
stopBtn.Enabled = working;
}
private void BatchForm_Load(object sender, EventArgs e)
{
SetWorking(BatchProcessing.busy);
RefreshGui();
}
private void runBtn_Click(object sender, EventArgs e)
{
stopBtn.Enabled = true;
BatchProcessing.Start();
//WindowState = FormWindowState.Minimized;
Program.mainForm.WindowState = FormWindowState.Normal;
Program.mainForm.BringToFront();
}
private void clearBtn_Click(object sender, EventArgs e)
{
Program.batchQueue.Clear();
RefreshGui();
}
private void stopBtn_Click(object sender, EventArgs e)
{
stopBtn.Enabled = false;
BatchProcessing.stopped = true;
}
private void forceStopBtn_Click(object sender, EventArgs e)
{
Interpolate.Cancel("Force stopped by user.");
BatchProcessing.stopped = true;
}
private void BatchForm_FormClosing(object sender, FormClosingEventArgs e)
{
BatchProcessing.currentBatchForm = null;
}
private void clearSelectedBtn_Click(object sender, EventArgs e)
{
if (taskList.SelectedItem == null) return;
Queue<InterpSettings> temp = new Queue<InterpSettings>();
for(int i = 0; i < Program.batchQueue.Count; i++)
{
if (i != taskList.SelectedIndex)
temp.Enqueue(Program.batchQueue.ElementAt(i));
}
Program.batchQueue = temp;
RefreshGui();
}
private void taskList_SelectedIndexChanged(object sender, EventArgs e)
{
clearSelectedBtn.Enabled = taskList.SelectedItem != null;
}
private void taskList_DragEnter(object sender, DragEventArgs e) { e.Effect = DragDropEffects.Copy; }
private async void taskList_DragDrop(object sender, DragEventArgs e)
{
string[] droppedPaths = (string[])e.Data.GetData(DataFormats.FileDrop);
await LoadDroppedPaths(droppedPaths);
}
public async Task LoadDroppedPaths (string[] droppedPaths)
{
foreach (string path in droppedPaths)
{
Logger.Log($"Dropped file: '{path}'", true);
string frame1 = Path.Combine(path, "00000001.png");
if (IOUtils.IsPathDirectory(path) && !File.Exists(frame1))
{
InterpolateUtils.ShowMessage($"Can't find frames in this folder:\n\n{frame1} does not exist.", "Error");
continue;
}
InterpSettings current = Program.mainForm.GetCurrentSettings();
current.UpdatePaths(path, path.GetParentDir());
current.inFps = await GetFramerate(path);
current.outFps = current.inFps * current.interpFactor;
Program.batchQueue.Enqueue(current);
RefreshGui();
await Task.Delay(100);
}
}
async Task<float> GetFramerate (string path)
{
float fps = Interpolate.current.inFps;
float fpsFromFile = await IOUtils.GetFpsFolderOrVideo(path);
if (fpsFromFile > 0)
return fpsFromFile;
return fps;
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,70 +0,0 @@
namespace Flowframes.Forms
{
partial class BigPreviewForm
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(BigPreviewForm));
this.picBox = new System.Windows.Forms.PictureBox();
((System.ComponentModel.ISupportInitialize)(this.picBox)).BeginInit();
this.SuspendLayout();
//
// picBox
//
this.picBox.Dock = System.Windows.Forms.DockStyle.Fill;
this.picBox.Image = global::Flowframes.Properties.Resources.baseline_image_white_48dp_4x_25pcAlpha;
this.picBox.Location = new System.Drawing.Point(0, 0);
this.picBox.Margin = new System.Windows.Forms.Padding(0);
this.picBox.Name = "picBox";
this.picBox.Size = new System.Drawing.Size(704, 601);
this.picBox.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
this.picBox.TabIndex = 0;
this.picBox.TabStop = false;
//
// BigPreviewForm
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(32)))), ((int)(((byte)(32)))), ((int)(((byte)(32)))));
this.ClientSize = new System.Drawing.Size(704, 601);
this.Controls.Add(this.picBox);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.SizableToolWindow;
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
this.Name = "BigPreviewForm";
this.Text = "Resizable Preview";
this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.BigPreviewForm_FormClosing);
this.Load += new System.EventHandler(this.BigPreviewForm_Load);
((System.ComponentModel.ISupportInitialize)(this.picBox)).EndInit();
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.PictureBox picBox;
}
}

View File

@@ -1,36 +0,0 @@
using Flowframes.Main;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Flowframes.Forms
{
public partial class BigPreviewForm : Form
{
public BigPreviewForm()
{
InitializeComponent();
}
private void BigPreviewForm_Load(object sender, EventArgs e)
{
}
public void SetImage (Image img)
{
picBox.Image = img;
}
private void BigPreviewForm_FormClosing(object sender, FormClosingEventArgs e)
{
InterpolateUtils.bigPreviewForm = null;
}
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,199 +0,0 @@
using Flowframes.IO;
using Flowframes.MiscUtils;
using Microsoft.WindowsAPICodePack.Dialogs;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Flowframes.Forms
{
public partial class SettingsForm : Form
{
bool initialized = false;
public SettingsForm()
{
AutoScaleMode = AutoScaleMode.None;
InitializeComponent();
}
private void SettingsForm_Load(object sender, EventArgs e)
{
LoadSettings();
initialized = true;
CheckModelCacheSize();
}
public async Task CheckModelCacheSize ()
{
long modelFoldersBytes = 0;
foreach (string modelFolder in ModelDownloader.GetAllModelFolders())
modelFoldersBytes += IOUtils.GetDirSize(modelFolder, true);
if (modelFoldersBytes > 1024 * 1024)
clearModelCacheBtn.Text = $"Clear Model Cache ({FormatUtils.Bytes(modelFoldersBytes)})";
else
clearModelCacheBtn.Enabled = false;
}
private void SettingsForm_FormClosing(object sender, FormClosingEventArgs e)
{
SaveSettings();
Program.mainForm.UpdateStepByStepControls(true);
}
void SaveSettings ()
{
// Clamp...
h264Crf.Text = h264Crf.GetInt().Clamp(0, 51).ToString();
h265Crf.Text = h265Crf.GetInt().Clamp(0, 51).ToString();
vp9Crf.Text = vp9Crf.GetInt().Clamp(0, 63).ToString();
// Remove spaces...
torchGpus.Text = torchGpus.Text.Replace(" ", "");
ncnnGpus.Text = ncnnGpus.Text.Replace(" ", "");
// General
ConfigParser.SaveComboxIndex(processingMode);
ConfigParser.SaveGuiElement(maxVidHeight, ConfigParser.StringMode.Int);
ConfigParser.SaveGuiElement(enableAlpha);
ConfigParser.SaveComboxIndex(tempFolderLoc);
ConfigParser.SaveGuiElement(keepTempFolder);
ConfigParser.SaveGuiElement(delLogsOnStartup);
ConfigParser.SaveGuiElement(clearLogOnInput);
ConfigParser.SaveGuiElement(modelSuffix);
// Interpolation
ConfigParser.SaveGuiElement(keepAudio);
ConfigParser.SaveGuiElement(keepSubs);
ConfigParser.SaveComboxIndex(dedupMode);
ConfigParser.SaveComboxIndex(mpdecimateMode);
ConfigParser.SaveGuiElement(dedupThresh);
ConfigParser.SaveGuiElement(enableLoop);
ConfigParser.SaveGuiElement(scnDetect);
ConfigParser.SaveGuiElement(scnDetectValue);
ConfigParser.SaveComboxIndex(autoEncMode);
ConfigParser.SaveGuiElement(sbsAllowAutoEnc);
// AI
ConfigParser.SaveGuiElement(torchGpus);
ConfigParser.SaveGuiElement(ncnnGpus);
ConfigParser.SaveGuiElement(ncnnThreads);
ConfigParser.SaveGuiElement(uhdThresh);
ConfigParser.SaveGuiElement(dainNcnnTilesize, ConfigParser.StringMode.Int);
// Video Export
ConfigParser.SaveGuiElement(minOutVidLength, ConfigParser.StringMode.Int);
ConfigParser.SaveComboxIndex(mp4Enc);
ConfigParser.SaveGuiElement(h264Crf);
ConfigParser.SaveGuiElement(h265Crf);
ConfigParser.SaveGuiElement(vp9Crf);
ConfigParser.SaveComboxIndex(proResProfile);
ConfigParser.SaveGuiElement(gifColors);
ConfigParser.SaveGuiElement(aviCodec);
ConfigParser.SaveGuiElement(aviColors);
ConfigParser.SaveGuiElement(maxFps);
ConfigParser.SaveComboxIndex(maxFpsMode);
ConfigParser.SaveComboxIndex(loopMode);
// Debugging
ConfigParser.SaveComboxIndex(cmdDebugMode);
ConfigParser.SaveGuiElement(autoDedupFrames);
ConfigParser.SaveGuiElement(modelsBaseUrl);
ConfigParser.SaveGuiElement(ffEncThreads, ConfigParser.StringMode.Int);
ConfigParser.SaveGuiElement(ffEncPreset);
ConfigParser.SaveGuiElement(ffEncArgs);
ConfigParser.SaveGuiElement(ffprobeCountFrames);
}
void LoadSettings()
{
// General
ConfigParser.LoadComboxIndex(processingMode);
ConfigParser.LoadGuiElement(maxVidHeight);
ConfigParser.LoadGuiElement(enableAlpha);
ConfigParser.LoadComboxIndex(tempFolderLoc); ConfigParser.LoadGuiElement(tempDirCustom);
ConfigParser.LoadGuiElement(delLogsOnStartup);
ConfigParser.LoadGuiElement(keepTempFolder);
ConfigParser.LoadGuiElement(clearLogOnInput);
ConfigParser.LoadGuiElement(modelSuffix);
// Interpolation
ConfigParser.LoadGuiElement(keepAudio);
ConfigParser.LoadGuiElement(keepSubs);
ConfigParser.LoadComboxIndex(dedupMode);
ConfigParser.LoadComboxIndex(mpdecimateMode);
ConfigParser.LoadGuiElement(dedupThresh);
ConfigParser.LoadGuiElement(enableLoop);
ConfigParser.LoadGuiElement(scnDetect);
ConfigParser.LoadGuiElement(scnDetectValue);
ConfigParser.LoadComboxIndex(autoEncMode);
ConfigParser.LoadGuiElement(sbsAllowAutoEnc);
// AI
ConfigParser.LoadGuiElement(torchGpus);
ConfigParser.LoadGuiElement(ncnnGpus);
ConfigParser.LoadGuiElement(ncnnThreads);
ConfigParser.LoadGuiElement(uhdThresh);
ConfigParser.LoadGuiElement(dainNcnnTilesize);
// Video Export
ConfigParser.LoadGuiElement(minOutVidLength);
ConfigParser.LoadComboxIndex(mp4Enc);
ConfigParser.LoadGuiElement(h264Crf);
ConfigParser.LoadGuiElement(h265Crf);
ConfigParser.LoadGuiElement(vp9Crf);
ConfigParser.LoadComboxIndex(proResProfile);
ConfigParser.LoadGuiElement(gifColors);
ConfigParser.LoadGuiElement(aviCodec);
ConfigParser.LoadGuiElement(aviColors);
ConfigParser.LoadGuiElement(maxFps);
ConfigParser.LoadComboxIndex(maxFpsMode);
ConfigParser.LoadComboxIndex(loopMode);
// Debugging
ConfigParser.LoadComboxIndex(cmdDebugMode);
ConfigParser.LoadGuiElement(autoDedupFrames);
ConfigParser.LoadGuiElement(modelsBaseUrl);
ConfigParser.LoadGuiElement(ffEncThreads);
ConfigParser.LoadGuiElement(ffEncPreset);
ConfigParser.LoadGuiElement(ffEncArgs);
ConfigParser.LoadGuiElement(ffprobeCountFrames);
}
private void tempFolderLoc_SelectedIndexChanged(object sender, EventArgs e)
{
tempDirBrowseBtn.Visible = tempFolderLoc.SelectedIndex == 4;
tempDirCustom.Visible = tempFolderLoc.SelectedIndex == 4;
}
private void tempDirBrowseBtn_Click(object sender, EventArgs e)
{
CommonOpenFileDialog dialog = new CommonOpenFileDialog();
dialog.InitialDirectory = tempDirCustom.Text.Trim();
dialog.IsFolderPicker = true;
if (dialog.ShowDialog() == CommonFileDialogResult.Ok)
tempDirCustom.Text = dialog.FileName;
ConfigParser.SaveGuiElement(tempDirCustom);
}
private void cmdDebugMode_SelectedIndexChanged(object sender, EventArgs e)
{
if (initialized && cmdDebugMode.SelectedIndex == 2)
MessageBox.Show("If you enable this, you need to close the CMD window manually after the process has finished, otherwise processing will be paused!", "Notice");
}
private void dedupMode_SelectedIndexChanged(object sender, EventArgs e)
{
dedupeSensLabel.Visible = dedupMode.SelectedIndex != 0;
magickDedupePanel.Visible = dedupMode.SelectedIndex == 1;
mpDedupePanel.Visible = dedupMode.SelectedIndex == 2;
}
private void clearModelCacheBtn_Click(object sender, EventArgs e)
{
ModelDownloader.DeleteAllModels();
clearModelCacheBtn.Text = "Clear Model Cache";
CheckModelCacheSize();
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,208 +0,0 @@
namespace Flowframes.Forms
{
partial class UpdaterForm
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(UpdaterForm));
this.titleLabel = new System.Windows.Forms.Label();
this.label13 = new System.Windows.Forms.Label();
this.updatePatreonBtn = new System.Windows.Forms.Button();
this.label1 = new System.Windows.Forms.Label();
this.label2 = new System.Windows.Forms.Label();
this.installedLabel = new System.Windows.Forms.Label();
this.latestLabel = new System.Windows.Forms.Label();
this.statusLabel = new System.Windows.Forms.Label();
this.downloadingLabel = new System.Windows.Forms.Label();
this.updateFreeBtn = new System.Windows.Forms.Button();
this.SuspendLayout();
//
// titleLabel
//
this.titleLabel.AutoSize = true;
this.titleLabel.Font = new System.Drawing.Font("Yu Gothic UI", 21.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.titleLabel.ForeColor = System.Drawing.Color.White;
this.titleLabel.Location = new System.Drawing.Point(12, 9);
this.titleLabel.Margin = new System.Windows.Forms.Padding(3, 0, 3, 10);
this.titleLabel.Name = "titleLabel";
this.titleLabel.Size = new System.Drawing.Size(121, 40);
this.titleLabel.TabIndex = 2;
this.titleLabel.Text = "Updater";
//
// label13
//
this.label13.AutoSize = true;
this.label13.Font = new System.Drawing.Font("Microsoft Sans Serif", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.label13.ForeColor = System.Drawing.Color.White;
this.label13.Location = new System.Drawing.Point(17, 67);
this.label13.Margin = new System.Windows.Forms.Padding(8, 8, 3, 0);
this.label13.Name = "label13";
this.label13.Size = new System.Drawing.Size(110, 16);
this.label13.TabIndex = 35;
this.label13.Text = "Installed Version:";
//
// updatePatreonBtn
//
this.updatePatreonBtn.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.updatePatreonBtn.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(48)))), ((int)(((byte)(48)))), ((int)(((byte)(48)))));
this.updatePatreonBtn.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.updatePatreonBtn.ForeColor = System.Drawing.Color.White;
this.updatePatreonBtn.Location = new System.Drawing.Point(12, 229);
this.updatePatreonBtn.Name = "updatePatreonBtn";
this.updatePatreonBtn.Size = new System.Drawing.Size(203, 40);
this.updatePatreonBtn.TabIndex = 36;
this.updatePatreonBtn.Text = "Download Patreon Version";
this.updatePatreonBtn.UseVisualStyleBackColor = true;
this.updatePatreonBtn.Click += new System.EventHandler(this.updatePatreonBtn_Click);
//
// label1
//
this.label1.AutoSize = true;
this.label1.Font = new System.Drawing.Font("Microsoft Sans Serif", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.label1.ForeColor = System.Drawing.Color.White;
this.label1.Location = new System.Drawing.Point(16, 93);
this.label1.Margin = new System.Windows.Forms.Padding(8, 10, 3, 0);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(96, 16);
this.label1.TabIndex = 37;
this.label1.Text = "Latest Version:";
//
// label2
//
this.label2.AutoSize = true;
this.label2.Font = new System.Drawing.Font("Microsoft Sans Serif", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.label2.ForeColor = System.Drawing.Color.White;
this.label2.Location = new System.Drawing.Point(16, 119);
this.label2.Margin = new System.Windows.Forms.Padding(8, 10, 3, 0);
this.label2.Name = "label2";
this.label2.Size = new System.Drawing.Size(48, 16);
this.label2.TabIndex = 38;
this.label2.Text = "Status:";
//
// installedLabel
//
this.installedLabel.AutoSize = true;
this.installedLabel.Font = new System.Drawing.Font("Microsoft Sans Serif", 9.75F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.installedLabel.ForeColor = System.Drawing.Color.White;
this.installedLabel.Location = new System.Drawing.Point(170, 67);
this.installedLabel.Margin = new System.Windows.Forms.Padding(8, 8, 3, 0);
this.installedLabel.Name = "installedLabel";
this.installedLabel.Size = new System.Drawing.Size(76, 16);
this.installedLabel.TabIndex = 39;
this.installedLabel.Text = "Loading...";
//
// latestLabel
//
this.latestLabel.AutoSize = true;
this.latestLabel.Font = new System.Drawing.Font("Microsoft Sans Serif", 9.75F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.latestLabel.ForeColor = System.Drawing.Color.White;
this.latestLabel.Location = new System.Drawing.Point(170, 93);
this.latestLabel.Margin = new System.Windows.Forms.Padding(8, 8, 3, 0);
this.latestLabel.Name = "latestLabel";
this.latestLabel.Size = new System.Drawing.Size(76, 16);
this.latestLabel.TabIndex = 40;
this.latestLabel.Text = "Loading...";
//
// statusLabel
//
this.statusLabel.AutoSize = true;
this.statusLabel.Font = new System.Drawing.Font("Microsoft Sans Serif", 9.75F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.statusLabel.ForeColor = System.Drawing.Color.White;
this.statusLabel.Location = new System.Drawing.Point(170, 119);
this.statusLabel.Margin = new System.Windows.Forms.Padding(8, 8, 3, 0);
this.statusLabel.Name = "statusLabel";
this.statusLabel.Size = new System.Drawing.Size(76, 16);
this.statusLabel.TabIndex = 41;
this.statusLabel.Text = "Loading...";
//
// downloadingLabel
//
this.downloadingLabel.AutoSize = true;
this.downloadingLabel.Font = new System.Drawing.Font("Microsoft Sans Serif", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.downloadingLabel.ForeColor = System.Drawing.Color.White;
this.downloadingLabel.Location = new System.Drawing.Point(226, 241);
this.downloadingLabel.Margin = new System.Windows.Forms.Padding(8, 10, 3, 0);
this.downloadingLabel.Name = "downloadingLabel";
this.downloadingLabel.Size = new System.Drawing.Size(0, 16);
this.downloadingLabel.TabIndex = 42;
//
// updateFreeBtn
//
this.updateFreeBtn.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.updateFreeBtn.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(48)))), ((int)(((byte)(48)))), ((int)(((byte)(48)))));
this.updateFreeBtn.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.updateFreeBtn.ForeColor = System.Drawing.Color.White;
this.updateFreeBtn.Location = new System.Drawing.Point(221, 229);
this.updateFreeBtn.Name = "updateFreeBtn";
this.updateFreeBtn.Size = new System.Drawing.Size(203, 40);
this.updateFreeBtn.TabIndex = 43;
this.updateFreeBtn.Text = "Download Free Version";
this.updateFreeBtn.UseVisualStyleBackColor = true;
this.updateFreeBtn.Click += new System.EventHandler(this.updateFreeBtn_Click);
//
// UpdaterForm
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(32)))), ((int)(((byte)(32)))), ((int)(((byte)(32)))));
this.ClientSize = new System.Drawing.Size(624, 281);
this.Controls.Add(this.updateFreeBtn);
this.Controls.Add(this.downloadingLabel);
this.Controls.Add(this.statusLabel);
this.Controls.Add(this.latestLabel);
this.Controls.Add(this.installedLabel);
this.Controls.Add(this.label2);
this.Controls.Add(this.label1);
this.Controls.Add(this.updatePatreonBtn);
this.Controls.Add(this.label13);
this.Controls.Add(this.titleLabel);
this.ForeColor = System.Drawing.Color.White;
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedToolWindow;
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
this.Name = "UpdaterForm";
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
this.Text = "Updater";
this.Load += new System.EventHandler(this.UpdaterForm_Load);
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.Label titleLabel;
private System.Windows.Forms.Label label13;
private System.Windows.Forms.Button updatePatreonBtn;
private System.Windows.Forms.Label label1;
private System.Windows.Forms.Label label2;
private System.Windows.Forms.Label installedLabel;
private System.Windows.Forms.Label latestLabel;
private System.Windows.Forms.Label statusLabel;
private System.Windows.Forms.Label downloadingLabel;
private System.Windows.Forms.Button updateFreeBtn;
}
}

View File

@@ -1,82 +0,0 @@
using Flowframes.Data;
using Flowframes.OS;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Flowframes.Forms
{
public partial class UpdaterForm : Form
{
Version installed;
Version latestPat;
Version latestFree;
public UpdaterForm()
{
AutoScaleMode = AutoScaleMode.None;
InitializeComponent();
}
private async void UpdaterForm_Load(object sender, EventArgs e)
{
installed = Updater.GetInstalledVer();
latestPat = Updater.GetLatestVer(true);
latestFree = Updater.GetLatestVer(false);
installedLabel.Text = installed.ToString();
await Task.Delay(100);
latestLabel.Text = $"{latestPat} (Patreon/Beta) - {latestFree} (Free/Stable)";
if (Updater.CompareVersions(installed, latestFree) == Updater.VersionCompareResult.Equal)
{
statusLabel.Text = "Latest Free Version Is Installed.";
if (Updater.CompareVersions(installed, latestPat) == Updater.VersionCompareResult.Newer)
statusLabel.Text += "\nBeta Update Available On Patreon.";
return;
}
if (Updater.CompareVersions(installed, latestPat) == Updater.VersionCompareResult.Equal)
{
statusLabel.Text = "Latest Patreon/Beta Version Is Installed.";
return;
}
if (Updater.CompareVersions(installed, latestPat) == Updater.VersionCompareResult.Newer)
{
statusLabel.Text = "Update available on Patreon!";
if (Updater.CompareVersions(installed, latestFree) == Updater.VersionCompareResult.Newer)
statusLabel.Text = $"Beta Updates Available On Patreon and Itch.io.";
return;
}
}
float lastProg = -1f;
public void SetProgLabel (float prog, string str)
{
if (prog == lastProg) return;
lastProg = prog;
downloadingLabel.Text = str;
}
private void updatePatreonBtn_Click(object sender, EventArgs e)
{
string link = Updater.GetLatestVerLink(true);
if(!string.IsNullOrWhiteSpace(link))
Process.Start(link);
}
private void updateFreeBtn_Click(object sender, EventArgs e)
{
string link = Updater.GetLatestVerLink(false);
if (!string.IsNullOrWhiteSpace(link))
Process.Start(link);
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,15 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Flowframes.IO
{
class CfgStrings
{
// public static string dedupMode = "dedupMode";
// public static string dedupThresh = "dedupThresh";
// public static string keepFrames = "keepFrames";
}
}

View File

@@ -1,182 +0,0 @@
using Flowframes.OS;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Windows.Forms;
namespace Flowframes.IO
{
internal class Config
{
private static string configPath;
private static string[] cachedLines;
public static void Init()
{
configPath = Path.Combine(Paths.GetDataPath(), "config.ini");
IOUtils.CreateFileIfNotExists(configPath);
Reload();
}
public static void Set(string key, string value)
{
string[] lines = new string[1];
try
{
lines = File.ReadAllLines(configPath);
}
catch
{
MessageBox.Show("Failed to read config file!\nFlowframes will try to re-create the file if it does not exist.", "Error");
if(!File.Exists(configPath))
Init();
}
for (int i = 0; i < lines.Length; i++)
{
if (lines[i].Split('|')[0] == key)
{
lines[i] = key + "|" + value;
File.WriteAllLines(configPath, lines);
cachedLines = lines;
return;
}
}
List<string> list = lines.ToList();
list.Add(key + "|" + value);
list = list.OrderBy(p => p).ToList();
string newFileContent = "";
foreach(string line in list)
newFileContent += line + "\n";
File.WriteAllText(configPath, newFileContent.Trim());
cachedLines = list.ToArray();
}
public static string Get(string key, string defaultVal)
{
WriteIfDoesntExist(key, defaultVal);
return Get(key);
}
public static string Get(string key, Type type = Type.String)
{
try
{
for (int i = 0; i < cachedLines.Length; i++)
{
string[] keyValuePair = cachedLines[i].Split('|');
if (keyValuePair[0] == key && !string.IsNullOrWhiteSpace(keyValuePair[1]))
return keyValuePair[1];
}
return WriteDefaultValIfExists(key, type);
}
catch (Exception e)
{
Logger.Log($"Failed to get {key.Wrap()} from config! {e.Message}");
}
return null;
}
public static bool GetBool(string key)
{
return bool.Parse(Get(key, Type.Bool));
}
public static bool GetBool(string key, bool defaultVal)
{
WriteIfDoesntExist(key, (defaultVal ? "True" : "False"));
return bool.Parse(Get(key, Type.Bool));
}
public static int GetInt(string key)
{
return Get(key, Type.Int).GetInt();
}
public static int GetInt(string key, int defaultVal)
{
WriteIfDoesntExist(key, defaultVal.ToString());
return GetInt(key);
}
public static float GetFloat(string key)
{
return float.Parse(Get(key, Type.Float), CultureInfo.InvariantCulture);
}
public static string GetFloatString (string key)
{
return Get(key, Type.Float).Replace(",", ".");
}
static void WriteIfDoesntExist (string key, string val)
{
foreach (string line in cachedLines)
if (line.Contains(key + "|"))
return;
Set(key, val);
}
public enum Type { String, Int, Float, Bool }
private static string WriteDefaultValIfExists(string key, Type type)
{
if (key == "maxVidHeight") return WriteDefault(key, "2160");
if (key == "delLogsOnStartup") return WriteDefault(key, "True");
if (key == "clearLogOnInput") return WriteDefault(key, "True");
if (key == "tempDirCustom") return WriteDefault(key, "C:/");
// Interpolation
if (key == "dedupMode") return WriteDefault(key, "2");
if (key == "dedupThresh") return WriteDefault(key, "2");
if (key == "keepAudio") return WriteDefault(key, "True");
if (key == "keepSubs") return WriteDefault(key, "True");
if (key == "autoDedupFrames") return WriteDefault(key, "100");
if (key == "scnDetectValue") return WriteDefault(key, "0.2");
if (key == "autoEncMode") return WriteDefault(key, "2");
// Video Export
if (key == "minOutVidLength") return WriteDefault(key, "5");
if (key == "h264Crf") return WriteDefault(key, "20");
if (key == "h265Crf") return WriteDefault(key, "24");
if (key == "vp9Crf") return WriteDefault(key, "32");
if (key == "proResProfile") return WriteDefault(key, "2");
if (key == "aviCodec") return WriteDefault(key, "ffv1");
if (key == "aviColors") return WriteDefault(key, "yuv420p");
if (key == "gifColors") return WriteDefault(key, "128 (High)");
if (key == "minVidLength") return WriteDefault(key, "2");
// AI
if (key == "uhdThresh") return WriteDefault(key, "1440");
if (key == "ncnnThreads") return WriteDefault(key, "1");
if (key == "dainNcnnTilesize") return WriteDefault(key, "768");
// Debug / Other / Experimental
if (key == "modelsBaseUrl") return WriteDefault(key, "https://dl.nmkd.de/flowframes/mdl/");
if (key == "ffEncPreset") return WriteDefault(key, "medium");
if (key == "ffEncArgs") return WriteDefault(key, "");
if (type == Type.Int || type == Type.Float) return WriteDefault(key, "0"); // Write default int/float (0)
if (type == Type.Bool) return WriteDefault(key, "False"); // Write default bool (False)
return WriteDefault(key, "0");
}
private static string WriteDefault(string key, string def)
{
Set(key, def);
return def;
}
private static void Reload()
{
List<string> validLines = new List<string>();
string[] lines = File.ReadAllLines(configPath);
foreach (string line in lines)
{
if(line != null && !string.IsNullOrWhiteSpace(line) && line.Length > 3)
validLines.Add(line);
}
cachedLines = validLines.ToArray();
}
}
}

View File

@@ -1,80 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Flowframes.IO
{
class ConfigParser
{
public enum StringMode { Any, Int, Float }
public static void SaveGuiElement(TextBox textbox, StringMode stringMode = StringMode.Any)
{
switch (stringMode)
{
case StringMode.Any: Config.Set(textbox.Name, textbox.Text); break;
case StringMode.Int: Config.Set(textbox.Name, textbox.Text.GetInt().ToString()); break;
case StringMode.Float: Config.Set(textbox.Name, textbox.Text.GetFloat().ToString()); break;
}
}
public static void SaveGuiElement(ComboBox comboBox, StringMode stringMode = StringMode.Any)
{
switch (stringMode)
{
case StringMode.Any: Config.Set(comboBox.Name, comboBox.Text); break;
case StringMode.Int: Config.Set(comboBox.Name, comboBox.Text.GetInt().ToString()); break;
case StringMode.Float: Config.Set(comboBox.Name, comboBox.Text.GetFloat().ToString().Replace(",", ".")); break;
}
}
public static void SaveGuiElement(CheckBox checkbox)
{
Config.Set(checkbox.Name, checkbox.Checked.ToString());
}
public static void SaveGuiElement(NumericUpDown upDown, StringMode stringMode = StringMode.Any)
{
switch (stringMode)
{
case StringMode.Any: Config.Set(upDown.Name, ((float)upDown.Value).ToString().Replace(",", ".")); break;
case StringMode.Int: Config.Set(upDown.Name, ((int)upDown.Value).ToString()); break;
case StringMode.Float: Config.Set(upDown.Name, ((float)upDown.Value).ToString().Replace(",", ".")); ; break;
}
}
public static void SaveComboxIndex(ComboBox comboBox)
{
Config.Set(comboBox.Name, comboBox.SelectedIndex.ToString());
}
public static void LoadGuiElement(ComboBox comboBox, string suffix = "")
{
comboBox.Text = Config.Get(comboBox.Name) + suffix;
}
public static void LoadGuiElement(TextBox textbox, string suffix = "")
{
textbox.Text = Config.Get(textbox.Name) + suffix; ;
}
public static void LoadGuiElement(CheckBox checkbox)
{
checkbox.Checked = Config.GetBool(checkbox.Name);
}
public static void LoadGuiElement(NumericUpDown upDown)
{
upDown.Value = Convert.ToDecimal(Config.GetFloat(upDown.Name));
}
public static void LoadComboxIndex(ComboBox comboBox)
{
comboBox.SelectedIndex = Config.GetInt(comboBox.Name);
}
}
}

View File

@@ -1,795 +0,0 @@

using Flowframes.Data;
using Flowframes.Main;
using Flowframes.MiscUtils;
using Flowframes.UI;
using Force.Crc32;
using Microsoft.WindowsAPICodePack.Shell;
using Standart.Hash.xxHash;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Flowframes.IO
{
class IOUtils
{
public static string GetExe()
{
return System.Reflection.Assembly.GetEntryAssembly().GetName().CodeBase.Replace("file:///", "");
}
public static string GetExeDir()
{
return AppDomain.CurrentDomain.BaseDirectory;
}
public static Image GetImage(string path)
{
using (FileStream stream = new FileStream(path, FileMode.Open, FileAccess.Read))
return Image.FromStream(stream);
}
public static string[] ReadLines(string path)
{
List<string> lines = new List<string>();
using (var fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, 0x1000, FileOptions.SequentialScan))
using (var sr = new StreamReader(fs, Encoding.UTF8))
{
string line;
while ((line = sr.ReadLine()) != null)
lines.Add(line);
}
return lines.ToArray();
}
public static bool IsPathDirectory(string path)
{
if (path == null)
{
throw new ArgumentNullException("path");
}
path = path.Trim();
if (Directory.Exists(path))
{
return true;
}
if (File.Exists(path))
{
return false;
}
if (new string[2]
{
"\\",
"/"
}.Any((string x) => path.EndsWith(x)))
{
return true;
}
return string.IsNullOrWhiteSpace(Path.GetExtension(path));
}
public static bool IsFileValid(string path)
{
if (path == null)
return false;
if (!File.Exists(path))
return false;
return true;
}
public static bool IsDirValid(string path)
{
if (path == null)
return false;
if (!Directory.Exists(path))
return false;
return true;
}
public static void Copy(string sourceDirectoryName, string targetDirectoryName, bool move = false)
{
Directory.CreateDirectory(targetDirectoryName);
DirectoryInfo source = new DirectoryInfo(sourceDirectoryName);
DirectoryInfo target = new DirectoryInfo(targetDirectoryName);
CopyWork(source, target, move);
}
private static void CopyWork(DirectoryInfo source, DirectoryInfo target, bool move)
{
DirectoryInfo[] directories = source.GetDirectories();
foreach (DirectoryInfo directoryInfo in directories)
{
CopyWork(directoryInfo, target.CreateSubdirectory(directoryInfo.Name), move);
}
FileInfo[] files = source.GetFiles();
foreach (FileInfo fileInfo in files)
{
if (move)
fileInfo.MoveTo(Path.Combine(target.FullName, fileInfo.Name));
else
fileInfo.CopyTo(Path.Combine(target.FullName, fileInfo.Name), overwrite: true);
}
}
public static void DeleteContentsOfDir(string path)
{
DirectoryInfo directoryInfo = new DirectoryInfo(path);
FileInfo[] files = directoryInfo.GetFiles();
foreach (FileInfo fileInfo in files)
{
fileInfo.Delete();
}
DirectoryInfo[] directories = directoryInfo.GetDirectories();
foreach (DirectoryInfo directoryInfo2 in directories)
{
directoryInfo2.Delete(recursive: true);
}
}
public static void ReplaceInFilenamesDir(string dir, string textToFind, string textToReplace, bool recursive = true, string wildcard = "*")
{
int counter = 1;
DirectoryInfo d = new DirectoryInfo(dir);
FileInfo[] files = null;
if (recursive)
files = d.GetFiles(wildcard, SearchOption.AllDirectories);
else
files = d.GetFiles(wildcard, SearchOption.TopDirectoryOnly);
foreach (FileInfo file in files)
{
ReplaceInFilename(file.FullName, textToFind, textToReplace);
counter++;
}
}
public static void ReplaceInFilename(string path, string textToFind, string textToReplace)
{
string ext = Path.GetExtension(path);
string newFilename = Path.GetFileNameWithoutExtension(path).Replace(textToFind, textToReplace);
string targetPath = Path.Combine(Path.GetDirectoryName(path), newFilename + ext);
if (File.Exists(targetPath))
{
//Program.Print("Skipped " + path + " because a file with the target name already exists.");
return;
}
File.Move(path, targetPath);
}
public static int GetFilenameCounterLength(string file, string prefixToRemove = "")
{
string filenameNoExt = Path.GetFileNameWithoutExtension(file);
if (!string.IsNullOrEmpty(prefixToRemove))
filenameNoExt = filenameNoExt.Replace(prefixToRemove, "");
string onlyNumbersFilename = Regex.Replace(filenameNoExt, "[^.0-9]", "");
return onlyNumbersFilename.Length;
}
public static int GetAmountOfFiles (string path, bool recursive, string wildcard = "*")
{
try
{
DirectoryInfo d = new DirectoryInfo(path);
FileInfo[] files = null;
if (recursive)
files = d.GetFiles(wildcard, SearchOption.AllDirectories);
else
files = d.GetFiles(wildcard, SearchOption.TopDirectoryOnly);
return files.Length;
}
catch
{
return 0;
}
}
static bool TryCopy(string source, string target, bool overwrite = true)
{
try
{
File.Copy(source, target, overwrite);
}
catch (Exception e)
{
Logger.Log($"Failed to move '{source}' to '{target}' (Overwrite: {overwrite}): {e.Message}");
return false;
}
return true;
}
public static bool TryMove(string source, string target, bool overwrite = true)
{
try
{
if (overwrite && File.Exists(target))
File.Delete(target);
File.Move(source, target);
}
catch (Exception e)
{
Logger.Log($"Failed to move '{source}' to '{target}' (Overwrite: {overwrite}): {e.Message}");
return false;
}
return true;
}
public static void RenameCounterDir(string path, bool inverse = false)
{
int counter = 1;
DirectoryInfo d = new DirectoryInfo(path);
FileInfo[] files = d.GetFiles();
var filesSorted = files.OrderBy(n => n);
if (inverse)
filesSorted.Reverse();
foreach (FileInfo file in files)
{
string dir = new DirectoryInfo(file.FullName).Parent.FullName;
int filesDigits = (int)Math.Floor(Math.Log10((double)files.Length) + 1);
File.Move(file.FullName, Path.Combine(dir, counter.ToString().PadLeft(filesDigits, '0') + Path.GetExtension(file.FullName)));
counter++;
//if (counter % 100 == 0) Program.Print("Renamed " + counter + " files...");
}
}
public static async Task<Dictionary<string, string>> RenameCounterDirReversibleAsync(string path, string ext, int startAt, int padding = 0)
{
Stopwatch sw = new Stopwatch();
sw.Restart();
Dictionary<string, string> oldNewNamesMap = new Dictionary<string, string>();
int counter = startAt;
FileInfo[] files = new DirectoryInfo(path).GetFiles($"*.{ext}", SearchOption.TopDirectoryOnly);
var filesSorted = files.OrderBy(n => n);
foreach (FileInfo file in files)
{
string dir = new DirectoryInfo(file.FullName).Parent.FullName;
int filesDigits = (int)Math.Floor(Math.Log10((double)files.Length) + 1);
string newFilename = (padding > 0) ? counter.ToString().PadLeft(padding, '0') : counter.ToString();
string outpath = outpath = Path.Combine(dir, newFilename + Path.GetExtension(file.FullName));
File.Move(file.FullName, outpath);
oldNewNamesMap.Add(file.FullName, outpath);
counter++;
if(sw.ElapsedMilliseconds > 100)
{
await Task.Delay(1);
sw.Restart();
}
}
return oldNewNamesMap;
}
public static async Task ReverseRenaming(string basePath, Dictionary<string, string> oldNewMap) // Relative -> absolute paths
{
Dictionary<string, string> absPaths = oldNewMap.ToDictionary(x => Path.Combine(basePath, x.Key), x => Path.Combine(basePath, x.Value));
await ReverseRenaming(absPaths);
}
public static async Task ReverseRenaming(Dictionary<string, string> oldNewMap) // Takes absolute paths only
{
if (oldNewMap == null || oldNewMap.Count < 1) return;
int counter = 0;
int failCount = 0;
foreach (KeyValuePair<string, string> pair in oldNewMap)
{
bool success = TryMove(pair.Value, pair.Key);
if (!success)
failCount++;
if (failCount >= 100)
break;
counter++;
if (counter % 1000 == 0)
await Task.Delay(1);
}
}
public static async Task<float> GetVideoFramerate (string path)
{
float fps = 0;
try
{
ShellFile shellFile = ShellFile.FromFilePath(path);
fps = (float)shellFile.Properties.System.Video.FrameRate.Value / 1000f;
Logger.Log("Detected FPS of " + Path.GetFileName(path) + " as " + fps + " FPS", true);
if (fps <= 0)
throw new Exception("FPS is 0.");
}
catch
{
Logger.Log("Failed to read FPS - Trying alternative method...", true);
try
{
fps = await FfmpegCommands.GetFramerate(path);
Logger.Log("Detected FPS of " + Path.GetFileName(path) + " as " + fps + " FPS", true);
}
catch
{
Logger.Log("Failed to read FPS - Please enter it manually.");
}
}
return fps;
}
public static float GetVideoFramerateForDir(string path)
{
float fps = 0;
try
{
string parentDir = path.GetParentDir();
string fpsFile = Path.Combine(parentDir, "fps.ini");
fps = float.Parse(ReadLines(fpsFile)[0]);
Logger.Log($"Got {fps} FPS from file: " + fpsFile);
float guiFps = Program.mainForm.GetCurrentSettings().inFps;
DialogResult dialogResult = MessageBox.Show("A frame rate file has been found in the parent directory.\n\n" +
$"Click \"Yes\" to use frame rate from the file ({fps}) or \"No\" to use current FPS set in GUI ({guiFps})", "Load Frame Rate From fps.ini?", MessageBoxButtons.YesNo);
if (dialogResult == DialogResult.Yes)
return fps;
else if (dialogResult == DialogResult.No)
return guiFps;
}
catch { }
return fps;
}
public static async Task<Size> GetVideoOrFramesRes (string path)
{
Size res = new Size();
if (!IsPathDirectory(path)) // If path is video
{
res = GetVideoRes(path);
}
else // Path is frame folder
{
Image thumb = await MainUiFunctions.GetThumbnail(path);
res = new Size(thumb.Width, thumb.Height);
}
return res;
}
public static Size GetVideoRes (string path)
{
Size size = new Size(0, 0);
try
{
ShellFile shellFile = ShellFile.FromFilePath(path);
int w = (int)shellFile.Properties.System.Video.FrameWidth.Value;
int h = (int)shellFile.Properties.System.Video.FrameHeight.Value;
return new Size(w, h);
}
catch (Exception e)
{
Logger.Log($"Failed to read video size ({e.Message}) - Trying alternative method...", true);
try
{
size = FfmpegCommands.GetSize(path);
Logger.Log($"Detected video size of {Path.GetFileName(path)} as {size.Width}x{size.Height}", true);
}
catch
{
Logger.Log("Failed to read video size!");
}
}
return size;
}
public static bool TryDeleteIfExists(string path) // Returns true if no exception occurs
{
try
{
if (path == null)
return false;
DeleteIfExists(path);
return true;
}
catch (Exception e)
{
Logger.Log($"TryDeleteIfExists: Error trying to delete {path}: {e.Message}", true);
return false;
}
}
public static bool DeleteIfExists (string path) // Returns true if the file/dir exists
{
if (!IsPathDirectory(path) && File.Exists(path))
{
File.Delete(path);
return true;
}
if (IsPathDirectory(path) && Directory.Exists(path))
{
Directory.Delete(path, true);
return true;
}
return false;
}
public static string GetCurrentExportSuffix ()
{
return GetExportSuffix(Interpolate.current.interpFactor, Interpolate.current.ai, Interpolate.current.model);
}
public static string GetExportSuffix(float factor, AI ai, string mdl)
{
string suffix = $"-{factor.ToStringDot()}x-{ai.aiNameShort.ToUpper()}";
if (Config.GetBool("modelSuffix"))
suffix += $"-{mdl}";
return suffix;
}
public static string GetHighestFrameNumPath (string path)
{
FileInfo highest = null;
int highestInt = -1;
foreach(FileInfo frame in new DirectoryInfo(path).GetFiles("*.*", SearchOption.TopDirectoryOnly))
{
int num = frame.Name.GetInt();
if (num > highestInt)
{
highest = frame;
highestInt = frame.Name.GetInt();
}
}
return highest.FullName;
}
public static string FilenameSuffix (string path, string suffix)
{
try
{
string ext = Path.GetExtension(path);
return Path.Combine(path.GetParentDir(), $"{Path.GetFileNameWithoutExtension(path)}{suffix}{ext}");
}
catch
{
return path;
}
}
public static string GetAudioFile (string basePath)
{
string[] exts = new string[] { "m4a", "wav", "ogg", "mp2", "mp3" };
foreach(string ext in exts)
{
string filename = Path.ChangeExtension(basePath, ext);
if (File.Exists(filename))
return filename;
}
return null;
}
public static async Task<float> GetFpsFolderOrVideo(string path)
{
try
{
if (IsPathDirectory(path))
{
float dirFps = GetVideoFramerateForDir(path);
if (dirFps > 0)
return dirFps;
}
else
{
float vidFps = await GetVideoFramerate(path);
if (vidFps > 0)
return vidFps;
}
}
catch (Exception e)
{
Logger.Log("GetFpsFolderOrVideo() Error: " + e.Message);
}
return 0;
}
public enum ErrorMode { HiddenLog, VisibleLog, Messagebox }
public static bool CanWriteToDir (string dir, ErrorMode errMode)
{
string tempFile = Path.Combine(dir, "flowframes-testfile.tmp");
try
{
File.Create(tempFile);
File.Delete(tempFile);
return true;
}
catch (Exception e)
{
Logger.Log($"Can't write to {dir}! {e.Message}", errMode == ErrorMode.HiddenLog);
if (errMode == ErrorMode.Messagebox && !BatchProcessing.busy)
MessageBox.Show($"Can't write to {dir}!\n\n{e.Message}", "Error");
return false;
}
}
public static bool CopyTo (string file, string targetFolder, bool overwrite = true)
{
string targetPath = Path.Combine(targetFolder, Path.GetFileName(file));
try
{
if (!Directory.Exists(targetFolder))
Directory.CreateDirectory(targetFolder);
File.Copy(file, targetPath, overwrite);
return true;
}
catch (Exception e)
{
Logger.Log($"Failed to copy {file} to {targetFolder}: {e.Message}");
return false;
}
}
public static bool MoveTo(string file, string targetFolder, bool overwrite = true)
{
string targetPath = Path.Combine(targetFolder, Path.GetFileName(file));
try
{
if (!Directory.Exists(targetFolder))
Directory.CreateDirectory(targetFolder);
if (overwrite)
DeleteIfExists(targetPath);
File.Move(file, targetPath);
return true;
}
catch (Exception e)
{
Logger.Log($"Failed to move {file} to {targetFolder}: {e.Message}");
return false;
}
}
public enum Hash { MD5, CRC32, xxHash }
public static string GetHash (string path, Hash hashType, bool log = true, bool quick = true)
{
Benchmarker.Start();
string hashStr = "";
if (IsPathDirectory(path))
{
Logger.Log($"Path '{path}' is directory! Returning empty hash.", true);
return hashStr;
}
try
{
var stream = File.OpenRead(path);
if (hashType == Hash.MD5)
{
MD5 md5 = MD5.Create();
var hash = md5.ComputeHash(stream);
hashStr = BitConverter.ToString(hash).Replace("-", "").ToLowerInvariant();
}
if (hashType == Hash.CRC32)
{
var crc = new Crc32Algorithm();
var crc32bytes = crc.ComputeHash(stream);
hashStr = BitConverter.ToUInt32(crc32bytes, 0).ToString();
}
if (hashType == Hash.xxHash)
{
ulong xxh64 = xxHash64.ComputeHash(stream, 8192, (ulong)GetFilesize(path));
hashStr = xxh64.ToString();
}
stream.Close();
}
catch (Exception e)
{
Logger.Log($"Error getting file hash for {Path.GetFileName(path)}: {e.Message}", true);
return "";
}
if (log)
Logger.Log($"Computed {hashType} for '{Path.GetFileNameWithoutExtension(path).Trunc(40) + Path.GetExtension(path)}' ({GetFilesizeStr(path)}) in {Benchmarker.GetTimeStr(true)}: {hashStr}", true);
return hashStr;
}
public static async Task<string> GetHashAsync(string path, Hash hashType, bool log = true, bool quick = true)
{
await Task.Delay(1);
return GetHash(path, hashType, log, quick);
}
public static bool CreateDir (string path) // Returns whether the dir already existed
{
if (!Directory.Exists(path))
{
Directory.CreateDirectory(path);
return false;
}
return true;
}
public static void ZeroPadDir(string path, string ext, int targetLength, bool recursive = false)
{
FileInfo[] files;
if (recursive)
files = new DirectoryInfo(path).GetFiles($"*.{ext}", SearchOption.AllDirectories);
else
files = new DirectoryInfo(path).GetFiles($"*.{ext}", SearchOption.TopDirectoryOnly);
ZeroPadDir(files.Select(x => x.FullName).ToList(), targetLength);
}
public static void ZeroPadDir(List<string> files, int targetLength, List<string> exclude = null, bool noLog = true)
{
if(exclude != null)
files = files.Except(exclude).ToList();
foreach (string file in files)
{
string fname = Path.GetFileNameWithoutExtension(file);
string targetFilename = Path.Combine(Path.GetDirectoryName(file), fname.PadLeft(targetLength, '0') + Path.GetExtension(file));
try
{
if (targetFilename != file)
File.Move(file, targetFilename);
}
catch (Exception e)
{
if(!noLog)
Logger.Log($"Failed to zero-pad {file} => {targetFilename}: {e.Message}", true);
}
}
}
public static bool CheckImageValid (string path)
{
try
{
Image img = GetImage(path);
if (img.Width > 1 && img.Height > 1)
return true;
return false;
}
catch
{
return false;
}
}
public static string[] GetFilesSorted (string path, bool recursive = false, string pattern = "*")
{
SearchOption opt = recursive ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly;
return Directory.GetFiles(path, pattern, opt).OrderBy(x => Path.GetFileName(x)).ToArray();
}
public static string[] GetFilesSorted(string path, string pattern = "*")
{
return GetFilesSorted(path, false, pattern);
}
public static string[] GetFilesSorted(string path)
{
return GetFilesSorted(path, false, "*");
}
public static FileInfo[] GetFileInfosSorted(string path, bool recursive = false, string pattern = "*")
{
SearchOption opt = recursive ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly;
DirectoryInfo dir = new DirectoryInfo(path);
return dir.GetFiles(pattern, opt).OrderBy(x => x.Name).ToArray();
}
public static bool CreateFileIfNotExists (string path)
{
if (File.Exists(path))
return false;
try
{
File.Create(path).Close();
return true;
}
catch (Exception e)
{
Logger.Log($"Failed to create file at '{path}': {e.Message}");
return false;
}
}
public static long GetDirSize(string path, bool recursive, string[] includedExtensions = null)
{
long size = 0;
// Add file sizes.
string[] files;
StringComparison ignCase = StringComparison.OrdinalIgnoreCase;
if (includedExtensions == null)
files = Directory.GetFiles(path);
else
files = Directory.GetFiles(path).Where(file => includedExtensions.Any(x => file.EndsWith(x, ignCase))).ToArray();
foreach (string file in files)
size += new FileInfo(file).Length;
if (!recursive)
return size;
// Add subdirectory sizes.
DirectoryInfo[] dis = new DirectoryInfo(path).GetDirectories();
foreach (DirectoryInfo di in dis)
size += GetDirSize(di.FullName, true, includedExtensions);
return size;
}
public static long GetFilesize(string path)
{
try
{
return new FileInfo(path).Length;
}
catch
{
return -1;
}
}
public static string GetFilesizeStr (string path)
{
try
{
return FormatUtils.Bytes(GetFilesize(path));
}
catch
{
return "?";
}
}
public static byte[] GetLastBytes (string path, int startAt, int bytesAmount)
{
byte[] buffer = new byte[bytesAmount];
using (BinaryReader reader = new BinaryReader(new FileStream(path, FileMode.Open)))
{
reader.BaseStream.Seek(startAt, SeekOrigin.Begin);
reader.Read(buffer, 0, bytesAmount);
}
return buffer;
}
public static bool HasBadChars(string str)
{
return str != str.StripBadChars();
}
public static void OverwriteFileWithText (string path, string text = "THIS IS A DUMMY FILE - DO NOT DELETE ME")
{
try
{
File.WriteAllText(path, text);
}
catch (Exception e)
{
Logger.Log($"OverwriteWithText failed for '{path}': {e.Message}");
}
}
}
}

View File

@@ -1,116 +0,0 @@
using Flowframes.IO;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using DT = System.DateTime;
namespace Flowframes
{
class Logger
{
public static TextBox textbox;
static string file;
public const string defaultLogName = "sessionlog";
public static long id;
public static void Log(string s, bool hidden = false, bool replaceLastLine = false, string filename = "")
{
if (string.IsNullOrWhiteSpace(s))
return;
Console.WriteLine(s);
try
{
if (replaceLastLine)
textbox.Text = textbox.Text.Remove(textbox.Text.LastIndexOf(Environment.NewLine));
}
catch { }
s = s.Replace("\n", Environment.NewLine);
if (!hidden && textbox != null)
textbox.AppendText((textbox.Text.Length > 1 ? Environment.NewLine : "") + s);
LogToFile(s, false, filename);
}
public static void LogToFile(string logStr, bool noLineBreak, string filename)
{
if (string.IsNullOrWhiteSpace(filename))
filename = defaultLogName;
if (Path.GetExtension(filename) != ".txt")
filename = Path.ChangeExtension(filename, "txt");
file = Path.Combine(Paths.GetLogPath(), filename);
logStr = logStr.Replace(Environment.NewLine, " ").TrimWhitespaces();
string time = DT.Now.Month + "-" + DT.Now.Day + "-" + DT.Now.Year + " " + DT.Now.Hour + ":" + DT.Now.Minute + ":" + DT.Now.Second;
try
{
if (!noLineBreak)
File.AppendAllText(file, $"{Environment.NewLine}[{id}] [{time}]: {logStr}");
else
File.AppendAllText(file, " " + logStr);
id++;
}
catch
{
// this if fine, i forgot why
}
}
public static void LogIfLastLineDoesNotContainMsg (string s, bool hidden = false, bool replaceLastLine = false, string filename = "")
{
if (!GetLastLine().Contains(s))
Log(s, hidden, replaceLastLine, filename);
}
public static void WriteToFile (string content, bool append, string filename)
{
if (string.IsNullOrWhiteSpace(filename))
filename = defaultLogName;
if (Path.GetExtension(filename) != ".txt")
filename = Path.ChangeExtension(filename, "txt");
file = Path.Combine(Paths.GetLogPath(), filename);
string time = DT.Now.Month + "-" + DT.Now.Day + "-" + DT.Now.Year + " " + DT.Now.Hour + ":" + DT.Now.Minute + ":" + DT.Now.Second;
try
{
if (append)
File.AppendAllText(file, Environment.NewLine + time + ":" + Environment.NewLine + content);
else
File.WriteAllText(file, Environment.NewLine + time + ":" + Environment.NewLine + content);
}
catch
{
}
}
public static void ClearLogBox ()
{
textbox.Text = "";
}
public static string GetLastLine ()
{
string[] lines = textbox.Text.SplitIntoLines();
if (lines.Length < 1)
return "";
return lines.Last();
}
public static void RemoveLastLine ()
{
textbox.Text = textbox.Text.Remove(textbox.Text.LastIndexOf(Environment.NewLine));
}
}
}

View File

@@ -1,201 +0,0 @@
using Flowframes.Data;
using Flowframes.MiscUtils;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
namespace Flowframes.IO
{
class ModelDownloader
{
public static async Task<Dictionary<string, string>> GetFilelist (string ai, string model)
{
var client = new WebClient();
string[] fileLines = client.DownloadString(GetMdlFileUrl(ai, model, "md5.txt")).SplitIntoLines();
Dictionary<string, string> filesDict = GetDict(fileLines);
return filesDict;
}
static string GetMdlUrl (string ai, string model)
{
string baseUrl = Config.Get("modelsBaseUrl");
return Path.Combine(baseUrl, ai.ToLower(), model);
}
static string GetMdlFileUrl(string ai, string model, string file)
{
return Path.Combine(GetMdlUrl(ai, model), file);
}
static string GetLocalPath(string ai, string model)
{
return Path.Combine(Paths.GetPkgPath(), ai, model);
}
static async Task DownloadTo (string url, string saveDir, int retries = 3)
{
string savePath = Path.Combine(saveDir, Path.GetFileName(url));
IOUtils.TryDeleteIfExists(savePath);
Logger.Log($"Downloading '{url}' to '{savePath}'", true);
Stopwatch sw = new Stopwatch();
sw.Restart();
bool completed = false;
int lastProgPercentage = -1;
var client = new WebClient();
client.DownloadProgressChanged += (sender, args) =>
{
if (sw.ElapsedMilliseconds > 200 && args.ProgressPercentage != lastProgPercentage)
{
sw.Restart();
lastProgPercentage = args.ProgressPercentage;
Logger.Log($"Downloading model file '{Path.GetFileName(url)}'... {args.ProgressPercentage}%", false, true);
}
};
client.DownloadFileCompleted += (sender, args) =>
{
if (args.Error != null)
Logger.Log("Download failed: " + args.Error.Message);
completed = true;
};
client.DownloadFileTaskAsync(url, savePath).ConfigureAwait(false);
while (!completed)
{
if (Interpolate.canceled)
{
client.CancelAsync();
client.Dispose();
return;
}
if (sw.ElapsedMilliseconds > 6000)
{
client.CancelAsync();
if(retries > 0)
{
await DownloadTo(url, saveDir, retries--);
}
else
{
Interpolate.Cancel("Model download failed.");
return;
}
}
await Task.Delay(500);
}
Logger.Log($"Downloaded '{Path.GetFileName(url)}' ({IOUtils.GetFilesize(savePath) / 1024} KB)", true);
}
public static async Task DownloadModelFiles (string ai, string model)
{
model = model.ToUpper();
Logger.Log($"DownloadModelFiles(string ai = {ai}, string model = {model})", true);
try
{
string mdlDir = GetLocalPath(ai, model);
if (AreFilesValid(ai, model))
return;
Logger.Log($"Downloading '{model}' model files...");
Directory.CreateDirectory(mdlDir);
await DownloadTo(GetMdlFileUrl(ai, model, "md5.txt"), mdlDir);
Dictionary<string, string> fileList = await GetFilelist(ai, model);
foreach (KeyValuePair<string, string> modelFile in fileList)
await DownloadTo(GetMdlFileUrl(ai, model, modelFile.Key), mdlDir);
Logger.Log($"Downloaded \"{model}\" model files.", false, true);
}
catch (Exception e)
{
Logger.Log($"DownloadModelFiles Error: {e.Message}\nStack Trace:\n{e.StackTrace}");
Interpolate.Cancel($"Error downloading model files: {e.Message}");
}
}
public static void DeleteAllModels ()
{
foreach(string modelFolder in GetAllModelFolders())
{
string size = FormatUtils.Bytes(IOUtils.GetDirSize(modelFolder, true));
if (IOUtils.TryDeleteIfExists(modelFolder))
Logger.Log($"Deleted cached model '{Path.GetFileName(modelFolder.GetParentDir())}/{Path.GetFileName(modelFolder)}' ({size})");
}
}
public static List<string> GetAllModelFolders()
{
List<string> modelPaths = new List<string>();
foreach (AI ai in Networks.networks)
{
string aiPkgFolder = PkgUtils.GetPkgFolder(ai.pkg);
string modelsFile = Path.Combine(aiPkgFolder, "models.txt");
if (!File.Exists(modelsFile)) continue;
foreach (string mdl in IOUtils.ReadLines(modelsFile))
{
string modelName = mdl.Split('-')[0].Remove(" ").Remove(".");
string mdlFolder = Path.Combine(aiPkgFolder, modelName);
if (!Directory.Exists(mdlFolder)) continue;
modelPaths.Add(mdlFolder);
}
}
return modelPaths;
}
public static bool AreFilesValid (string ai, string model)
{
string mdlDir = GetLocalPath(ai, model);
if (!Directory.Exists(mdlDir))
{
Logger.Log($"Files for model {model} not valid: {mdlDir} does not exist.", true);
return false;
}
string md5FilePath = Path.Combine(mdlDir, "md5.txt");
if (!File.Exists(md5FilePath) || IOUtils.GetFilesize(md5FilePath) < 32)
{
Logger.Log($"Files for model {model} not valid: {mdlDir} does not exist or is incomplete.", true);
return false;
}
string[] md5Lines = IOUtils.ReadLines(md5FilePath);
Dictionary<string, string> filesDict = GetDict(md5Lines);
foreach(KeyValuePair<string, string> file in filesDict)
{
string md5 = IOUtils.GetHash(Path.Combine(mdlDir, file.Key), IOUtils.Hash.MD5);
if (md5.Trim() != file.Value.Trim())
{
Logger.Log($"Files for model {model} not valid: MD5 of {file.Key} ({md5.Trim()}) does not equal validation MD5 ({file.Value.Trim()}).", true);
return false;
}
}
return true;
}
static Dictionary<string, string> GetDict (string[] lines, char sep = ':')
{
Dictionary<string, string> dict = new Dictionary<string, string>();
foreach (string line in lines)
{
if (line.Length < 3) continue;
string[] keyValuePair = line.Split(':');
dict.Add(keyValuePair[0], keyValuePair[1]);
}
return dict;
}
}
}

View File

@@ -1,43 +0,0 @@
using Flowframes.Data;
using Flowframes.Forms;
using System;
using System.Collections.Generic;
using System.IO;
using System.Windows.Forms;
namespace Flowframes.IO
{
class PkgUtils
{
public static string GetPkgFolder (FlowPackage pkg)
{
return Path.Combine(Paths.GetPkgPath(), Path.GetFileNameWithoutExtension(pkg.fileName));
}
public static bool IsInstalled(FlowPackage pkg)
{
string path = GetPkgFolder(pkg);
return (Directory.Exists(path) && IOUtils.GetAmountOfFiles(path, true) > 0);
}
public static bool IsUpToDate(FlowPackage pkg, int minVersion)
{
return (GetVersion(pkg) >= minVersion);
}
public static int GetVersion (FlowPackage pkg)
{
string versionFilePath = Path.Combine(GetPkgFolder(pkg), "ver.ini");
if (!File.Exists(versionFilePath))
return 0;
return IOUtils.ReadLines(versionFilePath)[0].Split('#')[0].GetInt();
}
public static bool IsAiAvailable(AI ai, bool msg = true)
{
Logger.Log("PkgInstaller.IsAiAvailable - Checking for AI " + ai.aiName, true);
return IsInstalled(ai.pkg);
}
}
}

View File

@@ -1,145 +0,0 @@
using Flowframes;
using Flowframes.IO;
using Flowframes.UI;
using ImageMagick;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Flowframes.Magick
{
class Converter
{
public static async Task Convert (string dir, MagickFormat format, int quality, string ext = "", bool print = true, bool setProgress = true)
{
var files = IOUtils.GetFilesSorted(dir);
if(print) Logger.Log($"Converting {files.Length} files in {dir}");
int counter = 0;
foreach (string file in files)
{
if (print) Logger.Log("Converting " + Path.GetFileName(file) + " to " + format.ToString().StripNumbers().ToUpper(), false, true);
MagickImage img = new MagickImage(file);
img.Format = format;
img.Quality = quality;
string outpath = file;
if (!string.IsNullOrWhiteSpace(ext)) outpath = Path.ChangeExtension(outpath, ext);
img.Write(outpath);
counter++;
if(setProgress)
Program.mainForm.SetProgress((int)Math.Round(((float)counter / files.Length) * 100f));
await Task.Delay(1);
}
}
public static async Task MakeBinary (string inputDir, string outputDir, bool print = true, bool setProgress = true)
{
try
{
var files = IOUtils.GetFilesSorted(inputDir);
if (print) Logger.Log($"Processing alpha channel...");
Directory.CreateDirectory(outputDir);
Stopwatch sw = new Stopwatch();
sw.Restart();
int counter = 0;
foreach (string file in files)
{
MagickImage img = new MagickImage(file);
img.Format = MagickFormat.Png24;
img.Quality = 10;
img.Threshold(new Percentage(75));
string outPath = Path.Combine(outputDir, Path.GetFileName(file));
img.Write(outPath);
counter++;
if (sw.ElapsedMilliseconds > 250)
{
if (setProgress)
Program.mainForm.SetProgress((int)Math.Round(((float)counter / files.Length) * 100f));
await Task.Delay(1);
sw.Restart();
}
}
}
catch (Exception e)
{
Logger.Log("MakeBinary Error: " + e.Message);
}
}
public static async Task ExtractAlpha (string inputDir, string outputDir, bool print = true, bool setProgress = true, bool removeInputAlpha = true)
{
try
{
var files = IOUtils.GetFilesSorted(inputDir);
if (print) Logger.Log($"Extracting alpha channel from images...");
Directory.CreateDirectory(outputDir);
Stopwatch sw = new Stopwatch();
sw.Restart();
int counter = 0;
foreach (string file in files)
{
MagickImage alphaImg = new MagickImage(file);
if (removeInputAlpha)
{
MagickImage rgbImg = alphaImg;
rgbImg.Format = MagickFormat.Png24;
rgbImg.Quality = 10;
MagickImage bg = new MagickImage(MagickColors.Black, rgbImg.Width, rgbImg.Height);
bg.Composite(rgbImg, CompositeOperator.Over);
rgbImg = bg;
rgbImg.Write(file);
}
alphaImg.Format = MagickFormat.Png24;
alphaImg.Quality = 10;
alphaImg.FloodFill(MagickColors.None, 0, 0); // Fill the image with a transparent background
alphaImg.InverseOpaque(MagickColors.None, MagickColors.White); // Change all the pixels that are not transparent to white.
alphaImg.ColorAlpha(MagickColors.Black); // Change the transparent pixels to black.
string outPath = Path.Combine(outputDir, Path.GetFileName(file));
alphaImg.Write(outPath);
counter++;
if (sw.ElapsedMilliseconds > 250)
{
if (setProgress)
Program.mainForm.SetProgress((int)Math.Round(((float)counter / files.Length) * 100f));
await Task.Delay(1);
sw.Restart();
}
}
}
catch (Exception e)
{
Logger.Log("ExtractAlpha Error: " + e.Message);
}
}
public static async Task Preprocess (string dir, bool setProgress = true)
{
var files = IOUtils.GetFilesSorted(dir);
Logger.Log($"Preprocessing {files} files in {dir}");
int counter = 0;
foreach (string file in files)
{
//Logger.Log("Converting " + Path.GetFileName(file) + " to " + format, false, true);
MagickImage img = new MagickImage(file);
//img.Format = MagickFormat.Bmp;
//img.Write(file);
//img = new MagickImage(file);
img.Format = MagickFormat.Png24;
img.Quality = 10;
counter++;
if (setProgress)
Program.mainForm.SetProgress((int)Math.Round(((float)counter / files.Length) * 100f));
await Task.Delay(1);
}
}
}
}

View File

@@ -1,234 +0,0 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Flowframes.IO;
using ImageMagick;
using Flowframes.OS;
using Flowframes.Data;
using System.Drawing;
using Paths = Flowframes.IO.Paths;
namespace Flowframes.Magick
{
class Dedupe
{
public enum Mode { None, Info, Enabled, Auto }
public static Mode currentMode;
public static float currentThreshold;
public static async Task Run(string path, bool testRun = false, bool setStatus = true)
{
if (path == null || !Directory.Exists(path) || Interpolate.canceled)
return;
currentMode = Mode.Auto;
if(setStatus)
Program.mainForm.SetStatus("Running frame de-duplication");
currentThreshold = Config.GetFloat("dedupThresh");
Logger.Log("Running accurate frame de-duplication...");
if (currentMode == Mode.Enabled || currentMode == Mode.Auto)
await RemoveDupeFrames(path, currentThreshold, "png", testRun, false, (currentMode == Mode.Auto));
}
public static Dictionary<string, MagickImage> imageCache = new Dictionary<string, MagickImage>();
static MagickImage GetImage(string path)
{
bool allowCaching = true;
if (!allowCaching)
return new MagickImage(path);
if (!imageCache.ContainsKey(path))
imageCache.Add(path, new MagickImage(path));
return imageCache[path];
}
public static void ClearCache ()
{
imageCache.Clear();
}
public static async Task RemoveDupeFrames(string path, float threshold, string ext, bool testRun = false, bool debugLog = false, bool skipIfNoDupes = false)
{
Stopwatch sw = new Stopwatch();
sw.Restart();
Logger.Log("Removing duplicate frames - Threshold: " + threshold.ToString("0.00"));
FileInfo[] framePaths = IOUtils.GetFileInfosSorted(path, false, "*." + ext);
List<string> framesToDelete = new List<string>();
int bufferSize = await GetBufferSize();
int currentOutFrame = 1;
int currentDupeCount = 0;
int statsFramesKept = 0;
int statsFramesDeleted = 0;
int skipAfterNoDupesFrames = Config.GetInt("autoDedupFrames");
bool hasEncounteredAnyDupes = false;
bool skipped = false;
bool hasReachedEnd = false;
string fileContent = "";
for (int i = 0; i < framePaths.Length; i++) // Loop through frames
{
if (hasReachedEnd)
break;
string frame1 = framePaths[i].FullName;
int compareWithIndex = i + 1;
while (true) // Loop dupes
{
//compareWithIndex++;
if (compareWithIndex >= framePaths.Length)
{
hasReachedEnd = true;
break;
}
if (framesToDelete.Contains(framePaths[compareWithIndex].FullName) || !File.Exists(framePaths[compareWithIndex].FullName))
{
//Logger.Log($"Frame {compareWithIndex} was already deleted - skipping");
compareWithIndex++;
}
else
{
string frame2 = framePaths[compareWithIndex].FullName;
float diff = GetDifference(frame1, frame2);
if (diff < threshold) // Is a duped frame.
{
if (!testRun)
{
framesToDelete.Add(frame2);
if (debugLog) Logger.Log("[Deduplication] Deleted " + Path.GetFileName(frame2));
hasEncounteredAnyDupes = true;
}
statsFramesDeleted++;
currentDupeCount++;
}
else
{
fileContent += $"{Path.GetFileNameWithoutExtension(framePaths[i].Name)}:{currentDupeCount}\n";
statsFramesKept++;
currentOutFrame++;
currentDupeCount = 0;
break;
}
if (sw.ElapsedMilliseconds >= 500 || (i+1) == framePaths.Length) // Print every 0.5s (or when done)
{
sw.Restart();
Logger.Log($"[Deduplication] Running de-duplication ({i}/{framePaths.Length}), deleted {statsFramesDeleted} ({(((float)statsFramesDeleted / framePaths.Length) * 100f).ToString("0")}%) duplicate frames so far...", false, true);
Program.mainForm.SetProgress((int)Math.Round(((float)i / framePaths.Length) * 100f));
if (imageCache.Count > bufferSize || (imageCache.Count > 50 && OSUtils.GetFreeRamMb() < 3500))
ClearCache();
}
}
}
// int oldIndex = -1; // TODO: Compare with 1st to fix loops?
// if (i >= framePaths.Length) // If this is the last frame, compare with 1st to avoid OutOfRange error
// {
// oldIndex = i;
// i = 0;
// }
if(i % 3 == 0)
await Task.Delay(1);
if (Interpolate.canceled) return;
if (!testRun && skipIfNoDupes && !hasEncounteredAnyDupes && skipAfterNoDupesFrames > 0 && i >= skipAfterNoDupesFrames)
{
skipped = true;
break;
}
}
foreach (string frame in framesToDelete)
IOUtils.TryDeleteIfExists(frame);
string testStr = testRun ? " [TestRun]" : "";
if (Interpolate.canceled) return;
int framesLeft = IOUtils.GetAmountOfFiles(path, false, $"*.png");
int framesDeleted = framePaths.Length - framesLeft;
float percentDeleted = ((float)framesDeleted / framePaths.Length) * 100f;
string keptPercent = $"{(100f - percentDeleted).ToString("0.0")}%";
if (skipped)
Logger.Log($"[Deduplication] First {skipAfterNoDupesFrames} frames did not have any duplicates - Skipping the rest!", false, true);
else
Logger.Log($"[Deduplication]{testStr} Done. Kept {framesLeft} ({keptPercent}) frames, deleted {framesDeleted} frames.", false, true);
if (statsFramesKept <= 0)
Interpolate.Cancel("No frames were left after de-duplication!\n\nTry decreasing the de-duplication threshold.");
}
static float GetDifference (string img1Path, string img2Path)
{
MagickImage img2 = GetImage(img2Path);
MagickImage img1 = GetImage(img1Path);
double err = img1.Compare(img2, ErrorMetric.Fuzz);
float errPercent = (float)err * 100f;
return errPercent;
}
static async Task<int> GetBufferSize ()
{
Size res = await Interpolate.current.GetScaledRes();
long pixels = res.Width * res.Height; // 4K = 8294400, 1440p = 3686400, 1080p = 2073600, 720p = 921600, 540p = 518400, 360p = 230400
int bufferSize = 100;
if (pixels < 518400) bufferSize = 1800;
if (pixels >= 518400) bufferSize = 1400;
if (pixels >= 921600) bufferSize = 800;
if (pixels >= 2073600) bufferSize = 400;
if (pixels >= 3686400) bufferSize = 200;
if (pixels >= 8294400) bufferSize = 100;
if (pixels == 0) bufferSize = 100;
Logger.Log($"Using magick dedupe buffer size {bufferSize} for frame resolution {res.Width}x{res.Height}", true);
return bufferSize;
}
public static async Task CreateDupesFile (string framesPath, int lastFrameNum)
{
string infoFile = Path.Combine(framesPath.GetParentDir(), $"dupes.ini");
string fileContent = "";
FileInfo[] frameFiles = IOUtils.GetFileInfosSorted(framesPath, false, "*.png");
for(int i = 0; i < frameFiles.Length; i++)
{
bool isLastItem = (i + 1) == frameFiles.Length;
int frameNum1 = frameFiles[i].Name.GetInt();
int frameNum2 = isLastItem ? lastFrameNum : frameFiles[i+1].Name.GetInt();
int diff = frameNum2 - frameNum1;
int dupes = diff - 1;
//if (File.Exists(Path.Combine(framesPath.GetParentDir(), Paths.scenesDir, frameFiles[i].Name)))
// dupes = 0;
fileContent += $"{Path.GetFileNameWithoutExtension(frameFiles[i].Name)}:{dupes}\n";
}
File.WriteAllText(infoFile, fileContent);
}
}
}

View File

@@ -1,178 +0,0 @@
using Flowframes.Media;
using Flowframes.Data;
using Flowframes.IO;
using Flowframes.MiscUtils;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Flowframes.Main
{
class AutoEncode
{
static string interpFramesFolder;
static string videoChunksFolder;
public static int chunkSize = 125; // Encode every n frames
public static int safetyBufferFrames = 90; // Ignore latest n frames to avoid using images that haven't been fully encoded yet
public static string[] interpFramesLines;
public static List<int> encodedFrameLines = new List<int>();
public static List<int> unencodedFrameLines = new List<int>();
public static bool busy;
public static bool paused;
public static void UpdateChunkAndBufferSizes ()
{
chunkSize = GetChunkSize((IOUtils.GetAmountOfFiles(Interpolate.current.framesFolder, false, "*.png") * Interpolate.current.interpFactor).RoundToInt());
bool isNcnn = Interpolate.current.ai.aiName.ToUpper().Contains("NCNN");
safetyBufferFrames = isNcnn ? Config.GetInt("autoEncSafeBufferNcnn", 90) : Config.GetInt("autoEncSafeBufferCuda", 30); // Use bigger safety buffer for NCNN
}
public static async Task MainLoop(string interpFramesPath)
{
try
{
UpdateChunkAndBufferSizes();
interpFramesFolder = interpFramesPath;
videoChunksFolder = Path.Combine(interpFramesPath.GetParentDir(), Paths.chunksDir);
if (Interpolate.currentlyUsingAutoEnc)
Directory.CreateDirectory(videoChunksFolder);
encodedFrameLines.Clear();
unencodedFrameLines.Clear();
Logger.Log($"[AutoEnc] Starting AutoEncode MainLoop - Chunk Size: {chunkSize} Frames - Safety Buffer: {safetyBufferFrames} Frames", true);
int videoIndex = 1;
string encFile = Path.Combine(interpFramesPath.GetParentDir(), Paths.GetFrameOrderFilename(Interpolate.current.interpFactor));
interpFramesLines = IOUtils.ReadLines(encFile).Select(x => x.Split('/').Last().Remove("'").Split('#').First()).ToArray(); // Array with frame filenames
while (!Interpolate.canceled && GetInterpFramesAmount() < 2)
await Task.Delay(2000);
int lastEncodedFrameNum = 0;
while (HasWorkToDo()) // Loop while proc is running and not all frames have been encoded
{
if (Interpolate.canceled) return;
if (paused)
{
//Logger.Log("autoenc paused");
await Task.Delay(200);
continue;
}
unencodedFrameLines.Clear();
for (int vfrLine = lastEncodedFrameNum; vfrLine < interpFramesLines.Length; vfrLine++)
unencodedFrameLines.Add(vfrLine);
bool aiRunning = !AiProcess.currentAiProcess.HasExited;
if (unencodedFrameLines.Count > 0 && (unencodedFrameLines.Count >= (chunkSize + safetyBufferFrames) || !aiRunning)) // Encode every n frames, or after process has exited
{
List<int> frameLinesToEncode = aiRunning ? unencodedFrameLines.Take(chunkSize).ToList() : unencodedFrameLines; // Take all remaining frames if process is done
string lastOfChunk = Path.Combine(interpFramesPath, interpFramesLines[frameLinesToEncode.Last()]);
if (!File.Exists(lastOfChunk))
{
await Task.Delay(500);
continue;
}
busy = true;
string outpath = Path.Combine(videoChunksFolder, "chunks", $"{videoIndex.ToString().PadLeft(4, '0')}{FFmpegUtils.GetExt(Interpolate.current.outMode)}");
int firstLineNum = frameLinesToEncode.First();
int lastLineNum = frameLinesToEncode.Last();
Logger.Log($"[AutoEnc] Encoding Chunk #{videoIndex} to '{outpath}' using line {firstLineNum} ({Path.GetFileName(interpFramesLines[firstLineNum])}) through {lastLineNum} ({Path.GetFileName(Path.GetFileName(interpFramesLines[frameLinesToEncode.Last()]))})", true, false, "ffmpeg");
await CreateVideo.EncodeChunk(outpath, Interpolate.current.outMode, firstLineNum, frameLinesToEncode.Count);
if (Interpolate.canceled) return;
if (aiRunning && Config.GetInt("autoEncMode") == 2)
Task.Run(() => DeleteOldFramesAsync(interpFramesPath, frameLinesToEncode));
if (Interpolate.canceled) return;
encodedFrameLines.AddRange(frameLinesToEncode);
Logger.Log("Done Encoding Chunk #" + videoIndex, true, false, "ffmpeg");
lastEncodedFrameNum = (frameLinesToEncode.Last() + 1 );
videoIndex++;
busy = false;
}
await Task.Delay(50);
}
if (Interpolate.canceled) return;
await CreateVideo.ChunksToVideos(Interpolate.current.tempFolder, videoChunksFolder, Interpolate.current.outFilename);
}
catch (Exception e)
{
Logger.Log($"AutoEnc Error: {e.Message}. Stack Trace:\n{e.StackTrace}");
Interpolate.Cancel("Auto-Encode encountered an error.");
}
}
static async Task DeleteOldFramesAsync (string interpFramesPath, List<int> frameLinesToEncode)
{
Logger.Log("[AutoEnc] Starting DeleteOldFramesAsync.", true, false, "ffmpeg");
Stopwatch sw = new Stopwatch();
sw.Restart();
int counter = 0;
foreach (int frame in frameLinesToEncode)
{
if (!FrameIsStillNeeded(interpFramesLines[frame], frame)) // Make sure frames are no longer needed (for dupes) before deleting!
{
string framePath = Path.Combine(interpFramesPath, interpFramesLines[frame]);
IOUtils.OverwriteFileWithText(framePath); // Overwrite to save space without breaking progress counter
}
if(counter % 1000 == 0)
await Task.Delay(1);
counter++;
}
Logger.Log("[AutoEnc] DeleteOldFramesAsync finished in " + FormatUtils.TimeSw(sw), true, false, "ffmpeg");
}
static bool FrameIsStillNeeded (string frameName, int frameIndex)
{
if ((frameIndex + 1) < interpFramesLines.Length && interpFramesLines[frameIndex+1].Contains(frameName))
return true;
return false;
}
public static bool HasWorkToDo ()
{
if (Interpolate.canceled || interpFramesFolder == null) return false;
// Logger.Log($"HasWorkToDo - Process Running: {(AiProcess.currentAiProcess != null && !AiProcess.currentAiProcess.HasExited)} - encodedFrameLines.Count: {encodedFrameLines.Count} - interpFramesLines.Length: {interpFramesLines.Length}");
return ((AiProcess.currentAiProcess != null && !AiProcess.currentAiProcess.HasExited) || encodedFrameLines.Count < interpFramesLines.Length);
}
static int GetChunkSize(int targetFramesAmount)
{
if (targetFramesAmount > 50000) return 2400;
if (targetFramesAmount > 20000) return 1200;
if (targetFramesAmount > 5000) return 600;
if (targetFramesAmount > 1000) return 300;
return 150;
}
static int GetInterpFramesAmount()
{
return IOUtils.GetAmountOfFiles(interpFramesFolder, false, $"*.{InterpolateUtils.GetOutExt()}");
}
}
}

View File

@@ -1,110 +0,0 @@
using Flowframes.Forms;
using Flowframes.IO;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Flowframes.Main
{
class BatchProcessing
{
public static bool stopped = false;
public static BatchForm currentBatchForm;
public static bool busy = false;
public static async void Start()
{
if (Config.GetBool("clearLogOnInput"))
Logger.ClearLogBox();
stopped = false;
Program.mainForm.SetTab("preview");
int initTaskCount = Program.batchQueue.Count;
for (int i = 0; i < initTaskCount; i++)
{
if (!stopped && Program.batchQueue.Count > 0)
{
Logger.Log($"[Queue] Running queue task {i + 1}/{initTaskCount}, {Program.batchQueue.Count} tasks left.");
await RunEntry(Program.batchQueue.Peek());
if (currentBatchForm != null)
currentBatchForm.RefreshGui();
}
await Task.Delay(1000);
}
Logger.Log("[Queue] Finished queue processing.");
SetBusy(false);
Program.mainForm.SetTab("interpolation");
}
public static void Stop()
{
stopped = true;
}
static async Task RunEntry(InterpSettings entry)
{
if (!EntryIsValid(entry))
{
Logger.Log("[Queue] Skipping entry because it's invalid.");
Program.batchQueue.Dequeue();
return;
}
string fname = Path.GetFileName(entry.inPath);
if (IOUtils.IsPathDirectory(entry.inPath)) fname = Path.GetDirectoryName(entry.inPath);
Logger.Log($"[Queue] Processing {fname} ({entry.interpFactor}x {entry.ai.aiNameShort}).");
SetBusy(true);
Program.mainForm.LoadBatchEntry(entry); // Load entry into GUI
Interpolate.current = entry;
Program.mainForm.runBtn_Click(null, null);
await Task.Delay(2000);
while (Program.busy)
await Task.Delay(1000);
SetBusy(false);
Program.batchQueue.Dequeue();
Logger.Log($"[Queue] Done processing {fname} ({entry.interpFactor}x {entry.ai.aiNameShort}).");
}
static void SetBusy(bool state)
{
busy = state;
if (currentBatchForm != null)
currentBatchForm.SetWorking(state);
Program.mainForm.SetWorking(state);
Program.mainForm.GetMainTabControl().Enabled = !state; // Lock GUI
}
static bool EntryIsValid(InterpSettings entry)
{
if (entry.inPath == null || (IOUtils.IsPathDirectory(entry.inPath) && !Directory.Exists(entry.inPath)) || (!IOUtils.IsPathDirectory(entry.inPath) && !File.Exists(entry.inPath)))
{
Logger.Log("[Queue] Can't process queue entry: Input path is invalid.");
return false;
}
if (entry.outPath == null || !Directory.Exists(entry.outPath))
{
Logger.Log("[Queue] Can't process queue entry: Output path is invalid.");
return false;
}
if (!PkgUtils.IsAiAvailable(entry.ai))
{
Logger.Log("[Queue] Can't process queue entry: Selected AI is not available.");
return false;
}
return true;
}
}
}

View File

@@ -1,228 +0,0 @@
using Flowframes;
using Flowframes.IO;
using Flowframes.Magick;
using Flowframes.Main;
using Flowframes.OS;
using Flowframes.UI;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
using Padding = Flowframes.Data.Padding;
using i = Flowframes.Interpolate;
using System.Diagnostics;
using Flowframes.Media;
namespace Flowframes.Main
{
class CreateVideo
{
static string currentOutFile; // Keeps track of the out file, in case it gets renamed (FPS limiting, looping, etc) before finishing export
public static async Task Export(string path, string outPath, i.OutMode mode, bool stepByStep)
{
if (!mode.ToString().ToLower().Contains("vid")) // Copy interp frames out of temp folder and skip video export for image seq export
{
try
{
await CopyOutputFrames(path, Path.GetFileNameWithoutExtension(outPath), stepByStep);
}
catch(Exception e)
{
Logger.Log("Failed to move interp frames folder: " + e.Message);
}
return;
}
if (IOUtils.GetAmountOfFiles(path, false, $"*.{InterpolateUtils.GetOutExt()}") <= 1)
{
i.Cancel("Output folder does not contain frames - An error must have occured during interpolation!", AiProcess.hasShownError);
return;
}
await Task.Delay(10);
Program.mainForm.SetStatus("Creating output video from frames...");
try
{
float maxFps = Config.GetFloat("maxFps");
bool fpsLimit = maxFps != 0 && i.current.outFps > maxFps;
bool dontEncodeFullFpsVid = fpsLimit && Config.GetInt("maxFpsMode") == 0;
if(!dontEncodeFullFpsVid)
await Encode(mode, path, outPath, i.current.outFps);
if (fpsLimit)
await Encode(mode, path, outPath.FilenameSuffix($"-{maxFps.ToStringDot("0.00")}fps"), i.current.outFps, maxFps);
}
catch (Exception e)
{
Logger.Log("FramesToVideo Error: " + e.Message, false);
MessageBox.Show("An error occured while trying to convert the interpolated frames to a video.\nCheck the log for details.");
}
}
static async Task CopyOutputFrames (string framesPath, string folderName, bool dontMove)
{
Program.mainForm.SetStatus("Copying output frames...");
string copyPath = Path.Combine(i.current.outPath, folderName);
Logger.Log($"Moving output frames to '{copyPath}'");
IOUtils.TryDeleteIfExists(copyPath);
IOUtils.CreateDir(copyPath);
Stopwatch sw = new Stopwatch();
sw.Restart();
string vfrFile = Path.Combine(framesPath.GetParentDir(), Paths.GetFrameOrderFilename(i.current.interpFactor));
string[] vfrLines = IOUtils.ReadLines(vfrFile);
for (int idx = 1; idx <= vfrLines.Length; idx++)
{
string line = vfrLines[idx-1];
string inFilename = line.Split('/').Last().Remove("'").RemoveComments();
string framePath = Path.Combine(framesPath, inFilename);
string outFilename = Path.Combine(copyPath, idx.ToString().PadLeft(Padding.interpFrames, '0')) + Path.GetExtension(framePath);
if (dontMove || ((idx < vfrLines.Length) && vfrLines[idx].Contains(inFilename))) // If file is re-used in the next line, copy instead of move
File.Copy(framePath, outFilename);
else
File.Move(framePath, outFilename);
if (sw.ElapsedMilliseconds >= 500 || idx == vfrLines.Length)
{
sw.Restart();
Logger.Log($"Moving output frames to '{Path.GetFileName(copyPath)}' - {idx}/{vfrLines.Length}", false, true);
await Task.Delay(1);
}
}
}
static async Task Encode(i.OutMode mode, string framesPath, string outPath, float fps, float resampleFps = -1)
{
currentOutFile = outPath;
string vfrFile = Path.Combine(framesPath.GetParentDir(), Paths.GetFrameOrderFilename(i.current.interpFactor));
if (mode == i.OutMode.VidGif)
{
await FfmpegEncode.FramesToGifConcat(vfrFile, outPath, fps, true, Config.GetInt("gifColors"), resampleFps);
}
else
{
await FfmpegEncode.FramesToVideoConcat(vfrFile, outPath, mode, fps, resampleFps);
await MergeAudio(i.current.inPath, outPath);
await Loop(currentOutFile, GetLoopTimes());
}
}
public static async Task ChunksToVideos(string tempFolder, string chunksFolder, string baseOutPath)
{
if (IOUtils.GetAmountOfFiles(chunksFolder, true, $"*{FFmpegUtils.GetExt(i.current.outMode)}") < 1)
{
i.Cancel("No video chunks found - An error must have occured during chunk encoding!", AiProcess.hasShownError);
return;
}
await Task.Delay(10);
Program.mainForm.SetStatus("Merging video chunks...");
try
{
DirectoryInfo chunksDir = new DirectoryInfo(chunksFolder);
foreach(DirectoryInfo dir in chunksDir.GetDirectories())
{
string suffix = dir.Name.Replace("chunks", "");
string tempConcatFile = Path.Combine(tempFolder, $"chunks-concat{suffix}.ini");
string concatFileContent = "";
foreach (string vid in IOUtils.GetFilesSorted(dir.FullName))
concatFileContent += $"file '{Paths.chunksDir}/{dir.Name}/{Path.GetFileName(vid)}'\n";
File.WriteAllText(tempConcatFile, concatFileContent);
Logger.Log($"CreateVideo: Running MergeChunks() for vfrFile '{Path.GetFileName(tempConcatFile)}'", true);
await MergeChunks(tempConcatFile, baseOutPath.FilenameSuffix(suffix));
}
}
catch (Exception e)
{
Logger.Log("ChunksToVideo Error: " + e.Message, false);
MessageBox.Show("An error occured while trying to merge the video chunks.\nCheck the log for details.");
}
}
static async Task MergeChunks(string vfrFile, string outPath)
{
await FfmpegCommands.ConcatVideos(vfrFile, outPath, -1);
await MergeAudio(i.current.inPath, outPath);
await Loop(outPath, GetLoopTimes());
}
public static async Task EncodeChunk(string outPath, i.OutMode mode, int firstFrameNum, int framesAmount)
{
string vfrFileOriginal = Path.Combine(i.current.tempFolder, Paths.GetFrameOrderFilename(i.current.interpFactor));
string vfrFile = Path.Combine(i.current.tempFolder, Paths.GetFrameOrderFilenameChunk(firstFrameNum, firstFrameNum + framesAmount));
File.WriteAllLines(vfrFile, IOUtils.ReadLines(vfrFileOriginal).Skip(firstFrameNum).Take(framesAmount));
float maxFps = Config.GetFloat("maxFps");
bool fpsLimit = maxFps != 0 && i.current.outFps > maxFps;
bool dontEncodeFullFpsVid = fpsLimit && Config.GetInt("maxFpsMode") == 0;
if(!dontEncodeFullFpsVid)
await FfmpegEncode.FramesToVideoConcat(vfrFile, outPath, mode, i.current.outFps, AvProcess.LogMode.Hidden, true); // Encode
if (fpsLimit)
{
string filename = Path.GetFileName(outPath);
string newParentDir = outPath.GetParentDir() + "-" + maxFps.ToStringDot("0.00") + "fps";
outPath = Path.Combine(newParentDir, filename);
await FfmpegEncode.FramesToVideoConcat(vfrFile, outPath, mode, i.current.outFps, maxFps, AvProcess.LogMode.Hidden, true); // Encode with limited fps
}
}
static async Task Loop(string outPath, int looptimes)
{
if (looptimes < 1 || !Config.GetBool("enableLoop")) return;
Logger.Log($"Looping {looptimes} {(looptimes == 1 ? "time" : "times")} to reach target length of {Config.GetInt("minOutVidLength")}s...");
await FfmpegCommands.LoopVideo(outPath, looptimes, Config.GetInt("loopMode") == 0);
}
static int GetLoopTimes()
{
int times = -1;
int minLength = Config.GetInt("minOutVidLength");
int minFrameCount = (minLength * i.current.outFps).RoundToInt();
int outFrames = (i.currentInputFrameCount * i.current.interpFactor).RoundToInt();
if (outFrames / i.current.outFps < minLength)
times = (int)Math.Ceiling((double)minFrameCount / (double)outFrames);
times--; // Not counting the 1st play (0 loops)
if (times <= 0) return -1; // Never try to loop 0 times, idk what would happen, probably nothing
return times;
}
public static async Task MergeAudio(string inputPath, string outVideo, int looptimes = -1)
{
if (!Config.GetBool("keepAudio")) return;
try
{
string audioFileBasePath = Path.Combine(i.current.tempFolder, "audio");
if (inputPath != null && IOUtils.IsPathDirectory(inputPath) && !File.Exists(IOUtils.GetAudioFile(audioFileBasePath))) // Try loading out of same folder as input if input is a folder
audioFileBasePath = Path.Combine(i.current.tempFolder.GetParentDir(), "audio");
if (!File.Exists(IOUtils.GetAudioFile(audioFileBasePath)))
await FfmpegAudioAndMetadata.ExtractAudio(inputPath, audioFileBasePath); // Extract from sourceVideo to audioFile unless it already exists
if (!File.Exists(IOUtils.GetAudioFile(audioFileBasePath)) || new FileInfo(IOUtils.GetAudioFile(audioFileBasePath)).Length < 4096)
{
Logger.Log("No compatible audio stream found.", true);
return;
}
await FfmpegAudioAndMetadata.MergeAudioAndSubs(outVideo, IOUtils.GetAudioFile(audioFileBasePath), i.current.tempFolder); // Merge from audioFile into outVideo
}
catch (Exception e)
{
Logger.Log("Failed to copy audio!");
Logger.Log("MergeAudio() Exception: " + e.Message, true);
}
}
}
}

View File

@@ -1,153 +0,0 @@
using Flowframes.Data;
using Flowframes.IO;
using Flowframes.UI;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Flowframes.Main
{
class FrameOrder
{
static Stopwatch benchmark = new Stopwatch();
public static async Task CreateFrameOrderFile(string framesPath, bool loopEnabled, float times)
{
Logger.Log("Generating frame order information...");
try
{
benchmark.Restart();
await CreateEncFile(framesPath, loopEnabled, times, false);
Logger.Log($"Generating frame order information... Done.", false, true);
Logger.Log($"Generated frame order info file in {benchmark.ElapsedMilliseconds} ms", true);
}
catch (Exception e)
{
Logger.Log($"Error generating frame order information: {e.Message}");
}
}
static Dictionary<string, int> dupesDict = new Dictionary<string, int>();
static void LoadDupesFile (string path)
{
dupesDict.Clear();
if (!File.Exists(path)) return;
string[] dupesFileLines = IOUtils.ReadLines(path);
foreach(string line in dupesFileLines)
{
string[] values = line.Split(':');
dupesDict.Add(values[0], values[1].GetInt());
}
}
public static async Task CreateEncFile (string framesPath, bool loopEnabled, float interpFactor, bool notFirstRun)
{
if (Interpolate.canceled) return;
Logger.Log($"Generating frame order information for {interpFactor}x...", false, true);
bool loop = Config.GetBool("enableLoop");
bool sceneDetection = true;
string ext = InterpolateUtils.GetOutExt();
FileInfo[] frameFiles = new DirectoryInfo(framesPath).GetFiles($"*.png");
string vfrFile = Path.Combine(framesPath.GetParentDir(), Paths.GetFrameOrderFilename(interpFactor));
string fileContent = "";
string dupesFile = Path.Combine(framesPath.GetParentDir(), $"dupes.ini");
LoadDupesFile(dupesFile);
string scnFramesPath = Path.Combine(framesPath.GetParentDir(), Paths.scenesDir);
string interpPath = Paths.interpDir;
List<string> sceneFrames = new List<string>();
if (Directory.Exists(scnFramesPath))
sceneFrames = Directory.GetFiles(scnFramesPath).Select(file => Path.GetFileNameWithoutExtension(file)).ToList();
bool debug = Config.GetBool("frameOrderDebug", false);
int interpFramesAmount = (int)interpFactor; // TODO: This code won't work with fractional factors
int totalFileCount = 0;
for (int i = 0; i < (frameFiles.Length - 1); i++)
{
if (Interpolate.canceled) return;
string inputFilenameNoExt = Path.GetFileNameWithoutExtension(frameFiles[i].Name);
int dupesAmount = dupesDict.ContainsKey(inputFilenameNoExt) ? dupesDict[inputFilenameNoExt] : 0;
bool discardThisFrame = (sceneDetection && (i + 2) < frameFiles.Length && sceneFrames.Contains(Path.GetFileNameWithoutExtension(frameFiles[i + 1].Name))); // i+2 is in scene detection folder, means i+1 is ugly interp frame
// If loop is enabled, account for the extra frame added to the end for loop continuity
if (loopEnabled && i == (frameFiles.Length - 2))
interpFramesAmount = interpFramesAmount * 2;
for (int frm = 0; frm < interpFramesAmount; frm++) // Generate frames file lines
{
if (discardThisFrame) // If frame is scene cut frame
{
totalFileCount++;
int lastNum = totalFileCount;
fileContent = WriteFrameWithDupes(dupesAmount, fileContent, totalFileCount, interpPath, ext, debug, $"[In: {inputFilenameNoExt}] [{((frm == 0) ? " Source " : $"Interp {frm}")}] [DiscardNext]");
for (int dupeCount = 1; dupeCount < interpFramesAmount; dupeCount++)
{
totalFileCount++;
fileContent = WriteFrameWithDupes(dupesAmount, fileContent, lastNum, interpPath, ext, debug, $"[In: {inputFilenameNoExt}] [DISCARDED]");
}
frm = interpFramesAmount;
}
else
{
totalFileCount++;
fileContent = WriteFrameWithDupes(dupesAmount, fileContent, totalFileCount, interpPath, ext, debug, $"[In: {inputFilenameNoExt}] [{((frm == 0) ? " Source " : $"Interp {frm}")}]");
}
}
if (i % 250 == 0)
{
if (i % 1000 == 0)
Logger.Log($"Generating frame order information... {i}/{frameFiles.Length}.", false, true);
await Task.Delay(1);
}
}
totalFileCount++;
fileContent += $"file '{interpPath}/{totalFileCount.ToString().PadLeft(Padding.interpFrames, '0')}.{ext}'\n";
if(loop)
fileContent = fileContent.Remove(fileContent.LastIndexOf("\n"));
File.WriteAllText(vfrFile, fileContent);
if (notFirstRun) return; // Skip all steps that only need to be done once
if (loop)
{
int lastFileNumber = frameFiles.Last().Name.GetInt() + 1;
string loopFrameTargetPath = Path.Combine(frameFiles.First().FullName.GetParentDir(), lastFileNumber.ToString().PadLeft(Padding.inputFrames, '0') + $".png");
if (File.Exists(loopFrameTargetPath))
{
if (debug) Logger.Log($"Won't copy loop frame - {Path.GetFileName(loopFrameTargetPath)} already exists.", true);
return;
}
File.Copy(frameFiles.First().FullName, loopFrameTargetPath);
if (debug) Logger.Log($"Copied loop frame to {loopFrameTargetPath}.", true);
}
}
static string WriteFrameWithDupes (int dupesAmount, string fileContent, int frameNum, string interpPath, string ext, bool debug, string note = "")
{
for (int writtenDupes = -1; writtenDupes < dupesAmount; writtenDupes++) // Write duplicates
{
if (debug) Logger.Log($"Writing frame {frameNum} (writtenDupes {writtenDupes})", true, false);
fileContent += $"file '{interpPath}/{frameNum.ToString().PadLeft(Padding.interpFrames, '0')}.{ext}'{(debug ? ($" # Dupe {(writtenDupes+1).ToString("000")} {note}").Replace("Dupe 000", " ") : "" )}\n";
}
return fileContent;
}
}
}

View File

@@ -1,254 +0,0 @@
using Flowframes;
using Flowframes.Media;
using Flowframes.Data;
using Flowframes.IO;
using Flowframes.Magick;
using Flowframes.Main;
using Flowframes.MiscUtils;
using Flowframes.OS;
using Flowframes.UI;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
using Padding = Flowframes.Data.Padding;
using Utils = Flowframes.Main.InterpolateUtils;
namespace Flowframes
{
public class Interpolate
{
public enum OutMode { VidMp4, VidMkv, VidWebm, VidProRes, VidAvi, VidGif, ImgPng }
public static int currentInputFrameCount;
public static bool currentlyUsingAutoEnc;
public static InterpSettings current;
public static bool canceled = false;
static Stopwatch sw = new Stopwatch();
public static async Task Start()
{
if (!BatchProcessing.busy && Program.busy) return;
canceled = false;
if (!Utils.InputIsValid(current.inPath, current.outPath, current.outFps, current.interpFactor, current.outMode)) return; // General input checks
if (!Utils.CheckAiAvailable(current.ai)) return; // Check if selected AI pkg is installed
if (!ResumeUtils.resumeNextRun && !Utils.CheckDeleteOldTempFolder()) return; // Try to delete temp folder if an old one exists
if (!Utils.CheckPathValid(current.inPath)) return; // Check if input path/file is valid
Utils.PathAsciiCheck(current.outPath, "output path");
currentInputFrameCount = await Utils.GetInputFrameCountAsync(current.inPath);
current.stepByStep = false;
Program.mainForm.SetStatus("Starting...");
Program.mainForm.SetWorking(true);
if (!ResumeUtils.resumeNextRun)
{
await GetFrames();
if (canceled) return;
sw.Restart();
await PostProcessFrames(false);
}
if (canceled) return;
await ResumeUtils.PrepareResumedRun();
//Task.Run(() => Utils.DeleteInterpolatedInputFrames());
await RunAi(current.interpFolder, current.ai);
if (canceled) return;
Program.mainForm.SetProgress(100);
if(!currentlyUsingAutoEnc)
await CreateVideo.Export(current.interpFolder, current.outFilename, current.outMode, false);
await IOUtils.ReverseRenaming(current.framesFolder, AiProcess.filenameMap); // Get timestamps back
AiProcess.filenameMap.Clear();
await Cleanup();
Program.mainForm.SetWorking(false);
Logger.Log("Total processing time: " + FormatUtils.Time(sw.Elapsed));
sw.Stop();
Program.mainForm.SetStatus("Done interpolating!");
}
public static async Task GetFrames (bool stepByStep = false)
{
current.RefreshAlpha();
if (!current.inputIsFrames) // Extract if input is video, import if image sequence
await ExtractFrames(current.inPath, current.framesFolder, current.alpha, !stepByStep);
else
await FfmpegExtract.ImportImages(current.inPath, current.framesFolder, current.alpha, await Utils.GetOutputResolution(current.inPath, true));
if (current.alpha)
{
Program.mainForm.SetStatus("Extracting transparency...");
Logger.Log("Extracting transparency... (1/2)");
await FfmpegAlpha.ExtractAlphaDir(current.framesFolder, current.framesFolder + Paths.alphaSuffix);
Logger.Log("Extracting transparency... (2/2)", false, true);
await FfmpegAlpha.RemoveAlpha(current.framesFolder, current.framesFolder);
}
}
public static async Task ExtractFrames(string inPath, string outPath, bool alpha, bool sceneDetect)
{
if (sceneDetect && Config.GetBool("scnDetect"))
{
Program.mainForm.SetStatus("Extracting scenes from video...");
await FfmpegExtract.ExtractSceneChanges(inPath, Path.Combine(current.tempFolder, Paths.scenesDir), current.inFps);
await Task.Delay(10);
}
if (canceled) return;
Program.mainForm.SetStatus("Extracting frames from video...");
bool mpdecimate = Config.GetInt("dedupMode") == 2;
await FfmpegExtract.VideoToFrames(inPath, outPath, alpha, current.inFps, mpdecimate, false, await Utils.GetOutputResolution(inPath, true, true));
if (mpdecimate)
{
int framesLeft = IOUtils.GetAmountOfFiles(outPath, false, $"*.png");
int framesDeleted = currentInputFrameCount - framesLeft;
float percentDeleted = ((float)framesDeleted / currentInputFrameCount) * 100f;
string keptPercent = $"{(100f - percentDeleted).ToString("0.0")}%";
Logger.Log($"[Deduplication] Kept {framesLeft} ({keptPercent}) frames, deleted {framesDeleted} frames.");
}
if(!Config.GetBool("allowConsecutiveSceneChanges", true))
Utils.FixConsecutiveSceneFrames(Path.Combine(current.tempFolder, Paths.scenesDir), current.framesFolder);
if (canceled) return;
Program.mainForm.SetStatus("Extracting audio from video...");
string audioFile = Path.Combine(current.tempFolder, "audio");
if (audioFile != null && !File.Exists(audioFile))
await FfmpegAudioAndMetadata.ExtractAudio(inPath, audioFile);
if (canceled) return;
Program.mainForm.SetStatus("Extracting subtitles from video...");
await FfmpegAudioAndMetadata.ExtractSubtitles(inPath, current.tempFolder, current.outMode);
}
public static async Task PostProcessFrames (bool stepByStep)
{
if (canceled) return;
int extractedFrames = IOUtils.GetAmountOfFiles(current.framesFolder, false, "*.png");
if (!Directory.Exists(current.framesFolder) || currentInputFrameCount <= 0 || extractedFrames < 2)
{
if(extractedFrames == 1)
Cancel("Only a single frame was extracted from your input file!\n\nPossibly your input is an image, not a video?");
else
Cancel("Frame extraction failed!\n\nYour input file might be incompatible.");
}
if (Config.GetInt("dedupMode") == 1)
await Dedupe.Run(current.framesFolder);
else
Dedupe.ClearCache();
if(!Config.GetBool("enableLoop"))
await Utils.CopyLastFrame(currentInputFrameCount);
if (Config.GetInt("dedupMode") > 0)
await Dedupe.CreateDupesFile(current.framesFolder, currentInputFrameCount);
if (canceled) return;
await FrameOrder.CreateFrameOrderFile(current.framesFolder, Config.GetBool("enableLoop"), current.interpFactor);
if (canceled) return;
try
{
Dictionary<string, string> renamedFilesDict = await IOUtils.RenameCounterDirReversibleAsync(current.framesFolder, "png", 1, Padding.inputFramesRenamed);
if(stepByStep)
AiProcess.filenameMap = renamedFilesDict.ToDictionary(x => Path.GetFileName(x.Key), x => Path.GetFileName(x.Value)); // Save rel paths
}
catch (Exception e)
{
Logger.Log($"Error renaming frame files: {e.Message}");
Cancel("Error renaming frame files. Check the log for details.");
}
}
public static async Task RunAi(string outpath, AI ai, bool stepByStep = false)
{
Program.mainForm.SetStatus("Downloading models...");
await ModelDownloader.DownloadModelFiles(Path.GetFileNameWithoutExtension(ai.pkg.fileName), current.model);
if (canceled) return;
currentlyUsingAutoEnc = Utils.CanUseAutoEnc(stepByStep, current);
IOUtils.CreateDir(outpath);
List<Task> tasks = new List<Task>();
if (ai.aiName == Networks.rifeCuda.aiName)
tasks.Add(AiProcess.RunRifeCuda(current.framesFolder, current.interpFactor, current.model));
if (ai.aiName == Networks.rifeNcnn.aiName)
tasks.Add(AiProcess.RunRifeNcnn(current.framesFolder, outpath, (int)current.interpFactor, current.model));
if (ai.aiName == Networks.dainNcnn.aiName)
tasks.Add(AiProcess.RunDainNcnn(current.framesFolder, outpath, current.interpFactor, current.model, Config.GetInt("dainNcnnTilesize", 512)));
if (currentlyUsingAutoEnc)
{
Logger.Log($"{Logger.GetLastLine()} (Using Auto-Encode)", true);
tasks.Add(AutoEncode.MainLoop(outpath));
}
Program.mainForm.SetStatus("Running AI...");
await Task.WhenAll(tasks);
}
public static void Cancel(string reason = "", bool noMsgBox = false)
{
if (AiProcess.currentAiProcess != null && !AiProcess.currentAiProcess.HasExited)
OSUtils.KillProcessTree(AiProcess.currentAiProcess.Id);
if (AvProcess.lastProcess != null && !AvProcess.lastProcess.HasExited)
OSUtils.KillProcessTree(AvProcess.lastProcess.Id);
canceled = true;
Program.mainForm.SetStatus("Canceled.");
Program.mainForm.SetProgress(0);
if (!current.stepByStep && !Config.GetBool("keepTempFolder"))
{
if(false /* IOUtils.GetAmountOfFiles(Path.Combine(current.tempFolder, Paths.resumeDir), true) > 0 */) // TODO: Uncomment for 1.23
{
DialogResult dialogResult = MessageBox.Show($"Delete the temp folder (Yes) or keep it for resuming later (No)?", "Delete temporary files?", MessageBoxButtons.YesNo);
if (dialogResult == DialogResult.Yes)
IOUtils.TryDeleteIfExists(current.tempFolder);
}
else
{
IOUtils.TryDeleteIfExists(current.tempFolder);
}
}
AutoEncode.busy = false;
Program.mainForm.SetWorking(false);
Program.mainForm.SetTab("interpolation");
Logger.LogIfLastLineDoesNotContainMsg("Canceled interpolation.");
if (!string.IsNullOrWhiteSpace(reason) && !noMsgBox)
Utils.ShowMessage($"Canceled:\n\n{reason}");
}
public static async Task Cleanup(bool ignoreKeepSetting = false, int retriesLeft = 3, bool isRetry = false)
{
if ((!ignoreKeepSetting && Config.GetBool("keepTempFolder")) || !Program.busy) return;
if (!isRetry)
Logger.Log("Deleting temporary files...");
try
{
Directory.Delete(current.tempFolder, true);
}
catch (Exception e)
{
Logger.Log("Cleanup Error: " + e.Message, true);
if(retriesLeft > 0)
{
await Task.Delay(1000);
await Cleanup(ignoreKeepSetting, retriesLeft - 1, true);
}
}
}
}
}

View File

@@ -1,134 +0,0 @@
using Flowframes.Media;
using Flowframes.Data;
using Flowframes.IO;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Flowframes.Main
{
using static Interpolate;
class InterpolateSteps
{
public enum Step { ExtractScnChanges, ExtractFrames, Interpolate, CreateVid, Reset }
public static async Task Run(string step)
{
Logger.Log($"[SBS] Running step '{step}'", true);
canceled = false;
Program.mainForm.SetWorking(true);
current = Program.mainForm.GetCurrentSettings();
current.RefreshAlpha();
current.stepByStep = false;
if (!InterpolateUtils.InputIsValid(current.inPath, current.outPath, current.outFps, current.interpFactor, current.outMode)) return; // General input checks
if (step.Contains("Extract Scene Changes"))
{
if (!current.inputIsFrames) // Input is video - extract frames first
await ExtractSceneChanges();
else
InterpolateUtils.ShowMessage("Scene changes can only be extracted from videos, not frames!", "Error");
}
if (step.Contains("Extract Frames"))
await ExtractFramesStep();
if (step.Contains("Run Interpolation"))
await DoInterpolate();
if (step.Contains("Export"))
await CreateOutputVid();
if (step.Contains("Cleanup"))
await Reset();
Program.mainForm.SetWorking(false);
Program.mainForm.SetStatus("Done running step.");
Logger.Log("Done running this step.");
}
public static async Task ExtractSceneChanges()
{
string scenesPath = Path.Combine(current.tempFolder, Paths.scenesDir);
if (!IOUtils.TryDeleteIfExists(scenesPath))
{
InterpolateUtils.ShowMessage("Failed to delete existing scenes folder - Make sure no file is opened in another program!", "Error");
return;
}
Program.mainForm.SetStatus("Extracting scenes from video...");
await FfmpegExtract.ExtractSceneChanges(current.inPath, scenesPath, current.inFps);
await Task.Delay(10);
}
public static async Task ExtractFramesStep()
{
if (!IOUtils.TryDeleteIfExists(current.framesFolder))
{
InterpolateUtils.ShowMessage("Failed to delete existing frames folder - Make sure no file is opened in another program!", "Error");
return;
}
currentInputFrameCount = await InterpolateUtils.GetInputFrameCountAsync(current.inPath);
AiProcess.filenameMap.Clear();
await GetFrames(true);
}
public static async Task DoInterpolate()
{
current.framesFolder = Path.Combine(current.tempFolder, Paths.framesDir);
if (!Directory.Exists(current.framesFolder) || IOUtils.GetAmountOfFiles(current.framesFolder, false, "*.png") < 2)
{
InterpolateUtils.ShowMessage("There are no extracted frames that can be interpolated!\nDid you run the extraction step?", "Error");
return;
}
if (!IOUtils.TryDeleteIfExists(current.interpFolder))
{
InterpolateUtils.ShowMessage("Failed to delete existing frames folder - Make sure no file is opened in another program!", "Error");
return;
}
currentInputFrameCount = await InterpolateUtils.GetInputFrameCountAsync(current.inPath);
// TODO: Check if this works lol, remove if it does
//if (Config.GetBool("sbsAllowAutoEnc"))
// nextOutPath = Path.Combine(currentOutPath, Path.GetFileNameWithoutExtension(current.inPath) + IOUtils.GetAiSuffix(current.ai, current.interpFactor) + InterpolateUtils.GetExt(current.outMode));
await PostProcessFrames(true);
if (canceled) return;
Program.mainForm.SetStatus("Running AI...");
await RunAi(current.interpFolder, current.ai, true);
await IOUtils.ReverseRenaming(current.framesFolder, AiProcess.filenameMap); // Get timestamps back
AiProcess.filenameMap.Clear();
Program.mainForm.SetProgress(0);
}
public static async Task CreateOutputVid()
{
string[] outFrames = IOUtils.GetFilesSorted(current.interpFolder, $"*.{InterpolateUtils.GetOutExt()}");
if (outFrames.Length > 0 && !IOUtils.CheckImageValid(outFrames[0]))
{
InterpolateUtils.ShowMessage("Invalid frame files detected!\n\nIf you used Auto-Encode, this is normal, and you don't need to run " +
"this step as the video was already created in the \"Interpolate\" step.", "Error");
return;
}
string outPath = Path.Combine(current.outPath, Path.GetFileNameWithoutExtension(current.inPath) + IOUtils.GetCurrentExportSuffix() + FFmpegUtils.GetExt(current.outMode));
await CreateVideo.Export(current.interpFolder, outPath, current.outMode, true);
}
public static async Task Reset()
{
await Cleanup(true);
}
}
}

View File

@@ -1,467 +0,0 @@
using Flowframes.Media;
using Flowframes.Data;
using Flowframes.Forms;
using Flowframes.IO;
using Flowframes.MiscUtils;
using Flowframes.OS;
using Flowframes.UI;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Windows.Forms;
using i = Flowframes.Interpolate;
using Padding = Flowframes.Data.Padding;
namespace Flowframes.Main
{
class InterpolateUtils
{
public static PictureBox preview;
public static BigPreviewForm bigPreviewForm;
public static async Task CopyLastFrame (int lastFrameNum)
{
try
{
lastFrameNum--; // We have to do this as extracted frames start at 0, not 1
bool frameFolderInput = IOUtils.IsPathDirectory(i.current.inPath);
string targetPath = Path.Combine(i.current.framesFolder, lastFrameNum.ToString().PadLeft(Padding.inputFrames, '0') + ".png");
if (File.Exists(targetPath)) return;
Size res = IOUtils.GetImage(IOUtils.GetFilesSorted(i.current.framesFolder, false).First()).Size;
if (frameFolderInput)
{
string lastFramePath = IOUtils.GetFilesSorted(i.current.inPath, false).Last();
await FfmpegExtract.ExtractLastFrame(lastFramePath, targetPath, res);
}
else
{
await FfmpegExtract.ExtractLastFrame(i.current.inPath, targetPath, res);
}
}
catch (Exception e)
{
Logger.Log("CopyLastFrame Error: " + e.Message);
}
}
public static string GetOutExt (bool withDot = false)
{
string dotStr = withDot ? "." : "";
if (Config.GetBool("jpegInterp"))
return dotStr + "jpg";
return dotStr + "png";
}
public static int targetFrames;
public static string currentOutdir;
public static float currentFactor;
public static bool progressPaused = false;
public static bool progCheckRunning = false;
public static async void GetProgressByFrameAmount(string outdir, int target)
{
progCheckRunning = true;
targetFrames = target;
currentOutdir = outdir;
Logger.Log($"Starting GetProgressByFrameAmount() loop for outdir '{currentOutdir}', target is {target} frames", true);
bool firstProgUpd = true;
Program.mainForm.SetProgress(0);
while (Program.busy)
{
if (!progressPaused && AiProcess.processTime.IsRunning && Directory.Exists(currentOutdir))
{
if (firstProgUpd && Program.mainForm.IsInFocus())
Program.mainForm.SetTab("preview");
firstProgUpd = false;
string[] frames = IOUtils.GetFilesSorted(currentOutdir, $"*.{GetOutExt()}");
if (frames.Length > 1)
UpdateInterpProgress(frames.Length, targetFrames, frames[frames.Length - 1]);
if (frames.Length >= targetFrames)
break;
await Task.Delay(GetProgressWaitTime(frames.Length));
}
else
{
await Task.Delay(200);
}
}
progCheckRunning = false;
if (i.canceled)
Program.mainForm.SetProgress(0);
}
public static int interpolatedInputFramesCount;
public static void UpdateInterpProgress(int frames, int target, string latestFramePath = "")
{
if (i.canceled) return;
interpolatedInputFramesCount = ((frames / i.current.interpFactor).RoundToInt() - 1);
ResumeUtils.Save();
frames = frames.Clamp(0, target);
int percent = (int)Math.Round(((float)frames / target) * 100f);
Program.mainForm.SetProgress(percent);
float generousTime = ((AiProcess.processTime.ElapsedMilliseconds - AiProcess.lastStartupTimeMs) / 1000f);
float fps = (float)frames / generousTime;
string fpsIn = (fps / currentFactor).ToString("0.00");
string fpsOut = fps.ToString("0.00");
float secondsPerFrame = generousTime / (float)frames;
int framesLeft = target - frames;
float eta = framesLeft * secondsPerFrame;
string etaStr = FormatUtils.Time(new TimeSpan(0, 0, eta.RoundToInt()), false);
bool replaceLine = Regex.Split(Logger.textbox.Text, "\r\n|\r|\n").Last().Contains("Average Speed: ");
string logStr = $"Interpolated {frames}/{target} frames ({percent}%) - Average Speed: {fpsIn} FPS In / {fpsOut} FPS Out - ";
logStr += $"Time: {FormatUtils.Time(AiProcess.processTime.Elapsed)} - ETA: {etaStr}";
if (AutoEncode.busy) logStr += " - Encoding...";
Logger.Log(logStr, false, replaceLine);
try
{
if (!string.IsNullOrWhiteSpace(latestFramePath) && frames > currentFactor)
{
if (bigPreviewForm == null && !preview.Visible /* ||Program.mainForm.WindowState != FormWindowState.Minimized */ /* || !Program.mainForm.IsInFocus()*/) return; // Skip if the preview is not visible or the form is not in focus
Image img = IOUtils.GetImage(latestFramePath);
SetPreviewImg(img);
}
}
catch { }
}
public static async Task DeleteInterpolatedInputFrames ()
{
interpolatedInputFramesCount = 0;
string[] inputFrames = IOUtils.GetFilesSorted(i.current.framesFolder);
for (int i = 0; i < inputFrames.Length; i++)
{
while (Program.busy && (i + 10) > interpolatedInputFramesCount) await Task.Delay(1000);
if (!Program.busy) break;
if(i != 0 && i != inputFrames.Length - 1)
IOUtils.OverwriteFileWithText(inputFrames[i]);
if (i % 10 == 0) await Task.Delay(10);
}
}
public static void SetPreviewImg (Image img)
{
if (img == null)
return;
preview.Image = img;
if (bigPreviewForm != null)
bigPreviewForm.SetImage(img);
}
public static Dictionary<string, int> frameCountCache = new Dictionary<string, int>();
public static async Task<int> GetInputFrameCountAsync (string path)
{
int maxMb = Config.GetInt("storeHashedFramecountMaxSizeMb", 256);
string hash = "";
if (IOUtils.GetFilesize(path) >= 0 && IOUtils.GetFilesize(path) < maxMb * 1024 * 1024)
hash = await IOUtils.GetHashAsync(path, IOUtils.Hash.xxHash); // Get checksum for caching
else
Logger.Log($"GetInputFrameCountAsync: File bigger than {maxMb}mb, won't hash.", true);
if (hash.Length > 1 && frameCountCache.ContainsKey(hash))
{
Logger.Log($"FrameCountCache contains this hash ({hash}), using cached frame count.", true);
return frameCountCache[hash];
}
else
{
Logger.Log($"Hash ({hash}) not cached, reading frame count.", true);
}
int frameCount = 0;
if (IOUtils.IsPathDirectory(path))
frameCount = IOUtils.GetAmountOfFiles(path, false);
else
frameCount = await FfmpegCommands.GetFrameCountAsync(path);
if (hash.Length > 1 && frameCount > 5000) // Cache if >5k frames to avoid re-reading it every single time
{
Logger.Log($"Adding hash ({hash}) with frame count {frameCount} to cache.", true);
frameCountCache[hash] = frameCount; // Use CRC32 instead of path to avoid using cached value if file was changed
}
return frameCount;
}
public static int GetProgressWaitTime(int numFrames)
{
float hddMultiplier = !Program.lastInputPathIsSsd ? 2f : 1f;
int waitMs = 200;
if (numFrames > 100)
waitMs = 500;
if (numFrames > 1000)
waitMs = 1000;
if (numFrames > 2500)
waitMs = 1500;
if (numFrames > 5000)
waitMs = 2500;
return (waitMs * hddMultiplier).RoundToInt();
}
public static string GetTempFolderLoc (string inPath, string outPath)
{
string basePath = inPath.GetParentDir();
if(Config.GetInt("tempFolderLoc") == 1)
basePath = outPath.GetParentDir();
if (Config.GetInt("tempFolderLoc") == 2)
basePath = outPath;
if (Config.GetInt("tempFolderLoc") == 3)
basePath = IOUtils.GetExeDir();
if (Config.GetInt("tempFolderLoc") == 4)
{
string custPath = Config.Get("tempDirCustom");
if(IOUtils.IsDirValid(custPath))
basePath = custPath;
}
return Path.Combine(basePath, Path.GetFileNameWithoutExtension(inPath).StripBadChars().Remove(" ").Trunc(30, false) + "-temp");
}
public static bool InputIsValid(string inDir, string outDir, float fpsOut, float factor, Interpolate.OutMode outMode)
{
bool passes = true;
bool isFile = !IOUtils.IsPathDirectory(inDir);
if ((passes && isFile && !IOUtils.IsFileValid(inDir)) || (!isFile && !IOUtils.IsDirValid(inDir)))
{
ShowMessage("Input path is not valid!");
passes = false;
}
if (passes && !IOUtils.IsDirValid(outDir))
{
ShowMessage("Output path is not valid!");
passes = false;
}
if (passes && /*factor != 2 && factor != 4 && factor != 8*/ factor > 16)
{
ShowMessage("Interpolation factor is not valid!");
passes = false;
}
if (passes && outMode == i.OutMode.VidGif && fpsOut > 50)
{
ShowMessage("Invalid output frame rate!\nGIF does not properly support frame rates above 40 FPS.\nPlease use MP4, WEBM or another video format.");
passes = false;
}
if (passes && fpsOut < 1 || fpsOut > 1000)
{
ShowMessage("Invalid output frame rate - Must be 1-1000.");
passes = false;
}
if (!passes)
i.Cancel("Invalid settings detected.", true);
return passes;
}
public static void PathAsciiCheck (string path, string pathTitle)
{
if (IOUtils.HasBadChars(path) || OSUtils.HasNonAsciiChars(path))
ShowMessage($"Warning: Your {pathTitle} includes special characters. This might cause problems.");
}
public static void GifCompatCheck (Interpolate.OutMode outMode, float fpsOut, int targetFrameCount)
{
if (outMode != Interpolate.OutMode.VidGif)
return;
if(fpsOut >= 50f)
Logger.Log("Warning: GIFs above 50 FPS might play slower on certain software/hardware! MP4 is recommended for higher frame rates.");
int maxGifFrames = 200;
if (targetFrameCount > maxGifFrames)
{
ShowMessage($"You can't use GIF with more than {maxGifFrames} output frames!\nPlease use MP4 for this.", "Error");
i.Cancel($"Can't use GIF encoding with more than {maxGifFrames} frames!");
}
}
public static bool CheckAiAvailable (AI ai)
{
if (!PkgUtils.IsAiAvailable(ai))
{
ShowMessage("The selected AI is not installed!\nYou can download it from the Package Installer.", "Error");
i.Cancel("Selected AI not available.", true);
return false;
}
return true;
}
public static bool CheckDeleteOldTempFolder ()
{
if (!IOUtils.TryDeleteIfExists(i.current.tempFolder))
{
ShowMessage("Failed to remove an existing temp folder of this video!\nMake sure you didn't open any frames in an editor.", "Error");
i.Cancel();
return false;
}
return true;
}
public static bool CheckPathValid (string path)
{
if (IOUtils.IsPathDirectory(path))
{
if (!IOUtils.IsDirValid(path))
{
ShowMessage("Input directory is not valid.");
i.Cancel();
return false;
}
}
else
{
if (!IsVideoValid(path))
{
ShowMessage("Input video file is not valid.");
return false;
}
}
return true;
}
public static bool IsVideoValid(string videoPath)
{
if (videoPath == null || !IOUtils.IsFileValid(videoPath))
return false;
return true;
}
public static void ShowMessage(string msg, string title = "Message")
{
if (!BatchProcessing.busy)
MessageBox.Show(msg, title);
Logger.Log("Message: " + msg, true);
}
public static async Task<Size> GetOutputResolution (string inputPath, bool print, bool returnZeroIfUnchanged = false)
{
Size resolution = await IOUtils.GetVideoOrFramesRes(inputPath);
return GetOutputResolution(resolution, print, returnZeroIfUnchanged);
}
public static Size GetOutputResolution(Size inputRes, bool print = false, bool returnZeroIfUnchanged = false)
{
int maxHeight = RoundDiv2(Config.GetInt("maxVidHeight"));
if (inputRes.Height > maxHeight)
{
float factor = (float)maxHeight / inputRes.Height;
Logger.Log($"Un-rounded downscaled size: {(inputRes.Width * factor).ToString("0.00")}x{Config.GetInt("maxVidHeight")}", true);
int width = RoundDiv2((inputRes.Width * factor).RoundToInt());
if (print)
Logger.Log($"Video is bigger than the maximum - Downscaling to {width}x{maxHeight}.");
return new Size(width, maxHeight);
}
else
{
//return new Size(RoundDiv2(inputRes.Width), RoundDiv2(inputRes.Height));
if (returnZeroIfUnchanged)
return new Size();
else
return inputRes;
}
}
public static int RoundDiv2(int n) // Round to a number that's divisible by 2 (for h264 etc)
{
int a = (n / 2) * 2; // Smaller multiple
int b = a + 2; // Larger multiple
return (n - a > b - n) ? b : a; // Return of closest of two
}
public static bool CanUseAutoEnc (bool stepByStep, InterpSettings current)
{
AutoEncode.UpdateChunkAndBufferSizes();
if (current.alpha)
{
Logger.Log($"Not Using AutoEnc: Alpha mode is enabled.", true);
return false;
}
if (!current.outMode.ToString().ToLower().Contains("vid") || current.outMode.ToString().ToLower().Contains("gif"))
{
Logger.Log($"Not Using AutoEnc: Out Mode is not video ({current.outMode.ToString()})", true);
return false;
}
if(stepByStep && !Config.GetBool("sbsAllowAutoEnc"))
{
Logger.Log($"Not Using AutoEnc: Using step-by-step mode, but 'sbsAllowAutoEnc' is false.", true);
return false;
}
if (!stepByStep && Config.GetInt("autoEncMode") == 0)
{
Logger.Log($"Not Using AutoEnc: 'autoEncMode' is 0.", true);
return false;
}
int inFrames = IOUtils.GetAmountOfFiles(current.framesFolder, false);
if (inFrames * current.interpFactor < (AutoEncode.chunkSize + AutoEncode.safetyBufferFrames) * 1.2f)
{
Logger.Log($"Not Using AutoEnc: Input frames ({inFrames}) * factor ({current.interpFactor}) is smaller than (chunkSize ({AutoEncode.chunkSize}) + safetyBufferFrames ({AutoEncode.safetyBufferFrames}) * 1.2f)", true);
return false;
}
return true;
}
public static async Task<bool> UseUHD ()
{
return (await GetOutputResolution(i.current.inPath, false)).Height >= Config.GetInt("uhdThresh");
}
public static void FixConsecutiveSceneFrames (string sceneFramesPath, string sourceFramesPath)
{
if (!Directory.Exists(sceneFramesPath) || IOUtils.GetAmountOfFiles(sceneFramesPath, false) < 1)
return;
List<string> sceneFrames = IOUtils.GetFilesSorted(sceneFramesPath).Select(x => Path.GetFileNameWithoutExtension(x)).ToList();
List<string> sourceFrames = IOUtils.GetFilesSorted(sourceFramesPath).Select(x => Path.GetFileNameWithoutExtension(x)).ToList();
List<string> sceneFramesToDelete = new List<string>();
foreach(string scnFrame in sceneFrames)
{
if (sceneFramesToDelete.Contains(scnFrame))
continue;
int sourceIndexForScnFrame = sourceFrames.IndexOf(scnFrame); // Get source index of scene frame
if ((sourceIndexForScnFrame + 1) == sourceFrames.Count)
continue;
string followingFrame = sourceFrames[sourceIndexForScnFrame + 1]; // Get filename/timestamp of the next source frame
if (sceneFrames.Contains(followingFrame)) // If next source frame is in scene folder, add to deletion list
sceneFramesToDelete.Add(followingFrame);
}
foreach (string frame in sceneFramesToDelete)
IOUtils.TryDeleteIfExists(Path.Combine(sceneFramesPath, frame + ".png"));
}
}
}

View File

@@ -1,120 +0,0 @@
using Flowframes.Data;
using Flowframes.IO;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using I = Flowframes.Interpolate;
namespace Flowframes.Main
{
class ResumeUtils
{
public static bool resumeNextRun;
public static float timeBetweenSaves = 10;
public static int minFrames = 100;
public static int safetyDelayFrames = 50;
public static string resumeFilename = "resume.ini";
public static string interpSettingsFilename = "interpSettings.ini";
public static string filenameMapFilename = "frameFilenames.ini";
public static Stopwatch timeSinceLastSave = new Stopwatch();
public static void Save ()
{
if (timeSinceLastSave.IsRunning && timeSinceLastSave.ElapsedMilliseconds < (timeBetweenSaves * 1000f).RoundToInt()) return;
int frames = (int)Math.Round((float)InterpolateUtils.interpolatedInputFramesCount / I.current.interpFactor) - safetyDelayFrames;
if (frames < 1) return;
timeSinceLastSave.Restart();
Directory.CreateDirectory(Path.Combine(I.current.tempFolder, Paths.resumeDir));
SaveState(frames);
SaveInterpSettings();
SaveFilenameMap();
}
static void SaveState (int frames)
{
ResumeState state = new ResumeState(I.currentlyUsingAutoEnc, frames);
string filePath = Path.Combine(I.current.tempFolder, Paths.resumeDir, resumeFilename);
File.WriteAllText(filePath, state.ToString());
}
static async Task SaveFilenameMap ()
{
string filePath = Path.Combine(I.current.tempFolder, Paths.resumeDir, filenameMapFilename);
if (File.Exists(filePath) && IOUtils.GetFilesize(filePath) > 0)
return;
string fileContent = "";
int counter = 0;
foreach (KeyValuePair<string, string> entry in AiProcess.filenameMap)
{
if (counter % 1000 == 0) await Task.Delay(1);
fileContent += $"{entry.Key}|{entry.Value}\n";
counter++;
}
File.WriteAllText(filePath, fileContent);
}
static void SaveInterpSettings ()
{
string filepath = Path.Combine(I.current.tempFolder, Paths.resumeDir, interpSettingsFilename);
File.WriteAllText(filepath, I.current.Serialize());
}
public static void LoadTempFolder (string tempFolderPath)
{
string resumeFolderPath = Path.Combine(tempFolderPath, Paths.resumeDir);
string interpSettingsPath = Path.Combine(resumeFolderPath, interpSettingsFilename);
InterpSettings interpSettings = new InterpSettings(File.ReadAllText(interpSettingsPath));
Program.mainForm.LoadBatchEntry(interpSettings);
}
public static async Task PrepareResumedRun ()
{
if (!resumeNextRun) return;
string stateFilepath = Path.Combine(I.current.tempFolder, Paths.resumeDir, resumeFilename);
ResumeState state = new ResumeState(File.ReadAllText(stateFilepath));
string fileMapFilepath = Path.Combine(I.current.tempFolder, Paths.resumeDir, filenameMapFilename);
List<string> inputFrameLines = File.ReadAllLines(fileMapFilepath).Where(l => l.Trim().Length > 3).ToList();
List<string> inputFrames = inputFrameLines.Select(l => Path.Combine(I.current.framesFolder, l.Split('|')[1])).ToList();
for (int i = 0; i < state.interpolatedInputFrames; i++)
{
IOUtils.TryDeleteIfExists(inputFrames[i]);
if (i % 1000 == 0) await Task.Delay(1);
}
Directory.Move(I.current.interpFolder, I.current.interpFolder + Paths.prevSuffix); // Move existing interp frames
Directory.CreateDirectory(I.current.interpFolder); // Re-create empty interp folder
LoadFilenameMap();
}
static void LoadFilenameMap()
{
Dictionary<string, string> dict = new Dictionary<string, string>();
string filePath = Path.Combine(I.current.tempFolder, Paths.resumeDir, filenameMapFilename);
string[] dictLines = File.ReadAllLines(filePath);
foreach (string line in dictLines)
{
if (line.Length < 5) continue;
string[] keyValuePair = line.Split('|');
dict.Add(keyValuePair[0].Trim(), keyValuePair[1].Trim());
}
AiProcess.filenameMap = dict;
}
}
}

View File

@@ -1,189 +0,0 @@
using Flowframes.IO;
using Flowframes.OS;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using Flowframes.MiscUtils;
namespace Flowframes
{
class AvProcess
{
public static Process lastProcess;
public static Stopwatch timeSinceLastOutput = new Stopwatch();
public enum TaskType { ExtractFrames, Encode, GetInfo, Merge, Other };
public static TaskType lastTask = TaskType.Other;
public static string lastOutputFfmpeg;
public static string lastOutputGifski;
public enum LogMode { Visible, OnlyLastLine, Hidden }
static LogMode currentLogMode;
static bool showProgressBar;
public static async Task RunFfmpeg(string args, LogMode logMode, TaskType taskType = TaskType.Other, bool progressBar = false)
{
await RunFfmpeg(args, "", logMode, taskType, progressBar);
}
public static async Task RunFfmpeg(string args, string workingDir, LogMode logMode, TaskType taskType = TaskType.Other, bool progressBar = false)
{
lastOutputFfmpeg = "";
currentLogMode = logMode;
showProgressBar = progressBar;
Process ffmpeg = OSUtils.NewProcess(true);
timeSinceLastOutput.Restart();
lastProcess = ffmpeg;
lastTask = taskType;
if(!string.IsNullOrWhiteSpace(workingDir))
ffmpeg.StartInfo.Arguments = $"{GetCmdArg()} cd /D {workingDir.Wrap()} & {Path.Combine(GetAvDir(), "ffmpeg.exe").Wrap()} -hide_banner -loglevel warning -y -stats {args}";
else
ffmpeg.StartInfo.Arguments = $"{GetCmdArg()} cd /D {GetAvDir().Wrap()} & ffmpeg.exe -hide_banner -loglevel warning -y -stats {args}";
if (logMode != LogMode.Hidden) Logger.Log("Running ffmpeg...", false);
Logger.Log("cmd.exe " + ffmpeg.StartInfo.Arguments, true, false, "ffmpeg");
ffmpeg.OutputDataReceived += new DataReceivedEventHandler(FfmpegOutputHandler);
ffmpeg.ErrorDataReceived += new DataReceivedEventHandler(FfmpegOutputHandler);
ffmpeg.Start();
ffmpeg.BeginOutputReadLine();
ffmpeg.BeginErrorReadLine();
while (!ffmpeg.HasExited)
await Task.Delay(1);
if(progressBar)
Program.mainForm.SetProgress(0);
}
static void FfmpegOutputHandler(object sendingProcess, DataReceivedEventArgs outLine)
{
timeSinceLastOutput.Restart();
if (outLine == null || outLine.Data == null)
return;
string line = outLine.Data;
lastOutputFfmpeg = lastOutputFfmpeg + "\n" + line;
bool hidden = currentLogMode == LogMode.Hidden;
bool replaceLastLine = currentLogMode == LogMode.OnlyLastLine;
string trimmedLine = line.Remove("q=-0.0").Remove("size=N/A").Remove("bitrate=N/A").TrimWhitespaces();
Logger.Log(trimmedLine, hidden, replaceLastLine, "ffmpeg");
if(line.Contains("Could not open file"))
Interpolate.Cancel($"FFmpeg Error: {line}");
if (line.Contains("No NVENC capable devices found"))
Interpolate.Cancel($"FFmpeg Error: {line}\nMake sure you have an NVENC-capable Nvidia GPU.");
if (!hidden && showProgressBar && line.Contains("time="))
{
Regex timeRegex = new Regex("(?<=time=).*(?= )");
UpdateFfmpegProgress(timeRegex.Match(line).Value);
}
}
static void FfmpegOutputHandlerSilent (object sendingProcess, DataReceivedEventArgs outLine)
{
timeSinceLastOutput.Restart();
if (outLine == null || outLine.Data == null || outLine.Data.Trim().Length < 2)
return;
string line = outLine.Data;
if (!string.IsNullOrWhiteSpace(lastOutputFfmpeg))
lastOutputFfmpeg += "\n";
lastOutputFfmpeg = lastOutputFfmpeg + line;
Logger.Log(line, true, false, "ffmpeg");
if (showProgressBar && line.Contains("time="))
{
Logger.Log($"showProgressBar, contains: {line.Contains("time=")}", true, false, "ffmpeg");
Regex timeRegex = new Regex("(?<=time=).*(?= )");
UpdateFfmpegProgress(timeRegex.Match(line).Value);
}
}
public static string GetFfmpegOutput (string args)
{
Process ffmpeg = OSUtils.NewProcess(true);
lastProcess = ffmpeg;
ffmpeg.StartInfo.Arguments = $"{GetCmdArg()} cd /D {GetAvDir().Wrap()} & ffmpeg.exe -hide_banner -y -stats {args}";
Logger.Log("cmd.exe " + ffmpeg.StartInfo.Arguments, true, false, "ffmpeg");
ffmpeg.Start();
ffmpeg.WaitForExit();
string output = ffmpeg.StandardOutput.ReadToEnd();
string err = ffmpeg.StandardError.ReadToEnd();
if (!string.IsNullOrWhiteSpace(err)) output += "\n" + err;
return output;
}
public static async Task<string> GetFfmpegOutputAsync(string args, bool setBusy = false, bool progressBar = false)
{
timeSinceLastOutput.Restart();
if (Program.busy) setBusy = false;
lastOutputFfmpeg = "";
showProgressBar = progressBar;
Process ffmpeg = OSUtils.NewProcess(true);
lastProcess = ffmpeg;
ffmpeg.StartInfo.Arguments = $"{GetCmdArg()} cd /D {GetAvDir().Wrap()} & ffmpeg.exe -hide_banner -y -stats {args}";
Logger.Log("cmd.exe " + ffmpeg.StartInfo.Arguments, true, false, "ffmpeg");
if (setBusy) Program.mainForm.SetWorking(true);
ffmpeg.OutputDataReceived += new DataReceivedEventHandler(FfmpegOutputHandlerSilent);
ffmpeg.ErrorDataReceived += new DataReceivedEventHandler(FfmpegOutputHandlerSilent);
ffmpeg.Start();
ffmpeg.BeginOutputReadLine();
ffmpeg.BeginErrorReadLine();
while (!ffmpeg.HasExited) await Task.Delay(50);
while(timeSinceLastOutput.ElapsedMilliseconds < 200) await Task.Delay(50);
if (setBusy) Program.mainForm.SetWorking(false);
return lastOutputFfmpeg;
}
public static string GetFfprobeOutput (string args)
{
Process ffprobe = OSUtils.NewProcess(true);
ffprobe.StartInfo.Arguments = $"{GetCmdArg()} cd /D {GetAvDir().Wrap()} & ffprobe.exe {args}";
Logger.Log("cmd.exe " + ffprobe.StartInfo.Arguments, true, false, "ffmpeg");
ffprobe.Start();
ffprobe.WaitForExit();
string output = ffprobe.StandardOutput.ReadToEnd();
string err = ffprobe.StandardError.ReadToEnd();
if (!string.IsNullOrWhiteSpace(err)) output += "\n" + err;
return output;
}
public static void UpdateFfmpegProgress(string ffmpegTime)
{
if (Program.mainForm.currInDuration < 1)
{
Program.mainForm.SetProgress(0);
return;
}
long total = Program.mainForm.currInDuration / 100;
long current = FormatUtils.MsFromTimestamp(ffmpegTime);
int progress = Convert.ToInt32(current / total);
Program.mainForm.SetProgress(progress);
}
static string GetAvDir ()
{
return Path.Combine(Paths.GetPkgPath(), Path.GetFileNameWithoutExtension(Packages.audioVideo.fileName));
}
static string GetCmdArg ()
{
return "/C";
}
public static async Task SetBusyWhileRunning ()
{
if (Program.busy) return;
await Task.Delay(100);
while(!lastProcess.HasExited)
await Task.Delay(10);
}
}
}

View File

@@ -1,182 +0,0 @@
using Flowframes.IO;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Flowframes.Media
{
class FFmpegUtils
{
public enum Codec { H264, H265, NVENC264, NVENC265, VP9, ProRes, AviRaw }
public static Codec GetCodec(Interpolate.OutMode mode)
{
if (mode == Interpolate.OutMode.VidMp4 || mode == Interpolate.OutMode.VidMkv)
{
int mp4Enc = Config.GetInt("mp4Enc");
if (mp4Enc == 0) return Codec.H264;
if (mp4Enc == 1) return Codec.H265;
if (mp4Enc == 2) return Codec.NVENC264;
if (mp4Enc == 3) return Codec.NVENC265;
}
if (mode == Interpolate.OutMode.VidWebm)
return Codec.VP9;
if (mode == Interpolate.OutMode.VidProRes)
return Codec.ProRes;
if (mode == Interpolate.OutMode.VidAvi)
return Codec.AviRaw;
return Codec.H264;
}
public static string GetEnc(Codec codec)
{
switch (codec)
{
case Codec.H264: return "libx264";
case Codec.H265: return "libx265";
case Codec.NVENC264: return "h264_nvenc";
case Codec.NVENC265: return "hevc_nvenc";
case Codec.VP9: return "libvpx-vp9";
case Codec.ProRes: return "prores_ks";
case Codec.AviRaw: return Config.Get("aviCodec");
}
return "libx264";
}
public static string GetEncArgs (Codec codec)
{
string args = $"-c:v { GetEnc(codec)} ";
if(codec == Codec.H264)
{
args += $"-crf {Config.GetInt("h264Crf")} -preset {Config.Get("ffEncPreset")} -pix_fmt yuv420p";
}
if (codec == Codec.H265)
{
args += $"-crf {Config.GetInt("h265Crf")} -preset {Config.Get("ffEncPreset")} -pix_fmt yuv420p";
}
if (codec == Codec.NVENC264)
{
args += $"-cq {Config.GetInt("h264Crf")} -preset slow -pix_fmt yuv420p";
}
if (codec == Codec.NVENC265)
{
args += $"-cq {Config.GetInt("h265Crf")} -preset slow -pix_fmt yuv420p";
}
if (codec == Codec.VP9)
{
int crf = Config.GetInt("vp9Crf");
string qualityStr = (crf > 0) ? $"-crf {crf}" : "-lossless 1";
string cpuUsed = Config.GetInt("vp9Speed", 3).ToString();
args += $"{qualityStr} -cpu-used {cpuUsed} -tile-columns 2 -tile-rows 2 -row-mt 1 -pix_fmt yuv420p";
}
if(codec == Codec.ProRes)
{
args += $"-profile:v {Config.GetInt("proResProfile")} -pix_fmt yuv420p";
}
if (codec == Codec.AviRaw)
{
args += $"-pix_fmt {Config.Get("aviColors")}";
}
return args;
}
public static string GetAudioEnc(Codec codec)
{
switch (codec)
{
case Codec.VP9: return "libopus";
}
return "aac";
}
public static string GetExt(Interpolate.OutMode outMode, bool dot = true)
{
string ext = dot ? "." : "";
switch (outMode)
{
case Interpolate.OutMode.VidMp4: ext += "mp4"; break;
case Interpolate.OutMode.VidMkv: ext += "mkv"; break;
case Interpolate.OutMode.VidWebm: ext += "webm"; break;
case Interpolate.OutMode.VidProRes: ext += "mov"; break;
case Interpolate.OutMode.VidAvi: ext += "avi"; break;
case Interpolate.OutMode.VidGif: ext += "gif"; break;
}
return ext;
}
public static string GetAudioExt(string videoFile)
{
switch (FfmpegCommands.GetAudioCodec(videoFile))
{
case "vorbis": return "ogg";
case "opus": return "ogg";
case "mp2": return "mp2";
case "aac": return "m4a";
default: return "wav";
}
}
public static string GetAudioFallbackArgs (string containerExt)
{
containerExt = containerExt.Remove(".");
string codec = "aac";
string bitrate = $"{Config.GetInt("aacBitrate", 160)}";
if(containerExt == "webm" || containerExt == "mkv")
{
codec = "libopus";
bitrate = $"{Config.GetInt("opusBitrate", 128)}";
}
return $"-c:a {codec} -b:a {bitrate}k -ac 2";
}
public static string GetAudioExtForContainer(string containerExt)
{
containerExt = containerExt.Remove(".");
string ext = "m4a";
if (containerExt == "webm" || containerExt == "mkv")
ext = "ogg";
return ext;
}
public static string GetSubCodecForContainer(string containerExt)
{
containerExt = containerExt.Remove(".");
if (containerExt == "mp4") return "mov_text";
if (containerExt == "webm") return "webvtt";
return "copy"; // Default: Copy SRT subs
}
public static bool ContainerSupportsSubs(string containerExt, bool showWarningIfNotSupported = true)
{
containerExt = containerExt.Remove(".");
bool supported = (containerExt == "mp4" || containerExt == "mkv" || containerExt == "webm" || containerExt == "mov");
Logger.Log($"Subtitles {(supported ? "are supported" : "not supported")} by {containerExt.ToUpper()}", true);
if (Config.GetBool("keepSubs") && !supported)
Logger.Log($"Warning: Subtitles are enabled, but {containerExt.ToUpper()} does not support them. MKV is recommended instead.");
return supported;
}
}
}

View File

@@ -1,52 +0,0 @@
using Flowframes.Data;
using Flowframes.IO;
using Flowframes.Main;
using Flowframes.MiscUtils;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using static Flowframes.AvProcess;
namespace Flowframes.Media
{
class FfmpegAlpha
{
public static async Task ExtractAlphaDir(string rgbDir, string alphaDir)
{
Directory.CreateDirectory(alphaDir);
foreach (FileInfo file in IOUtils.GetFileInfosSorted(rgbDir))
{
string args = $"-i {file.FullName.Wrap()} -vf format=yuva444p16le,alphaextract,format=yuv420p {Path.Combine(alphaDir, file.Name).Wrap()}";
await RunFfmpeg(args, LogMode.Hidden);
}
}
public static async Task RemoveAlpha(string inputDir, string outputDir, string fillColor = "black")
{
Directory.CreateDirectory(outputDir);
foreach (FileInfo file in IOUtils.GetFileInfosSorted(inputDir))
{
string outFilename = Path.Combine(outputDir, "_" + file.Name);
Size res = IOUtils.GetImage(file.FullName).Size;
string args = $" -f lavfi -i color={fillColor}:s={res.Width}x{res.Height} -i {file.FullName.Wrap()} " +
$"-filter_complex overlay=0:0:shortest=1 -pix_fmt rgb24 {outFilename.Wrap()}";
await RunFfmpeg(args, LogMode.Hidden);
file.Delete();
File.Move(outFilename, file.FullName);
}
}
public static async Task MergeAlphaIntoRgb(string rgbDir, int rgbPad, string alphaDir, int aPad, bool deleteAlphaDir)
{
string filter = "-filter_complex [0:v:0][1:v:0]alphamerge[out] -map [out]";
string args = $"-i \"{rgbDir}/%{rgbPad}d.png\" -i \"{alphaDir}/%{aPad}d.png\" {filter} \"{rgbDir}/%{rgbPad}d.png\"";
await RunFfmpeg(args, LogMode.Hidden);
if (deleteAlphaDir)
IOUtils.TryDeleteIfExists(alphaDir);
}
}
}

View File

@@ -1,178 +0,0 @@
using Flowframes.Data;
using Flowframes.IO;
using Flowframes.Main;
using Flowframes.MiscUtils;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using static Flowframes.AvProcess;
using Utils = Flowframes.Media.FFmpegUtils;
namespace Flowframes.Media
{
partial class FfmpegAudioAndMetadata : FfmpegCommands
{
public static async Task ExtractAudio(string inputFile, string outFile) // https://stackoverflow.com/a/27413824/14274419
{
try
{
string audioExt = Utils.GetAudioExt(inputFile);
outFile = Path.ChangeExtension(outFile, audioExt);
Logger.Log($"[FFCmds] Extracting audio from {inputFile} to {outFile}", true);
string args = $" -loglevel panic -i {inputFile.Wrap()} -vn -c:a copy {outFile.Wrap()}";
await RunFfmpeg(args, LogMode.Hidden);
if (File.Exists(outFile) && IOUtils.GetFilesize(outFile) < 512)
{
Logger.Log("Failed to extract audio losslessly! Trying to re-encode.");
File.Delete(outFile);
outFile = Path.ChangeExtension(outFile, Utils.GetAudioExtForContainer(Path.GetExtension(inputFile)));
args = $" -loglevel panic -i {inputFile.Wrap()} -vn {Utils.GetAudioFallbackArgs(Path.GetExtension(inputFile))} {outFile.Wrap()}";
await RunFfmpeg(args, LogMode.Hidden);
if ((File.Exists(outFile) && IOUtils.GetFilesize(outFile) < 512) || lastOutputFfmpeg.Contains("Invalid data"))
{
Logger.Log("Failed to extract audio, even with re-encoding. Output will not have audio.");
IOUtils.TryDeleteIfExists(outFile);
return;
}
Logger.Log($"Source audio has been re-encoded as it can't be extracted losslessly. This may decrease the quality slightly.", false, true);
}
}
catch (Exception e)
{
Logger.Log("Error extracting audio: " + e.Message);
}
}
public static async Task ExtractSubtitles(string inputFile, string outFolder, Interpolate.OutMode outMode,bool showMsg = true)
{
try
{
string msg = "Extracting subtitles from video...";
if (showMsg) Logger.Log(msg);
List<SubtitleTrack> subtitleTracks = await GetSubtitleTracks(inputFile);
int counter = 1;
foreach (SubtitleTrack subTrack in subtitleTracks)
{
string outPath = Path.Combine(outFolder, $"{subTrack.streamIndex}_{subTrack.langFriendly}_{subTrack.encoding}.srt");
string args = $" -loglevel error -sub_charenc {subTrack.encoding} -i {inputFile.Wrap()} -map 0:s:{subTrack.streamIndex} {outPath.Wrap()}";
await RunFfmpeg(args, LogMode.Hidden);
if (subtitleTracks.Count > 4) Program.mainForm.SetProgress(FormatUtils.RatioInt(counter, subtitleTracks.Count));
Logger.Log($"[FFCmds] Extracted subtitle track {subTrack.streamIndex} to {outPath} ({FormatUtils.Bytes(IOUtils.GetFilesize(outPath))})", true, false, "ffmpeg");
counter++;
}
if (subtitleTracks.Count > 0)
Utils.ContainerSupportsSubs(Utils.GetExt(outMode), true);
Logger.Log($"Extracted {subtitleTracks.Count} subtitle tracks from the input video.".Replace(" 0 ", " no "), false, Logger.GetLastLine().Contains(msg));
}
catch (Exception e)
{
Logger.Log("Error extracting subtitles: " + e.Message);
}
Program.mainForm.SetProgress(0);
}
public static async Task<List<SubtitleTrack>> GetSubtitleTracks(string inputFile)
{
List<SubtitleTrack> subtitleTracks = new List<SubtitleTrack>();
string args = $"-i {inputFile.Wrap()}";
Logger.Log("GetSubtitleTracks()", true, false, "ffmpeg");
string[] outputLines = (await GetFfmpegOutputAsync(args)).SplitIntoLines();
int idx = 0;
for (int i = 0; i < outputLines.Length; i++)
{
string line = outputLines[i];
if (!line.Contains(" Subtitle: ")) continue;
string lang = "unknown";
string subEnc = "UTF-8";
if (line.Contains("(") && line.Contains("): Subtitle: ")) // Lang code in stream name, like "Stream #0:2(eng): Subtitle: ..."
lang = line.Split('(')[1].Split(')')[0];
if ((i + 2 < outputLines.Length) && outputLines[i + 1].Contains("Metadata:") && outputLines[i + 2].Contains("SUB_CHARENC")) // Subtitle encoding is in metadata!
subEnc = outputLines[i + 2].Remove("SUB_CHARENC").Remove(":").TrimWhitespaces();
Logger.Log($"Found subtitle track #{idx} with language '{lang}' and encoding '{subEnc}'", true, false, "ffmpeg");
subtitleTracks.Add(new SubtitleTrack(idx, lang, subEnc));
idx++;
}
return subtitleTracks;
}
public static async Task MergeAudioAndSubs(string inputFile, string audioPath, string tempFolder, int looptimes = -1) // https://superuser.com/a/277667
{
Logger.Log($"[FFCmds] Merging audio from {audioPath} into {inputFile}", true);
string containerExt = Path.GetExtension(inputFile);
string tempPath = Path.Combine(tempFolder, $"vid{containerExt}"); // inputFile + "-temp" + Path.GetExtension(inputFile);
string outPath = Path.Combine(tempFolder, $"muxed{containerExt}"); // inputFile + "-temp" + Path.GetExtension(inputFile);
File.Move(inputFile, tempPath);
string inName = Path.GetFileName(tempPath);
string audioName = Path.GetFileName(audioPath);
string outName = Path.GetFileName(outPath);
bool subs = Utils.ContainerSupportsSubs(containerExt, false) && Config.GetBool("keepSubs");
string subInputArgs = "";
string subMapArgs = "";
string subMetaArgs = "";
string[] subTracks = subs ? IOUtils.GetFilesSorted(tempFolder, false, "*.srt") : new string[0];
for (int subTrack = 0; subTrack < subTracks.Length; subTrack++)
{
subInputArgs += $" -i {Path.GetFileName(subTracks[subTrack])}";
subMapArgs += $" -map {subTrack + 2}";
subMetaArgs += $" -metadata:s:s:{subTrack} language={Path.GetFileNameWithoutExtension(subTracks[subTrack]).Split('_')[1]}";
}
string subCodec = Utils.GetSubCodecForContainer(containerExt);
string args = $" -i {inName} -stream_loop {looptimes} -i {audioName.Wrap()}" +
$"{subInputArgs} -map 0:v -map 1:a {subMapArgs} -c:v copy -c:a copy -c:s {subCodec} {subMetaArgs} -shortest {outName}";
await RunFfmpeg(args, tempFolder, LogMode.Hidden);
if ((File.Exists(outPath) && IOUtils.GetFilesize(outPath) < 1024) || lastOutputFfmpeg.Contains("Invalid data") || lastOutputFfmpeg.Contains("Error initializing output stream"))
{
Logger.Log("Failed to merge audio losslessly! Trying to re-encode.", false, false, "ffmpeg");
args = $" -i {inName} -stream_loop {looptimes} -i {audioName.Wrap()}" +
$"{subInputArgs} -map 0:v -map 1:a {subMapArgs} -c:v copy {Utils.GetAudioFallbackArgs(Path.GetExtension(inputFile))} -c:s {subCodec} {subMetaArgs} -shortest {outName}";
await RunFfmpeg(args, tempFolder, LogMode.Hidden);
if ((File.Exists(outPath) && IOUtils.GetFilesize(outPath) < 1024) || lastOutputFfmpeg.Contains("Invalid data") || lastOutputFfmpeg.Contains("Error initializing output stream"))
{
Logger.Log("Failed to merge audio, even with re-encoding. Output will not have audio.", false, false, "ffmpeg");
IOUtils.TryMove(tempPath, inputFile); // Move temp file back
IOUtils.TryDeleteIfExists(tempPath);
return;
}
string audioExt = Path.GetExtension(audioPath).Remove(".").ToUpper();
Logger.Log($"Source audio ({audioExt}) has been re-encoded to fit into the target container ({containerExt.Remove(".").ToUpper()}). This may decrease the quality slightly.", false, true, "ffmpeg");
}
if (File.Exists(outPath) && IOUtils.GetFilesize(outPath) > 512)
{
File.Delete(tempPath);
File.Move(outPath, inputFile);
}
else
{
File.Move(tempPath, inputFile);
}
}
}
}

View File

@@ -1,196 +0,0 @@
using Flowframes.Media;
using Flowframes.Data;
using Flowframes.IO;
using Flowframes.Main;
using Flowframes.MiscUtils;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using static Flowframes.AvProcess;
using Utils = Flowframes.Media.FFmpegUtils;
namespace Flowframes
{
class FfmpegCommands
{
public static string divisionFilter = "pad=width=ceil(iw/2)*2:height=ceil(ih/2)*2:color=black@0";
public static string pngComprArg = "-compression_level 3";
public static string mpDecDef = "\"mpdecimate\"";
public static string mpDecAggr = "\"mpdecimate=hi=64*32:lo=64*32:frac=0.1\"";
public static async Task ConcatVideos(string concatFile, string outPath, int looptimes = -1)
{
Logger.Log($"Merging videos...", false, Logger.GetLastLine().Contains("frame"));
string loopStr = (looptimes > 0) ? $"-stream_loop {looptimes}" : "";
string vfrFilename = Path.GetFileName(concatFile);
string args = $" {loopStr} -vsync 1 -f concat -i {vfrFilename} -c copy -movflags +faststart {outPath.Wrap()}";
await RunFfmpeg(args, concatFile.GetParentDir(), LogMode.Hidden, TaskType.Merge);
}
public static async Task LoopVideo(string inputFile, int times, bool delSrc = false)
{
string pathNoExt = Path.ChangeExtension(inputFile, null);
string ext = Path.GetExtension(inputFile);
string args = $" -stream_loop {times} -i {inputFile.Wrap()} -c copy \"{pathNoExt}-Loop{times}{ext}\"";
await RunFfmpeg(args, LogMode.Hidden);
if (delSrc)
DeleteSource(inputFile);
}
public static async Task ChangeSpeed(string inputFile, float newSpeedPercent, bool delSrc = false)
{
string pathNoExt = Path.ChangeExtension(inputFile, null);
string ext = Path.GetExtension(inputFile);
float val = newSpeedPercent / 100f;
string speedVal = (1f / val).ToString("0.0000").Replace(",", ".");
string args = " -itsscale " + speedVal + " -i \"" + inputFile + "\" -c copy \"" + pathNoExt + "-" + newSpeedPercent + "pcSpeed" + ext + "\"";
await RunFfmpeg(args, LogMode.OnlyLastLine);
if (delSrc)
DeleteSource(inputFile);
}
public static long GetDuration(string inputFile)
{
Logger.Log($"GetDuration({inputFile}) - Reading Duration using ffprobe.", true, false, "ffmpeg");
string args = $" -v panic -select_streams v:0 -show_entries format=duration -of csv=s=x:p=0 -sexagesimal {inputFile.Wrap()}";
string info = GetFfprobeOutput(args);
return FormatUtils.MsFromTimestamp(info);
}
public static async Task<float> GetFramerate(string inputFile)
{
Logger.Log($"GetFramerate('{inputFile}')", true, false, "ffmpeg");
try
{
string args = $" -i {inputFile.Wrap()}";
string output = await GetFfmpegOutputAsync(args);
string[] entries = output.Split(',');
foreach (string entry in entries)
{
if (entry.Contains(" fps") && !entry.Contains("Input ")) // Avoid reading FPS from the filename, in case filename contains "fps"
{
string num = entry.Replace(" fps", "").Trim().Replace(",", ".");
float value;
float.TryParse(num, NumberStyles.Any, CultureInfo.InvariantCulture, out value);
return value;
}
}
}
catch(Exception e)
{
Logger.Log("GetFramerate Error: " + e.Message, true, false);
}
return 0f;
}
public static Size GetSize(string inputFile)
{
string args = $" -v panic -select_streams v:0 -show_entries stream=width,height -of csv=s=x:p=0 {inputFile.Wrap()}";
string output = GetFfprobeOutput(args);
if (output.Length > 4 && output.Contains("x"))
{
string[] numbers = output.Split('x');
return new Size(numbers[0].GetInt(), numbers[1].GetInt());
}
return new Size(0, 0);
}
public static async Task<int> GetFrameCountAsync(string inputFile)
{
Logger.Log($"GetFrameCountAsync('{inputFile}') - Trying ffprobe first.", true, false, "ffmpeg");
int frames = 0;
frames = await ReadFrameCountFfprobeAsync(inputFile, Config.GetBool("ffprobeCountFrames")); // Try reading frame count with ffprobe
if (frames > 0) return frames;
Logger.Log($"Failed to get frame count using ffprobe (frames = {frames}). Trying to calculate with duration * fps.", true, false, "ffmpeg");
frames = await ReadFrameCountFfmpegAsync(inputFile); // Try reading frame count with ffmpeg
if (frames > 0) return frames;
Logger.Log("Failed to get total frame count of video.");
return 0;
}
static int ReadFrameCountFromDuration (string inputFile, long durationMs, float fps)
{
float durationSeconds = durationMs / 1000f;
float frameCount = durationSeconds * fps;
int frameCountRounded = frameCount.RoundToInt();
Logger.Log($"ReadFrameCountFromDuration: Got frame count of {frameCount}, rounded to {frameCountRounded}");
return frameCountRounded;
}
static async Task<int> ReadFrameCountFfprobeAsync(string inputFile, bool readFramesSlow)
{
string args = $" -v panic -select_streams v:0 -show_entries stream=nb_frames -of default=noprint_wrappers=1 {inputFile.Wrap()}";
if (readFramesSlow)
{
Logger.Log("Counting total frames using FFprobe. This can take a moment...");
await Task.Delay(10);
args = $" -v panic -count_frames -select_streams v:0 -show_entries stream=nb_read_frames -of default=nokey=1:noprint_wrappers=1 {inputFile.Wrap()}";
}
string info = GetFfprobeOutput(args);
string[] entries = info.SplitIntoLines();
try
{
if (readFramesSlow)
return info.GetInt();
foreach (string entry in entries)
{
if (entry.Contains("nb_frames="))
return entry.GetInt();
}
}
catch { }
return -1;
}
static async Task<int> ReadFrameCountFfmpegAsync (string inputFile)
{
string args = $" -loglevel panic -i {inputFile.Wrap()} -map 0:v:0 -c copy -f null - ";
string info = await GetFfmpegOutputAsync(args, true, true);
try
{
string[] lines = info.SplitIntoLines();
string lastLine = lines.Last();
return lastLine.Substring(0, lastLine.IndexOf("fps")).GetInt();
}
catch
{
return -1;
}
}
public static string GetAudioCodec(string path)
{
string args = $" -v panic -show_streams -select_streams a -show_entries stream=codec_name {path.Wrap()}";
string info = GetFfprobeOutput(args);
string[] entries = info.SplitIntoLines();
foreach (string entry in entries)
{
if (entry.Contains("codec_name="))
return entry.Split('=')[1];
}
return "";
}
public static void DeleteSource(string path)
{
Logger.Log("[FFCmds] Deleting input file/dir: " + path, true);
if (IOUtils.IsPathDirectory(path) && Directory.Exists(path))
Directory.Delete(path, true);
if (!IOUtils.IsPathDirectory(path) && File.Exists(path))
File.Delete(path);
}
}
}

View File

@@ -1,65 +0,0 @@
using Flowframes.Data;
using Flowframes.IO;
using Flowframes.Main;
using Flowframes.MiscUtils;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using static Flowframes.AvProcess;
using Utils = Flowframes.Media.FFmpegUtils;
namespace Flowframes.Media
{
partial class FfmpegEncode : FfmpegCommands
{
public static async Task FramesToVideoConcat(string framesFile, string outPath, Interpolate.OutMode outMode, float fps, LogMode logMode = LogMode.OnlyLastLine, bool isChunk = false)
{
await FramesToVideoConcat(framesFile, outPath, outMode, fps, 0, logMode, isChunk);
}
public static async Task FramesToVideoConcat(string framesFile, string outPath, Interpolate.OutMode outMode, float fps, float resampleFps, LogMode logMode = LogMode.OnlyLastLine, bool isChunk = false)
{
if (logMode != LogMode.Hidden)
Logger.Log((resampleFps <= 0) ? $"Encoding video..." : $"Encoding video resampled to {resampleFps.ToString().Replace(",", ".")} FPS...");
Directory.CreateDirectory(outPath.GetParentDir());
string encArgs = Utils.GetEncArgs(Utils.GetCodec(outMode));
if (!isChunk) encArgs += $" -movflags +faststart";
string vfrFilename = Path.GetFileName(framesFile);
string rate = fps.ToString().Replace(",", ".");
string vf = (resampleFps <= 0) ? "" : $"-vf fps=fps={resampleFps.ToStringDot()}";
string extraArgs = Config.Get("ffEncArgs");
string args = $"-loglevel error -vsync 0 -f concat -r {rate} -i {vfrFilename} {encArgs} {vf} {extraArgs} -threads {Config.GetInt("ffEncThreads")} {outPath.Wrap()}";
await RunFfmpeg(args, framesFile.GetParentDir(), logMode, TaskType.Encode, !isChunk);
}
public static async Task FramesToGifConcat(string framesFile, string outPath, float fps, bool palette, int colors = 64, float resampleFps = -1, LogMode logMode = LogMode.OnlyLastLine)
{
if (logMode != LogMode.Hidden)
Logger.Log((resampleFps <= 0) ? $"Encoding GIF..." : $"Encoding GIF resampled to {resampleFps.ToString().Replace(",", ".")} FPS...");
string vfrFilename = Path.GetFileName(framesFile);
string paletteFilter = palette ? $"-vf \"split[s0][s1];[s0]palettegen={colors}[p];[s1][p]paletteuse=dither=floyd_steinberg:diff_mode=rectangle\"" : "";
string fpsFilter = (resampleFps <= 0) ? "" : $"fps=fps={resampleFps.ToStringDot()}";
string vf = FormatUtils.ConcatStrings(new string[] { paletteFilter, fpsFilter });
string rate = fps.ToStringDot();
string args = $"-loglevel error -f concat -r {rate} -i {vfrFilename.Wrap()} -f gif {vf} {outPath.Wrap()}";
await RunFfmpeg(args, framesFile.GetParentDir(), LogMode.OnlyLastLine, TaskType.Encode);
}
public static async Task Encode(string inputFile, string vcodec, string acodec, int crf, int audioKbps = 0, bool delSrc = false)
{
string outPath = Path.ChangeExtension(inputFile, null) + "-convert.mp4";
string args = $" -i {inputFile.Wrap()} -c:v {vcodec} -crf {crf} -pix_fmt yuv420p -c:a {acodec} -b:a {audioKbps}k -vf {divisionFilter} {outPath.Wrap()}";
if (string.IsNullOrWhiteSpace(acodec))
args = args.Replace("-c:a", "-an");
if (audioKbps < 0)
args = args.Replace($" -b:a {audioKbps}", "");
await RunFfmpeg(args, LogMode.OnlyLastLine, TaskType.Encode, true);
if (delSrc)
DeleteSource(inputFile);
}
}
}

View File

@@ -1,107 +0,0 @@
using Flowframes.Data;
using Flowframes.IO;
using Flowframes.Main;
using Flowframes.MiscUtils;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using static Flowframes.AvProcess;
namespace Flowframes.Media
{
partial class FfmpegExtract : FfmpegCommands
{
public static async Task ExtractSceneChanges(string inputFile, string frameFolderPath, float rate)
{
Logger.Log("Extracting scene changes...");
await VideoToFrames(inputFile, frameFolderPath, false, rate, false, false, new Size(320, 180), true);
bool hiddenLog = Interpolate.currentInputFrameCount <= 50;
int amount = IOUtils.GetAmountOfFiles(frameFolderPath, false);
Logger.Log($"Detected {amount} scene {(amount == 1 ? "change" : "changes")}.".Replace(" 0 ", " no "), false, !hiddenLog);
}
public static async Task VideoToFrames(string inputFile, string framesDir, bool alpha, float rate, bool deDupe, bool delSrc)
{
await VideoToFrames(inputFile, framesDir, alpha, rate, deDupe, delSrc, new Size());
}
public static async Task VideoToFrames(string inputFile, string framesDir, bool alpha, float rate, bool deDupe, bool delSrc, Size size, bool sceneDetect = false)
{
if (!sceneDetect) Logger.Log("Extracting video frames from input video...");
string sizeStr = (size.Width > 1 && size.Height > 1) ? $"-s {size.Width}x{size.Height}" : "";
IOUtils.CreateDir(framesDir);
string timecodeStr = /* timecodes ? $"-copyts -r {FrameOrder.timebase} -frame_pts true" : */ "-copyts -frame_pts true";
string scnDetect = sceneDetect ? $"\"select='gt(scene,{Config.GetFloatString("scnDetectValue")})'\"" : "";
string mpStr = deDupe ? ((Config.GetInt("mpdecimateMode") == 0) ? mpDecDef : mpDecAggr) : "";
string filters = FormatUtils.ConcatStrings(new string[] { divisionFilter, scnDetect, mpStr });
string vf = filters.Length > 2 ? $"-vf {filters}" : "";
string rateArg = (rate > 0) ? $" -r {rate.ToStringDot()}" : "";
string pixFmt = alpha ? "-pix_fmt rgba" : "-pix_fmt rgb24"; // Use RGBA for GIF for alpha support
string args = $"{rateArg} -i {inputFile.Wrap()} {pngComprArg} -vsync 0 {pixFmt} {timecodeStr} {vf} {sizeStr} \"{framesDir}/%{Padding.inputFrames}d.png\"";
LogMode logMode = Interpolate.currentInputFrameCount > 50 ? LogMode.OnlyLastLine : LogMode.Hidden;
await AvProcess.RunFfmpeg(args, logMode, TaskType.ExtractFrames, true);
int amount = IOUtils.GetAmountOfFiles(framesDir, false, "*.png");
if (!sceneDetect) Logger.Log($"Extracted {amount} {(amount == 1 ? "frame" : "frames")} from input.", false, true);
await Task.Delay(1);
if (delSrc)
DeleteSource(inputFile);
}
public static async Task ImportImages(string inpath, string outpath, bool alpha, Size size, bool delSrc = false, bool showLog = true)
{
if (showLog) Logger.Log("Importing images...");
Logger.Log($"Importing images from {inpath} to {outpath}.", true);
IOUtils.CreateDir(outpath);
string concatFile = Path.Combine(Paths.GetDataPath(), "png-concat-temp.ini");
string concatFileContent = "";
string[] files = IOUtils.GetFilesSorted(inpath);
foreach (string img in files)
concatFileContent += $"file '{img.Replace(@"\", "/")}'\n";
File.WriteAllText(concatFile, concatFileContent);
string sizeStr = (size.Width > 1 && size.Height > 1) ? $"-s {size.Width}x{size.Height}" : "";
string pixFmt = alpha ? "-pix_fmt rgba" : "-pix_fmt rgb24"; // Use RGBA for GIF for alpha support
string vf = alpha ? $"-filter_complex \"[0:v]{divisionFilter},split[a][b];[a]palettegen=reserve_transparent=on:transparency_color=ffffff[p];[b][p]paletteuse\"" : $"-vf {divisionFilter}";
string args = $" -loglevel panic -f concat -safe 0 -i {concatFile.Wrap()} {pngComprArg} {sizeStr} {pixFmt} -vsync 0 {vf} \"{outpath}/%{Padding.inputFrames}d.png\"";
LogMode logMode = IOUtils.GetAmountOfFiles(inpath, false) > 50 ? LogMode.OnlyLastLine : LogMode.Hidden;
await AvProcess.RunFfmpeg(args, logMode, TaskType.ExtractFrames);
if (delSrc)
DeleteSource(inpath);
}
public static async Task ImportSingleImage(string inputFile, string outPath, Size size)
{
string sizeStr = (size.Width > 1 && size.Height > 1) ? $"-s {size.Width}x{size.Height}" : "";
bool isPng = (Path.GetExtension(outPath).ToLower() == ".png");
string comprArg = isPng ? pngComprArg : "";
string pixFmt = "-pix_fmt " + (isPng ? $"rgb24 {comprArg}" : "yuvj420p");
string args = $"-i {inputFile.Wrap()} {comprArg} {sizeStr} {pixFmt} -vf {divisionFilter} {outPath.Wrap()}";
await AvProcess.RunFfmpeg(args, LogMode.Hidden, TaskType.ExtractFrames);
}
public static async Task ExtractSingleFrame(string inputFile, string outputPath, int frameNum)
{
bool isPng = (Path.GetExtension(outputPath).ToLower() == ".png");
string comprArg = isPng ? pngComprArg : "";
string pixFmt = "-pix_fmt " + (isPng ? $"rgb24 {comprArg}" : "yuvj420p");
string args = $"-i {inputFile.Wrap()} -vf \"select=eq(n\\,{frameNum})\" -vframes 1 {pixFmt} {outputPath.Wrap()}";
await AvProcess.RunFfmpeg(args, LogMode.Hidden, TaskType.ExtractFrames);
}
public static async Task ExtractLastFrame(string inputFile, string outputPath, Size size)
{
if (IOUtils.IsPathDirectory(outputPath))
outputPath = Path.Combine(outputPath, "last.png");
bool isPng = (Path.GetExtension(outputPath).ToLower() == ".png");
string comprArg = isPng ? pngComprArg : "";
string pixFmt = "-pix_fmt " + (isPng ? $"rgb24 {comprArg}" : "yuvj420p");
string sizeStr = (size.Width > 1 && size.Height > 1) ? $"-s {size.Width}x{size.Height}" : "";
string args = $"-sseof -1 -i {inputFile.Wrap()} -update 1 {pixFmt} {sizeStr} {outputPath.Wrap()}";
await AvProcess.RunFfmpeg(args, LogMode.Hidden, TaskType.ExtractFrames);
}
}
}

View File

@@ -1,43 +0,0 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Flowframes.MiscUtils
{
class Benchmarker
{
static Stopwatch sw = new Stopwatch();
public static void Start ()
{
sw.Restart();
}
public static string GetTimeStr (bool stop)
{
if (stop)
sw.Stop();
return FormatUtils.TimeSw(sw);
}
public static TimeSpan GetTime(bool stop)
{
if (stop)
sw.Stop();
return sw.Elapsed;
}
public static long GetTimeMs(bool stop)
{
if (stop)
sw.Stop();
return sw.ElapsedMilliseconds;
}
}
}

View File

@@ -1,133 +0,0 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Flowframes.MiscUtils
{
class FormatUtils
{
public static string Bytes(long sizeBytes)
{
try
{
string[] suf = { "B", "KB", "MB", "GB", "TB", "PB", "EB" };
if (sizeBytes == 0)
return "0" + suf[0];
long bytes = Math.Abs(sizeBytes);
int place = Convert.ToInt32(Math.Floor(Math.Log(bytes, 1024)));
double num = Math.Round(bytes / Math.Pow(1024, place), 1);
return ($"{Math.Sign(sizeBytes) * num} {suf[place]}");
}
catch
{
return "N/A B";
}
}
public static string Time(long milliseconds)
{
double secs = (milliseconds / 1000f);
if (milliseconds <= 1000)
{
return milliseconds + "ms";
}
return secs.ToString("0.00") + "s";
}
public static string Time (TimeSpan span, bool allowMs = true)
{
if(span.TotalHours >= 1f)
return span.ToString(@"hh\:mm\:ss");
if (span.TotalMinutes >= 1f)
return span.ToString(@"mm\:ss");
if (span.TotalSeconds >= 1f || !allowMs)
return span.ToString(@"ss".TrimStart('0').PadLeft(1, '0')) + "s";
return span.ToString(@"fff").TrimStart('0').PadLeft(1, '0') + "ms";
}
public static string TimeSw(Stopwatch sw)
{
long elapsedMs = sw.ElapsedMilliseconds;
return Time(elapsedMs);
}
public static long MsFromTimestamp(string timestamp)
{
try
{
string[] values = timestamp.Split(':');
int hours = int.Parse(values[0]);
int minutes = int.Parse(values[1]);
int seconds = int.Parse(values[2].Split('.')[0]);
int milliseconds = int.Parse(values[2].Split('.')[1].Substring(0, 2)) * 10;
long ms = hours * 3600000 + minutes * 60000 + seconds * 1000 + milliseconds;
return ms;
}
catch (Exception e)
{
Logger.Log($"MsFromTimeStamp({timestamp}) Exception: {e.Message}", true);
return 0;
}
}
public static string MsToTimestamp(long milliseconds)
{
return (new DateTime(1970, 1, 1)).AddMilliseconds(milliseconds).ToString("HH:mm:ss");
}
public static string Ratio(long numFrom, long numTo)
{
float ratio = ((float)numFrom / (float)numTo) * 100f;
return ratio.ToString("0.00") + "%";
}
public static int RatioInt(long numFrom, long numTo)
{
double ratio = Math.Round(((float)numFrom / (float)numTo) * 100f);
return (int)ratio;
}
public static string RatioIntStr(long numFrom, long numTo)
{
double ratio = Math.Round(((float)numFrom / (float)numTo) * 100f);
return ratio + "%";
}
public static string ConcatStrings(string[] strings, char delimiter = ',', bool distinct = false)
{
string outStr = "";
strings = strings.Where(s => !string.IsNullOrWhiteSpace(s)).ToArray();
if(distinct)
strings = strings.Distinct().ToArray();
for (int i = 0; i < strings.Length; i++)
{
outStr += strings[i];
if (i + 1 != strings.Length)
outStr += delimiter;
}
return outStr;
}
public static System.Drawing.Size ParseSize (string str)
{
try
{
string[] values = str.Split('x');
return new System.Drawing.Size(values[0].GetInt(), values[1].GetInt());
}
catch
{
return new System.Drawing.Size();
}
}
}
}

View File

@@ -1,359 +0,0 @@
using Flowframes.IO;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using Flowframes.OS;
using Flowframes.UI;
using Flowframes.Main;
using Flowframes.Data;
using Flowframes.MiscUtils;
using Flowframes.Magick;
using Flowframes.Media;
namespace Flowframes
{
class AiProcess
{
public static bool hasShownError;
public static Process currentAiProcess;
public static Stopwatch processTime = new Stopwatch();
public static Stopwatch processTimeMulti = new Stopwatch();
public static int lastStartupTimeMs = 1000;
static string lastInPath;
public static Dictionary<string, string> filenameMap = new Dictionary<string, string>(); // TODO: Store on disk instead for crashes?
static void AiStarted (Process proc, int startupTimeMs, string inPath = "")
{
lastStartupTimeMs = startupTimeMs;
processTime.Restart();
currentAiProcess = proc;
lastInPath = string.IsNullOrWhiteSpace(inPath) ? Interpolate.current.framesFolder : inPath;
hasShownError = false;
}
static void SetProgressCheck(string interpPath, float factor)
{
int frames = IOUtils.GetAmountOfFiles(lastInPath, false, "*.png");
int target = ((frames * factor) - (factor - 1)).RoundToInt();
InterpolateUtils.progressPaused = false;
InterpolateUtils.currentFactor = factor;
if (InterpolateUtils.progCheckRunning)
InterpolateUtils.targetFrames = target;
else
InterpolateUtils.GetProgressByFrameAmount(interpPath, target);
}
static async Task AiFinished (string aiName)
{
if (Interpolate.canceled) return;
Program.mainForm.SetProgress(100);
InterpolateUtils.UpdateInterpProgress(IOUtils.GetAmountOfFiles(Interpolate.current.interpFolder, false, "*.png"), InterpolateUtils.targetFrames);
string logStr = $"Done running {aiName} - Interpolation took {FormatUtils.Time(processTime.Elapsed)}";
if (Interpolate.currentlyUsingAutoEnc && AutoEncode.HasWorkToDo())
logStr += " - Waiting for encoding to finish...";
Logger.Log(logStr);
processTime.Stop();
while (Interpolate.currentlyUsingAutoEnc && Program.busy)
{
if (AvProcess.lastProcess != null && !AvProcess.lastProcess.HasExited && AvProcess.lastTask == AvProcess.TaskType.Encode)
{
string lastLine = AvProcess.lastOutputFfmpeg.SplitIntoLines().Last();
Logger.Log(lastLine.Trim().TrimWhitespaces(), false, Logger.GetLastLine().Contains("frame"));
}
if (AvProcess.timeSinceLastOutput.IsRunning && AvProcess.timeSinceLastOutput.ElapsedMilliseconds > 2500)
break;
await Task.Delay(500);
}
if (!Interpolate.canceled && Interpolate.current.alpha)
{
Logger.Log("Processing alpha...");
string rgbInterpDir = Path.Combine(Interpolate.current.tempFolder, Paths.interpDir);
string alphaInterpDir = Path.Combine(Interpolate.current.tempFolder, Paths.interpDir + Paths.alphaSuffix);
if (!Directory.Exists(alphaInterpDir)) return;
await FfmpegAlpha.MergeAlphaIntoRgb(rgbInterpDir, Padding.interpFrames, alphaInterpDir, Padding.interpFrames, false);
}
}
public static async Task RunRifeCuda(string framesPath, float interpFactor, string mdl)
{
string rifeDir = Path.Combine(Paths.GetPkgPath(), Path.GetFileNameWithoutExtension(Packages.rifeCuda.fileName));
string script = "rife.py";
if (!File.Exists(Path.Combine(rifeDir, script)))
{
Interpolate.Cancel("RIFE script not found! Make sure you didn't modify any files.");
return;
}
await RunRifeCudaProcess(framesPath, Paths.interpDir, script, interpFactor, mdl);
if (!Interpolate.canceled && Interpolate.current.alpha)
{
InterpolateUtils.progressPaused = true;
Logger.Log("Interpolating alpha channel...");
await RunRifeCudaProcess(framesPath + Paths.alphaSuffix, Paths.interpDir + Paths.alphaSuffix, script, interpFactor, mdl);
}
await AiFinished("RIFE");
}
public static async Task RunRifeCudaProcess (string inPath, string outDir, string script, float interpFactor, string mdl)
{
bool parallel = false;
string uhdStr = await InterpolateUtils.UseUHD() ? "--UHD" : "";
string outPath = Path.Combine(inPath.GetParentDir(), outDir);
string args = $" --input {inPath.Wrap()} --output {outDir} --model {mdl} --exp {(int)Math.Log(interpFactor, 2)} ";
if (parallel) args = $" --input {inPath.Wrap()} --output {outPath} --model {mdl} --factor {interpFactor}";
if (parallel) script = "rife-parallel.py";
Process rifePy = OSUtils.NewProcess(!OSUtils.ShowHiddenCmd());
AiStarted(rifePy, 3500);
SetProgressCheck(Path.Combine(Interpolate.current.tempFolder, outDir), interpFactor);
rifePy.StartInfo.Arguments = $"{OSUtils.GetCmdArg()} cd /D {PkgUtils.GetPkgFolder(Packages.rifeCuda).Wrap()} & " +
$"set CUDA_VISIBLE_DEVICES={Config.Get("torchGpus")} & {Python.GetPyCmd()} {script} {args}";
Logger.Log($"Running RIFE {(await InterpolateUtils.UseUHD() ? "(UHD Mode)" : "")} ({script})...".TrimWhitespaces(), false);
Logger.Log("cmd.exe " + rifePy.StartInfo.Arguments, true);
if (!OSUtils.ShowHiddenCmd())
{
rifePy.OutputDataReceived += (sender, outLine) => { LogOutput("[O] " + outLine.Data, "rife-cuda-log"); };
rifePy.ErrorDataReceived += (sender, outLine) => { LogOutput("[E] " + outLine.Data, "rife-cuda-log", true); };
}
rifePy.Start();
if (!OSUtils.ShowHiddenCmd())
{
rifePy.BeginOutputReadLine();
rifePy.BeginErrorReadLine();
}
while (!rifePy.HasExited) await Task.Delay(1);
}
public static async Task RunRifeNcnn (string framesPath, string outPath, int factor, string mdl)
{
processTimeMulti.Restart();
Logger.Log($"Running RIFE{(await InterpolateUtils.UseUHD() ? " (UHD Mode)" : "")}...", false);
await RunRifeNcnnMulti(framesPath, outPath, factor, mdl);
if (!Interpolate.canceled && Interpolate.current.alpha)
{
InterpolateUtils.progressPaused = true;
Logger.Log("Interpolating alpha channel...");
await RunRifeNcnnMulti(framesPath + Paths.alphaSuffix, outPath + Paths.alphaSuffix, factor, mdl);
}
await AiFinished("RIFE");
}
static async Task RunRifeNcnnMulti(string framesPath, string outPath, int factor, string mdl)
{
int times = (int)Math.Log(factor, 2);
if (times > 1)
AutoEncode.paused = true; // Disable autoenc until the last iteration
for (int iteration = 1; iteration <= times; iteration++)
{
if (Interpolate.canceled) return;
if (Interpolate.currentlyUsingAutoEnc && iteration == times) // Enable autoenc if this is the last iteration
AutoEncode.paused = false;
if (iteration > 1)
{
Logger.Log($"Re-Running RIFE for {Math.Pow(2, iteration)}x interpolation...", false);
string lastInterpPath = outPath + $"-run{iteration - 1}";
Directory.Move(outPath, lastInterpPath); // Rename last interp folder
await RunRifeNcnnProcess(lastInterpPath, outPath, mdl);
IOUtils.TryDeleteIfExists(lastInterpPath);
}
else
{
await RunRifeNcnnProcess(framesPath, outPath, mdl);
}
}
}
static async Task RunRifeNcnnProcess(string inPath, string outPath, string mdl)
{
Directory.CreateDirectory(outPath);
Process rifeNcnn = OSUtils.NewProcess(!OSUtils.ShowHiddenCmd());
AiStarted(rifeNcnn, 1500, inPath);
SetProgressCheck(outPath, 2);
string uhdStr = await InterpolateUtils.UseUHD() ? "-u" : "";
string ttaStr = Config.GetBool("rifeNcnnUseTta", false) ? "-x" : "";
rifeNcnn.StartInfo.Arguments = $"{OSUtils.GetCmdArg()} cd /D {PkgUtils.GetPkgFolder(Packages.rifeNcnn).Wrap()} & rife-ncnn-vulkan.exe " +
$" -v -i {inPath.Wrap()} -o {outPath.Wrap()} -m {mdl.ToLower()} {ttaStr} {uhdStr} -g {Config.Get("ncnnGpus")} -f {GetNcnnPattern()} -j {GetNcnnThreads()}";
Logger.Log("cmd.exe " + rifeNcnn.StartInfo.Arguments, true);
if (!OSUtils.ShowHiddenCmd())
{
rifeNcnn.OutputDataReceived += (sender, outLine) => { LogOutput("[O] " + outLine.Data, "rife-ncnn-log"); };
rifeNcnn.ErrorDataReceived += (sender, outLine) => { LogOutput("[E] " + outLine.Data, "rife-ncnn-log", true); };
}
rifeNcnn.Start();
if (!OSUtils.ShowHiddenCmd())
{
rifeNcnn.BeginOutputReadLine();
rifeNcnn.BeginErrorReadLine();
}
while (!rifeNcnn.HasExited) await Task.Delay(1);
}
public static async Task RunDainNcnn(string framesPath, string outPath, float factor, string mdl, int tilesize)
{
await RunDainNcnnProcess(framesPath, outPath, factor, mdl, tilesize);
if (!Interpolate.canceled && Interpolate.current.alpha)
{
InterpolateUtils.progressPaused = true;
Logger.Log("Interpolating alpha channel...");
await RunDainNcnnProcess(framesPath + Paths.alphaSuffix, outPath + Paths.alphaSuffix, factor, mdl, tilesize);
}
await AiFinished("DAIN");
}
public static async Task RunDainNcnnProcess (string framesPath, string outPath, float factor, string mdl, int tilesize)
{
string dainDir = Path.Combine(Paths.GetPkgPath(), Path.GetFileNameWithoutExtension(Packages.dainNcnn.fileName));
Directory.CreateDirectory(outPath);
Process dain = OSUtils.NewProcess(!OSUtils.ShowHiddenCmd());
AiStarted(dain, 1500);
SetProgressCheck(outPath, factor);
int targetFrames = ((IOUtils.GetAmountOfFiles(lastInPath, false, "*.png") * factor).RoundToInt()) - (factor.RoundToInt() - 1); // TODO: Won't work with fractional factors
string args = $" -v -i {framesPath.Wrap()} -o {outPath.Wrap()} -n {targetFrames} -m {mdl.ToLower()}" +
$" -t {GetNcnnTilesize(tilesize)} -g {Config.Get("ncnnGpus")} -f {GetNcnnPattern()} -j 2:1:2";
dain.StartInfo.Arguments = $"{OSUtils.GetCmdArg()} cd /D {dainDir.Wrap()} & dain-ncnn-vulkan.exe {args}";
Logger.Log("Running DAIN...", false);
Logger.Log("cmd.exe " + dain.StartInfo.Arguments, true);
if (!OSUtils.ShowHiddenCmd())
{
dain.OutputDataReceived += (sender, outLine) => { LogOutput("[O] " + outLine.Data, "dain-ncnn-log"); };
dain.ErrorDataReceived += (sender, outLine) => { LogOutput("[E] " + outLine.Data, "dain-ncnn-log", true); };
}
dain.Start();
if (!OSUtils.ShowHiddenCmd())
{
dain.BeginOutputReadLine();
dain.BeginErrorReadLine();
}
while (!dain.HasExited)
await Task.Delay(100);
}
static void LogOutput (string line, string logFilename, bool err = false)
{
if (string.IsNullOrWhiteSpace(line) || line.Length < 6)
return;
Logger.LogToFile(line, false, logFilename);
if (line.Contains("ff:nocuda-cpu"))
Logger.Log("WARNING: CUDA-capable GPU device is not available, running on CPU instead!");
if (!hasShownError && err && line.ToLower().Contains("out of memory"))
{
hasShownError = true;
InterpolateUtils.ShowMessage($"Your GPU ran out of VRAM! Please try a video with a lower resolution or use the Max Video Size option in the settings.\n\n{line}", "Error");
}
if (!hasShownError && err && line.ToLower().Contains("modulenotfounderror"))
{
hasShownError = true;
InterpolateUtils.ShowMessage($"A python module is missing.\nCheck {logFilename} for details.\n\n{line}", "Error");
if(!Python.HasEmbeddedPyFolder())
Process.Start("https://github.com/n00mkrad/flowframes/blob/main/PythonDependencies.md");
}
if (!hasShownError && line.ToLower().Contains("no longer supports this gpu"))
{
hasShownError = true;
InterpolateUtils.ShowMessage($"Your GPU seems to be outdated and is not supported!\n\n{line}", "Error");
}
if (!hasShownError && err && (line.Contains("RuntimeError") || line.Contains("ImportError") || line.Contains("OSError")))
{
hasShownError = true;
InterpolateUtils.ShowMessage($"A python error occured during interpolation!\nCheck {logFilename} for details.\n\n{line}", "Error");
}
if (!hasShownError && err && line.Contains("vk") && line.Contains(" failed"))
{
hasShownError = true;
string dain = (Interpolate.current.ai.aiName == Networks.dainNcnn.aiName) ? "\n\nTry reducing the tile size in the AI settings." : "";
InterpolateUtils.ShowMessage($"A Vulkan error occured during interpolation!\n\n{line}{dain}", "Error");
}
if (!hasShownError && err && line.Contains("vkAllocateMemory failed"))
{
hasShownError = true;
bool usingDain = (Interpolate.current.ai.aiName == Networks.dainNcnn.aiName);
string msg = usingDain ? "\n\nTry reducing the tile size in the AI settings." : "Try a lower resolution (Settings -> Max Video Size).";
InterpolateUtils.ShowMessage($"Vulkan ran out of memory!\n\n{line}{msg}", "Error");
}
if (!hasShownError && err && line.Contains("invalid gpu device"))
{
hasShownError = true;
InterpolateUtils.ShowMessage($"A Vulkan error occured during interpolation!\n\n{line}\n\nAre your GPU IDs set correctly?", "Error");
}
if (hasShownError)
Interpolate.Cancel();
}
static string GetNcnnPattern ()
{
return $"%0{Padding.interpFrames}d.{InterpolateUtils.GetOutExt()}";
}
static string GetNcnnTilesize(int tilesize)
{
int gpusAmount = Config.Get("ncnnGpus").Split(',').Length;
string tilesizeStr = $"{tilesize}";
for (int i = 1; i < gpusAmount; i++)
tilesizeStr += $",{tilesize}";
return tilesizeStr;
}
static string GetNcnnThreads ()
{
int gpusAmount = Config.Get("ncnnGpus").Split(',').Length;
int procThreads = Config.GetInt("ncnnThreads");
string progThreadsStr = $"{procThreads}";
for (int i = 1; i < gpusAmount; i++)
progThreadsStr += $",{procThreads}";
return $"4:{progThreadsStr}:4"; ;
}
}
}

View File

@@ -1,76 +0,0 @@
using NvAPIWrapper;
using NvAPIWrapper.GPU;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Flowframes.OS
{
class NvApi
{
static PhysicalGPU gpu;
public static async void Init()
{
try
{
NVIDIA.Initialize();
PhysicalGPU[] gpus = PhysicalGPU.GetPhysicalGPUs();
if (gpus.Length == 0)
return;
gpu = gpus[0];
Logger.Log($"Initialized NvApi. GPU: {gpu.FullName}");
}
catch (Exception e)
{
Logger.Log($"Failed to initialize NvApi: {e.Message}\nIgnore this if you don't have an Nvidia GPU.");
}
}
public static float GetVramGb ()
{
try
{
return (gpu.MemoryInformation.AvailableDedicatedVideoMemoryInkB / 1000f / 1024f);
}
catch (Exception e)
{
return 0f;
}
}
public static float GetFreeVramGb()
{
try
{
return (gpu.MemoryInformation.CurrentAvailableDedicatedVideoMemoryInkB / 1000f / 1024f);
}
catch (Exception e)
{
return 0f;
}
}
public static string GetGpuName()
{
try
{
NVIDIA.Initialize();
PhysicalGPU[] gpus = PhysicalGPU.GetPhysicalGPUs();
if (gpus.Length == 0)
return "";
return gpus[0].FullName;
}
catch
{
return "";
}
}
}
}

View File

@@ -1,139 +0,0 @@
using System.Collections.Generic;
using System.Text;
using System.Security.Principal;
using System;
using System.Diagnostics;
using System.Management;
using Flowframes.IO;
using DiskDetector;
using DiskDetector.Models;
using Microsoft.VisualBasic.Devices;
namespace Flowframes.OS
{
class OSUtils
{
public static bool IsUserAdministrator()
{
//bool value to hold our return value
bool isAdmin;
WindowsIdentity user = null;
try
{
//get the currently logged in user
user = WindowsIdentity.GetCurrent();
WindowsPrincipal principal = new WindowsPrincipal(user);
isAdmin = principal.IsInRole(WindowsBuiltInRole.Administrator);
}
catch (UnauthorizedAccessException ex)
{
isAdmin = false;
}
catch (Exception ex)
{
isAdmin = false;
}
finally
{
if (user != null)
user.Dispose();
}
return isAdmin;
}
public static Process SetStartInfo(Process proc, bool hidden, string filename = "cmd.exe")
{
proc.StartInfo.UseShellExecute = !hidden;
proc.StartInfo.RedirectStandardOutput = hidden;
proc.StartInfo.RedirectStandardError = hidden;
proc.StartInfo.CreateNoWindow = hidden;
proc.StartInfo.FileName = filename;
return proc;
}
public static Process NewProcess(bool hidden, string filename = "cmd.exe")
{
Process proc = new Process();
return SetStartInfo(proc, hidden, filename);
}
public static void KillProcessTree(int pid)
{
ManagementObjectSearcher processSearcher = new ManagementObjectSearcher
("Select * From Win32_Process Where ParentProcessID=" + pid);
ManagementObjectCollection processCollection = processSearcher.Get();
try
{
Process proc = Process.GetProcessById(pid);
if (!proc.HasExited) proc.Kill();
}
catch (ArgumentException)
{
// Process already exited.
}
if (processCollection != null)
{
foreach (ManagementObject mo in processCollection)
{
KillProcessTree(Convert.ToInt32(mo["ProcessID"])); //kill child processes(also kills childrens of childrens etc.)
}
}
}
public static string GetCmdArg()
{
bool stayOpen = Config.GetInt("cmdDebugMode") == 2;
if (stayOpen)
return "/K";
else
return "/C";
}
public static bool ShowHiddenCmd()
{
return Config.GetInt("cmdDebugMode") > 0;
}
public static bool DriveIsSSD(string path)
{
try
{
var detectedDrives = Detector.DetectFixedDrives(QueryType.SeekPenalty);
if (detectedDrives.Count != 0)
{
char pathDriveLetter = (path[0].ToString().ToUpper())[0];
foreach (var detectedDrive in detectedDrives)
{
if (detectedDrive.DriveLetter == pathDriveLetter && detectedDrive.HardwareType.ToString().ToLower().Trim() == "ssd")
return true;
}
}
}
catch (Exception e)
{
Logger.Log("Failed to detect drive type: " + e.Message);
return true; // Default to SSD on fail
}
return false;
}
public static bool HasNonAsciiChars(string str)
{
return (Encoding.UTF8.GetByteCount(str) != str.Length);
}
public static int GetFreeRamMb ()
{
try
{
return (int)(new ComputerInfo().AvailablePhysicalMemory / 1048576);
}
catch
{
return 1000;
}
}
}
}

View File

@@ -1,182 +0,0 @@
using Flowframes.IO;
using Flowframes.MiscUtils;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Flowframes.OS
{
class Python
{
static bool hasCheckedSysPy = false;
static bool sysPyInstalled = false;
public static string compactOutput;
public static async Task CheckCompression ()
{
if(HasEmbeddedPyFolder() && (Config.Get("compressedPyVersion") != Updater.GetInstalledVer().ToString()))
{
Program.mainForm.SetWorking(true, false);
Stopwatch sw = new Stopwatch();
sw.Restart();
try
{
bool shownPatienceMsg = false;
Logger.Log("Compressing python runtime. This only needs to be done once.");
compactOutput = "";
Process compact = OSUtils.NewProcess(true);
compact.StartInfo.Arguments = $"/C compact /C /S:{GetPyFolder().Wrap()} /EXE:LZX";
compact.OutputDataReceived += new DataReceivedEventHandler(CompactOutputHandler);
compact.ErrorDataReceived += new DataReceivedEventHandler(CompactOutputHandler);
compact.Start();
compact.BeginOutputReadLine();
compact.BeginErrorReadLine();
while (!compact.HasExited)
{
await Task.Delay(500);
if(sw.ElapsedMilliseconds > 10000)
{
Logger.Log($"This can take up to a few minutes... (Elapsed: {FormatUtils.Time(sw.Elapsed)})", false, shownPatienceMsg);
shownPatienceMsg = true;
await Task.Delay(500);
}
}
Config.Set("compressedPyVersion", Updater.GetInstalledVer().ToString());
Logger.Log("Done compressing python runtime.");
Logger.WriteToFile(compactOutput, true, "compact");
}
catch { }
Program.mainForm.SetWorking(false);
}
}
static void CompactOutputHandler (object sendingProcess, DataReceivedEventArgs outLine)
{
if (outLine == null || outLine.Data == null)
return;
string line = outLine.Data;
compactOutput = compactOutput + line + "\n";
}
public static string GetPyCmd ()
{
if (HasEmbeddedPyFolder())
{
Logger.Log("Using embedded Python runtime.");
return Path.Combine(GetPyFolder(), "python.exe").Wrap();
}
else
{
if (IsSysPyInstalled())
{
return "python";
}
else
{
MessageBox.Show("System python installation not found!\nPlease install Python or download the package from the package installer.");
Interpolate.Cancel("Neither the Flowframes Python Runtime nor System Python installation could be found!");
}
}
return "";
}
public static bool HasEmbeddedPyFolder ()
{
return (Directory.Exists(GetPyFolder()) && IOUtils.GetDirSize(GetPyFolder(), false) > 1024 * 1024 * 5);
}
public static string GetPyFolder ()
{
if (Directory.Exists(Path.Combine(Paths.GetPkgPath(), "py-amp")))
return Path.Combine(Paths.GetPkgPath(), "py-amp");
if (Directory.Exists(Path.Combine(Paths.GetPkgPath(), "py-tu")))
return Path.Combine(Paths.GetPkgPath(), "py-tu");
return "";
}
public static bool IsPytorchReady ()
{
string torchVer = GetPytorchVer();
if (!string.IsNullOrWhiteSpace(torchVer) && torchVer.Length <= 35)
return true;
else
return false;
}
static string GetPytorchVer()
{
try
{
Process py = OSUtils.NewProcess(true);
py.StartInfo.Arguments = "\"/C\" " + GetPyCmd() + " -c \"import torch; print(torch.__version__)\"";
Logger.Log("[DepCheck] CMD: " + py.StartInfo.Arguments);
py.Start();
py.WaitForExit();
string output = py.StandardOutput.ReadToEnd();
string err = py.StandardError.ReadToEnd();
if (!string.IsNullOrWhiteSpace(err)) output += "\n" + err;
Logger.Log("[DepCheck] Pytorch Check Output: " + output.Trim());
return output;
}
catch
{
return "";
}
}
public static bool IsSysPyInstalled ()
{
if (hasCheckedSysPy)
return sysPyInstalled;
bool isInstalled = false;
Logger.Log("Checking if system Python is available...", true);
string sysPyVer = GetSysPyVersion();
if (!string.IsNullOrWhiteSpace(sysPyVer) && !sysPyVer.ToLower().Contains("not found") && sysPyVer.Length <= 35)
{
isInstalled = true;
Logger.Log("Using Python installation: " + sysPyVer, true);
}
hasCheckedSysPy = true;
sysPyInstalled = isInstalled;
return sysPyInstalled;
}
static string GetSysPyVersion()
{
string pythonOut = GetSysPythonOutput();
Logger.Log("[DepCheck] System Python Check Output: " + pythonOut.Trim(), true);
try
{
string ver = pythonOut.Split('(')[0].Trim();
Logger.Log("[DepCheck] Sys Python Ver: " + ver, true);
return ver;
}
catch
{
return "";
}
}
static string GetSysPythonOutput()
{
Process py = OSUtils.NewProcess(true);
py.StartInfo.Arguments = "/C python -V";
Logger.Log("[DepCheck] CMD: " + py.StartInfo.Arguments, true);
py.Start();
py.WaitForExit();
string output = py.StandardOutput.ReadToEnd();
string err = py.StandardError.ReadToEnd();
return output + "\n" + err;
}
}
}

View File

@@ -1,135 +0,0 @@
using Flowframes.Data;
using Flowframes.Forms;
using Flowframes.IO;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Flowframes.OS
{
class Updater
{
public enum VersionCompareResult { Older, Newer, Equal };
public static string latestVerUrl = "https://dl.nmkd.de/flowframes/exe/ver.ini";
public static Version GetInstalledVer()
{
try
{
string verStr = IOUtils.ReadLines(Paths.GetVerPath())[0];
return new Version(verStr);
}
catch (Exception e)
{
Logger.Log("Error getting installed version: " + e.Message);
return new Version(0, 0, 0);
}
}
public static VersionCompareResult CompareVersions (Version currentVersion, Version newVersion)
{
Logger.Log($"Checking if {newVersion} > {currentVersion}", true);
int result = newVersion.CompareTo(currentVersion);
if (result > 0)
{
Logger.Log($"{newVersion} is newer than {currentVersion}.", true);
return VersionCompareResult.Newer;
}
if (result < 0)
{
Logger.Log($"{newVersion} is older than {currentVersion}.", true);
return VersionCompareResult.Older;
}
Logger.Log($"{newVersion} is equal to {currentVersion}.", true);
return VersionCompareResult.Equal;
}
public static Version GetLatestVer (bool patreon)
{
var client = new WebClient();
int line = patreon ? 0 : 2;
return new Version(client.DownloadString(latestVerUrl).SplitIntoLines()[line]);
}
public static string GetLatestVerLink(bool patreon)
{
int line = patreon ? 1 : 3;
var client = new WebClient();
try
{
return client.DownloadString(latestVerUrl).SplitIntoLines()[line].Trim();
}
catch
{
Logger.Log("Failed to get latest version link from ver.ini!", true);
return "";
}
}
public static async Task UpdateTo (int version, UpdaterForm form = null)
{
Logger.Log("Updating to " + version, true);
string savePath = Path.Combine(IOUtils.GetExeDir(), $"FlowframesV{version}");
try
{
var client = new WebClient();
client.DownloadProgressChanged += async (sender, args) =>
{
if (form != null && (args.ProgressPercentage % 5 == 0))
{
Logger.Log("Downloading update... " + args.ProgressPercentage, true);
form.SetProgLabel(args.ProgressPercentage, $"Downloading latest version... {args.ProgressPercentage}%");
await Task.Delay(20);
}
};
client.DownloadFileCompleted += (sender, args) =>
{
form.SetProgLabel(100f, $"Downloading latest version... 100%");
};
await client.DownloadFileTaskAsync(new Uri($"https://dl.nmkd.de/flowframes/exe/{version}/Flowframes.exe"), savePath);
}
catch (Exception e)
{
MessageBox.Show("Error: Failed to download update.\n\n" + e.Message, "Error");
Logger.Log("Updater Error during download: " + e.Message, true);
return;
}
try
{
Logger.Log("Installing v" + version, true);
string runningExePath = IOUtils.GetExe();
string oldExePath = runningExePath + ".old";
IOUtils.TryDeleteIfExists(oldExePath);
File.Move(runningExePath, oldExePath);
File.Move(savePath, runningExePath);
}
catch (Exception e)
{
MessageBox.Show("Error: Failed to install update.\n\n" + e.Message, "Error");
Logger.Log("Updater Error during install: " + e.Message, true);
return;
}
form.SetProgLabel(101f, $"Update downloaded.");
await Task.Delay(20);
MessageBox.Show("Update was installed!\nFlowframes will now close. Restart it to use the new version.", "Message");
Application.Exit();
}
public static async Task AsyncUpdateCheck ()
{
Version installed = GetInstalledVer();
Version latestPat = GetLatestVer(true);
Version latestFree = GetLatestVer(false);
Logger.Log($"You are running Flowframes {installed}. The latest Patreon version is {latestPat}, the latest free version is {latestFree}.");
}
}
}

View File

@@ -1,46 +0,0 @@
using Flowframes.Data;
using Flowframes.IO;
using Flowframes.OS;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Flowframes
{
static class Program
{
public static Form1 mainForm;
public static bool busy = false;
public static string lastInputPath;
public static bool lastInputPathIsSsd;
public static Queue<InterpSettings> batchQueue = new Queue<InterpSettings>();
[STAThread]
static void Main()
{
Config.Init();
if (Config.GetBool("delLogsOnStartup"))
IOUtils.DeleteContentsOfDir(Paths.GetLogPath()); // Clear out older logs not from this session
string oldExePath = IOUtils.GetExe() + ".old";
IOUtils.TryDeleteIfExists(oldExePath);
Networks.Init();
NvApi.Init();
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
mainForm = new Form1();
Application.Run(mainForm);
}
}
}

View File

@@ -1,38 +0,0 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("Flowframes")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Flowframes")]
[assembly: AssemblyCopyright("Copyright © 2020")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: System.Resources.NeutralResourcesLanguage("en-US")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("389e42dd-a163-49d7-9e0a-ae41090a07b3")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

View File

@@ -1,243 +0,0 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace Flowframes.Properties {
using System;
/// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary>
// This class was auto-generated by the StronglyTypedResourceBuilder
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Resources {
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal Resources() {
}
/// <summary>
/// Returns the cached ResourceManager instance used by this class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Flowframes.Properties.Resources", typeof(Resources).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set {
resourceCulture = value;
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap baseline_create_white_18dp {
get {
object obj = ResourceManager.GetObject("baseline_create_white_18dp", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap baseline_create_white_18dp_semiTransparent {
get {
object obj = ResourceManager.GetObject("baseline_create_white_18dp-semiTransparent", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap baseline_fact_check_white_48dp {
get {
object obj = ResourceManager.GetObject("baseline_fact_check_white_48dp", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap baseline_image_white_48dp {
get {
object obj = ResourceManager.GetObject("baseline_image_white_48dp", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap baseline_image_white_48dp_4x {
get {
object obj = ResourceManager.GetObject("baseline_image_white_48dp-4x", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap baseline_image_white_48dp_4x_25pcAlpha {
get {
object obj = ResourceManager.GetObject("baseline_image_white_48dp-4x-25pcAlpha", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap baseline_queue_white_48dp {
get {
object obj = ResourceManager.GetObject("baseline_queue_white_48dp", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap baseline_settings_white_48dp {
get {
object obj = ResourceManager.GetObject("baseline_settings_white_48dp", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap baseline_system_update_alt_white_48dp {
get {
object obj = ResourceManager.GetObject("baseline_system_update_alt_white_48dp", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap discordIco {
get {
object obj = ResourceManager.GetObject("discordIco", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap discordIcoColored {
get {
object obj = ResourceManager.GetObject("discordIcoColored", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap flowframesIcoNew_512px {
get {
object obj = ResourceManager.GetObject("flowframesIcoNew_512px", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap patreon256px {
get {
object obj = ResourceManager.GetObject("patreon256px", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap patreon256pxColored {
get {
object obj = ResourceManager.GetObject("patreon256pxColored", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap paypal256px {
get {
object obj = ResourceManager.GetObject("paypal256px", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap questmark_72px_bordeer {
get {
object obj = ResourceManager.GetObject("questmark-72px-bordeer", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap separatorTest1 {
get {
object obj = ResourceManager.GetObject("separatorTest1", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// </summary>
internal static byte[] x64_7za {
get {
object obj = ResourceManager.GetObject("x64_7za", resourceCulture);
return ((byte[])(obj));
}
}
}
}

View File

@@ -1,175 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<data name="baseline_image_white_48dp-4x" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\baseline_image_white_48dp-4x.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="baseline_queue_white_48dp" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\baseline_queue_white_48dp.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="x64_7za" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\7za.exe;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="baseline_fact_check_white_48dp" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\baseline_fact_check_white_48dp.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="paypal256px" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\paypal256px.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="baseline_system_update_alt_white_48dp" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\baseline_system_update_alt_white_48dp.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="patreon256px" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\patreon256px.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="questmark-72px-bordeer" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\questmark-72px-bordeer.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="baseline_create_white_18dp" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\baseline_create_white_18dp.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="discordIco" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\discordIco.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="patreon256pxColored" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\patreon256pxColored.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="discordIcoColored" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\discordIcoColored.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="separatorTest1" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\separatorTest1.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="baseline_image_white_48dp" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\baseline_image_white_48dp.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="baseline_create_white_18dp-semiTransparent" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\baseline_create_white_18dp-semiTransparent.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="baseline_settings_white_48dp" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\baseline_settings_white_48dp.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="baseline_image_white_48dp-4x-25pcAlpha" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\baseline_image_white_48dp-4x-25pcAlpha.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="flowframesIcoNew_512px" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\flowframesIcoNew-512px.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
</root>

View File

@@ -1,26 +0,0 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace Flowframes.Properties {
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.7.0.0")]
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
public static Settings Default {
get {
return defaultInstance;
}
}
}
}

View File

@@ -1,7 +0,0 @@
<?xml version='1.0' encoding='utf-8'?>
<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)">
<Profiles>
<Profile Name="(Default)" />
</Profiles>
<Settings />
</SettingsFile>

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 431 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 206 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 485 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 597 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 371 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 334 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

View File

@@ -1,78 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Flowframes.UI
{
class GetWebInfo
{
public static async Task LoadNews (Label newsLabel)
{
string url = $"http://dl.nmkd.de/flowframes/changelog.txt";
var client = new WebClient();
var str = await client.DownloadStringTaskAsync(new Uri(url));
newsLabel.Text = str;
}
public static async Task LoadPatronList(Label patronsLabel)
{
string url = $"http://dl.nmkd.de/flowframes/patreon.txt";
var client = new WebClient();
var str = await client.DownloadStringTaskAsync(new Uri(url));
patronsLabel.Text = str;
}
public static async Task LoadPatronListCsv(Label patronsLabel)
{
string url = $"http://dl.nmkd.de/flowframes/patrons.csv";
var client = new WebClient();
var csvData = await client.DownloadStringTaskAsync(new Uri(url));
patronsLabel.Text = ParsePatreonCsv(csvData);
}
public static string ParsePatreonCsv(string csvData)
{
try
{
List<string> goldPatrons = new List<string>();
List<string> silverPatrons = new List<string>();
string str = "Gold:\n";
string[] lines = csvData.SplitIntoLines();
for (int i = 0; i < lines.Length; i++)
{
string line = lines[i].Replace(";", ",");
string[] values = line.Split(',');
if (i == 0 || line.Length < 10 || values.Length < 5) continue;
string name = values[0];
float amount = float.Parse(values[7], System.Globalization.CultureInfo.InvariantCulture);
if (amount >= 4.5f)
{
if (amount >= 11f)
goldPatrons.Add(name);
else
silverPatrons.Add(name);
}
}
foreach (string pat in goldPatrons)
str += pat + "\n";
str += "\nSilver:\n";
foreach (string pat in silverPatrons)
str += pat + "\n";
return str;
}
catch (Exception e)
{
Logger.Log("Failed to parse Patreon CSV: " + e.Message, true);
return "Failed to load patron list.";
}
}
}
}

Some files were not shown because too many files have changed in this diff Show More