mirror of
https://github.com/advplyr/audiobookshelf.git
synced 2025-08-03 17:54:54 +02:00
Use local image as cover if found, adding release-it version control
This commit is contained in:
parent
7d4e2e3d97
commit
f30fa2fb0c
18 changed files with 2200 additions and 142 deletions
|
@ -1,3 +1,4 @@
|
|||
const Path = require('path')
|
||||
class Book {
|
||||
constructor(book = null) {
|
||||
this.olid = null
|
||||
|
@ -42,7 +43,6 @@ class Book {
|
|||
}
|
||||
|
||||
setData(data) {
|
||||
console.log('SET DATA', data)
|
||||
this.olid = data.olid || null
|
||||
this.title = data.title || null
|
||||
this.author = data.author || null
|
||||
|
@ -51,6 +51,14 @@ class Book {
|
|||
this.description = data.description || null
|
||||
this.cover = data.cover || null
|
||||
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) {
|
||||
|
|
|
@ -13,7 +13,6 @@ const ApiController = require('./ApiController')
|
|||
const HlsController = require('./HlsController')
|
||||
const StreamManager = require('./StreamManager')
|
||||
const Logger = require('./Logger')
|
||||
const streamTest = require('./streamTest')
|
||||
|
||||
class Server {
|
||||
constructor(PORT, CONFIG_PATH, METADATA_PATH, AUDIOBOOK_PATH) {
|
||||
|
@ -110,7 +109,6 @@ class Server {
|
|||
const distPath = Path.join(global.appRoot, '/client/dist')
|
||||
app.use(express.static(distPath))
|
||||
}
|
||||
|
||||
app.use(express.static(this.AudiobookPath))
|
||||
app.use(express.static(this.MetadataPath))
|
||||
app.use(express.urlencoded({ extended: true }));
|
||||
|
@ -122,13 +120,6 @@ class Server {
|
|||
app.get('/', (req, res) => {
|
||||
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('/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
|
||||
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 series = null
|
||||
if (splitDir.length > 1) series = splitDir.shift()
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue