added more downloading info (audio downloading, more statuses)
This commit is contained in:
parent
60fde780fe
commit
20fc3c2ac5
101
pages/index.vue
101
pages/index.vue
@ -18,33 +18,70 @@
|
||||
<div class="flex flex-col w-full">
|
||||
<div class="flex flex-row h-full">
|
||||
<div class="flex flex-col">
|
||||
<div v-if="p.status === 'failed'" class="flex flex-row items-center justify-center gap-1 text-xs capitalize p-1.5 bg-[#863232] rounded-lg">
|
||||
<Icon name="bitcoin-icons:cross-filled" class="h-3.5 w-3.5 text-white" />
|
||||
{{ p.status }}
|
||||
</div>
|
||||
<div v-if="p.status === 'waiting'" class="flex flex-row items-center justify-center gap-1 text-xs capitalize p-1.5 bg-[#866332] rounded-lg">
|
||||
<Icon name="mdi:clock" class="h-3.5 w-3.5 text-white" />
|
||||
{{ p.status }}
|
||||
</div>
|
||||
<div v-if="p.status === 'preparing'" class="flex flex-row items-center justify-center gap-1 text-xs capitalize p-1.5 bg-[#866332] rounded-lg">
|
||||
<Icon name="mdi:clock" class="h-3.5 w-3.5 text-white" />
|
||||
{{ p.status }}
|
||||
</div>
|
||||
<div v-if="p.status === 'downloading'" class="flex flex-row items-center justify-center gap-1 text-xs capitalize p-1.5 bg-[#60501b] rounded-lg">
|
||||
<Icon name="mdi:loading" class="h-3.5 w-3.5 text-white animate-spin" />
|
||||
{{ p.status }}
|
||||
</div>
|
||||
<div v-if="p.status === 'merging'" class="flex flex-row items-center justify-center gap-1 text-xs capitalize p-1.5 bg-[#866332] rounded-lg">
|
||||
<Icon name="mdi:loading" class="h-3.5 w-3.5 text-white animate-spin" />
|
||||
{{ p.status }}
|
||||
</div>
|
||||
<div v-if="p.status === 'decrypting'" class="flex flex-row items-center justify-center gap-1 text-xs capitalize p-1.5 bg-[#866332] rounded-lg">
|
||||
<Icon name="mdi:loading" class="h-3.5 w-3.5 text-white animate-spin" />
|
||||
{{ p.status }}
|
||||
</div>
|
||||
<div v-if="p.status === 'completed'" class="flex flex-row items-center justify-center gap-1 text-xs capitalize p-1.5 bg-[#266326] rounded-lg">
|
||||
<Icon name="material-symbols:check" class="h-3.5 w-3.5 text-white" />
|
||||
{{ p.status }}
|
||||
<div class="flex flex-row">
|
||||
<div v-if="p.status === 'failed'" class="flex flex-row items-center justify-center gap-1 text-xs capitalize p-1.5 bg-[#863232] rounded-lg">
|
||||
<Icon name="bitcoin-icons:cross-filled" class="h-3.5 w-3.5 text-white" />
|
||||
{{ p.status }}
|
||||
</div>
|
||||
<div v-if="p.status === 'waiting'" class="flex flex-row items-center justify-center gap-1 text-xs capitalize p-1.5 bg-[#866332] rounded-lg">
|
||||
<Icon name="mdi:clock" class="h-3.5 w-3.5 text-white" />
|
||||
{{ p.status }}
|
||||
</div>
|
||||
<div v-if="p.status === 'preparing'" class="flex flex-row items-center justify-center gap-1 text-xs capitalize p-1.5 bg-[#866332] rounded-lg">
|
||||
<Icon name="mdi:clock" class="h-3.5 w-3.5 text-white" />
|
||||
{{ p.status }}
|
||||
</div>
|
||||
<div
|
||||
v-if="p.status === 'waiting for playlist'"
|
||||
class="flex flex-row items-center justify-center gap-1 text-xs capitalize p-1.5 bg-[#866332] rounded-lg"
|
||||
>
|
||||
<Icon name="mdi:loading" class="h-3.5 w-3.5 text-white animate-spin" />
|
||||
{{ p.status }}
|
||||
</div>
|
||||
<div
|
||||
v-if="p.status === 'waiting for sub playlist'"
|
||||
class="flex flex-row items-center justify-center gap-1 text-xs capitalize p-1.5 bg-[#866332] rounded-lg"
|
||||
>
|
||||
<Icon name="mdi:loading" class="h-3.5 w-3.5 text-white animate-spin" />
|
||||
{{ p.status }}
|
||||
</div>
|
||||
<div
|
||||
v-if="p.status === 'waiting for dub playlist'"
|
||||
class="flex flex-row items-center justify-center gap-1 text-xs capitalize p-1.5 bg-[#866332] rounded-lg"
|
||||
>
|
||||
<Icon name="mdi:loading" class="h-3.5 w-3.5 text-white animate-spin" />
|
||||
{{ p.status }}
|
||||
</div>
|
||||
<div v-if="p.status === 'downloading'" class="flex flex-row items-center justify-center gap-1 text-xs capitalize p-1.5 bg-[#60501b] rounded-lg">
|
||||
<Icon name="mdi:loading" class="h-3.5 w-3.5 text-white animate-spin" />
|
||||
{{ p.status }}
|
||||
</div>
|
||||
<div v-if="p.status === 'merging video'" class="flex flex-row items-center justify-center gap-1 text-xs capitalize p-1.5 bg-[#866332] rounded-lg">
|
||||
<Icon name="mdi:loading" class="h-3.5 w-3.5 text-white animate-spin" />
|
||||
{{ p.status }}
|
||||
</div>
|
||||
<div v-if="p.status === 'decrypting video'" class="flex flex-row items-center justify-center gap-1 text-xs capitalize p-1.5 bg-[#866332] rounded-lg">
|
||||
<Icon name="mdi:loading" class="h-3.5 w-3.5 text-white animate-spin" />
|
||||
{{ p.status }}
|
||||
</div>
|
||||
<div v-if="p.status === 'awaiting all dubs downloaded'" class="flex flex-row items-center justify-center gap-1 text-xs capitalize p-1.5 bg-[#866332] rounded-lg">
|
||||
<Icon name="mdi:loading" class="h-3.5 w-3.5 text-white animate-spin" />
|
||||
{{ p.status }}
|
||||
</div>
|
||||
<div v-if="p.status === 'merging video & audio'" class="flex flex-row items-center justify-center gap-1 text-xs capitalize p-1.5 bg-[#866332] rounded-lg">
|
||||
<Icon name="mdi:loading" class="h-3.5 w-3.5 text-white animate-spin" />
|
||||
{{ p.status }}
|
||||
</div>
|
||||
<div v-if="p.status === 'completed'" class="flex flex-row items-center justify-center gap-1 text-xs capitalize p-1.5 bg-[#266326] rounded-lg">
|
||||
<Icon name="material-symbols:check" class="h-3.5 w-3.5 text-white" />
|
||||
{{ p.status }}
|
||||
</div>
|
||||
<div v-for="a in p.audiosdownloading">
|
||||
<div v-if="a.status && a.audio && a.status !== 'finished'" class="ml-2 flex flex-row items-center justify-center gap-1 text-xs capitalize p-1.5 bg-[#866332] rounded-lg">
|
||||
<Icon name="mdi:loading" class="h-3.5 w-3.5 text-white animate-spin" />
|
||||
{{ a.status }} Audio {{ a.audio }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="text-xs capitalize ml-auto">
|
||||
@ -63,7 +100,7 @@
|
||||
<div class="text-xs">{{ p.quality }}p</div>
|
||||
<div class="text-xs uppercase">{{ p.format }}</div>
|
||||
<div class="text-xs">Dubs: {{ p.dub.map((t) => t.name).join(', ') }}</div>
|
||||
<div class="text-xs mr-14">Subs: {{ p.sub.length !== 0 ? p.sub.map((t) => t.name).join(', ') : '-' }}</div>
|
||||
<div class="text-xs mr-20">Subs: {{ p.sub.length !== 0 ? p.sub.map((t) => t.name).join(', ') : '-' }}</div>
|
||||
<div class="absolute flex flex-col ml-auto gap-0.5 right-0 bottom-0">
|
||||
<div v-if="p.totaldownloaded && p.status === 'downloading'" class="text-xs ml-auto"
|
||||
>{{ (p.totaldownloaded / Math.pow(1024, 2)).toFixed(2) }} MB</div
|
||||
@ -103,6 +140,10 @@ const playlist = ref<
|
||||
quality: number
|
||||
service: string
|
||||
format: string
|
||||
audiosdownloading: {
|
||||
status: string,
|
||||
audio: string
|
||||
}[]
|
||||
}>
|
||||
>()
|
||||
|
||||
@ -123,6 +164,10 @@ const getPlaylist = async () => {
|
||||
quality: number
|
||||
service: string
|
||||
format: string
|
||||
audiosdownloading: {
|
||||
status: string,
|
||||
audio: string
|
||||
}[]
|
||||
}>
|
||||
>('http://localhost:9941/api/service/playlist')
|
||||
|
||||
|
@ -29,7 +29,7 @@ interface AccountCreateAttributes {
|
||||
|
||||
interface PlaylistAttributes {
|
||||
id: number
|
||||
status: 'waiting' | 'preparing' | 'downloading' | 'merging' | 'decrypting' | 'completed' | 'failed'
|
||||
status: 'waiting' | 'preparing' | 'waiting for playlist' | 'waiting for sub playlist' | 'waiting for dub playlist' | 'downloading' | 'merging video' | 'decrypting video' | 'awaiting all dubs downloaded' | 'merging video & audio' | 'completed' | 'failed'
|
||||
media: CrunchyEpisode | ADNEpisode
|
||||
dub: Array<string>
|
||||
sub: Array<string>
|
||||
@ -49,7 +49,7 @@ interface PlaylistCreateAttributes {
|
||||
dir: string
|
||||
quality: 1080 | 720 | 480 | 360 | 240
|
||||
hardsub: boolean
|
||||
status: 'waiting' | 'preparing' | 'downloading' | 'merging' | 'decrypting' | 'completed' | 'failed'
|
||||
status: 'waiting' | 'preparing' | 'waiting for playlist' | 'waiting for sub playlist' | 'waiting for dub playlist' | 'downloading' | 'merging video' | 'decrypting video' | 'awaiting all dubs downloaded' | 'merging video & audio' | 'completed' | 'failed'
|
||||
service: 'CR' | 'ADN'
|
||||
format: 'mp4' | 'mkv'
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ import { addEpisodeToPlaylist, deleteAccountID, getAllAccounts, getDownloading,
|
||||
import { CrunchyEpisodes } from '../../types/crunchyroll'
|
||||
import { adnLogin } from '../adn/adn.service'
|
||||
import { server } from '../../api'
|
||||
import { getDownloadingAudio } from '../../services/audio'
|
||||
|
||||
export async function checkLoginController(
|
||||
request: FastifyRequest<{
|
||||
@ -121,8 +122,9 @@ export async function getPlaylistController(request: FastifyRequest, reply: Fast
|
||||
if (!playlist) return
|
||||
|
||||
for (const v of playlist) {
|
||||
if (v.dataValues.status === 'downloading') {
|
||||
if (v.dataValues.status !== 'completed') {
|
||||
const found = await getDownloading(v.dataValues.id)
|
||||
const foundAudio = await getDownloadingAudio(v.dataValues.id)
|
||||
if (found) {
|
||||
;(v as any).dataValues = {
|
||||
...v.dataValues,
|
||||
@ -132,6 +134,12 @@ export async function getPlaylistController(request: FastifyRequest, reply: Fast
|
||||
totaldownloaded: found.totalDownloaded
|
||||
}
|
||||
}
|
||||
if (foundAudio) {
|
||||
;(v as any).dataValues = {
|
||||
...v.dataValues,
|
||||
audiosdownloading: foundAudio
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -164,7 +164,7 @@ deletePlaylistandTMP();
|
||||
// Update Playlist Item
|
||||
export async function updatePlaylistByID(
|
||||
id: number,
|
||||
status?: 'waiting' | 'preparing' | 'downloading' | 'merging' | 'decrypting' | 'completed' | 'failed',
|
||||
status?: 'waiting' | 'preparing' | 'waiting for playlist' | 'waiting for sub playlist' | 'waiting for dub playlist' | 'downloading' | 'merging video' | 'decrypting video' | 'awaiting all dubs downloaded' | 'merging video & audio' | 'completed' | 'failed',
|
||||
quality?: 1080 | 720 | 480 | 360 | 240,
|
||||
installedDir?: string
|
||||
) {
|
||||
@ -199,7 +199,7 @@ export async function addEpisodeToPlaylist(
|
||||
d: Array<string>,
|
||||
dir: string,
|
||||
hardsub: boolean,
|
||||
status: 'waiting' | 'preparing' | 'downloading' | 'merging' | 'decrypting' | 'completed' | 'failed',
|
||||
status: 'waiting' | 'preparing' | 'waiting for playlist' | 'waiting for sub playlist' | 'waiting for dub playlist' | 'downloading' | 'merging video' | 'decrypting video' | 'awaiting all dubs downloaded' | 'merging video & audio' | 'completed' | 'failed',
|
||||
quality: 1080 | 720 | 480 | 360 | 240,
|
||||
service: 'CR' | 'ADN',
|
||||
format: 'mp4' | 'mkv'
|
||||
@ -222,6 +222,7 @@ export async function addEpisodeToPlaylist(
|
||||
// Define Downloading Array
|
||||
var downloading: Array<{
|
||||
id: number
|
||||
status: string
|
||||
downloadedParts: number
|
||||
partsToDownload: number
|
||||
downloadSpeed: number
|
||||
@ -318,6 +319,7 @@ export async function downloadADNPlaylist(
|
||||
) {
|
||||
downloading.push({
|
||||
id: downloadID,
|
||||
status: 'downloading',
|
||||
downloadedParts: 0,
|
||||
partsToDownload: 0,
|
||||
downloadSpeed: 0,
|
||||
@ -462,13 +464,6 @@ export async function downloadCrunchyrollPlaylist(
|
||||
format: 'mp4' | 'mkv',
|
||||
geo: string | undefined
|
||||
) {
|
||||
downloading.push({
|
||||
id: downloadID,
|
||||
downloadedParts: 0,
|
||||
partsToDownload: 0,
|
||||
downloadSpeed: 0,
|
||||
totalDownloaded: 0
|
||||
})
|
||||
|
||||
const accmaxstream = await checkAccountMaxStreams();
|
||||
|
||||
@ -476,7 +471,7 @@ export async function downloadCrunchyrollPlaylist(
|
||||
maxLimit = accmaxstream
|
||||
}
|
||||
|
||||
await updatePlaylistByID(downloadID, 'downloading')
|
||||
await updatePlaylistByID(downloadID, 'waiting for playlist')
|
||||
|
||||
await incrementPlaylistCounter();
|
||||
var playlist = await crunchyGetPlaylist(e, geo)
|
||||
@ -562,6 +557,8 @@ export async function downloadCrunchyrollPlaylist(
|
||||
isDub: boolean
|
||||
}> = []
|
||||
|
||||
await updatePlaylistByID(downloadID, 'waiting for sub playlist')
|
||||
|
||||
for (const s of subs) {
|
||||
var subPlaylist
|
||||
|
||||
@ -612,6 +609,8 @@ export async function downloadCrunchyrollPlaylist(
|
||||
decrementPlaylistCounter()
|
||||
}
|
||||
|
||||
await updatePlaylistByID(downloadID, 'waiting for dub playlist')
|
||||
|
||||
for (const d of dubs) {
|
||||
var found
|
||||
if (playlist.data.versions) {
|
||||
@ -665,6 +664,8 @@ export async function downloadCrunchyrollPlaylist(
|
||||
}
|
||||
}
|
||||
|
||||
await updatePlaylistByID(downloadID, 'downloading')
|
||||
|
||||
const subDownload = async () => {
|
||||
const sbs: Array<string> = []
|
||||
for (const sub of subDownloadList) {
|
||||
@ -756,7 +757,7 @@ export async function downloadCrunchyrollPlaylist(
|
||||
})
|
||||
}
|
||||
|
||||
const path = await downloadMPDAudio(p, audioFolder, list.data.audioLocale, keys ? keys : undefined)
|
||||
const path = await downloadMPDAudio(p, audioFolder, list.data.audioLocale, downloadID, keys ? keys : undefined)
|
||||
|
||||
audios.push(path as string)
|
||||
}
|
||||
@ -764,6 +765,16 @@ export async function downloadCrunchyrollPlaylist(
|
||||
}
|
||||
|
||||
const downloadVideo = async () => {
|
||||
|
||||
downloading.push({
|
||||
id: downloadID,
|
||||
status: 'Waiting for Playlist',
|
||||
downloadedParts: 0,
|
||||
partsToDownload: 0,
|
||||
downloadSpeed: 0,
|
||||
totalDownloaded: 0
|
||||
})
|
||||
|
||||
var code
|
||||
|
||||
if (!playlist) return
|
||||
@ -949,6 +960,8 @@ export async function downloadCrunchyrollPlaylist(
|
||||
|
||||
const file = await downloadParts(p, downloadID, videoFolder, keys ? keys : undefined)
|
||||
|
||||
await updatePlaylistByID(downloadID, 'awaiting all dubs downloaded')
|
||||
|
||||
return file
|
||||
}
|
||||
|
||||
@ -956,6 +969,7 @@ export async function downloadCrunchyrollPlaylist(
|
||||
|
||||
if (!audios) return
|
||||
|
||||
await updatePlaylistByID(downloadID, 'merging video & audio')
|
||||
await mergeVideoFile(file as string, audios, subss, seasonFolder, `${name.replace(/[/\\?%*:|"<>]/g, '')} Season ${season} Episode ${episode}`, format, downloadID)
|
||||
|
||||
await updatePlaylistByID(downloadID, 'completed')
|
||||
@ -1039,7 +1053,7 @@ async function mergeParts(parts: { filename: string; url: string }[], downloadID
|
||||
try {
|
||||
const list: Array<string> = []
|
||||
|
||||
await updatePlaylistByID(downloadID, 'merging')
|
||||
await updatePlaylistByID(downloadID, 'merging video')
|
||||
isDownloading--
|
||||
|
||||
for (const [index, part] of parts.entries()) {
|
||||
@ -1057,7 +1071,7 @@ async function mergeParts(parts: { filename: string; url: string }[], downloadID
|
||||
await concatenateTSFiles(list, concatenatedFile)
|
||||
|
||||
if (drmkeys) {
|
||||
await updatePlaylistByID(downloadID, 'decrypting')
|
||||
await updatePlaylistByID(downloadID, 'decrypting video')
|
||||
console.log('Video Decryption started')
|
||||
const inputFilePath = `${tmp}/temp-main.m4s`
|
||||
const outputFilePath = `${tmp}/main.m4s`
|
||||
|
@ -8,11 +8,39 @@ import { getMP4DecryptPath } from '../services/mp4decrypt'
|
||||
const ffmpegP = getFFMPEGPath()
|
||||
const mp4e = getMP4DecryptPath()
|
||||
import util from 'util'
|
||||
import { server } from '../api'
|
||||
const exec = util.promisify(require('child_process').exec)
|
||||
|
||||
export async function downloadMPDAudio(parts: { filename: string; url: string }[], dir: string, name: string, drmkeys?: { kid: string; key: string }[] | undefined) {
|
||||
// Define Downloading Array
|
||||
var downloading: Array<{
|
||||
id: number
|
||||
status: string
|
||||
audio: string
|
||||
}> = []
|
||||
|
||||
export async function getDownloadingAudio(id: number) {
|
||||
const found = downloading.filter((i) => i.id === id)
|
||||
|
||||
if (found) return found
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
export async function downloadMPDAudio(
|
||||
parts: { filename: string; url: string }[],
|
||||
dir: string,
|
||||
name: string,
|
||||
downloadID: number,
|
||||
drmkeys?: { kid: string; key: string }[] | undefined
|
||||
) {
|
||||
const path = await createFolder()
|
||||
|
||||
downloading.push({
|
||||
id: downloadID,
|
||||
status: `downloading`,
|
||||
audio: name
|
||||
})
|
||||
|
||||
const maxParallelDownloads = 5
|
||||
const downloadPromises = []
|
||||
|
||||
@ -42,27 +70,89 @@ export async function downloadMPDAudio(parts: { filename: string; url: string }[
|
||||
}
|
||||
}
|
||||
|
||||
return await mergePartsAudio(parts, path, dir, name, drmkeys)
|
||||
return await mergePartsAudio(parts, path, dir, name, downloadID, drmkeys)
|
||||
}
|
||||
|
||||
async function fetchAndPipe(url: string, stream: fs.WriteStream, index: number) {
|
||||
const { body } = await fetch(url)
|
||||
const readableStream = Readable.from(body as any)
|
||||
try {
|
||||
const response = await fetch(url)
|
||||
|
||||
return new Promise<void>((resolve, reject) => {
|
||||
readableStream
|
||||
.pipe(stream)
|
||||
.on('finish', () => {
|
||||
console.log(`Fragment ${index} downloaded`)
|
||||
resolve()
|
||||
// Check if fetch was successful
|
||||
if (!response.ok) {
|
||||
server.logger.log({
|
||||
level: 'error',
|
||||
message: 'Error while downloading an Audio Fragment',
|
||||
fragment: index,
|
||||
error: await response.text(),
|
||||
timestamp: new Date().toISOString(),
|
||||
section: 'audiofragmentCrunchyrollFetch'
|
||||
})
|
||||
.on('error', (error) => {
|
||||
reject(error)
|
||||
throw new Error(`Failed to fetch URL: ${response.statusText}`)
|
||||
}
|
||||
|
||||
const body = response.body
|
||||
|
||||
// Check if the body exists and is readable
|
||||
if (!body) {
|
||||
server.logger.log({
|
||||
level: 'error',
|
||||
message: 'Error while downloading an Audio Fragment',
|
||||
fragment: index,
|
||||
error: 'Response body is not a readable stream',
|
||||
timestamp: new Date().toISOString(),
|
||||
section: 'audiofragmentCrunchyrollFetch'
|
||||
})
|
||||
})
|
||||
throw new Error('Response body is not a readable stream')
|
||||
}
|
||||
|
||||
const readableStream = Readable.from(body as any)
|
||||
|
||||
return new Promise<void>((resolve, reject) => {
|
||||
readableStream
|
||||
.pipe(stream)
|
||||
.on('finish', () => {
|
||||
console.log(`Fragment ${index} downloaded`)
|
||||
resolve()
|
||||
})
|
||||
.on('error', (error) => {
|
||||
server.logger.log({
|
||||
level: 'error',
|
||||
message: 'Error while downloading an Audio Fragment',
|
||||
fragment: index,
|
||||
error: error,
|
||||
timestamp: new Date().toISOString(),
|
||||
section: 'audiofragmentCrunchyrollFetch'
|
||||
})
|
||||
reject(error)
|
||||
})
|
||||
})
|
||||
} catch (error) {
|
||||
server.logger.log({
|
||||
level: 'error',
|
||||
message: 'Error while downloading an Audio Fragment',
|
||||
fragment: index,
|
||||
error: error,
|
||||
timestamp: new Date().toISOString(),
|
||||
section: 'audiofragmentCrunchyrollFetch'
|
||||
})
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
async function mergePartsAudio(parts: { filename: string; url: string }[], tmp: string, dir: string, name: string, drmkeys?: { kid: string; key: string }[] | undefined) {
|
||||
async function mergePartsAudio(
|
||||
parts: { filename: string; url: string }[],
|
||||
tmp: string,
|
||||
dir: string,
|
||||
name: string,
|
||||
downloadID: number,
|
||||
drmkeys?: { kid: string; key: string }[] | undefined
|
||||
) {
|
||||
const dn = downloading.find((i) => i.id === downloadID && i.audio === name)
|
||||
|
||||
if (dn) {
|
||||
dn.status = 'merging'
|
||||
}
|
||||
|
||||
try {
|
||||
const list: Array<string> = []
|
||||
|
||||
@ -81,6 +171,9 @@ async function mergePartsAudio(parts: { filename: string; url: string }[], tmp:
|
||||
await concatenateTSFiles(list, concatenatedFile)
|
||||
|
||||
if (drmkeys) {
|
||||
if (dn) {
|
||||
dn.status = 'decrypting'
|
||||
}
|
||||
console.log(`Audio Decryption started`)
|
||||
const inputFilePath = `${tmp}/temp-main.m4s`
|
||||
const outputFilePath = `${tmp}/main.m4s`
|
||||
@ -105,6 +198,10 @@ async function mergePartsAudio(parts: { filename: string; url: string }[], tmp:
|
||||
console.log('Merging finished')
|
||||
await deleteFolder(tmp)
|
||||
|
||||
if (dn) {
|
||||
dn.status = 'finished'
|
||||
}
|
||||
|
||||
return resolve(`${dir}/${name}.aac`)
|
||||
})
|
||||
})
|
||||
|
Reference in New Issue
Block a user