瀏覽代碼

生词组件增加自动生成音频功能

natasha 1 周之前
父節點
當前提交
40df49d9fc

+ 94 - 54
src/views/book/courseware/create/components/question/article/NewWord.vue

@@ -201,13 +201,16 @@
       </div>
     </div>
     <el-button icon="el-icon-plus" style="margin: 24px 0" @click="addElement">增加一个</el-button>
-    <SelectUpload
-      label="生词音频"
-      type="audio"
-      width="500px"
-      :style="{ marginBottom: data.audio_data.url.length === 0 ? '5px' : '' }"
-      @uploadSuccess="uploadAudioSuccess"
-    />
+    <div class="btn-box">
+      <SelectUpload
+        label="生词音频"
+        type="audio"
+        width="500px"
+        :style="{ marginBottom: data.audio_data.url.length === 0 ? '5px' : '' }"
+        @uploadSuccess="uploadAudioSuccess"
+      />
+      <el-button :loading="autoLoading" @click="handleAutoAudio">自动生成音频</el-button>
+    </div>
     <div v-if="data.audio_data.url.length > 0" class="upload-file">
       <div class="file-name">
         <span>
@@ -264,28 +267,26 @@
         </el-select>
       </el-form-item>
 
-      <template v-if="data.property.audio_generation_method === 'auto'">
-        <el-form-item label="音色">
-          <el-select v-model="data.property.voice_type" placeholder="请选择">
-            <el-option
-              v-for="{ voice_type, name } in voice_type_list"
-              :key="voice_type"
-              :label="name"
-              :value="voice_type"
-            />
-          </el-select>
-        </el-form-item>
-        <el-form-item label="风格情感">
-          <el-select v-model="data.property.emotion">
-            <el-option v-for="{ emotion, name } in emotion_list" :key="emotion" :label="name" :value="emotion" />
-          </el-select>
-        </el-form-item>
-        <el-form-item label="语速">
-          <el-select v-model="data.property.speed_ratio">
-            <el-option v-for="{ value, label } in speedRatioList" :key="value" :label="label" :value="value" />
-          </el-select>
-        </el-form-item>
-      </template>
+      <el-form-item label="音色">
+        <el-select v-model="data.property.voice_type" placeholder="请选择">
+          <el-option
+            v-for="{ voice_type, name } in voice_type_list"
+            :key="voice_type"
+            :label="name"
+            :value="voice_type"
+          />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="风格情感">
+        <el-select v-model="data.property.emotion">
+          <el-option v-for="{ emotion, name } in emotion_list" :key="emotion" :label="name" :value="emotion" />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="语速">
+        <el-select v-model="data.property.speed_ratio">
+          <el-option v-for="{ value, label } in speedRatioList" :key="value" :label="label" :value="value" />
+        </el-select>
+      </el-form-item>
 
       <el-form-item label="拼音位置">
         <el-radio-group v-model="data.property.pinyin_position">
