multiple fixes and updated ffmpeg
This commit is contained in:
parent
db94aeb1dc
commit
21622c375b
1
.gitignore
vendored
1
.gitignore
vendored
@ -9,6 +9,7 @@ node_modules
|
|||||||
dist
|
dist
|
||||||
.DS_Store
|
.DS_Store
|
||||||
build/
|
build/
|
||||||
|
ffmpeg/
|
||||||
|
|
||||||
# Electron
|
# Electron
|
||||||
crunchyroll-downloader-output
|
crunchyroll-downloader-output
|
||||||
|
1
build.js
1
build.js
@ -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
20087
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
21
package.json
21
package.json
@ -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"
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
943
pnpm-lock.yaml
generated
943
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@ -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 = [
|
||||||
{
|
{
|
||||||
|
@ -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']
|
||||||
|
@ -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`)
|
||||||
|
21
src/api/services/ffmpeg.ts
Normal file
21
src/api/services/ffmpeg.ts
Normal 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 }
|
||||||
|
}
|
||||||
|
}
|
@ -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()
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user