multiple fixes and updated ffmpeg

This commit is contained in:
Daniel Haller 2024-04-29 15:54:59 +02:00
parent db94aeb1dc
commit 21622c375b
10 changed files with 490 additions and 20640 deletions

1
.gitignore vendored
View File

@ -9,6 +9,7 @@ node_modules
dist dist
.DS_Store .DS_Store
build/ build/
ffmpeg/
# Electron # Electron
crunchyroll-downloader-output crunchyroll-downloader-output

View File

@ -18,6 +18,7 @@ const options = {
directories: { directories: {
output: 'crunchyroll-downloader-output-${version}' output: 'crunchyroll-downloader-output-${version}'
}, },
win: { win: {
artifactName: 'crunchyroll-downloader-${version}-windows-installer.${ext}', artifactName: 'crunchyroll-downloader-${version}-windows-installer.${ext}',
icon: "public/favicon.ico", icon: "public/favicon.ico",

20087
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -2,7 +2,7 @@
"name": "crunchyroll-downloader", "name": "crunchyroll-downloader",
"author": "Stratum", "author": "Stratum",
"description": "Crunchyroll Downloader", "description": "Crunchyroll Downloader",
"version": "1.0.3", "version": "1.0.4",
"private": true, "private": true,
"main": ".output/src/electron/background.js", "main": ".output/src/electron/background.js",
"scripts": { "scripts": {
@ -16,9 +16,11 @@
"build:electron": "pnpm build && pnpm transpile-src && node build.js" "build:electron": "pnpm build && pnpm transpile-src && node build.js"
}, },
"devDependencies": { "devDependencies": {
"7zip-bin": "^5.2.0",
"@nuxtjs/eslint-config-typescript": "^12.1.0", "@nuxtjs/eslint-config-typescript": "^12.1.0",
"@nuxtjs/google-fonts": "^3.2.0", "@nuxtjs/google-fonts": "^3.2.0",
"@nuxtjs/tailwindcss": "^6.12.0", "@nuxtjs/tailwindcss": "^6.12.0",
"@pinia/nuxt": "^0.4.11",
"@types/express": "^4.17.21", "@types/express": "^4.17.21",
"concurrently": "^8.2.2", "concurrently": "^8.2.2",
"electron": "^30.0.1", "electron": "^30.0.1",
@ -36,37 +38,28 @@
"wait-on": "^7.2.0" "wait-on": "^7.2.0"
}, },
"dependencies": { "dependencies": {
"7zip-bin": "^5.2.0",
"@fastify/cors": "^9.0.1", "@fastify/cors": "^9.0.1",
"@pinia/nuxt": "^0.4.11",
"@types/crypto-js": "^4.2.2", "@types/crypto-js": "^4.2.2",
"@types/fluent-ffmpeg": "^2.1.24", "@types/fluent-ffmpeg": "^2.1.24",
"@types/node-cron": "^3.0.11", "@types/node-cron": "^3.0.11",
"@types/uuid": "^9.0.8",
"ass-compiler": "^0.1.11", "ass-compiler": "^0.1.11",
"crypto-js": "^4.2.0", "crypto-js": "^4.2.0",
"electron-log": "^5.1.2", "electron-log": "^5.1.2",
"electron-settings": "^4.0.4", "electron-settings": "^4.0.4",
"electron-updater": "^5.3.0", "electron-updater": "^6.1.8",
"express": "^4.19.2", "express": "^4.19.2",
"fastify": "^4.26.2", "fastify": "^4.26.2",
"ffmpeg-static": "^5.2.0",
"ffprobe-static": "^3.1.0",
"fluent-ffmpeg": "^2.1.2", "fluent-ffmpeg": "^2.1.2",
"jsencrypt": "^3.3.2", "jsencrypt": "^3.3.2",
"mpd-parser": "^1.3.0", "mpd-parser": "^1.3.0",
"node-cache": "^5.1.2", "node-cache": "^5.1.2",
"node-cron": "^3.0.3", "node-cron": "^3.0.3",
"sequelize": "^6.37.3", "sequelize": "^6.37.3",
"sqlite3": "5.1.6", "sqlite3": "5.1.6"
"uuid": "^9.0.1"
}, },
"build": { "build": {
"extends": null, "extraResources": [
"asarUnpack": [ "./ffmpeg/**"
"node_modules/ffmpeg-static/bin/${os}/${arch}/ffmpeg",
"node_modules/ffmpeg-static/index.js",
"node_modules/ffmpeg-static/package.json"
] ]
} }
} }

File diff suppressed because it is too large Load Diff

View File

@ -4,6 +4,7 @@ import { VideoPlaylist } from '../../types/crunchyroll'
import { useFetch } from '../useFetch' import { useFetch } from '../useFetch'
import { parse as mpdParse } from 'mpd-parser' import { parse as mpdParse } from 'mpd-parser'
import { loggedInCheck } from '../service/service.service' import { loggedInCheck } from '../service/service.service'
import { app } from 'electron'
const crErrors = [ const crErrors = [
{ {

View File

@ -13,8 +13,8 @@ import Ffmpeg from 'fluent-ffmpeg'
import { adnGetM3U8Playlist, adnGetPlaylist } from '../adn/adn.service' import { adnGetM3U8Playlist, adnGetPlaylist } from '../adn/adn.service'
import { ADNEpisode } from '../../types/adn' import { ADNEpisode } from '../../types/adn'
import { setProgressBar } from '../../../electron/background' import { setProgressBar } from '../../../electron/background'
const ffmpegPath = require('ffmpeg-static').replace('app.asar', 'app.asar.unpacked') import { getFFMPEGPath } from '../../services/ffmpeg'
const ffprobePath = require('ffprobe-static').path.replace('app.asar', 'app.asar.unpacked') const ffmpegP = getFFMPEGPath()
// DB Account existence check // DB Account existence check
export async function loggedInCheck(service: string) { export async function loggedInCheck(service: string) {
@ -639,8 +639,8 @@ async function mergeParts(parts: { filename: string; url: string }[], downloadID
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
Ffmpeg() Ffmpeg()
.setFfmpegPath(ffmpegPath) .setFfmpegPath(ffmpegP.ffmpeg)
.setFfprobePath(ffprobePath) .setFfprobePath(ffmpegP.ffprobe)
.input(concatenatedFile) .input(concatenatedFile)
.outputOptions('-c copy') .outputOptions('-c copy')
.save(dir + `/${tempname}.mp4`) .save(dir + `/${tempname}.mp4`)
@ -684,7 +684,7 @@ async function mergeVideoFile(video: string, audios: Array<string>, subs: Array<
] ]
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
var output = Ffmpeg().setFfmpegPath(ffmpegPath).setFfprobePath(ffprobePath) var output = Ffmpeg().setFfmpegPath(ffmpegP.ffmpeg).setFfprobePath(ffmpegP.ffprobe)
var ffindex = 1 var ffindex = 1
output.addInput(video) output.addInput(video)
var options = ['-map_metadata -1', '-metadata:s:v:0 VENDOR_ID=', '-metadata:s:v:0 language=', '-c copy', '-map 0'] var options = ['-map_metadata -1', '-metadata:s:v:0 VENDOR_ID=', '-metadata:s:v:0 language=', '-c copy', '-map 0']

View File

@ -3,20 +3,40 @@ import { Readable } from 'stream'
import { createFolder, deleteFolder } from './folder' import { createFolder, deleteFolder } from './folder'
import { concatenateTSFiles } from './concatenate' import { concatenateTSFiles } from './concatenate'
import Ffmpeg from 'fluent-ffmpeg' import Ffmpeg from 'fluent-ffmpeg'
const ffmpegPath = require('ffmpeg-static').replace('app.asar', 'app.asar.unpacked') import { getFFMPEGPath } from './ffmpeg'
const ffprobePath = require('ffprobe-static').path.replace('app.asar', 'app.asar.unpacked') const ffmpegP = getFFMPEGPath()
export async function downloadMPDAudio(parts: { filename: string; url: string }[], dir: string, name: string) { export async function downloadMPDAudio(parts: { filename: string; url: string }[], dir: string, name: string) {
const path = await createFolder() const path = await createFolder()
const maxParallelDownloads = 5
const downloadPromises = [] const downloadPromises = []
for (const [index, part] of parts.entries()) { for (const [index, part] of parts.entries()) {
const stream = fs.createWriteStream(`${path}/${part.filename}`) let retries = 0
const downloadPromise = fetchAndPipe(part.url, stream, index + 1)
downloadPromises.push(downloadPromise)
}
await Promise.all(downloadPromises) const downloadPromise = async () => {
let downloadSuccess = false
while (!downloadSuccess) {
try {
const stream = fs.createWriteStream(`${path}/${part.filename}`)
await fetchAndPipe(part.url, stream, index + 1)
downloadSuccess = true
} catch (error) {
retries++
console.error(`Failed to download part ${part.filename}, retrying (${retries})...`)
await new Promise((resolve) => setTimeout(resolve, 1000))
}
}
}
downloadPromises.push(downloadPromise())
if (downloadPromises.length === maxParallelDownloads || index === parts.length - 1) {
await Promise.all(downloadPromises)
downloadPromises.length = 0
}
}
return await mergePartsAudio(parts, path, dir, name) return await mergePartsAudio(parts, path, dir, name)
} }
@ -51,8 +71,8 @@ async function mergePartsAudio(parts: { filename: string; url: string }[], tmp:
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
Ffmpeg() Ffmpeg()
.setFfmpegPath(ffmpegPath) .setFfmpegPath(ffmpegP.ffmpeg)
.setFfprobePath(ffprobePath) .setFfprobePath(ffmpegP.ffprobe)
.input(concatenatedFile) .input(concatenatedFile)
.outputOptions('-c copy') .outputOptions('-c copy')
.save(`${dir}/${name}.aac`) .save(`${dir}/${name}.aac`)

View File

@ -0,0 +1,21 @@
import { app } from 'electron'
import path from 'path'
import { messageBox } from '../../electron/background'
const isDev = process.env.NODE_ENV === 'development'
const appPath = app.getAppPath()
const resourcesPath = path.dirname(appPath)
const ffmpegPath = path.join(resourcesPath, 'ffmpeg')
export function getFFMPEGPath() {
if (isDev) {
const ffmpeg = '../../../ffmpeg/ffmpeg.exe'
const ffprobe = '../../../ffmpeg/ffprobe.exe'
return { ffmpeg: ffmpeg, ffprobe: ffprobe }
} else {
const ffmpeg = path.join(ffmpegPath, 'ffmpeg.exe')
const ffprobe = path.join(ffmpegPath, 'ffprobe.exe')
return { ffmpeg: ffmpeg, ffprobe: ffprobe }
}
}

View File

@ -93,13 +93,6 @@ function createWindow() {
// App events // App events
// ========== // ==========
app.whenReady().then(async () => { app.whenReady().then(async () => {
if (!isProduction) {
try {
await session.defaultSession.loadExtension(path.join(__dirname, '../..', '__extensions', 'vue-devtools'))
} catch (err) {
console.log('[Electron::loadExtensions] An error occurred: ', err)
}
}
startAPI() startAPI()