3737 @change =" saveSelectedQuality ()"
3838 />
3939 </div >
40+ <div v-if =" audioTracks && audioTracks.length > 0" class =" download-video-config-item" >
41+ <div class =" download-video-config-title" >AI 原声翻译:</div >
42+ <VDropdown
43+ v-model =" selectedAudioTrack "
44+ :items =" audioTrackOptions "
45+ value-key="name"
46+ @change =" saveSelectedAudioTrack ()"
47+ />
48+ </div >
4049 <template v-if =" ! testData .multiple && selectedQuality " >
4150 <div v-if =" testData.videoInfo" class =" download-video-config-description" >
4251 预计大小: {{ formatFileSize(testData.videoInfo.totalSize) }}
@@ -166,6 +175,8 @@ const getFallbackTestVideoInfo = () =>
166175 title: getFriendlyTitle (true ),
167176 } as DownloadVideoInputItem )
168177
178+ const DEFAULT_AUDIO_TRACK = { name: ' ' , displayName: ' 原声' }
179+
169180export default Vue .extend ({
170181 components: {
171182 VPopup ,
@@ -199,6 +210,8 @@ export default Vue.extend({
199210 assets ,
200211 qualities: [],
201212 selectedQuality: undefined ,
213+ audioTracks: [],
214+ selectedAudioTrack: undefined ,
202215 inputs: [],
203216 selectedInput: undefined ,
204217 apis: [],
@@ -220,12 +233,19 @@ export default Vue.extend({
220233 }
221234 return this .qualities
222235 },
236+ audioTrackOptions() {
237+ const options = this .audioTracks .map (t => ({ name: t .id , displayName: t .name }))
238+ if (options .length > 0 ) {
239+ options .unshift (DEFAULT_AUDIO_TRACK )
240+ }
241+ return options
242+ },
223243 canStartDownload() {
224244 if (this .busy || ! this .open ) {
225245 return false
226246 }
227247 const isAnySelectionEmpty = Object .entries (this )
228- .filter (([key ]) => key .startsWith (' selected' ))
248+ .filter (([key ]) => key .startsWith (' selected' ) && key !== ' selectedAudioTrack ' )
229249 .some (([, value ]) => ! value )
230250 if (isAnySelectionEmpty ) {
231251 return false
@@ -289,6 +309,11 @@ export default Vue.extend({
289309 basicConfig .quality = quality .value
290310 this .updateTestVideoInfo ()
291311 },
312+ saveSelectedAudioTrack() {
313+ // 避免冗余请求:这里不再使用引用对比,依赖 VDropdown 的 value-key="name" 属性
314+ // 它能够正确阻止触发不需要的 change 事件
315+ this .updateTestVideoInfo ()
316+ },
292317 async getVideoItems() {
293318 const input = this .selectedInput as DownloadVideoInput
294319 const videoItems = await input .getInputs (this .$refs .inputOptions )
@@ -307,6 +332,8 @@ export default Vue.extend({
307332 try {
308333 const videoInfo = await api .downloadVideoInfo (testItem )
309334 this .qualities = videoInfo .qualities
335+ this .audioTracks = videoInfo .audioTracks || []
336+
310337 const isSelectedQualityOutdated =
311338 ! this .selectedQuality ||
312339 ! videoInfo .qualities .some (q => q .value === this .selectedQuality .value )
@@ -319,8 +346,22 @@ export default Vue.extend({
319346 }
320347 }
321348 }
349+
350+ const isSelectedAudioTrackOutdated =
351+ ! this .selectedAudioTrack ||
352+ (this .selectedAudioTrack .name !== ' ' &&
353+ ! this .audioTracks .some (t => t .id === this .selectedAudioTrack .name ))
354+
355+ if (isSelectedAudioTrackOutdated ) {
356+ if (this .audioTracks .length > 0 ) {
357+ this .selectedAudioTrack = DEFAULT_AUDIO_TRACK
358+ } else {
359+ this .selectedAudioTrack = undefined
360+ }
361+ }
322362 // 填充 quality 后要再请求一次得到对应 quality 的统计数据
323363 testItem .quality = this .selectedQuality
364+ testItem .audioTrack = this .selectedAudioTrack ?.name
324365 const qualityVideoInfo = await api .downloadVideoInfo (testItem )
325366 this .testData .videoInfo = qualityVideoInfo
326367 console .log (' [qualityVideoInfo]' , qualityVideoInfo )
@@ -341,6 +382,7 @@ export default Vue.extend({
341382 }
342383 videoInputs .forEach (item => {
343384 item .quality = this .selectedQuality
385+ item .audioTrack = this .selectedAudioTrack ?.name
344386 })
345387 const videoInfos = await Promise .all (videoInputs .map (i => api .downloadVideoInfo (i )))
346388 if (videoInfos .length === 0 || lodash .sumBy (videoInfos , it => it .fragments .length ) === 0 ) {
0 commit comments