mirror of
https://github.com/advplyr/audiobookshelf.git
synced 2025-01-03 00:06:46 +01:00
Use local image as cover if found, adding release-it version control
This commit is contained in:
parent
30700c1eb0
commit
eab8edce8d
@ -1,3 +1,4 @@
|
|||||||
|
.env
|
||||||
node_modules
|
node_modules
|
||||||
npm-debug.log
|
npm-debug.log
|
||||||
.git
|
.git
|
||||||
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,3 +1,4 @@
|
|||||||
|
.env
|
||||||
dev.js
|
dev.js
|
||||||
node_modules/
|
node_modules/
|
||||||
/config/
|
/config/
|
||||||
|
5
.release-it.json
Normal file
5
.release-it.json
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"github": {
|
||||||
|
"release": true
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,5 @@
|
|||||||
### STAGE 0: FFMPEG ###
|
### STAGE 0: FFMPEG ###
|
||||||
FROM jrottenberg/ffmpeg:4.1-alpine AS ffmpeg
|
FROM jrottenberg/ffmpeg:4.1-alpine AS ffmpeg
|
||||||
# FROM alfg/ffmpeg AS ffmpeg
|
|
||||||
|
|
||||||
### STAGE 1: Build client ###
|
### STAGE 1: Build client ###
|
||||||
FROM node:12-alpine AS build
|
FROM node:12-alpine AS build
|
||||||
@ -11,8 +10,6 @@ RUN npm run generate
|
|||||||
|
|
||||||
### STAGE 2: Build server ###
|
### STAGE 2: Build server ###
|
||||||
FROM node:12-alpine
|
FROM node:12-alpine
|
||||||
# RUN apk add --no-cache ffmpeg
|
|
||||||
# RUN apt-get install -y ffmpeg
|
|
||||||
ENV NODE_ENV=production
|
ENV NODE_ENV=production
|
||||||
ENV LOG_LEVEL=INFO
|
ENV LOG_LEVEL=INFO
|
||||||
COPY --from=build /client/dist /client/dist
|
COPY --from=build /client/dist /client/dist
|
||||||
@ -22,5 +19,4 @@ COPY package.json package.json
|
|||||||
COPY server server
|
COPY server server
|
||||||
RUN npm install --production
|
RUN npm install --production
|
||||||
EXPOSE 80
|
EXPOSE 80
|
||||||
# CMD ["node", "index.js"]
|
|
||||||
CMD ["npm", "start"]
|
CMD ["npm", "start"]
|
||||||
|
@ -1,7 +1,13 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="relative rounded-sm overflow-hidden" :style="{ height: width * 1.6 + 'px', width: width + 'px', maxWidth: width + 'px', minWidth: width + 'px' }">
|
<div class="relative rounded-sm overflow-hidden" :style="{ height: width * 1.6 + 'px', width: width + 'px', maxWidth: width + 'px', minWidth: width + 'px' }">
|
||||||
<img ref="cover" :src="cover" class="w-full h-full object-cover" />
|
<img ref="cover" :src="cover" @error="imageError" class="w-full h-full object-cover" />
|
||||||
|
|
||||||
|
<div v-if="imageFailed" class="absolute top-0 left-0 right-0 bottom-0 w-full h-full bg-red-100" :style="{ padding: placeholderCoverPadding + 'rem' }">
|
||||||
|
<div class="w-full h-full border-2 border-error flex flex-col items-center justify-center">
|
||||||
|
<img src="/LogoTransparent.png" class="mb-2" :style="{ height: 64 * sizeMultiplier + 'px' }" />
|
||||||
|
<p class="text-center font-book text-error" :style="{ fontSize: titleFontSize + 'rem' }">Invalid Cover</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div v-if="!hasCover" class="absolute top-0 left-0 right-0 bottom-0 w-full h-full flex items-center justify-center" :style="{ padding: placeholderCoverPadding + 'rem' }">
|
<div v-if="!hasCover" class="absolute top-0 left-0 right-0 bottom-0 w-full h-full flex items-center justify-center" :style="{ padding: placeholderCoverPadding + 'rem' }">
|
||||||
<div>
|
<div>
|
||||||
<p class="text-center font-book" style="color: rgb(247 223 187)" :style="{ fontSize: titleFontSize + 'rem' }">{{ titleCleaned }}</p>
|
<p class="text-center font-book" style="color: rgb(247 223 187)" :style="{ fontSize: titleFontSize + 'rem' }">{{ titleCleaned }}</p>
|
||||||
@ -26,7 +32,9 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {}
|
return {
|
||||||
|
imageFailed: false
|
||||||
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
book() {
|
book() {
|
||||||
@ -56,23 +64,28 @@ export default {
|
|||||||
hasCover() {
|
hasCover() {
|
||||||
return !!this.book.cover
|
return !!this.book.cover
|
||||||
},
|
},
|
||||||
fontSizeMultiplier() {
|
sizeMultiplier() {
|
||||||
return this.width / 120
|
return this.width / 120
|
||||||
},
|
},
|
||||||
titleFontSize() {
|
titleFontSize() {
|
||||||
return 0.75 * this.fontSizeMultiplier
|
return 0.75 * this.sizeMultiplier
|
||||||
},
|
},
|
||||||
authorFontSize() {
|
authorFontSize() {
|
||||||
return 0.6 * this.fontSizeMultiplier
|
return 0.6 * this.sizeMultiplier
|
||||||
},
|
},
|
||||||
placeholderCoverPadding() {
|
placeholderCoverPadding() {
|
||||||
return 0.8 * this.fontSizeMultiplier
|
return 0.8 * this.sizeMultiplier
|
||||||
},
|
},
|
||||||
authorBottom() {
|
authorBottom() {
|
||||||
return 0.75 * this.fontSizeMultiplier
|
return 0.75 * this.sizeMultiplier
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
imageError(err) {
|
||||||
|
console.error('ImgError', err)
|
||||||
|
this.imageFailed = true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {},
|
|
||||||
mounted() {}
|
mounted() {}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="w-full">
|
<div class="w-full">
|
||||||
<p class="px-1 text-sm">{{ label }}</p>
|
<p class="px-1 text-sm font-semibold">{{ label }}</p>
|
||||||
<div ref="wrapper" class="relative">
|
<div ref="wrapper" class="relative">
|
||||||
<form @submit.prevent="submitForm">
|
<form @submit.prevent="submitForm">
|
||||||
<div ref="inputWrapper" style="min-height: 40px" class="flex-wrap relative w-full shadow-sm flex items-center bg-primary border border-gray-600 rounded-md px-2 py-1 cursor-text" @click.stop.prevent="clickWrapper" @mouseup.stop.prevent @mousedown.prevent>
|
<div ref="inputWrapper" style="min-height: 40px" class="flex-wrap relative w-full shadow-sm flex items-center bg-primary border border-gray-600 rounded-md px-2 py-1 cursor-text" @click.stop.prevent="clickWrapper" @mouseup.stop.prevent @mousedown.prevent>
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="w-full">
|
<div class="w-full">
|
||||||
<p class="px-1 text-sm">{{ label }}</p>
|
<p class="px-1 text-sm font-semibold">{{ label }}</p>
|
||||||
<ui-text-input v-model="inputValue" :disabled="disabled" :type="type" class="w-full" />
|
<ui-text-input v-model="inputValue" :disabled="disabled" :type="type" class="w-full" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="w-full">
|
<div class="w-full">
|
||||||
<p class="px-1 text-sm">{{ label }}</p>
|
<p class="px-1 text-sm font-semibold">{{ label }}</p>
|
||||||
<ui-textarea-input v-model="inputValue" :rows="rows" class="w-full" />
|
<ui-textarea-input v-model="inputValue" :rows="rows" class="w-full" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
@ -136,6 +136,11 @@ export default {
|
|||||||
this.socket.on('scan_start', this.scanStart)
|
this.socket.on('scan_start', this.scanStart)
|
||||||
this.socket.on('scan_complete', this.scanComplete)
|
this.socket.on('scan_complete', this.scanComplete)
|
||||||
this.socket.on('scan_progress', this.scanProgress)
|
this.socket.on('scan_progress', this.scanProgress)
|
||||||
|
},
|
||||||
|
checkVersion() {
|
||||||
|
this.$axios.$get('http://github.com/advplyr/audiobookshelf/raw/master/package.json').then((data) => {
|
||||||
|
console.log('GOT DATA', data)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
beforeMount() {
|
beforeMount() {
|
||||||
@ -145,6 +150,7 @@ export default {
|
|||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.initializeSocket()
|
this.initializeSocket()
|
||||||
|
this.checkVersion()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
@ -35,7 +35,7 @@ module.exports = {
|
|||||||
],
|
],
|
||||||
link: [
|
link: [
|
||||||
{ rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' },
|
{ rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' },
|
||||||
{ rel: 'stylesheet', href: 'https://fonts.googleapis.com/css2?family=Fira+Mono&family=Ubuntu+Mono&family=Open+Sans:wght@600&family=Gentium+Book+Basic' },
|
{ rel: 'stylesheet', href: 'https://fonts.googleapis.com/css2?family=Fira+Mono&family=Ubuntu+Mono&family=Open+Sans:wght@400;600&family=Gentium+Book+Basic' },
|
||||||
{ rel: 'stylesheet', href: 'https://fonts.googleapis.com/icon?family=Material+Icons' }
|
{ rel: 'stylesheet', href: 'https://fonts.googleapis.com/icon?family=Material+Icons' }
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@ -69,7 +69,8 @@ module.exports = {
|
|||||||
],
|
],
|
||||||
|
|
||||||
proxy: {
|
proxy: {
|
||||||
'/dev/': { target: 'http://localhost:3333', pathRewrite: { '^/dev/': '' } }
|
'/dev/': { target: 'http://localhost:3333', pathRewrite: { '^/dev/': '' } },
|
||||||
|
'/local/': { target: process.env.NODE_ENV !== 'production' ? 'http://localhost:3333' : '/', pathRewrite: { '^/local/': '' } }
|
||||||
},
|
},
|
||||||
|
|
||||||
io: {
|
io: {
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="h-0.5 bg-primary bg-opacity-50 w-full" />
|
<div class="h-0.5 bg-primary bg-opacity-50 w-full" />
|
||||||
<div class="flex items-center py-4">
|
<div class="flex items-center py-4">
|
||||||
<p class="font-mono">Beta v{{ $config.version }}</p>
|
<p class="font-mono">v{{ $config.version }}</p>
|
||||||
<div class="flex-grow" />
|
<div class="flex-grow" />
|
||||||
<p class="pr-2 text-sm font-book text-yellow-400">Report bugs, request features, provide feedback, and contribute on <a class="underline" href="https://github.com/advplyr/audiobookshelf" target="_blank">github</a>.</p>
|
<p class="pr-2 text-sm font-book text-yellow-400">Report bugs, request features, provide feedback, and contribute on <a class="underline" href="https://github.com/advplyr/audiobookshelf" target="_blank">github</a>.</p>
|
||||||
<a href="https://github.com/advplyr/audiobookshelf" target="_blank" class="text-white hover:text-gray-200 hover:scale-150 hover:rotate-6 transform duration-500">
|
<a href="https://github.com/advplyr/audiobookshelf" target="_blank" class="text-white hover:text-gray-200 hover:scale-150 hover:rotate-6 transform duration-500">
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
export default function ({ $axios, store }) {
|
export default function ({ $axios, store }) {
|
||||||
$axios.onRequest(config => {
|
$axios.onRequest(config => {
|
||||||
console.log('Making request to ' + config.url)
|
console.log('Making request to ' + config.url)
|
||||||
|
if (config.url.startsWith('http:') || config.url.startsWith('https:')) {
|
||||||
|
return
|
||||||
|
}
|
||||||
var bearerToken = store.state.user ? store.state.user.token : null
|
var bearerToken = store.state.user ? store.state.user.token : null
|
||||||
// console.log('Bearer token', bearerToken)
|
// console.log('Bearer token', bearerToken)
|
||||||
if (bearerToken) {
|
if (bearerToken) {
|
||||||
|
2137
package-lock.json
generated
2137
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -5,7 +5,9 @@
|
|||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "node index.js",
|
"dev": "node index.js",
|
||||||
"start": "node index.js"
|
"start": "node index.js",
|
||||||
|
"release": "dotenv release-it --disable-metrics --no-npm --npm.skipChecks",
|
||||||
|
"release-dry": "dotenv release-it --disable-metrics --no-npm --npm.skipChecks --dry-run"
|
||||||
},
|
},
|
||||||
"author": "advplyr",
|
"author": "advplyr",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
@ -22,5 +24,9 @@
|
|||||||
"njodb": "^0.4.20",
|
"njodb": "^0.4.20",
|
||||||
"node-dir": "^0.1.17",
|
"node-dir": "^0.1.17",
|
||||||
"socket.io": "^4.1.3"
|
"socket.io": "^4.1.3"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"dotenv-cli": "^4.0.0",
|
||||||
|
"release-it": "^14.11.5"
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,3 +1,4 @@
|
|||||||
|
const Path = require('path')
|
||||||
class Book {
|
class Book {
|
||||||
constructor(book = null) {
|
constructor(book = null) {
|
||||||
this.olid = null
|
this.olid = null
|
||||||
@ -42,7 +43,6 @@ class Book {
|
|||||||
}
|
}
|
||||||
|
|
||||||
setData(data) {
|
setData(data) {
|
||||||
console.log('SET DATA', data)
|
|
||||||
this.olid = data.olid || null
|
this.olid = data.olid || null
|
||||||
this.title = data.title || null
|
this.title = data.title || null
|
||||||
this.author = data.author || null
|
this.author = data.author || null
|
||||||
@ -51,6 +51,14 @@ class Book {
|
|||||||
this.description = data.description || null
|
this.description = data.description || null
|
||||||
this.cover = data.cover || null
|
this.cover = data.cover || null
|
||||||
this.genres = data.genres || []
|
this.genres = data.genres || []
|
||||||
|
|
||||||
|
// Use first image file as cover
|
||||||
|
if (data.otherFiles && data.otherFiles.length) {
|
||||||
|
var imageFile = data.otherFiles.find(f => f.filetype === 'image')
|
||||||
|
if (imageFile) {
|
||||||
|
this.cover = Path.join('/local', imageFile.path)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
update(payload) {
|
update(payload) {
|
||||||
|
@ -13,7 +13,6 @@ const ApiController = require('./ApiController')
|
|||||||
const HlsController = require('./HlsController')
|
const HlsController = require('./HlsController')
|
||||||
const StreamManager = require('./StreamManager')
|
const StreamManager = require('./StreamManager')
|
||||||
const Logger = require('./Logger')
|
const Logger = require('./Logger')
|
||||||
const streamTest = require('./streamTest')
|
|
||||||
|
|
||||||
class Server {
|
class Server {
|
||||||
constructor(PORT, CONFIG_PATH, METADATA_PATH, AUDIOBOOK_PATH) {
|
constructor(PORT, CONFIG_PATH, METADATA_PATH, AUDIOBOOK_PATH) {
|
||||||
@ -110,7 +109,6 @@ class Server {
|
|||||||
const distPath = Path.join(global.appRoot, '/client/dist')
|
const distPath = Path.join(global.appRoot, '/client/dist')
|
||||||
app.use(express.static(distPath))
|
app.use(express.static(distPath))
|
||||||
}
|
}
|
||||||
|
|
||||||
app.use(express.static(this.AudiobookPath))
|
app.use(express.static(this.AudiobookPath))
|
||||||
app.use(express.static(this.MetadataPath))
|
app.use(express.static(this.MetadataPath))
|
||||||
app.use(express.urlencoded({ extended: true }));
|
app.use(express.urlencoded({ extended: true }));
|
||||||
@ -122,13 +120,6 @@ class Server {
|
|||||||
app.get('/', (req, res) => {
|
app.get('/', (req, res) => {
|
||||||
res.sendFile('/index.html')
|
res.sendFile('/index.html')
|
||||||
})
|
})
|
||||||
app.get('/test/:id', (req, res) => {
|
|
||||||
var audiobook = this.audiobooks.find(a => a.id === req.params.id)
|
|
||||||
var startTime = !isNaN(req.query.start) ? Number(req.query.start) : 0
|
|
||||||
Logger.info('/test with audiobook', audiobook.title)
|
|
||||||
streamTest.start(audiobook, startTime)
|
|
||||||
res.sendStatus(200)
|
|
||||||
})
|
|
||||||
|
|
||||||
app.post('/login', (req, res) => this.auth.login(req, res))
|
app.post('/login', (req, res) => this.auth.login(req, res))
|
||||||
app.post('/logout', this.logout.bind(this))
|
app.post('/logout', this.logout.bind(this))
|
||||||
|
@ -1,112 +0,0 @@
|
|||||||
const Ffmpeg = require('fluent-ffmpeg')
|
|
||||||
const Path = require('path')
|
|
||||||
const fs = require('fs-extra')
|
|
||||||
const Logger = require('./Logger')
|
|
||||||
const { secondsToTimestamp } = require('./utils/fileUtils')
|
|
||||||
|
|
||||||
function escapeSingleQuotes(path) {
|
|
||||||
return path.replace(/\\/g, '/').replace(/ /g, '\\ ').replace(/'/g, '\\\'')
|
|
||||||
}
|
|
||||||
|
|
||||||
function getNumSegments(audiobook, segmentLength) {
|
|
||||||
var numSegments = Math.floor(audiobook.totalDuration / segmentLength)
|
|
||||||
var remainingTime = audiobook.totalDuration - (numSegments * segmentLength)
|
|
||||||
if (remainingTime > 0) numSegments++
|
|
||||||
return numSegments
|
|
||||||
}
|
|
||||||
|
|
||||||
async function start(audiobook, startTime = 0, segmentLength = 6) {
|
|
||||||
var testDir = Path.join(global.appRoot, 'test', audiobook.id)
|
|
||||||
var existsAlready = await fs.pathExists(testDir)
|
|
||||||
if (existsAlready) {
|
|
||||||
await fs.remove(testDir).then(() => {
|
|
||||||
Logger.info('Deleted test dir data', testDir)
|
|
||||||
}).catch((err) => {
|
|
||||||
Logger.error('Failed to delete test dir', err)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fs.ensureDirSync(testDir)
|
|
||||||
var concatFilePath = Path.join(testDir, 'concat.txt')
|
|
||||||
var playlistPath = Path.join(testDir, 'output.m3u8')
|
|
||||||
|
|
||||||
|
|
||||||
const numSegments = getNumSegments(audiobook, segmentLength)
|
|
||||||
const segmentStartNumber = Math.floor(startTime / segmentLength)
|
|
||||||
Logger.info(`[STREAM] START STREAM - Num Segments: ${numSegments} - Segment Start: ${segmentStartNumber}`)
|
|
||||||
|
|
||||||
const tracks = audiobook.tracks
|
|
||||||
|
|
||||||
const ffmpeg = Ffmpeg()
|
|
||||||
|
|
||||||
var currTrackEnd = 0
|
|
||||||
|
|
||||||
var startingTrack = tracks.find(t => {
|
|
||||||
currTrackEnd += t.duration
|
|
||||||
return startTime < currTrackEnd
|
|
||||||
})
|
|
||||||
var trackStartTime = currTrackEnd - startingTrack.duration
|
|
||||||
var currInpoint = startTime - trackStartTime
|
|
||||||
Logger.info('Starting Track Index', startingTrack.index)
|
|
||||||
|
|
||||||
var tracksToInclude = tracks.filter(t => t.index >= startingTrack.index)
|
|
||||||
var trackPaths = tracksToInclude.map(t => {
|
|
||||||
var line = 'file ' + escapeSingleQuotes(t.fullPath) + '\n' + `duration ${t.duration}`
|
|
||||||
// if (t.index === startingTrack.index) {
|
|
||||||
// currInpoint = 60 * 5 + 4
|
|
||||||
// line += `\ninpoint ${currInpoint}`
|
|
||||||
// }
|
|
||||||
return line
|
|
||||||
})
|
|
||||||
|
|
||||||
var inputstr = trackPaths.join('\n\n')
|
|
||||||
await fs.writeFile(concatFilePath, inputstr)
|
|
||||||
|
|
||||||
ffmpeg.addInput(concatFilePath)
|
|
||||||
ffmpeg.inputFormat('concat')
|
|
||||||
ffmpeg.inputOption('-safe 0')
|
|
||||||
|
|
||||||
var shiftedStartTime = startTime - trackStartTime
|
|
||||||
if (startTime > 0) {
|
|
||||||
Logger.info(`[STREAM] Starting Stream at startTime ${secondsToTimestamp(startTime)} and Segment #${segmentStartNumber}`)
|
|
||||||
ffmpeg.inputOption(`-ss ${shiftedStartTime}`)
|
|
||||||
ffmpeg.inputOption('-noaccurate_seek')
|
|
||||||
}
|
|
||||||
|
|
||||||
ffmpeg.addOption([
|
|
||||||
'-loglevel warning',
|
|
||||||
'-map 0:a',
|
|
||||||
'-c:a copy'
|
|
||||||
])
|
|
||||||
ffmpeg.addOption([
|
|
||||||
'-f hls',
|
|
||||||
"-copyts",
|
|
||||||
"-avoid_negative_ts disabled",
|
|
||||||
"-max_delay 5000000",
|
|
||||||
"-max_muxing_queue_size 2048",
|
|
||||||
`-hls_time 6`,
|
|
||||||
"-hls_segment_type mpegts",
|
|
||||||
`-start_number ${segmentStartNumber}`,
|
|
||||||
"-hls_playlist_type vod",
|
|
||||||
"-hls_list_size 0",
|
|
||||||
"-hls_allow_cache 0"
|
|
||||||
])
|
|
||||||
var segmentFilename = Path.join(testDir, 'output-%d.ts')
|
|
||||||
ffmpeg.addOption(`-hls_segment_filename ${segmentFilename}`)
|
|
||||||
ffmpeg.output(playlistPath)
|
|
||||||
|
|
||||||
ffmpeg.on('start', (command) => {
|
|
||||||
Logger.info('[FFMPEG-START] FFMPEG transcoding started with command: ' + command)
|
|
||||||
})
|
|
||||||
ffmpeg.on('stderr', (stdErrline) => {
|
|
||||||
Logger.info('[FFMPEG-STDERR]', stdErrline)
|
|
||||||
})
|
|
||||||
ffmpeg.on('error', (err, stdout, stderr) => {
|
|
||||||
Logger.info('[FFMPEG-ERROR]', err)
|
|
||||||
})
|
|
||||||
ffmpeg.on('end', (stdout, stderr) => {
|
|
||||||
Logger.info('[FFMPEG] Transcode ended')
|
|
||||||
})
|
|
||||||
ffmpeg.run()
|
|
||||||
}
|
|
||||||
module.exports.start = start
|
|
@ -40,6 +40,10 @@ async function getAllAudiobookFiles(abRootPath) {
|
|||||||
|
|
||||||
// If relative file directory has 3 folders, then the middle folder will be series
|
// If relative file directory has 3 folders, then the middle folder will be series
|
||||||
var splitDir = pathformat.dir.split(Path.sep)
|
var splitDir = pathformat.dir.split(Path.sep)
|
||||||
|
if (splitDir.length === 1) {
|
||||||
|
Logger.error('Invalid file in root dir', filepath)
|
||||||
|
return
|
||||||
|
}
|
||||||
var author = splitDir.shift()
|
var author = splitDir.shift()
|
||||||
var series = null
|
var series = null
|
||||||
if (splitDir.length > 1) series = splitDir.shift()
|
if (splitDir.length > 1) series = splitDir.shift()
|
||||||
|
Loading…
Reference in New Issue
Block a user