123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373 |
- <template>
- <view class="content">
- <view class="uni-margin-wrap">
- <swiper class="swiper" circular :indicator-dots="true" indicator-color="#DE868F" indicator-active-color="#fff"
- :autoplay="true" :interval="5000" :duration="1000">
- <swiper-item>
- <view class="swiper-item"><text>创建步骤1<br>填写视频名称</text></view>
- </swiper-item>
- <swiper-item>
- <view class="swiper-item">创建步骤2<br>选择个人形象照片,最好是正面照</view>
- </swiper-item>
- <swiper-item>
- <view class="swiper-item">创建步骤3<br>选择生成视频内容的方式:<br>若选择文字输入,则输入口播的文字内容及使用音色;<br>若选择语音录入则点击开始录音,录音结束后再点击停止录音,可在下方播放容器试听录音内容;<br>若选择音频选择,则选择本机的音频文件</view>
- </swiper-item>
- </swiper>
- </view>
- <form class="form-area">
- <view class="form-area-item">
- <text class="form-area-item-text">视频名称</text>
- <input type="text" v-model="videoName" placeholder="请输入视频名称">
- </view>
- <view class="form-area-item">
- <text class="form-area-item-text">选择您的形象</text>
- <button @click="chooseImage" class="cu-btn bg-red">选择图片</button>
- <text class="none-file" v-if="!imagePath">未选择图片</text>
- <image :src="imagePath" v-else mode="aspectFit" style="width: 30px; height: 30px;margin-left:10px" />
- </view>
- <view class="form-area-item" style="align-items: baseline;">
- <text class="form-area-item-text">视频内容</text>
- <uni-data-checkbox selectedColor="#BD3124" selectedTextColor="#BD3124" v-model="current"
- :localdata="videoContent" />
- </view>
- <view class="form-area-item" v-if="current=='text'">
- <textarea v-model="videoText" placeholder="请输入视频中的文字内容" />
- </view>
- <view class="form-area-item" v-if="current=='text'">
- <text class="form-area-item-text">音色选择</text>
- <uni-data-checkbox selectedColor="#BD3124" selectedTextColor="#BD3124" v-model="timbre"
- :localdata="timbreContent" />
- </view>
- <view class="form-area-item" v-if="current=='record'">
- <button @click="toggleRecording">{{ isRecording ? '停止录音' : '开始录音' }}</button>
- </view>
- <view class="form-area-item" v-if="current=='audio'" :key="timeStamp">
- <text class="form-area-item-text">选择音频文件</text>
- <button @click="chooseFile" class="cu-btn bg-red">选择文件</button>
- <text class="file-name" v-if="fileInfo.name">{{fileInfo.name}}</text>
- <text class="none-file" v-if="!showPerson">未选择文件</text>
- </view>
- <audio v-if="audioPath" class="audio-bar" :src="audioPath" name="语音试听" poster="../static/images/xijiao/avator.png"
- :action="audioAction" controls></audio>
- </form>
- <view class="btn-area">
- <button @click="jumpToList" class="bg-red lg round create-project">生成数字人视频</button>
- <uni-popup ref="alertDialog" type="dialog">
- <uni-popup-dialog type="warning" cancelText="确定" title="提示" :content="missingContent"
- @close="dialogClose"></uni-popup-dialog>
- </uni-popup>
- </view>
- </view>
- </template>
- <script>
- import {
- uploadPerson,
- audioCreateVideo,
- textCreateVideo
- } from "@/api/system/user"
- import store from '@/store'
- const recorderManager = uni.getRecorderManager();
- const innerAudioContext = uni.createInnerAudioContext();
- innerAudioContext.autoplay = true;
- export default {
- data() {
- return {
- videoName: '',
- fileInfo: {},
- videoContent: [{
- value: 'text',
- text: '文字输入'
- },
- {
- value: 'record',
- text: '语音录入'
- },
- {
- value: 'audio',
- text: '音频选择'
- },
- ],
- current: 'text',
- imagePath: '',
- isRecording: false,
- audioPath: null,
- recorderManager: null,
- innerAudioContext: null,
- showPerson: false,
- timeStamp: null,
- audioAction: {
- method: 'pause'
- },
- videoText: '',
- missingContent: [],
- timbre: 'a',
- timbreContent: [{
- value: 'a',
- text: 'timbre1'
- },
- {
- value: 'b',
- text: 'timbre2'
- }
- ],
- personPath: '',
- createVideoPath: '',
- }
- },
- onLoad() {
- this.recorderManager = uni.getRecorderManager();
- this.innerAudioContext = uni.createInnerAudioContext();
- // 监听录音停止
- this.recorderManager.onStop((res) => {
- console.log('录音结束,临时路径:', res.tempFilePath);
- this.audioPath = res.tempFilePath; // 替换为新录音路径
- this.isRecording = false;
- });
- // 监听录音错误
- this.recorderManager.onError((err) => {
- uni.showToast({
- title: '录音出错',
- icon: 'none'
- });
- });
- },
- onShow() {
- this.timeStamp = new Date().getTime()
- this.fileInfo.path = uni.getStorageSync('filePath');
- this.fileInfo.name = uni.getStorageSync('fileName');
- if (this.fileInfo.name) {
- this.showPerson = true
- this.uploadAudioPath(this.fileInfo.path)
- }
- },
- methods: {
- // 选择音频文件
- chooseFile() {
- if(!this.imagePath) {
- uni.showToast({
- title: '请先选择形象照片',
- icon: 'none'
- });
- return
- }
- uni.navigateTo({
- url: "/pages/root-filelist/root-filelist",
- });
- },
- // 选择图片文件
- async chooseImage() {
- const that = this;
- uni.chooseImage({
- count: 1,
- sizeType: ['original', 'compressed'],
- sourceType: ['album', 'camera'],
- success: function(res) {
- that.imagePath = res.tempFilePaths[0];
- that.uploadImagePath()
- },
- fail: function(err) {
- uni.showToast({
- title: '图片选择失败',
- icon: 'none'
- });
- }
- });
- },
- // 开始/停止录音
- toggleRecording() {
- if (this.isRecording) {
- this.recorderManager.stop();
- this.uploadAudioPath(this.audioPath)
- } else {
- // 开始录音前,如果已有录音则清空
- if (this.audioPath) {
- this.audioPath = null;
- }
- // 开始录音
- this.recorderManager.start({
- duration: 600000, // 最大录音时间(毫秒)
- sampleRate: 44100,
- numberOfChannels: 1,
- encodeBitRate: 192000,
- format: 'wav',
- });
- this.isRecording = true;
- }
- },
- // 上传形象照片
- uploadImagePath() {
- let data = {
- file: this.imagePath
- }
- uploadPerson(data).then(response => {
- this.personPath = response.data.url
- })
- },
- // 上传音频文件
- uploadAudioPath(url) {
- let data = {
- file: url
- }
- uploadPerson(data).then(response => {
- this.personAudio = response.data.url
- })
- },
- // 点击生成视频,跳转生成页面
- jumpToList() {
- let missingFields = [];
- if (!this.videoName.trim()) {
- missingFields.push('视频名称');
- }
- if (!this.imagePath) {
- missingFields.push('人物形象');
- }
- const hasContent = this.videoText.trim() !== '' && this.timbre;
- const hasVoice = this.audioPath;
- if (!hasContent && !hasVoice) {
- missingFields.push('文字内容或语音输入');
- }
- if (missingFields.length > 0) {
- this.missingContent = `请确定:${missingFields.join('、')}是否填写完整!`
- this.$refs.alertDialog.open()
- return;
- }
- uni.navigateTo({
- url: 'list/creatingVideo/creatingVideo',
- });
- if (this.current == 'record' || this.current == 'audio') {
- let data = {
- 'persona_template': this.personPath,
- 'persona_audio': this.personAudio,
- }
- audioCreateVideo(data).then(response => {
- if (response.status == 200) {
- this.createVideoPath = response.data
- }
- }).catch(e => {
- uni.showToast({
- title: '视频返回成功'
- })
- })
- } else if (this.current == 'text') {
- let data = {
- 'persona_template': this.personPath,
- 'voice_type': this.timbre,
- 'audio_text': this.videoText,
- }
- textCreateVideo(data).then(response => {
- if (response.status == 200) {
- this.createVideoPath = response.data
- }
- })
- }
- },
- dialogClose() {
- console.log('点击关闭')
- },
- }
- }
- </script>
- <style scoped lang="scss">
- .content {
- display: flex;
- flex-direction: column;
- }
- .uni-margin-wrap {
- width: 690rpx;
- width: 100%;
- }
- .swiper {
- height: 350rpx;
- }
- .swiper-item {
- display: block;
- height: 350rpx;
- text-align: center;
- background-color: #BD3124;
- color: #fff;
- padding-top:30px;
- }
- .form-area {
- padding: 20px;
- .form-area-item {
- display: flex;
- flex-direction: row;
- margin-top: 30px;
- align-items: center;
- .form-area-item-text {
- width: 120px;
- }
- /deep/ uni-input {
- border: 1px solid #e5e5e5;
- border-radius: 4px;
- height: 30px;
- width: 200px;
- }
- /deep/ uni-picker {
- border-bottom: 1px solid #aaa;
- height: 30px;
- width: 200px;
- display: flex;
- align-items: center;
- }
- /deep/ uni-radio-group,
- /deep/ uni-label {
- display: flex;
- align-items: center;
- }
- /deep/ uni-label {
- margin-right: 10px;
- }
- /deep/ textarea {
- border: 1px solid #aaa;
- border-radius: 4px;
- width: 320px;
- padding: 5px;
- margin: 0 auto;
- }
- .none-file {
- margin-left: 10px;
- color: #aaa;
- }
- .file-name {
- margin-left: 10px;
- width: 50px;
- overflow: hidden;
- white-space: nowrap;
- text-overflow: ellipsis;
- }
- }
- }
- .btn-area {
- display: flex;
- justify-content: center;
- margin: 20px auto;
- width: 100%;
- }
- .audio-bar {
- text-align: center;
- display: block;
- margin-top: 10px;
- }
- /deep/ .uni-border-left {
- display: none;
- }
- </style>
|