mirror of
				https://github.com/advplyr/audiobookshelf.git
				synced 2025-10-27 11:18:14 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			212 lines
		
	
	
		
			7.1 KiB
		
	
	
	
		
			Vue
		
	
	
	
	
	
			
		
		
	
	
			212 lines
		
	
	
		
			7.1 KiB
		
	
	
	
		
			Vue
		
	
	
	
	
	
| <template>
 | |
|   <div class="w-full py-2">
 | |
|     <div class="flex -mb-px">
 | |
|       <button type="button" :disabled="disabled" class="w-1/2 h-8 rounded-tl-md relative border border-black-200 flex items-center justify-center disabled:cursor-not-allowed" :class="!showAdvancedView ? 'text-white bg-bg hover:bg-bg/60 border-b-bg' : 'text-gray-400 hover:text-gray-300 bg-primary/70 hover:bg-primary/60'" @click="showAdvancedView = false">
 | |
|         <p class="text-sm">{{ $strings.HeaderPresets }}</p>
 | |
|       </button>
 | |
|       <button type="button" :disabled="disabled" class="w-1/2 h-8 rounded-tr-md relative border border-black-200 flex items-center justify-center -ml-px disabled:cursor-not-allowed" :class="showAdvancedView ? 'text-white bg-bg hover:bg-bg/60 border-b-bg' : 'text-gray-400 hover:text-gray-300 bg-primary/70 hover:bg-primary/60'" @click="showAdvancedView = true">
 | |
|         <p class="text-sm">{{ $strings.HeaderAdvanced }}</p>
 | |
|       </button>
 | |
|     </div>
 | |
|     <div class="p-4 md:p-8 border border-black-200 rounded-b-md mr-px bg-bg">
 | |
|       <template v-if="!showAdvancedView">
 | |
|         <div class="flex flex-wrap gap-4 sm:gap-8 justify-start sm:justify-center">
 | |
|           <div class="flex flex-col items-start gap-2">
 | |
|             <p class="text-sm w-40">{{ $strings.LabelCodec }}</p>
 | |
|             <ui-toggle-btns v-model="selectedCodec" :items="codecItems" :disabled="disabled" />
 | |
|             <p class="text-xs text-gray-300">
 | |
|               {{ $strings.LabelCurrently }} <span class="text-white">{{ currentCodec }}</span> <span v-if="isCodecsDifferent" class="text-warning">(mixed)</span>
 | |
|             </p>
 | |
|           </div>
 | |
|           <div class="flex flex-col items-start gap-2">
 | |
|             <p class="text-sm w-40">{{ $strings.LabelBitrate }}</p>
 | |
|             <ui-toggle-btns v-model="selectedBitrate" :items="bitrateItems" :disabled="disabled" />
 | |
|             <p class="text-xs text-gray-300">
 | |
|               {{ $strings.LabelCurrently }} <span class="text-white">{{ currentBitrate }} KB/s</span>
 | |
|             </p>
 | |
|           </div>
 | |
|           <div class="flex flex-col items-start gap-2">
 | |
|             <p class="text-sm w-40">{{ $strings.LabelChannels }}</p>
 | |
|             <ui-toggle-btns v-model="selectedChannels" :items="channelsItems" :disabled="disabled" />
 | |
|             <p class="text-xs text-gray-300">
 | |
|               {{ $strings.LabelCurrently }} <span class="text-white">{{ currentChannels }} ({{ currentChanelLayout }})</span>
 | |
|             </p>
 | |
|           </div>
 | |
|         </div>
 | |
|       </template>
 | |
|       <template v-else>
 | |
|         <div>
 | |
|           <div class="flex flex-wrap gap-4 sm:gap-8 justify-start sm:justify-center mb-4">
 | |
|             <div class="w-40">
 | |
|               <ui-text-input-with-label v-model="customCodec" :label="$strings.LabelAudioCodec" :disabled="disabled" @input="customCodecChanged" />
 | |
|             </div>
 | |
|             <div class="w-40">
 | |
|               <ui-text-input-with-label v-model="customBitrate" :label="$strings.LabelAudioBitrate" :disabled="disabled" @input="customBitrateChanged" />
 | |
|             </div>
 | |
|             <div class="w-40">
 | |
|               <ui-text-input-with-label v-model="customChannels" :label="$strings.LabelAudioChannels" type="number" :disabled="disabled" @input="customChannelsChanged" />
 | |
|             </div>
 | |
|           </div>
 | |
|           <p class="text-xs sm:text-sm text-warning sm:text-center">{{ $strings.LabelEncodingWarningAdvancedSettings }}</p>
 | |
|         </div>
 | |
|       </template>
 | |
|     </div>
 | |
|   </div>
 | |
| </template>
 | |
| 
 | |
| <script>
 | |
