mirror of
				https://github.com/advplyr/audiobookshelf.git
				synced 2025-10-27 11:18:14 +01:00 
			
		
		
		
	Fix: temp fix for aac codec error by forcing aac encode #172, Change: Failed streams will close the stream and show error
This commit is contained in:
		
							parent
							
								
									8316a8c18b
								
							
						
					
					
						commit
						ac72ec1317
					
				| @ -194,6 +194,13 @@ export default { | ||||
|         console.error('No Audio Ref') | ||||
|       } | ||||
|     }, | ||||
|     streamError(streamId) { | ||||
|       if (this.stream && (this.stream.id === streamId || streamId === 'n/a')) { | ||||
|         this.terminateStream() | ||||
|         this.$store.commit('clearStreamAudiobook', this.stream.audiobook.id) | ||||
|         this.stream = null | ||||
|       } | ||||
|     }, | ||||
|     sendStreamSync(syncData) { | ||||
|       var diff = syncData.currentTime - this.lastServerUpdateSentSeconds | ||||
|       if (Math.abs(diff) < 1 && !syncData.timeListened) { | ||||
|  | ||||
| @ -134,6 +134,10 @@ export default { | ||||
|     streamReset(payload) { | ||||
|       if (this.$refs.streamContainer) this.$refs.streamContainer.streamReset(payload) | ||||
|     }, | ||||
|     streamError({ id, errorMessage }) { | ||||
|       this.$toast.error(`Stream Failed: ${errorMessage}`) | ||||
|       if (this.$refs.streamContainer) this.$refs.streamContainer.streamError(id) | ||||
|     }, | ||||
|     audiobookAdded(audiobook) { | ||||
|       this.$store.commit('audiobooks/addUpdate', audiobook) | ||||
|     }, | ||||
| @ -327,6 +331,7 @@ export default { | ||||
|       this.socket.on('stream_progress', this.streamProgress) | ||||
|       this.socket.on('stream_ready', this.streamReady) | ||||
|       this.socket.on('stream_reset', this.streamReset) | ||||
|       this.socket.on('stream_error', this.streamError) | ||||
| 
 | ||||
|       // Audiobook Listeners | ||||
|       this.socket.on('audiobook_updated', this.audiobookUpdated) | ||||
|  | ||||
| @ -1,6 +1,6 @@ | ||||
| { | ||||
|   "name": "audiobookshelf-client", | ||||
|   "version": "1.6.16", | ||||
|   "version": "1.6.17", | ||||
|   "description": "Audiobook manager and player", | ||||
|   "main": "index.js", | ||||
|   "scripts": { | ||||
|  | ||||
| @ -1,6 +1,6 @@ | ||||
| { | ||||
|   "name": "audiobookshelf", | ||||
|   "version": "1.6.16", | ||||
|   "version": "1.6.17", | ||||
|   "description": "Self-hosted audiobook server for managing and playing audiobooks", | ||||
|   "main": "index.js", | ||||
|   "scripts": { | ||||
|  | ||||
| @ -28,8 +28,12 @@ class StreamManager { | ||||
|     this.streams = this.streams.filter(s => s.id !== stream.id) | ||||
|   } | ||||
| 
 | ||||
|   async openStream(client, audiobook) { | ||||
|     var stream = new Stream(this.StreamsPath, client, audiobook) | ||||
|   async openStream(client, audiobook, transcodeOptions = {}) { | ||||
|     if (!client || !client.user) { | ||||
|       Logger.error('[StreamManager] Cannot open stream invalid client', client) | ||||
|       return | ||||
|     } | ||||
|     var stream = new Stream(this.StreamsPath, client, audiobook, transcodeOptions) | ||||
| 
 | ||||
|     stream.on('closed', () => { | ||||
|       this.removeStream(stream) | ||||
|  | ||||
| @ -10,13 +10,15 @@ const hlsPlaylistGenerator = require('../utils/hlsPlaylistGenerator') | ||||
| const UserListeningSession = require('./UserListeningSession') | ||||
| 
 | ||||
| class Stream extends EventEmitter { | ||||
|   constructor(streamPath, client, audiobook) { | ||||
|   constructor(streamPath, client, audiobook, transcodeOptions = {}) { | ||||
|     super() | ||||
| 
 | ||||
|     this.id = (Date.now() + Math.trunc(Math.random() * 1000)).toString(36) | ||||
|     this.client = client | ||||
|     this.audiobook = audiobook | ||||
| 
 | ||||
|     this.transcodeOptions = transcodeOptions | ||||
| 
 | ||||
|     this.segmentLength = 6 | ||||
|     this.maxSeekBackTime = 30 | ||||
|     this.streamPath = Path.join(streamPath, this.id) | ||||
| @ -110,6 +112,14 @@ class Stream extends EventEmitter { | ||||
|     return Number(prog.toFixed(3)) | ||||
|   } | ||||
| 
 | ||||
|   get isAACEncodable() { | ||||
|     return ['mp4', 'm4a', 'm4b'].includes(this.tracksAudioFileType) | ||||
|   } | ||||
| 
 | ||||
|   get transcodeForceAAC() { | ||||
|     return !!this.transcodeOptions.forceAAC | ||||
|   } | ||||
| 
 | ||||
|   toJSON() { | ||||
|     return { | ||||
|       id: this.id, | ||||
| @ -314,8 +324,8 @@ class Stream extends EventEmitter { | ||||
|       this.ffmpeg.inputOption('-noaccurate_seek') | ||||
|     } | ||||
| 
 | ||||
|     const logLevel = process.env.NODE_ENV === 'production' ? 'error' : 'error' | ||||
|     const audioCodec = (this.hlsSegmentType === 'fmp4' || this.tracksAudioFileType === 'opus') ? 'aac' : 'copy' | ||||
|     const logLevel = process.env.NODE_ENV === 'production' ? 'error' : 'warning' | ||||
|     const audioCodec = (this.hlsSegmentType === 'fmp4' || this.tracksAudioFileType === 'opus' || this.transcodeForceAAC) ? 'aac' : 'copy' | ||||
|     this.ffmpeg.addOption([ | ||||
|       `-loglevel ${logLevel}`, | ||||
|       '-map 0:a', | ||||
| @ -349,11 +359,13 @@ class Stream extends EventEmitter { | ||||
|       Logger.info('[INFO] FFMPEG transcoding started with command: ' + command) | ||||
|       Logger.info('') | ||||
|       if (this.isResetting) { | ||||
|         // AAC encode is much slower
 | ||||
|         const clearIsResettingTime = this.transcodeForceAAC ? 3000 : 500 | ||||
|         setTimeout(() => { | ||||
|           Logger.info('[STREAM] Clearing isResetting') | ||||
|           this.isResetting = false | ||||
|           this.startLoop() | ||||
|         }, 500) | ||||
|         }, clearIsResettingTime) | ||||
|       } else { | ||||
|         this.startLoop() | ||||
|       } | ||||
| @ -368,10 +380,21 @@ class Stream extends EventEmitter { | ||||
|         // This is an intentional SIGKILL
 | ||||
|         Logger.info('[FFMPEG] Transcode Killed') | ||||
|         this.ffmpeg = null | ||||
|         clearInterval(this.loop) | ||||
|       } else { | ||||
|         Logger.error('Ffmpeg Err', err.message) | ||||
|         Logger.error('Ffmpeg Err', '"' + err.message + '"') | ||||
| 
 | ||||
|         // Temporary workaround for https://github.com/advplyr/audiobookshelf/issues/172
 | ||||
|         const aacErrorMsg = 'ffmpeg exited with code 1: Could not write header for output file #0 (incorrect codec parameters ?)' | ||||
|         if (audioCodec === 'copy' && this.isAACEncodable && err.message && err.message.startsWith(aacErrorMsg)) { | ||||
|           Logger.info(`[Stream] Re-attempting stream with AAC encode`) | ||||
|           this.transcodeOptions.forceAAC = true | ||||
|           this.reset(this.startTime) | ||||
|         } else { | ||||
|           // Close stream show error
 | ||||
|           this.close(err.message) | ||||
|         } | ||||
|       } | ||||
|       clearInterval(this.loop) | ||||
|     }) | ||||
| 
 | ||||
|     this.ffmpeg.on('end', (stdout, stderr) => { | ||||
| @ -392,7 +415,7 @@ class Stream extends EventEmitter { | ||||
|     this.ffmpeg.run() | ||||
|   } | ||||
| 
 | ||||
|   async close() { | ||||
|   async close(errorMessage = null) { | ||||
|     clearInterval(this.loop) | ||||
| 
 | ||||
|     Logger.info('Closing Stream', this.id) | ||||
| @ -407,7 +430,8 @@ class Stream extends EventEmitter { | ||||
|     }) | ||||
| 
 | ||||
|     if (this.socket) { | ||||
|       this.socket.emit('stream_closed', this.id) | ||||
|       if (errorMessage) this.socket.emit('stream_error', { id: this.id, error: (errorMessage || '').trim() }) | ||||
|       else this.socket.emit('stream_closed', this.id) | ||||
|     } | ||||
| 
 | ||||
|     this.emit('closed') | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user