1
1
mirror of https://github.com/neosubhamoy/neodlp.git synced 2026-05-06 19:45:50 +05:30

10 Commits

7 changed files with 150 additions and 23 deletions

4
.github/FUNDING.yml vendored
View File

@@ -1,6 +1,6 @@
# These are supported funding model platforms
github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
github: neosubhamoy
patreon: # Replace with a single Patreon username
open_collective: # Replace with a single Open Collective username
ko_fi: # Replace with a single Ko-fi username
@@ -10,6 +10,6 @@ liberapay: # Replace with a single Liberapay username
issuehunt: # Replace with a single IssueHunt username
lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
polar: # Replace with a single Polar username
buy_me_a_coffee: neosubhamoy
buy_me_a_coffee: # Replace with a single Buy Me a Coffee username
thanks_dev: # Replace with a single thanks.dev username
custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']

View File

@@ -2,6 +2,12 @@ on:
push:
tags:
- 'v*.*.*'
workflow_dispatch:
inputs:
tag_name:
description: 'Draft release tag (e.g. v0.4.5-test)'
required: true
default: 'v0.0.0-test'
name: 🚀 Release on GitHub
jobs:
@@ -13,15 +19,29 @@ jobs:
matrix:
include:
- platform: 'macos-latest'
target_platform: 'darwin'
target_arch: 'arm64'
args: '--target aarch64-apple-darwin --config ./src-tauri/tauri.macos-aarch64.conf.json'
- platform: 'macos-latest'
target_platform: 'darwin'
target_arch: 'x64'
args: '--target x86_64-apple-darwin --config ./src-tauri/tauri.macos-x86_64.conf.json'
- platform: 'ubuntu-22.04'
target_platform: 'linux'
target_arch: 'x64'
args: '--target x86_64-unknown-linux-gnu --config ./src-tauri/tauri.linux-x86_64.conf.json'
- platform: 'ubuntu-22.04-arm'
target_platform: 'linux'
target_arch: 'arm64'
args: '--target aarch64-unknown-linux-gnu --config ./src-tauri/tauri.linux-aarch64.conf.json'
- platform: 'windows-latest'
target_platform: 'win32'
target_arch: 'x64'
args: ''
- platform: 'windows-11-arm'
target_platform: 'win32'
target_arch: 'arm64'
args: '--target aarch64-pc-windows-msvc'
runs-on: ${{ matrix.platform }}
steps:
- name: 🚚 Checkout repository
@@ -53,20 +73,20 @@ jobs:
run: npm install
- name: 📥 Download binaries
run: npm run download
run: npm run download -- ${{ matrix.target_platform }} ${{ matrix.target_arch }}
- name: 📄 Read and Process CHANGELOG (Unix)
if: matrix.platform != 'windows-latest'
if: matrix.platform != 'windows-latest' && matrix.platform != 'windows-11-arm'
id: changelog_unix
shell: bash
run: |
if [ -f CHANGELOG.md ]; then
# Extract version number from tag
VERSION_NUM=$(echo "${{ github.ref_name }}" | sed -E 's/^v([0-9]+\.[0-9]+\.[0-9]+)(-.*)?$/\1/')
VERSION_NUM=$(echo "${{ inputs.tag_name || github.ref_name }}" | sed -E 's/^v([0-9]+\.[0-9]+\.[0-9]+)(-.*)?$/\1/')
# Read and replace placeholders
CONTENT=$(cat CHANGELOG.md)
CONTENT=${CONTENT//<release_tag>/${{ github.ref_name }}}
CONTENT=${CONTENT//<release_tag>/${{ inputs.tag_name || github.ref_name }}}
CONTENT=${CONTENT//<version>/$VERSION_NUM}
echo "content<<EOF" >> $GITHUB_OUTPUT
@@ -77,17 +97,17 @@ jobs:
fi
- name: 📄 Read and Process CHANGELOG (Windows)
if: matrix.platform == 'windows-latest'
if: matrix.platform == 'windows-latest' || matrix.platform == 'windows-11-arm'
id: changelog_windows
shell: pwsh
run: |
if (Test-Path "CHANGELOG.md") {
# Extract version number from tag
$version_num = "${{ github.ref_name }}" -replace '^v([0-9]+\.[0-9]+\.[0-9]+)(-.*)?$','$1'
$version_num = "${{ inputs.tag_name || github.ref_name }}" -replace '^v([0-9]+\.[0-9]+\.[0-9]+)(-.*)?$','$1'
# Read and replace placeholders
$content = Get-Content -Path CHANGELOG.md -Raw
$content = $content -replace '<release_tag>', "${{ github.ref_name }}"
$content = $content -replace '<release_tag>', "${{ inputs.tag_name || github.ref_name }}"
$content = $content -replace '<version>', "$version_num"
"content<<EOF" >> $env:GITHUB_OUTPUT
@@ -104,9 +124,9 @@ jobs:
TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }}
TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY_PASSWORD }}
with:
tagName: ${{ github.ref_name }}
releaseName: ${{ github.event.repository.name }}-${{ github.ref_name }}
releaseBody: ${{ matrix.platform == 'windows-latest' && steps.changelog_windows.outputs.content || steps.changelog_unix.outputs.content }}
tagName: ${{ inputs.tag_name || github.ref_name }}
releaseName: ${{ github.event.repository.name }}-${{ inputs.tag_name || github.ref_name }}
releaseBody: ${{ (matrix.platform == 'windows-latest' || matrix.platform == 'windows-11-arm') && steps.changelog_windows.outputs.content || steps.changelog_unix.outputs.content }}
releaseDraft: true
prerelease: false
includeUpdaterJson: true