| export default {
 | |
|   props: {
 | |
|     audioTracks: {
 | |
|       type: Array,
 | |
|       default: () => []
 | |
|     },
 | |
|     disabled: {
 | |
|       type: Boolean,
 | |
|       default: false
 | |
|     }
 | |
|   },
 | |
|   data() {
 | |
|     return {
 | |
|       showAdvancedView: false,
 | |
|       selectedCodec: 'aac',
 | |
|       selectedBitrate: '128k',
 | |
|       selectedChannels: 2,
 | |
|       customCodec: 'aac',
 | |
|       customBitrate: '128k',
 | |
|       customChannels: 2,
 | |
|       currentCodec: '',
 | |
|       currentBitrate: '',
 | |
|       currentChannels: '',
 | |
|       currentChanelLayout: '',
 | |
|       isCodecsDifferent: false
 | |
|     }
 | |
|   },
 | |
|   computed: {
 | |
|     codecItems() {
 | |
|       return [
 | |
|         {
 | |
|           text: 'Copy',
 | |
|           value: 'copy'
 | |
|         },
 | |
|         {
 | |
|           text: 'AAC',
 | |
|           value: 'aac'
 | |
|         },
 | |
|         {
 | |
|           text: 'OPUS',
 | |
|           value: 'opus'
 | |
|         }
 | |
|       ]
 | |
|     },
 | |
|     bitrateItems() {
 | |
|       return [
 | |
|         {
 | |
|           text: '32k',
 | |
|           value: '32k'
 | |
|         },
 | |
|         {
 | |
|           text: '64k',
 | |
|           value: '64k'
 | |
|         },
 | |
|         {
 | |
|           text: '128k',
 | |
|           value: '128k'
 | |
|         },
 | |
|         {
 | |
|           text: '192k',
 | |
|           value: '192k'
 | |
|         }
 | |
|       ]
 | |
|     },
 | |
|     channelsItems() {
 | |
|       return [
 | |
|         {
 | |
|           text: '1 (mono)',
 | |
|           value: 1
 | |
|         },
 | |
|         {
 | |
|           text: '2 (stereo)',
 | |
|           value: 2
 | |
|         }
 | |
|       ]
 | |
|     }
 | |
|   },
 | |
|   methods: {
 | |
|     customBitrateChanged(val) {
 | |
|       localStorage.setItem('embedMetadataBitrate', val)
 | |
|     },
 | |
|     customChannelsChanged(val) {
 | |
|       localStorage.setItem('embedMetadataChannels', val)
 | |
|     },
 | |
|     customCodecChanged(val) {
 | |
|       localStorage.setItem('embedMetadataCodec', val)
 | |
|     },
 | |
|     getEncodingOptions() {
 | |
|       return {
 | |
|         codec: this.selectedCodec || 'aac',
 | |
|         bitrate: this.selectedBitrate || '128k',
 | |
|         channels: this.selectedChannels || 2
 | |
|       }
 | |
|     },
 | |
|     setPreset() {
 | |
|       // If already AAC and not mixed, set copy
 | |
|       if (this.currentCodec === 'aac' && !this.isCodecsDifferent) {
 | |
|         this.selectedCodec = 'copy'
 | |
|       } else {
 | |
|         this.selectedCodec = 'aac'
 | |
|       }
 | |
| 
 | |
|       if (!this.currentBitrate) {
 | |
|         this.selectedBitrate = '128k'
 | |
|       } else {
 | |
|         // Find closest bitrate rounding up
 | |
|         const bitratesToMatch = [32, 64, 128, 192]
 | |
|         const closestBitrate = bitratesToMatch.find((bitrate) => bitrate >= this.currentBitrate)
 | |
|         this.selectedBitrate = closestBitrate + 'k'
 | |
|       }
 | |
| 
 | |
|       if (!this.currentChannels || isNaN(this.currentChannels)) {
 | |
|         this.selectedChannels = 2
 | |
|       } else {
 | |
|         // Either 1 or 2
 | |
|         this.selectedChannels = Math.max(Math.min(Number(this.currentChannels), 2), 1)
 | |
|       }
 | |
|     },
 | |
|     setCurrentValues() {
 | |
|       if (this.audioTracks.length === 0) return
 | |
| 
 | |
|       this.currentChannels = this.audioTracks[0].channels
 | |
|       this.currentChanelLayout = this.audioTracks[0].channelLayout
 | |
|       this.currentCodec = this.audioTracks[0].codec
 | |
| 
 | |
|       let totalBitrate = 0
 | |
|       for (const track of this.audioTracks) {
 | |
|         const trackBitrate = !isNaN(track.bitRate) ? track.bitRate : 0
 | |
|         totalBitrate += trackBitrate
 | |
| 
 | |
|         if (track.channels > this.currentChannels) this.currentChannels = track.channels
 | |
|         if (track.codec !== this.currentCodec) {
 | |
|           console.warn('Audio track codec is different from the first track', track.codec)
 | |
|           this.isCodecsDifferent = true
 | |
|         }
 | |
|       }
 | |
| 
 | |
|       this.currentBitrate = Math.round(totalBitrate / this.audioTracks.length / 1000)
 | |
|     },
 | |
|     init() {
 | |
|       this.customBitrate = localStorage.getItem('embedMetadataBitrate') || '128k'
 | |
|       this.customChannels = localStorage.getItem('embedMetadataChannels') || 2
 | |
|       this.customCodec = localStorage.getItem('embedMetadataCodec') || 'aac'
 | |
| 
 | |
|       this.setCurrentValues()
 | |
| 
 | |
|       this.setPreset()
 | |
|     }
 | |
|   },
 | |
|   mounted() {
 | |
|     this.init()
 | |
|   }
 | |
| }
 | |
| </script>
 |