mirror of
https://github.com/advplyr/audiobookshelf.git
synced 2026-03-01 13:39:41 +00:00
112 lines
3.4 KiB
JavaScript
112 lines
3.4 KiB
JavaScript
const { expect } = require('chai')
|
|
const sinon = require('sinon')
|
|
const EventEmitter = require('events')
|
|
const fs = require('../../../server/libs/fsExtra')
|
|
const { mergeAudioFiles } = require('../../../server/utils/ffmpegHelpers')
|
|
|
|
describe('mergeAudioFiles', () => {
|
|
let ffmpegStub
|
|
let audioTracks
|
|
let encodingOptions
|
|
let itemCachePath
|
|
let outputFilePath
|
|
|
|
beforeEach(() => {
|
|
ffmpegStub = new EventEmitter()
|
|
ffmpegStub.input = sinon.stub().returnsThis()
|
|
ffmpegStub.inputOptions = sinon.stub().returnsThis()
|
|
ffmpegStub.outputOptions = sinon.stub().returnsThis()
|
|
ffmpegStub.output = sinon.stub().returnsThis()
|
|
ffmpegStub.run = sinon.stub().callsFake(() => {
|
|
ffmpegStub.emit('end')
|
|
})
|
|
|
|
audioTracks = [
|
|
{
|
|
index: 0,
|
|
ino: 'ino1',
|
|
metadata: { path: '/path/to/track1.mp3', ext: '.mp3' },
|
|
duration: 100
|
|
},
|
|
{
|
|
index: 1,
|
|
ino: 'ino2',
|
|
metadata: { path: '/path/to/track2.mp3', ext: '.mp3' },
|
|
duration: 120
|
|
}
|
|
]
|
|
|
|
encodingOptions = {
|
|
codec: 'aac',
|
|
bitrate: '128k',
|
|
channels: 2
|
|
}
|
|
|
|
itemCachePath = '/path/to/cache'
|
|
outputFilePath = '/path/to/output.m4b'
|
|
|
|
sinon.stub(fs, 'writeFile').resolves()
|
|
sinon.stub(fs, 'remove').resolves()
|
|
})
|
|
|
|
afterEach(() => {
|
|
sinon.restore()
|
|
})
|
|
|
|
it('should use re-encoding by default (codec aac)', async () => {
|
|
await mergeAudioFiles(audioTracks, 220, itemCachePath, outputFilePath, encodingOptions, null, ffmpegStub)
|
|
|
|
const calls = ffmpegStub.outputOptions.getCalls()
|
|
const allArgs = calls.flatMap(call => call.args[0])
|
|
|
|
expect(allArgs).to.include('-acodec aac')
|
|
expect(allArgs).to.include('-ac 2')
|
|
expect(allArgs).to.include('-b:a 128k')
|
|
})
|
|
|
|
it('should use stream copy when codec is copy', async () => {
|
|
encodingOptions.codec = 'copy'
|
|
|
|
await mergeAudioFiles(audioTracks, 220, itemCachePath, outputFilePath, encodingOptions, null, ffmpegStub)
|
|
|
|
// Should hit the 'else' block which uses '-c:a copy'
|
|
expect(ffmpegStub.outputOptions.calledWith(['-c:a copy'])).to.be.true
|
|
|
|
// Should NOT contain bitrate or channels or acodec
|
|
const outputOptionsCalls = ffmpegStub.outputOptions.getCalls()
|
|
outputOptionsCalls.forEach(call => {
|
|
const args = call.args[0]
|
|
if (Array.isArray(args)) {
|
|
expect(args.some(arg => arg.includes('-b:a'))).to.be.false
|
|
expect(args.some(arg => arg.includes('-ac '))).to.be.false // space to avoid matching '-acodec'
|
|
expect(args.some(arg => arg.includes('-acodec'))).to.be.false
|
|
}
|
|
})
|
|
})
|
|
|
|
it('should handle single track with copy', async () => {
|
|
encodingOptions.codec = 'copy'
|
|
const singleTrack = [audioTracks[0]]
|
|
|
|
await mergeAudioFiles(singleTrack, 100, itemCachePath, outputFilePath, encodingOptions, null, ffmpegStub)
|
|
|
|
expect(ffmpegStub.outputOptions.calledWith(['-c:a copy'])).to.be.true
|
|
})
|
|
|
|
it('should handle single track m4b with copy', async () => {
|
|
encodingOptions.codec = 'copy'
|
|
const singleTrack = [
|
|
{
|
|
index: 0,
|
|
ino: 'ino1',
|
|
metadata: { path: '/path/to/track1.m4b', ext: '.m4b' },
|
|
duration: 100
|
|
}
|
|
]
|
|
|
|
await mergeAudioFiles(singleTrack, 100, itemCachePath, outputFilePath, encodingOptions, null, ffmpegStub)
|
|
|
|
// Code says: if (isOneTrack && firstTrackIsM4b) ffmpeg.outputOptions(['-c copy'])
|
|
expect(ffmpegStub.outputOptions.calledWith(['-c copy'])).to.be.true
|
|
})
|
|
})
|