@@ -354,6 +355,7 @@ export default {
       voice_type_list: [],
       emotion_list: [],
       speedRatioList,
+      autoLoading: false,
     };
   },
   methods: {
@@ -423,30 +425,30 @@ export default {
           file_id,
         };
         this.data.file_id_list.push(file_id);
-        let _this = this;
-        _this.loading = true;
-        let data = {
-          file_id,
-        };
-        fileToBase64Text(data)
-          .then((res) => {
-            let taskIddata = {
-              fileName: name,
-              speechBase64: res.base64_text,
-              language: 'ch',
-            };
-            prepareTranscribe(taskIddata)
-              .then((reses) => {
-                _this.loading = false;
-                _this.$set(_this.data, 'taskId', reses.data.taskId);
-              })
-              .catch(() => {
-                _this.loading = false;
-              });
-          })
-          .catch(() => {
-            _this.loading = false;
-          });
+        // let _this = this;
+        // _this.loading = true;
+        // let data = {
+        //   file_id,
+        // };
+        // fileToBase64Text(data)
+        //   .then((res) => {
+        //     let taskIddata = {
+        //       fileName: name,
+        //       speechBase64: res.base64_text,
+        //       language: 'ch',
+        //     };
+        //     prepareTranscribe(taskIddata)
+        //       .then((reses) => {
+        //         _this.loading = false;
+        //         _this.$set(_this.data, 'taskId', reses.data.taskId);
+        //       })
+        //       .catch(() => {
+        //         _this.loading = false;
+        //       });
+        //   })
+        //   .catch(() => {
+        //     _this.loading = false;
+        //   });
       }
     },
     getBase64(file) {
@@ -588,7 +590,7 @@ export default {
       row.pinyin = cnchar.spell(cons, 'array', 'low', 'tone').join(' ');
     },
     createWordTimes() {
-      if (this.data.taskId) {
+      if (this.data.audio_data.file_id) {
         let text = '';
         this.data.new_word_list.forEach((sItem, index) => {
           // item.forEach((sItem, sIndex) => {
@@ -696,6 +698,38 @@ export default {
         })
         .catch(() => {});
     },
+    // 自动生成音频
+    handleAutoAudio() {
+      this.autoLoading = true;
+      let text = '';
+      this.data.new_word_list.forEach((sItem, index) => {
+        // item.forEach((sItem, sIndex) => {
+        text += `${sItem.new_word}。`;
+        // });
+      });
+      TextToAudioFile({
+        text: text,
+        voice_type: this.data.property.voice_type,
+        emotion: this.data.property.emotion,
+        speed_ratio: this.data.property.speed_ratio,
+      })
+        .then(({ status, file_id, file_url }) => {
+          this.autoLoading = false;
+          if (status === 1) {
+            this.data.audio_data = {
+              name: '自动生成课文音频.mp3',
+              media_duration: 0,
+              temporary_url: file_url,
+              url: file_id,
+              file_id,
+            };
+            this.data.file_id_list.push(file_id);
+          }
+        })
+        .catch(() => {
+          this.autoLoading = false;
+        });
+    },
   },
   created() {
     this.getTextToAudioConfParamList();
@@ -783,6 +817,12 @@ export default {
     margin: 0;
   }
 }
+
+.btn-box {
+  display: flex;
+  flex-flow: wrap;
+  gap: 10px;
+}
 </style>
 <style lang="scss">
 .tox .tox-editor-header {

+ 75 - 32
src/views/book/courseware/create/components/question/new_word/NewWord.vue

@@ -346,13 +346,17 @@
       </div>
 
       <el-button icon="el-icon-plus" style="margin: 24px 0" @click="addElement">增加一个</el-button>
-      <SelectUpload
-        label="生词音频"
-        type="audio"
-        width="500px"
-        :style="{ marginBottom: data.audio_data.url.length === 0 ? '5px' : '' }"
-        @uploadSuccess="uploadAudioSuccess"
-      />
+      <div class="btn-box">
+        <SelectUpload
+          label="生词音频"
+          type="audio"
+          width="500px"
+          :style="{ marginBottom: data.audio_data.url.length === 0 ? '5px' : '' }"
+          @uploadSuccess="uploadAudioSuccess"
+        />
+        <el-button :loading="autoLoading" @click="handleAutoAudio">自动生成音频</el-button>
+      </div>
+
       <div v-if="data.audio_data.url.length > 0" class="upload-file">
         <div class="file-name">
           <span>
@@ -439,6 +443,7 @@ export default {
       multilingualText: '',
       visible: false,
       subtitleList: [],
+      autoLoading: false,
     };
   },
   watch: {
@@ -496,30 +501,30 @@ export default {
           file_id,
         };
         this.data.file_id_list.push(file_id);
-        let _this = this;
-        _this.loading = true;
-        let data = {
-          file_id,
-        };
-        fileToBase64Text(data)
-          .then((res) => {
-            let taskIddata = {
-              fileName: name,
-              speechBase64: res.base64_text,
-              language: 'ch',
-            };
-            prepareTranscribe(taskIddata)
-              .then((reses) => {
-                _this.loading = false;
-                _this.$set(_this.data, 'taskId', reses.data.taskId);
-              })
-              .catch(() => {
-                _this.loading = false;
-              });
-          })
-          .catch(() => {
-            _this.loading = false;
-          });
+        // let _this = this;
+        // _this.loading = true;
+        // let data = {
+        //   file_id,
+        // };
+        // fileToBase64Text(data)
+        //   .then((res) => {
+        //     let taskIddata = {
+        //       fileName: name,
+        //       speechBase64: res.base64_text,
+        //       language: 'ch',
+        //     };
+        //     prepareTranscribe(taskIddata)
+        //       .then((reses) => {
+        //         _this.loading = false;
+        //         _this.$set(_this.data, 'taskId', reses.data.taskId);
+        //       })
+        //       .catch(() => {
+        //         _this.loading = false;
+        //       });
+        //   })
+        //   .catch(() => {
+        //     _this.loading = false;
+        //   });
       }
     },
     getBase64(file) {
@@ -718,7 +723,7 @@ export default {
       this.data.source_courseware_id = val[val.length - 1];
     },
     createWordTimes() {
-      if (this.data.taskId) {
+      if (this.data.audio_data.file_id) {
         let text = '';
         this.data.new_word_list.forEach((sItem, index) => {
           // item.forEach((sItem, sIndex) => {
@@ -838,6 +843,38 @@ export default {
         .filter((item) => item.length > 0)
         .join(' ');
     },
+    // 自动生成音频
+    handleAutoAudio() {
+      this.autoLoading = true;
+      let text = '';
+      this.data.new_word_list.forEach((sItem, index) => {
+        // item.forEach((sItem, sIndex) => {
+        text += `${sItem.new_word}。`;
+        // });
+      });
+      TextToAudioFile({
+        text: text,
+        voice_type: this.data.property.voice_type,
+        emotion: this.data.property.emotion,
+        speed_ratio: this.data.property.speed_ratio,
+      })
+        .then(({ status, file_id, file_url }) => {
+          this.autoLoading = false;
+          if (status === 1) {
+            this.data.audio_data = {
+              name: '自动生成课文音频.mp3',
+              media_duration: 0,
+              temporary_url: file_url,
+              url: file_id,
+              file_id,
+            };
+            this.data.file_id_list.push(file_id);
+          }
+        })
+        .catch(() => {
+          this.autoLoading = false;
+        });
+    },
   },
 };
 </script>
@@ -927,6 +964,12 @@ export default {
     margin: 0;
   }
 }
+
+.btn-box {
+  display: flex;
+  flex-flow: wrap;
+  gap: 10px;
+}
 </style>
 <style lang="scss">
 .tox .tox-editor-header {

+ 20 - 22
src/views/book/courseware/create/components/question/new_word/NewWordSetting.vue

@@ -21,28 +21,26 @@
           <el-option v-for="{ value, label } in audioGenerationMethodList" :key="value" :label="label" :value="value" />
         </el-select>
       </el-form-item>
-      <template v-if="property.audio_generation_method === 'auto'">
-        <el-form-item label="音色">
-          <el-select v-model="property.voice_type" placeholder="请选择">
-            <el-option
-              v-for="{ voice_type, name } in voice_type_list"
-              :key="voice_type"
-              :label="name"
-              :value="voice_type"
-            />
-          </el-select>
-        </el-form-item>
-        <el-form-item label="风格情感">
-          <el-select v-model="property.emotion">
-            <el-option v-for="{ emotion, name } in emotion_list" :key="emotion" :label="name" :value="emotion" />
-          </el-select>
-        </el-form-item>
-        <el-form-item label="语速">
-          <el-select v-model="property.speed_ratio">
-            <el-option v-for="{ value, label } in speedRatioList" :key="value" :label="label" :value="value" />
-          </el-select>
-        </el-form-item>
-      </template>
+      <el-form-item label="音色">
+        <el-select v-model="property.voice_type" placeholder="请选择">
+          <el-option
+            v-for="{ voice_type, name } in voice_type_list"
+            :key="voice_type"
+            :label="name"
+            :value="voice_type"
+          />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="风格情感">
+        <el-select v-model="property.emotion">
+          <el-option v-for="{ emotion, name } in emotion_list" :key="emotion" :label="name" :value="emotion" />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="语速">
+        <el-select v-model="property.speed_ratio">
+          <el-option v-for="{ value, label } in speedRatioList" :key="value" :label="label" :value="value" />
+        </el-select>
+      </el-form-item>
       <el-form-item label="拼音位置">
         <el-radio-group v-model="property.pinyin_position">
           <el-radio v-for="{ value, label } in pinyinPositionList" :key="value" :label="value">