diff --git a/server/managers/AbMergeManager.js b/server/managers/AbMergeManager.js
index 1b3801c0..25e571e2 100644
--- a/server/managers/AbMergeManager.js
+++ b/server/managers/AbMergeManager.js
@@ -120,20 +120,22 @@ class AbMergeManager {
       }
     }
 
-    var chaptersFilePath = null
-    if (libraryItem.media.chapters.length) {
-      chaptersFilePath = Path.join(task.data.itemCachePath, 'chapters.txt')
-      try {
-        await toneHelpers.writeToneChaptersFile(libraryItem.media.chapters, chaptersFilePath)
-      } catch (error) {
-        Logger.error(`[AbMergeManager] Write chapters.txt failed`, error)
-        chaptersFilePath = null
-      }
+    var toneJsonPath = null
+    try {
+      toneJsonPath = Path.join(itemCacheDir, 'metadata.json')
+      await toneHelpers.writeToneMetadataJsonFile(libraryItem, toneJsonPath)
+    } catch (error) {
+      Logger.error(`[AudioMetadataManager] Write metadata.json failed`, error)
+      toneJsonPath = null
     }
 
     const toneMetadataObject = toneHelpers.getToneMetadataObject(libraryItem, chaptersFilePath)
     toneMetadataObject.TrackNumber = 1
     task.data.toneMetadataObject = toneMetadataObject
+    task.data.toneJsonObject = {
+      'ToneJsonFile': toneJsonPath,
+      'TrackNumber': 1,
+    }
 
     Logger.debug(`[AbMergeManager] Book "${libraryItem.media.metadata.title}" tone metadata object=`, toneMetadataObject)
 
@@ -190,7 +192,7 @@ class AbMergeManager {
     }
 
     // Write metadata to merged file
-    const success = await toneHelpers.tagAudioFile(task.data.tempFilepath, task.data.toneMetadataObject)
+    const success = await toneHelpers.tagAudioFile(task.data.tempFilepath, task.data.toneJsonObject)
     if (!success) {
       Logger.error(`[AbMergeManager] Failed to write metadata to file "${task.data.tempFilepath}"`)
       task.setFailed('Failed to write metadata to m4b file')
diff --git a/server/managers/AudioMetadataManager.js b/server/managers/AudioMetadataManager.js
index 02a44ce1..bcf51aed 100644
--- a/server/managers/AudioMetadataManager.js
+++ b/server/managers/AudioMetadataManager.js
@@ -43,23 +43,18 @@ class AudioMetadataMangaer {
     this.emitter('audio_metadata_started', itemAudioMetadataPayload)
 
     // Write chapters file
-    var chaptersFilePath = null
+    var toneJsonPath = null
     const itemCacheDir = Path.join(global.MetadataPath, `cache/items/${libraryItem.id}`)
     await fs.ensureDir(itemCacheDir)
 
-    if (libraryItem.media.chapters.length) {
-      chaptersFilePath = Path.join(itemCacheDir, 'chapters.txt')
-      try {
-        await toneHelpers.writeToneChaptersFile(libraryItem.media.chapters, chaptersFilePath)
-      } catch (error) {
-        Logger.error(`[AudioMetadataManager] Write chapters.txt failed`, error)
-        chaptersFilePath = null
-      }
+    try {
+      toneJsonPath = Path.join(itemCacheDir, 'metadata.json')
+      await toneHelpers.writeToneMetadataJsonFile(libraryItem, toneJsonPath)
+    } catch (error) {
+      Logger.error(`[AudioMetadataManager] Write metadata.json failed`, error)
+      toneJsonPath = null
     }
 
-    const toneMetadataObject = toneHelpers.getToneMetadataObject(libraryItem, chaptersFilePath)
-    Logger.debug(`[AudioMetadataManager] Book "${libraryItem.media.metadata.title}" tone metadata object=`, toneMetadataObject)
-
     const results = []
     for (const af of audioFiles) {
       const result = await this.updateAudioFileMetadataWithTone(libraryItem.id, af, toneMetadataObject, itemCacheDir)
@@ -74,7 +69,7 @@ class AudioMetadataMangaer {
     this.emitter('audio_metadata_finished', itemAudioMetadataPayload)
   }
 
-  async updateAudioFileMetadataWithTone(libraryItemId, audioFile, toneMetadataObject, itemCacheDir) {
+  async updateAudioFileMetadataWithTone(libraryItemId, audioFile, toneJsonPath, itemCacheDir) {
     const resultPayload = {
       libraryItemId,
       index: audioFile.index,
@@ -93,8 +88,8 @@ class AudioMetadataMangaer {
     }
 
     const _toneMetadataObject = {
-      ...toneMetadataObject,
-      'TrackNumber': audioFile.index
+      'ToneJsonFile': toneJsonPath,
+      'TrackNumber': audioFile.index,
     }
 
     resultPayload.success = await toneHelpers.tagAudioFile(audioFile.metadata.path, _toneMetadataObject)
diff --git a/server/utils/toneHelpers.js b/server/utils/toneHelpers.js
index fc88c169..54add6bd 100644
--- a/server/utils/toneHelpers.js
+++ b/server/utils/toneHelpers.js
@@ -72,6 +72,71 @@ module.exports.getToneMetadataObject = (libraryItem, chaptersFile) => {
   return metadataObject
 }
 
+module.exports.writeToneMetadataJsonFile = (libraryItem, filePath) => {
+  const bookMetadata = libraryItem.media.metadata
+  const coverPath = libraryItem.media.coverPath
+  const chapters = libraryItem.media.chapters
+
+  const metadataObject = {
+    'album': bookMetadata.title || '',
+    'title': bookMetadata.title || '',
+    'trackTotal': libraryItem.media.tracks.length,
+    'additionalFields': {}
+  }
+  if (bookMetadata.subtitle) {
+    metadataObject['subtitle'] = bookMetadata.subtitle
+  }
+  if (bookMetadata.authorName) {
+    metadataObject['artist'] = bookMetadata.authorName
+    metadataObject['albumArtist'] = bookMetadata.authorName
+  }
+  if (bookMetadata.description) {
+    metadataObject['comment'] = bookMetadata.description
+    metadataObject['description'] = bookMetadata.description
+  }
+  if (bookMetadata.narratorName) {
+    metadataObject['narrator'] = bookMetadata.narratorName
+    metadataObject['composer'] = bookMetadata.narratorName
+  }
+  if (bookMetadata.firstSeriesName) {
+    metadataObject['movementName'] = bookMetadata.firstSeriesName
+  }
+  if (bookMetadata.firstSeriesSequence) {
+    metadataObject['movement'] = bookMetadata.firstSeriesSequence
+  }
+  if (bookMetadata.genres.length) {
+    metadataObject['genre'] = bookMetadata.genres.join('/')
+  }
+  if (bookMetadata.publisher) {
+    metadataObject['publisher'] = bookMetadata.publisher
+  }
+  if (bookMetadata.asin) {
+    metadataObject.additionalFields['asin'] = bookMetadata.asin
+  }
+  if (bookMetadata.isbn) {
+    metadataObject.additionalFields['isbn'] = bookMetadata.isbn
+  }
+  if (coverPath) {
+    metadataObject['coverFile'] = coverPath
+  }
+  if (parsePublishedYear(bookMetadata.publishedYear)) {
+    metadataObject['publishingDate'] = parsePublishedYear(bookMetadata.publishedYear)
+  }
+  if (chapters && chapters.length > 0) {
+    let metadataChapters = []
+    for (const chapter of chapters) {
+      metadataChapters.push({
+        start: chapter.start,
+        length: chapter.end - chapter.start,
+        title: chapter.title,
+      })
+    }
+    metadataObject['chapters'] = chaptersFile
+  }
+
+  return fs.writeFile(filePath, JSON.stringify({ metadata: metadataObject }))
+}
+
 module.exports.tagAudioFile = (filePath, payload) => {
   return tone.tag(filePath, payload).then((data) => {
     return true