View File

@@ -34,12 +34,10 @@
| Architecture | Windows (msi) ⬆️ | Windows (exe) ⬆️ | Linux (deb) | Linux (rpm) | Linux (AppImage) ⬆️ | MacOS (dmg) ⬆️ | MacOS (app) ⬆️ |
| :---- | :---- | :---- | :---- | :---- | :---- | :---- | :---- |
| x86_64 | [Download](https://github.com/neosubhamoy/neodlp/releases/download/<release_tag>/NeoDLP_<version>_x64_en-US.msi) | [Download](https://github.com/neosubhamoy/neodlp/releases/download/<release_tag>/NeoDLP_<version>_x64-setup.exe) | [Download](https://github.com/neosubhamoy/neodlp/releases/download/<release_tag>/NeoDLP_<version>_amd64.deb) | [Download](https://github.com/neosubhamoy/neodlp/releases/download/<release_tag>/NeoDLP-<version>-1.x86_64.rpm) | 🚫 [Download](https://github.com/neosubhamoy/neodlp/releases/download/<release_tag>/NeoDLP_<version>_amd64.AppImage) | [Download](https://github.com/neosubhamoy/neodlp/releases/download/<release_tag>/NeoDLP_<version>_x64.dmg) | [Download](https://github.com/neosubhamoy/neodlp/releases/download/<release_tag>/NeoDLP_x64.app.tar.gz) |
| ARM64 | N/A | 🪟 [Download](https://github.com/neosubhamoy/neodlp/releases/download/<release_tag>/NeoDLP_<version>_x64-setup.exe) | [Download](https://github.com/neosubhamoy/neodlp/releases/download/<release_tag>/NeoDLP_<version>_arm64.deb) | [Download](https://github.com/neosubhamoy/neodlp/releases/download/<release_tag>/NeoDLP-<version>-1.aarch64.rpm) | N/A | ⚠️ [Download](https://github.com/neosubhamoy/neodlp/releases/download/<release_tag>/NeoDLP_<version>_aarch64.dmg) | ⚠️ [Download](https://github.com/neosubhamoy/neodlp/releases/download/<release_tag>/NeoDLP_aarch64.app.tar.gz) |
| ARM64 | [Download](https://github.com/neosubhamoy/neodlp/releases/download/<release_tag>/NeoDLP_<version>_arm64_en-US.msi) | [Download](https://github.com/neosubhamoy/neodlp/releases/download/<release_tag>/NeoDLP_<version>_arm64-setup.exe) | [Download](https://github.com/neosubhamoy/neodlp/releases/download/<release_tag>/NeoDLP_<version>_arm64.deb) | [Download](https://github.com/neosubhamoy/neodlp/releases/download/<release_tag>/NeoDLP-<version>-1.aarch64.rpm) | N/A | ⚠️ [Download](https://github.com/neosubhamoy/neodlp/releases/download/<release_tag>/NeoDLP_<version>_aarch64.dmg) | ⚠️ [Download](https://github.com/neosubhamoy/neodlp/releases/download/<release_tag>/NeoDLP_aarch64.app.tar.gz) |
> ⬆️ icon indicates this packaging format supports in-built app-updater
> 🪟 Windows x86_64 binary also works on ARM64 (Windows on ARM) devices with emulation (Not planning to release native Windows ARM64 build anytime soon as, x86_64 one works fine on ARM64 without noticeable performance impact)
> 🚫 Linux AppImage builds are experimental and does not support neodlp's browser intergration features and yt-dlp updates due to it's limitations. Also, don't run the AppImage with portable (.home, .config) folders, it will break things (it is highly recommended to use native [DEB, RPM, AUR] builds if possible for the full experiance, otherwise AppImages are good for trying out NeoDLP without installing)
> ⚠️ MacOS ARM64 binary downloads are experimental and may not open on Apple Silicon Macs if downloaded from browser (You will get 'Damaged File' error) it's because the binaries are not signed (signing MacOS binaries requires 99$/year Apple Developer Account subscription, which I can't afford RN!) and Apple Silicon Macs don't allow unsigned apps (downloaded from browser) to be installed on the system. If you want to use NeoDLP on your Apple Silicon Macs, There are few ways you can bypass these restrictions:

View File

@@ -10,7 +10,7 @@ Cross-platform Video/Audio Downloader Desktop App based on YT-DLP with Modern UI
[![github license](https://img.shields.io/github/license/neosubhamoy/neodlp?color=blue&style=for-the-badge)](https://github.com/neosubhamoy/neodlp/blob/main/LICENSE)
> [!TIP]
> **🥰 Liked this project? Please consider giving it a star (🌟) on github to show us your appreciation and help the algorythm recommend this project to even more awesome people like you!**
> **🥰 Liked this project? Please consider giving it a star (🌟) on github to show us your appreciation and help the algorithm recommend this project to even more awesome people like you!**
[![winget version](https://img.shields.io/winget/v/neosubhamoy.neodlp?color=lime-green&style=flat-square)](https://github.com/microsoft/winget-pkgs/tree/master/manifests/n/neosubhamoy/neodlp)
[![flathub version](https://img.shields.io/flathub/v/com.neosubhamoy.neodlp?color=lime-green&style=flat-square)](https://flathub.org/en/apps/com.neosubhamoy.neodlp)

View File

@@ -17,6 +17,10 @@
"tauri:build:macos-x64": "npm run tauri build -- --config ./src-tauri/tauri.macos-x86_64.conf.json",
"tauri:dev:macos-arm64": "npm run tauri dev -- --config ./src-tauri/tauri.macos-aarch64.conf.json",
"tauri:build:macos-arm64": "npm run tauri build -- --config ./src-tauri/tauri.macos-aarch64.conf.json",
"tauri:dev:windows-x64": "npm run tauri dev -- --target x86_64-pc-windows-msvc",
"tauri:build:windows-x64": "npm run tauri build -- --target x86_64-pc-windows-msvc",
"tauri:dev:windows-arm64": "npm run tauri dev -- --target aarch64-pc-windows-msvc",
"tauri:build:windows-arm64": "npm run tauri build -- --target aarch64-pc-windows-msvc",
"download": "node ./scripts/download-bins.js"
},
"dependencies": {

View File

@@ -12,8 +12,23 @@ const downloadDir = path.join(projectRoot, 'src-tauri', 'resources', 'downloads'
const binDir = path.join(projectRoot, 'src-tauri', 'binaries');
const platform = os.platform();
const arch = os.arch();
const targetPlatform = process.argv[2];
const targetBin = process.argv[3];
const targetArch = process.argv[3];
const targetBin = process.argv[4];
function getArchesForBin(bin) {
const paths = [
...(bin.dest || []),
...((bin.archive && bin.archive.binDest) || [])
];
const arches = new Set();
for (const path of paths) {
if (path.includes('-x86_64-') || path.includes('-x64-')) arches.add('x64');
if (path.includes('-aarch64-') || path.includes('-arm64-')) arches.add('arm64');
}
return arches;
}
const versions = {
'yt-dlp': '2026.03.21.233500',
@@ -38,6 +53,19 @@ const binaries = {
path.join(downloadDir, 'yt-dlp-x86_64-pc-windows-msvc.exe')
]
},
{
name: 'yt-dlp-aarch64-pc-windows-msvc',
platform: 'win32',
url: `https://github.com/yt-dlp/yt-dlp-nightly-builds/releases${versions['yt-dlp'] === 'latest' ? '/latest' : ''}/download${versions['yt-dlp'] !== 'latest' ? '/'+versions['yt-dlp'] : ''}/yt-dlp_arm64.exe`,
src: path.join(downloadDir, 'yt-dlp-aarch64-pc-windows-msvc.exe'),
dest: [
path.join(binDir, 'yt-dlp-aarch64-pc-windows-msvc.exe')
],
archive: null,
cleanup: [
path.join(downloadDir, 'yt-dlp-aarch64-pc-windows-msvc.exe')
]
},
{
name: 'yt-dlp-x86_64-unknown-linux-gnu',
platform: 'linux',
@@ -102,6 +130,28 @@ const binaries = {
path.join(downloadDir, 'ffmpeg-master-latest-win64-gpl')
]
},
{
name: 'ffmpeg-ffprobe-aarch64-pc-windows-msvc',
platform: 'win32',
url: `https://github.com/yt-dlp/FFmpeg-Builds/releases${versions['ffmpeg-ffprobe'] === 'latest' ? '/latest' : ''}/download${versions['ffmpeg-ffprobe'] !== 'latest' ? '/'+versions['ffmpeg-ffprobe'] : ''}/ffmpeg-master-latest-winarm64-gpl.zip`,
src: path.join(downloadDir, 'ffmpeg-master-latest-winarm64-gpl.zip'),
dest: null,
archive: {
type: 'zip',
binSrc: [
path.join(downloadDir, 'ffmpeg-master-latest-winarm64-gpl', 'bin', 'ffmpeg.exe'),
path.join(downloadDir, 'ffmpeg-master-latest-winarm64-gpl', 'bin', 'ffprobe.exe')
],
binDest: [
path.join(binDir, 'ffmpeg-aarch64-pc-windows-msvc.exe'),
path.join(binDir, 'ffprobe-aarch64-pc-windows-msvc.exe')
]
},
cleanup: [
path.join(downloadDir, 'ffmpeg-master-latest-winarm64-gpl.zip'),
path.join(downloadDir, 'ffmpeg-master-latest-winarm64-gpl')
]
},
{
name: 'ffmpeg-ffprobe-x86_64-unknown-linux-gnu',
platform: 'linux',
@@ -256,6 +306,26 @@ const binaries = {
path.join(downloadDir, 'deno.exe')
]
},
{
name: 'deno-aarch64-pc-windows-msvc',
platform: 'win32',
url: `https://github.com/denoland/deno/releases${versions['deno'] === 'latest' ? '/latest' : ''}/download${versions['deno'] !== 'latest' ? '/v'+versions['deno'] : ''}/deno-aarch64-pc-windows-msvc.zip`,
src: path.join(downloadDir, 'deno-aarch64-pc-windows-msvc.zip'),
dest: null,
archive: {
type: 'zip',
binSrc: [
path.join(downloadDir, 'deno.exe')
],
binDest: [
path.join(binDir, 'deno-aarch64-pc-windows-msvc.exe')
]
},
cleanup: [
path.join(downloadDir, 'deno-aarch64-pc-windows-msvc.zip'),
path.join(downloadDir, 'deno.exe')
]
},
{
name: 'deno-x86_64-unknown-linux-gnu',
platform: 'linux',
@@ -358,6 +428,26 @@ const binaries = {
path.join(downloadDir, `aria2-${versions['aria2c']}-win-64bit-build1`)
]
},
{
name: 'aria2c-aarch64-pc-windows-msvc',
platform: 'win32',
url: `https://github.com/minnyres/aria2-windows-arm64/releases/download/v${versions['aria2c']}/aria2_${versions['aria2c']}_arm64.zip`,
src: path.join(downloadDir, `aria2_${versions['aria2c']}_arm64.zip`),
dest: null,
archive: {
type: 'zip',
binSrc: [
path.join(downloadDir, 'aria2c.exe')
],
binDest: [
path.join(binDir, 'aria2c-aarch64-pc-windows-msvc.exe')
]
},
cleanup: [
path.join(downloadDir, `aria2_${versions['aria2c']}_arm64.zip`),
path.join(downloadDir, 'aria2c.exe')
]
},
{
name: 'aria2c-x86_64-unknown-linux-gnu',
platform: 'linux',
@@ -406,7 +496,8 @@ const binaries = {
url: `https://github.com/jim60105/bgutil-ytdlp-pot-provider-rs/releases${versions['neodlp-pot'] === 'latest' ? '/latest' : ''}/download${versions['neodlp-pot'] !== 'latest' ? '/v'+versions['neodlp-pot'] : ''}/bgutil-pot-windows-x86_64.exe`,
src: path.join(downloadDir, 'bgutil-pot-windows-x86_64.exe'),
dest: [
path.join(binDir, 'neodlp-pot-x86_64-pc-windows-msvc.exe')
path.join(binDir, 'neodlp-pot-x86_64-pc-windows-msvc.exe'),
path.join(binDir, 'neodlp-pot-aarch64-pc-windows-msvc.exe')
],
archive: null,
cleanup: [
@@ -527,15 +618,21 @@ if (targetPlatform && !['win32', 'linux', 'darwin', 'all'].includes(targetPlatfo
process.exit(1);
}
if (targetArch && !['x64', 'arm64', 'all'].includes(targetArch)) {
console.error(`ERROR: Invalid arch specified: '${targetArch}'. Use one of: x64, arm64, or all`);
process.exit(1);
}
if (targetBin && !binaries.hasOwnProperty(targetBin) && targetBin !== 'all') {
console.error(`ERROR: Invalid binary specified: '${targetBin}'. Use one of: ${Object.keys(binaries).join(', ')}, or all`);
process.exit(1);
}
const effectivePlatform = targetPlatform || platform;
const effectiveArch = targetArch || arch;
const effectiveBin = targetBin || 'all';
console.log(`RUNNING: 📦 Binary Downloader (platform: ${effectivePlatform} | binary: ${effectiveBin})`);
console.log(`RUNNING: 📦 Binary Downloader (platform: ${effectivePlatform} | arch: ${effectiveArch} | binary: ${effectiveBin})`);
Object.keys(binaries).forEach((binKey) => {
if (effectiveBin !== 'all' && binKey !== effectiveBin) {
@@ -547,6 +644,13 @@ Object.keys(binaries).forEach((binKey) => {
return;
}
if (effectiveArch !== 'all') {
const binArches = getArchesForBin(bin);
if (!binArches.has(effectiveArch)) {
return;
}
}
downloadAndProcess(bin);
});
});

View File

@@ -13,7 +13,7 @@ import { useLogger } from "@/helpers/use-logger";
import { ulid } from "ulid";
import { sendNotification } from '@tauri-apps/plugin-notification';
import { FetchVideoMetadataParams, StartDownloadParams } from "@/providers/appContextProvider";
import { useDebouncedCallback } from '@tanstack/react-pacer/debouncer';
import { useThrottledCallback } from '@tanstack/react-pacer/throttler';
import { fetchDownloadStateById } from "@/services/database";
import { dataDir } from "@tauri-apps/api/path";
@@ -102,7 +102,7 @@ export default function useDownloader() {
const isProcessingQueueRef = useRef(false);
const lastProcessedDownloadIdRef = useRef<string | null>(null);
const updateDownloadProgress = useDebouncedCallback((state: DownloadState) => {
const updateDownloadProgress = useThrottledCallback((state: DownloadState) => {
downloadStateSaver.mutate(state, {
onSuccess: (_data) => {
// console.log("Download State saved successfully:", data);
@@ -572,9 +572,10 @@ export default function useDownloader() {
console.log('Starting download with args:', args);
const isFlatpak = await invoke<boolean>('is_flatpak');
const xdgDataDir = await dataDir();
const spawnOpts = { env: { PYTHONUNBUFFERED: '1' } };
const command = isFlatpak
? Command.create('sh', ['-c', `${xdgDataDir}/yt-dlp/yt-dlp ${args.map(arg => `'${arg.replace(/'/g, "'\\''")}'`).join(' ')}`])
: Command.sidecar('binaries/yt-dlp', args);
? Command.create('sh', ['-c', `${xdgDataDir}/yt-dlp/yt-dlp ${args.map(arg => `'${arg.replace(/'/g, "'\\''")}'`).join(' ')}`], spawnOpts)
: Command.sidecar('binaries/yt-dlp', args, spawnOpts);
command.on('close', async (data) => {
if (data.code !== 0) {