|
@@ -56,7 +56,10 @@
|
|
|
</div>
|
|
|
</el-col>
|
|
|
<el-col :span="6">
|
|
|
-
|
|
|
+ <div class="citem-nav" @click="menuIndex = '8'">
|
|
|
+ <img src="../assets/image/a-tiqu.png" class="citem-img" />
|
|
|
+ <p class="citem-name">音频提取</p>
|
|
|
+ </div>
|
|
|
</el-col>
|
|
|
</el-row>
|
|
|
</div>
|
|
@@ -87,20 +90,41 @@
|
|
|
<el-tab-pane label="音频变速" name="5"></el-tab-pane>
|
|
|
<el-tab-pane label="音量调整" name="6"></el-tab-pane>
|
|
|
<el-tab-pane label="倒序播放" name="7"></el-tab-pane>
|
|
|
+ <el-tab-pane label="音频提取" name="8"></el-tab-pane>
|
|
|
</el-tabs>
|
|
|
</el-col>
|
|
|
</el-row>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
- <div v-if="audioList.length == 0" class="upload-area">
|
|
|
+ <div v-if="(menuIndex != '8' && audioList.length == 0) || (menuIndex == 8 && videoList.length == 0)" class="upload-area">
|
|
|
<div class="file-area" @click="pickFile()" id="drag-audio" @dragover.prevent @drop="handleDrop">
|
|
|
<div class="file-area-pos">
|
|
|
- <img src="../assets/image/upload.png" style="width: 220px;"/>
|
|
|
+ <!-- <img src="../assets/image/upload.png" style="width: 220px;"/> -->
|
|
|
+ <img v-if="menuIndex == '1'" src="../assets/image/a-geshi.png" class="upload-img"/>
|
|
|
+ <img v-if="menuIndex == '2'" src="../assets/image/a-hebing.png" class="upload-img"/>
|
|
|
+ <img v-if="menuIndex == '3'" src="../assets/image/a-yasuo.png" class="upload-img"/>
|
|
|
+ <img v-if="menuIndex == '4'" src="../assets/image/a-feige.png" class="upload-img"/>
|
|
|
+ <img v-if="menuIndex == '5'" src="../assets/image/a-biansu.png" class="upload-img"/>
|
|
|
+ <img v-if="menuIndex == '6'" src="../assets/image/a-yinliang.png" class="upload-img"/>
|
|
|
+ <img v-if="menuIndex == '7'" src="../assets/image/a-daoxu.png" class="upload-img"/>
|
|
|
+ <img v-if="menuIndex == '8'" src="../assets/image/a-tiqu.png" class="upload-img"/>
|
|
|
<p style="font-size: 16px;">点击添加文件或拖拽文件到此</p>
|
|
|
- <p style="font-size: 12px; color: #999;margin-top:15px;">不支持音乐平台付费格式音频,支持以下格式:</p>
|
|
|
- <p style="font-size: 12px; color: #999;">mp3/wav/ogg/flac/mp2/m4a/m4r/ac3/amr/wma/aiff/</p>
|
|
|
- <p style="font-size: 12px; color: #999;">aifc/caf/aac/ape/mmf/wv/au/voc/3gpp/mka/mp4</p>
|
|
|
+ <template v-if="menuIndex != '8'">
|
|
|
+ <div style="font-size: 12px; color: #999;padding-top:15px;">
|
|
|
+ <p>音乐平台会员音频为加密格式不支持,支持以下格式:</p>
|
|
|
+ <p>mp3/wav/ogg/flac/mp2/m4a/m4r/ac3/amr/wma/aiff/</p>
|
|
|
+ <p>aifc/caf/aac/ape/mmf/wv/au/voc/3gpp/mka/mp4</p>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ <template v-else>
|
|
|
+ <div style="font-size: 12px; color: #999;padding-top:15px;">
|
|
|
+ <p>提取音频支持以下非加密视频格式:</p>
|
|
|
+ <p>webm/f4v/ogv/3gp/avi/flv/mkv/mov/mp4/mgp/rmvb/</p>
|
|
|
+ <p>wmv/wtv/mpeg/rm/asf/m4v/m2v/ts/mts/</p>
|
|
|
+ <p>m2t/m2ts/dv/mxf/mpg/3gpp/aif/mod/m4s</p>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
@@ -109,6 +133,7 @@
|
|
|
<div class="content-left">
|
|
|
<div class="table-scroll" @dragover.prevent @drop="handleDrop">
|
|
|
<vxe-table
|
|
|
+ v-show="menuIndex != '8'"
|
|
|
show-overflow
|
|
|
class="img-table"
|
|
|
max-height="100%"
|
|
@@ -118,8 +143,7 @@
|
|
|
:row-config="{isHover: true}"
|
|
|
:edit-config="{trigger: 'click', mode: 'cell'}"
|
|
|
:data="audioList"
|
|
|
- :scroll-y="{enabled: true}"
|
|
|
- @cell-click="selectTab">
|
|
|
+ :scroll-y="{enabled: true}">
|
|
|
<vxe-column field="name" :title="'文件名称'+'(' + audioList.length + ')'"></vxe-column>
|
|
|
|
|
|
<vxe-column field="sort" title="排序" width="140" v-if="menuIndex == '2'">
|
|
@@ -143,9 +167,45 @@
|
|
|
<el-progress :text-inside="true" :stroke-width="20" :percentage="row.percent"></el-progress>
|
|
|
</template>
|
|
|
</vxe-column>
|
|
|
- <vxe-column title="操作" width="80">
|
|
|
+ <vxe-column title="操作" width="90">
|
|
|
+ <template #default="{ row, rowIndex }">
|
|
|
+ <i class="el-icon-view cur-pointer" style="font-size: 20px; margin-right: 5px;" @click="showFile(rowIndex)"></i>
|
|
|
+ <i class="el-icon-delete cur-pointer" style="font-size: 20px;" @click="delFile(rowIndex)"></i>
|
|
|
+ </template>
|
|
|
+ </vxe-column>
|
|
|
+ </vxe-table>
|
|
|
+
|
|
|
+ <vxe-table
|
|
|
+ v-show="menuIndex == '8'"
|
|
|
+ show-overflow
|
|
|
+ class="img-table"
|
|
|
+ max-height="100%"
|
|
|
+ empty-text="没有更多数据了!"
|
|
|
+ :loading="tabLoading"
|
|
|
+ :loading-config="{icon: 'vxe-icon-indicator roll', text: '音频加载中...'}"
|
|
|
+ :row-config="{isHover: true}"
|
|
|
+ :edit-config="{trigger: 'click', mode: 'cell'}"
|
|
|
+ :data="videoList"
|
|
|
+ :scroll-y="{enabled: true}">
|
|
|
+ <vxe-column field="name" :title="'文件名称'+'(' + videoList.length + ')'"></vxe-column>
|
|
|
+ <vxe-column field="size" title="大小" width="140">
|
|
|
+ <template #default="{ row }">
|
|
|
+ <span>{{$utils.handleSize(row.size)}}</span>
|
|
|
+ </template>
|
|
|
+ </vxe-column>
|
|
|
+ <vxe-column field="duration" title="时间" width="140">
|
|
|
+ <template #default="{ row }">
|
|
|
+ <span>{{formatSeconds(row.duration)}}</span>
|
|
|
+ </template>
|
|
|
+ </vxe-column>
|
|
|
+ <vxe-column field="progress" title="转换进度" width="200">
|
|
|
+ <template #default="{ row }">
|
|
|
+ <el-progress :text-inside="true" :stroke-width="20" :percentage="row.percent"></el-progress>
|
|
|
+ </template>
|
|
|
+ </vxe-column>
|
|
|
+ <vxe-column title="操作" width="90">
|
|
|
<template #default="{ row, rowIndex }">
|
|
|
- <i class="el-icon-delete cur-pointer" @click="delFile(rowIndex)"></i>
|
|
|
+ <i class="el-icon-delete cur-pointer" style="font-size: 20px;" @click="delVideoFile(rowIndex)"></i>
|
|
|
</template>
|
|
|
</vxe-column>
|
|
|
</vxe-table>
|
|
@@ -154,7 +214,7 @@
|
|
|
</div>
|
|
|
</div>
|
|
|
<!-- 底部设置区域 -->
|
|
|
- <div class="img-footer-area" v-if="audioList.length > 0">
|
|
|
+ <div class="img-footer-area" v-if="(menuIndex != '8' && audioList.length > 0) || (menuIndex == 8 && videoList.length > 0)">
|
|
|
<div class="footer-line-between">
|
|
|
<!-- 1格式转化 -->
|
|
|
<div class="handle-item" v-if="menuIndex == '1' || menuIndex == '2'">
|
|
@@ -170,6 +230,7 @@
|
|
|
</el-select>
|
|
|
<label class="handle-label">码率:</label>
|
|
|
<el-select v-model="handleData.quality" style="width:100px;" size="small">
|
|
|
+ <el-option value="1" label="同源音频"></el-option>
|
|
|
<el-option value="8k" label="8 kbps"></el-option>
|
|
|
<el-option value="16k" label="16 kbps"></el-option>
|
|
|
<el-option value="24k" label="24 kbps"></el-option>
|
|
@@ -220,7 +281,7 @@
|
|
|
<label class="handle-label">分割模式:</label>
|
|
|
<el-select v-model="handleData.split_type" style="width:100px;" size="small">
|
|
|
<el-option :value="1" label="按份分割"></el-option>
|
|
|
- <el-option :value="2" label="时长分割"></el-option>
|
|
|
+ <!-- <el-option :value="2" label="截取分割"></el-option> -->
|
|
|
<el-option :value="3" label="平均分割"></el-option>
|
|
|
</el-select>
|
|
|
|
|
@@ -239,7 +300,8 @@
|
|
|
</el-select>
|
|
|
</template>
|
|
|
<template v-else>
|
|
|
- <label class="handle-label">分割时间:</label>
|
|
|
+ <label v-if="handleData.split_type == 2" class="handle-label">截取时间:</label>
|
|
|
+ <label v-else class="handle-label">分割时间:</label>
|
|
|
<el-time-picker arrow-control @change="selectTime" v-model="split_timeStr" placeholder="选择时间" style="width:120px;" size="small"></el-time-picker>
|
|
|
</template>
|
|
|
</div>
|
|
@@ -265,6 +327,14 @@
|
|
|
</el-select>
|
|
|
</div>
|
|
|
|
|
|
+ <!-- 提取音频 -->
|
|
|
+ <div class="handle-item" v-if="menuIndex == '8'">
|
|
|
+ <label class="handle-label">提取格式:</label>
|
|
|
+ <el-select v-model="videoFormat" style="width:100px;margin-left: 5px;" size="small">
|
|
|
+ <el-option v-for="(item, key) in outputVideo" :key="key" :value="item" :label="item"></el-option>
|
|
|
+ </el-select>
|
|
|
+ </div>
|
|
|
+
|
|
|
<div v-else></div>
|
|
|
|
|
|
<div>
|
|
@@ -273,19 +343,71 @@
|
|
|
<el-popover placement="bottom" popper-class="popper-open" trigger="hover" content="打开保存目录">
|
|
|
<i class="el-icon-folder-opened" slot="reference" style="padding-left: 5px; cursor: pointer; font-size: 22px; vertical-align: middle;" @click="openFolder()"></i>
|
|
|
</el-popover>
|
|
|
- <el-button type="danger" style="margin: 0 20px;" @click="exportFile()" :loading="loading">开始处理</el-button>
|
|
|
+ <el-button type="danger" style="margin-left: 20px;" @click="exportFile()" :loading="loading">开始处理</el-button>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
</template>
|
|
|
-
|
|
|
+
|
|
|
+ <!-- 文件信息弹窗 -->
|
|
|
+ <el-dialog title="文件详情" :visible.sync="fileDetailModel" width="500px">
|
|
|
+ <el-descriptions v-if="showIndex !== ''" class="margin-top" :column="1" size="medium" border>
|
|
|
+ <el-descriptions-item>
|
|
|
+ <template slot="label">
|
|
|
+ 文件名
|
|
|
+ </template>
|
|
|
+ {{audioList[showIndex].name}}
|
|
|
+ </el-descriptions-item>
|
|
|
+ <el-descriptions-item>
|
|
|
+ <template slot="label">
|
|
|
+ 比特率
|
|
|
+ </template>
|
|
|
+ {{audioList[showIndex].bitrate}}bps
|
|
|
+ </el-descriptions-item>
|
|
|
+ <el-descriptions-item>
|
|
|
+ <template slot="label">
|
|
|
+ 时长
|
|
|
+ </template>
|
|
|
+ {{formatSeconds(audioList[showIndex].duration)}}
|
|
|
+ </el-descriptions-item>
|
|
|
+ <el-descriptions-item>
|
|
|
+ <template slot="label">
|
|
|
+ 采样率
|
|
|
+ </template>
|
|
|
+ {{audioList[showIndex].sample_rate}}HZ
|
|
|
+ </el-descriptions-item>
|
|
|
+ <el-descriptions-item>
|
|
|
+ <template slot="label">
|
|
|
+ 歌手
|
|
|
+ </template>
|
|
|
+ {{audioList[showIndex].tags ? audioList[showIndex].tags.artist : '-'}}
|
|
|
+ </el-descriptions-item>
|
|
|
+ <el-descriptions-item>
|
|
|
+ <template slot="label">
|
|
|
+ 标题
|
|
|
+ </template>
|
|
|
+ {{audioList[showIndex].tags ? audioList[showIndex].tags.title : '-'}}
|
|
|
+ </el-descriptions-item>
|
|
|
+ <el-descriptions-item>
|
|
|
+ <template slot="label">
|
|
|
+ 唱片辑
|
|
|
+ </template>
|
|
|
+ {{audioList[showIndex].tags ? audioList[showIndex].tags.album : '-'}}
|
|
|
+ </el-descriptions-item>
|
|
|
+ <el-descriptions-item>
|
|
|
+ <template slot="label">
|
|
|
+ 其他
|
|
|
+ </template>
|
|
|
+ {{audioList[showIndex].tags ? audioList[showIndex].tags.encoder : '-'}}
|
|
|
+ </el-descriptions-item>
|
|
|
+ </el-descriptions>
|
|
|
+ </el-dialog>
|
|
|
</el-main>
|
|
|
<el-footer height="48px">
|
|
|
<!-- 更新 -->
|
|
|
<soft-update ref="updateRef" :showDowload="dowloadModel"
|
|
|
:dowloadFinish="finishModel"></soft-update>
|
|
|
</el-footer>
|
|
|
-
|
|
|
|
|
|
</el-container>
|
|
|
</div>
|
|
@@ -314,6 +436,7 @@ export default {
|
|
|
},
|
|
|
data() {
|
|
|
return {
|
|
|
+ fileDetailModel: false,
|
|
|
//
|
|
|
loading: false,
|
|
|
tabLoading: false,
|
|
@@ -324,12 +447,17 @@ export default {
|
|
|
imgUrl: this.$api.imgUrl,
|
|
|
imgSrc: '',
|
|
|
audioList: [],
|
|
|
+ videoList: [],
|
|
|
imgInfo: '',
|
|
|
menuIndex: '', // 选中菜单
|
|
|
|
|
|
inputAudio: ['mp3', 'wav', 'ogg', 'flac', 'mp2', 'm4a', 'm4r', 'ac3', 'amr', 'wma', 'aiff','aifc','caf','aac','ape','mmf','wv','au','voc','3gpp','mka','mp4'],
|
|
|
outputAudio: ['mp3', 'wav', 'ogg', 'flac', 'mp2', 'm4a', 'm4r', 'ac3', 'amr', 'wma', 'aiff','aifc','caf','aac','ape','mmf','wv','au','voc','3gpp','mka','mp4'],
|
|
|
-
|
|
|
+
|
|
|
+ inputVideo: ['video/x-msvideo', 'video/webm', 'video/f4v', 'video/ogv', 'video/3gp', 'video/avi', 'video/flv', 'video/mkv', 'video/mov', 'video/mp4', 'video/mgp', 'video/rmvb', 'video/wmv', 'video/wtv', 'video/mpeg', 'video/rm', 'video/asf', 'video/m4v', 'video/m2v', 'video/ts', 'video/mts', 'video/m2t', 'video/m2ts', 'video/dv', 'video/mxf', 'video/mpg', 'video/3gpp', 'video/aif', 'video/mod', 'video/m4s'],
|
|
|
+ outputVideo: ['mp3', 'wav', 'aac'],
|
|
|
+ videoFormat: 'mp3',
|
|
|
+
|
|
|
downloadDir: '', // 默认下载目录
|
|
|
handleData: {
|
|
|
pathType: 2,
|
|
@@ -337,7 +465,7 @@ export default {
|
|
|
format: 'mp3',
|
|
|
newPath: os.userInfo().homedir + separator + "Downloads", // 新路径
|
|
|
type: 1, // 声道
|
|
|
- quality: '128k', // 图片品质
|
|
|
+ quality: '1', // 图片品质
|
|
|
compressLevel: 1,
|
|
|
split_type: 1,
|
|
|
split_num: 2,
|
|
@@ -356,6 +484,7 @@ export default {
|
|
|
|
|
|
loadingTips: '',
|
|
|
execLimit: 5,
|
|
|
+ showIndex: '',
|
|
|
};
|
|
|
},
|
|
|
mounted() {
|
|
@@ -403,7 +532,12 @@ export default {
|
|
|
for(let i = 0; i < files.length; i++){
|
|
|
pathArr.push(files[i].path);
|
|
|
}
|
|
|
- this.pushFileToList(pathArr);
|
|
|
+ if(this.menuIndex != '8'){
|
|
|
+ this.pushFileToList(pathArr);
|
|
|
+ }else{
|
|
|
+ this.pushFileToList2(pathArr);
|
|
|
+ }
|
|
|
+
|
|
|
},
|
|
|
openVip() {
|
|
|
this.$refs.headerRef.openVip();
|
|
@@ -435,13 +569,15 @@ export default {
|
|
|
// 清除列表
|
|
|
clearList() {
|
|
|
this.audioList = [];
|
|
|
+ this.videoList = [];
|
|
|
+ this.showIndex = '';
|
|
|
this.handleData = {
|
|
|
pathType: 2,
|
|
|
isOriginal: true,
|
|
|
format: 'mp3',
|
|
|
newPath: os.userInfo().homedir + separator + "Downloads", // 新路径
|
|
|
type: 2, //
|
|
|
- quality: '128k', //
|
|
|
+ quality: '1', //
|
|
|
compressLevel: 1,
|
|
|
split_type: 1,
|
|
|
split_num: 2,
|
|
@@ -450,18 +586,29 @@ export default {
|
|
|
},
|
|
|
async pickFile(){
|
|
|
let formatArr = [];
|
|
|
- this.inputAudio.map(item => {
|
|
|
- formatArr.push(item.substr(item.lastIndexOf('/')+1))
|
|
|
- })
|
|
|
+ if(this.menuIndex != '8'){
|
|
|
+ this.inputAudio.map(item => {
|
|
|
+ formatArr.push(item.substr(item.lastIndexOf('/')+1))
|
|
|
+ })
|
|
|
+ }else{
|
|
|
+ this.inputVideo.map(item => {
|
|
|
+ formatArr.push(item.substr(item.lastIndexOf('/')+1))
|
|
|
+ })
|
|
|
+ }
|
|
|
const spinLoad = this.$loading();
|
|
|
await electronApi.call('pickFile', [formatArr.join(','),true]).then(async(files) =>{
|
|
|
if(files.length > 0){
|
|
|
- this.pushFileToList(files);
|
|
|
+ if(this.menuIndex != '8'){
|
|
|
+ this.pushFileToList(files);
|
|
|
+ }else{
|
|
|
+ this.pushFileToList2(files);
|
|
|
+ }
|
|
|
}
|
|
|
spinLoad.close();
|
|
|
}).catch(err => {
|
|
|
spinLoad.close();
|
|
|
});
|
|
|
+
|
|
|
},
|
|
|
async pickDir(){
|
|
|
const spinLoad = this.$loading();
|
|
@@ -481,7 +628,11 @@ export default {
|
|
|
var stat = fs.statSync(filePath);
|
|
|
|
|
|
if (stat.isFile()) {
|
|
|
- this.pushFileToList([filePath]);
|
|
|
+ if(this.menuIndex != '8'){
|
|
|
+ this.pushFileToList([filePath]);
|
|
|
+ }else{
|
|
|
+ this.pushFileToList2([filePath]);
|
|
|
+ }
|
|
|
} else if (stat.isDirectory()) {
|
|
|
this.dealDir(filePath)
|
|
|
}
|
|
@@ -551,11 +702,6 @@ export default {
|
|
|
this.audioList[index].channel = result.streams[0]['channels'];
|
|
|
this.audioList[index].sample_rate = result.streams[0]['sample_rate'];
|
|
|
this.audioList[index].tags = result.format.tags;
|
|
|
-
|
|
|
- // 设置第一个为默认信息
|
|
|
- if(i == 0){
|
|
|
- this.selectTab('',0);
|
|
|
- }
|
|
|
|
|
|
if(index == this.audioList.length - 1){
|
|
|
this.tabLoading = false;
|
|
@@ -576,6 +722,120 @@ export default {
|
|
|
this.tabLoading = false;
|
|
|
}, 500)
|
|
|
},
|
|
|
+ pushFileToList2(files) {
|
|
|
+ this.tabLoading = true;
|
|
|
+ for (let i = 0; i < files.length; i++) {
|
|
|
+ let path = files[i];
|
|
|
+ let filename = path.substr(path.lastIndexOf(separator)+1);
|
|
|
+ let suffix = filename.lastIndexOf('.') == -1 ? '' : filename.substr(filename.lastIndexOf('.')+1);
|
|
|
+ let size = fs.statSync(path).size;
|
|
|
+ let index = i;
|
|
|
+
|
|
|
+ if (this.inputVideo.indexOf('video/'+suffix.toLowerCase()) == -1) {
|
|
|
+ this.$message({message: '不是有效的视频文件或该文件暂不支持!' + suffix , type: 'warning'});
|
|
|
+ continue;
|
|
|
+ } else {
|
|
|
+ if(!this.$refs.headerRef.authority.isAuthority){
|
|
|
+ if(size > 1024*500){
|
|
|
+ this.$notify.error({
|
|
|
+ title: '错误提示',
|
|
|
+ message: '免费版,文件最大不能超过500KB!'
|
|
|
+ });
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ let imgInfo = {
|
|
|
+ name: filename,
|
|
|
+ size: Number(size),
|
|
|
+ path: path,
|
|
|
+ type: suffix,
|
|
|
+ duration: 0,
|
|
|
+ bitrate: '',
|
|
|
+ fenbianlv: '',
|
|
|
+ suffix: suffix,
|
|
|
+ percent: 0,
|
|
|
+ brand: '',
|
|
|
+ };
|
|
|
+
|
|
|
+ let flag = true;
|
|
|
+ for (let m = 0; m < this.videoList.length; m++) {
|
|
|
+ if (this.videoList[m].name == imgInfo.name && this.videoList[m].path == imgInfo.path) {
|
|
|
+ flag = false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (flag) {
|
|
|
+ this.videoList.push(imgInfo);
|
|
|
+ index = this.videoList.length - 1;
|
|
|
+ }else{
|
|
|
+ setTimeout(() => {
|
|
|
+ this.$message({message: '该文件已经在队列中 - ' + path, type: 'warning'});
|
|
|
+ }, 1000)
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ setTimeout(() => {
|
|
|
+ electronApi.spawnExec(['ffprobe.exe','-i', path,'-v','quiet','-print_format','json','-show_format', '-show_streams', '-hide_banner']).then((result) => {
|
|
|
+ result = result.stdout.toString();
|
|
|
+ result = JSON.parse(result);
|
|
|
+ // 帧率
|
|
|
+ this.videoList[index].r_frame_rate = result.streams[0].r_frame_rate;
|
|
|
+ this.videoList[index].duration = result.format.duration;
|
|
|
+ this.videoList[index].bitrate = result.format.bit_rate;
|
|
|
+
|
|
|
+ let type = filename.substr(filename.lastIndexOf('.')+1);
|
|
|
+ let brand = "";
|
|
|
+ let audioBitrate = "";
|
|
|
+ let fenbianlv = "";
|
|
|
+ let rotate = 0;
|
|
|
+ let v_codec_name = '';
|
|
|
+ let a_codec_name = '';
|
|
|
+ result.streams[1] = result.streams[1] ? result.streams[1] : {};
|
|
|
+
|
|
|
+ if(result.format.tags && result.format.tags.compatible_brands){
|
|
|
+ brand = result.format.tags.compatible_brands;
|
|
|
+ }
|
|
|
+ if(result.streams[1] && result.streams[1].bit_rate){
|
|
|
+ audioBitrate = result.streams[1].bit_rate;
|
|
|
+ }
|
|
|
+ if(result.streams && result.streams[0]){
|
|
|
+ if(type.toLowerCase() == 'mpg' || type.toLowerCase() == 'vob'){
|
|
|
+ if(result.streams[1].width || result.streams[1].height){
|
|
|
+ fenbianlv = result.streams[1].width + 'x'+ result.streams[1].height;
|
|
|
+ }
|
|
|
+ v_codec_name = result.streams[1].codec_name;
|
|
|
+ a_codec_name = result.streams[2].codec_name;
|
|
|
+ }else{
|
|
|
+ if(result.streams[0].width || result.streams[0].height){
|
|
|
+ fenbianlv = result.streams[0].width + 'x'+ result.streams[0].height;
|
|
|
+ }
|
|
|
+ v_codec_name = result.streams[0].codec_name;
|
|
|
+ a_codec_name = result.streams[1].codec_name;
|
|
|
+ }
|
|
|
+
|
|
|
+ if(result.streams[0].tags){
|
|
|
+ rotate = result.streams[0].tags.rotate;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ this.videoList[index].fenbianlv = fenbianlv;
|
|
|
+ this.videoList[index].brand = brand;
|
|
|
+ this.videoList[index].audioBitrate = audioBitrate;
|
|
|
+ this.videoList[index].rotate = rotate;
|
|
|
+ this.videoList[index].v_codec_name = v_codec_name;
|
|
|
+ this.videoList[index].a_codec_name = a_codec_name;
|
|
|
+ });
|
|
|
+
|
|
|
+ if(index == this.videoList.length - 1){
|
|
|
+ this.tabLoading = false;
|
|
|
+ }
|
|
|
+ }, 200)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ setTimeout(()=>{
|
|
|
+ this.tabLoading = false;
|
|
|
+ }, 500)
|
|
|
+ },
|
|
|
// 音频时间转为秒
|
|
|
getSs(rawDuration){
|
|
|
const $ar = rawDuration.split(":");
|
|
@@ -597,7 +857,7 @@ export default {
|
|
|
// 导出
|
|
|
async exportFile(flag) {
|
|
|
let authority = this.$refs.headerRef.authority;
|
|
|
- if (this.audioList.length > 0) {
|
|
|
+ if ((this.audioList.length > 0 && this.menuIndex != '8') || (this.videoList.length > 0 && this.menuIndex == '8')) {
|
|
|
if (!authority.isAuthority && !flag) {
|
|
|
this.$refs.headerRef.memberModel = true;
|
|
|
this.$refs.headerRef.isClick = true;
|
|
@@ -610,7 +870,7 @@ export default {
|
|
|
}, 3000)
|
|
|
}
|
|
|
|
|
|
- if(this.handleData.pathType == '2'){ // 自定义文件架判断有无 优速音频处理器 文件夹
|
|
|
+ if(this.handleData.pathType == '2'){ // 自定义文件架判断有无 音频处理器 文件夹
|
|
|
if(fs.existsSync(this.downloadDir + separator + pjson.softInfo.softName)){
|
|
|
this.handleData.newPath = this.downloadDir + separator + pjson.softInfo.softName;
|
|
|
} else {
|
|
@@ -621,21 +881,40 @@ export default {
|
|
|
|
|
|
let taskArr = [];
|
|
|
if(this.menuIndex != '2'){
|
|
|
- for(let i=0; i< this.audioList.length; i++){
|
|
|
- // 处理音频
|
|
|
- let task = this.dealVideo(i, this.audioList[i]);
|
|
|
- if(task){
|
|
|
- taskArr.push(task);
|
|
|
+ if(this.menuIndex == '8'){
|
|
|
+ for(let i=0; i< this.videoList.length; i++){
|
|
|
+ // 处理音频
|
|
|
+ let task = this.dealVideo(i, this.videoList[i]);
|
|
|
+ if(task){
|
|
|
+ taskArr.push(task);
|
|
|
+ }
|
|
|
+
|
|
|
+ if((i+1) % this.execLimit == 0){
|
|
|
+ await Promise.all(taskArr).then(result => {
|
|
|
+ taskArr = [];
|
|
|
+ }).catch(err => {
|
|
|
+ this.$message.error('部分音频操作错误,请调整参数后再试!');
|
|
|
+ })
|
|
|
+ }
|
|
|
}
|
|
|
-
|
|
|
- if((i+1) % this.execLimit == 0){
|
|
|
- await Promise.all(taskArr).then(result => {
|
|
|
- taskArr = [];
|
|
|
- }).catch(err => {
|
|
|
- this.$message.error('部分音频操作错误,请调整参数后再试!');
|
|
|
- })
|
|
|
+ }else{
|
|
|
+ for(let i=0; i< this.audioList.length; i++){
|
|
|
+ // 处理音频
|
|
|
+ let task = this.dealVideo(i, this.audioList[i]);
|
|
|
+ if(task){
|
|
|
+ taskArr.push(task);
|
|
|
+ }
|
|
|
+
|
|
|
+ if((i+1) % this.execLimit == 0){
|
|
|
+ await Promise.all(taskArr).then(result => {
|
|
|
+ taskArr = [];
|
|
|
+ }).catch(err => {
|
|
|
+ this.$message.error('部分音频操作错误,请调整参数后再试!');
|
|
|
+ })
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
}else{
|
|
|
await this.dealConcatVideo();
|
|
|
}
|
|
@@ -650,11 +929,17 @@ export default {
|
|
|
}
|
|
|
|
|
|
// 打开文件夹
|
|
|
- if(this.audioList.length > 0){
|
|
|
+ if(this.audioList.length > 0 && this.menuIndex != '8'){
|
|
|
this.$message('恭喜你,任务已完成!');
|
|
|
let outPath = this.handleData.newPath + separator + this.audioList[0].name.slice(this.audioList[0].name.lastIndexOf('/')+1);
|
|
|
electronApi.call('showItemInfolder',[outPath])
|
|
|
}
|
|
|
+ // 打开文件夹
|
|
|
+ if(this.videoList.length > 0 && this.menuIndex == '8'){
|
|
|
+ this.$message('恭喜你,任务已完成!');
|
|
|
+ let outPath = this.handleData.newPath + separator + this.videoList[0].name.slice(this.videoList[0].name.lastIndexOf('/')+1);
|
|
|
+ electronApi.call('showItemInfolder',[outPath])
|
|
|
+ }
|
|
|
}
|
|
|
},
|
|
|
// 处理音频
|
|
@@ -664,6 +949,7 @@ export default {
|
|
|
const regexTime = /time=(.*?) bitrate/;
|
|
|
switch (this.menuIndex) {
|
|
|
case '1': // 格式转换
|
|
|
+ case '2': // 音频合并
|
|
|
case '7': // 音频倒放
|
|
|
task = new Promise((resolve,reject) =>{
|
|
|
let filePath = file.path;
|
|
@@ -673,12 +959,14 @@ export default {
|
|
|
|
|
|
if(this.menuIndex == '1'){
|
|
|
outPath = this.handleData.newPath + separator + file.name.slice(0, file.name.lastIndexOf('.')) + '.' + suffix;
|
|
|
- }else {
|
|
|
+ }else if(this.menuIndex == '7'){
|
|
|
let ss = suffix;
|
|
|
if(this.handleData.isOriginal){
|
|
|
ss = suffix2;
|
|
|
}
|
|
|
outPath = this.handleData.newPath + separator + file.name.slice(0, file.name.lastIndexOf('.')) + '.' + ss;
|
|
|
+ }else{
|
|
|
+ outPath = os.tmpdir() + separator + file.name.slice(0, file.name.lastIndexOf('.')) + '.' + suffix;;
|
|
|
}
|
|
|
|
|
|
let params = [];
|
|
@@ -714,8 +1002,13 @@ export default {
|
|
|
params.push('-vn');
|
|
|
}
|
|
|
|
|
|
- params.push('-b:a')
|
|
|
- params.push(this.handleData.quality)
|
|
|
+ if(this.handleData.quality != '1' && this.menuIndex != '7'){
|
|
|
+ params.push('-b:a')
|
|
|
+ params.push(this.handleData.quality)
|
|
|
+ }else{
|
|
|
+ params.push('-b:a')
|
|
|
+ params.push(file.bitrate / 1000 + 'k');
|
|
|
+ }
|
|
|
|
|
|
if(this.menuIndex == '7'){
|
|
|
params.push('-af');
|
|
@@ -978,7 +1271,7 @@ export default {
|
|
|
let params = [
|
|
|
'-i',
|
|
|
filePath,
|
|
|
- '-filter:a',
|
|
|
+ '-af',
|
|
|
'volume='+this.handleData.volume,
|
|
|
'-vn',
|
|
|
outPath,
|
|
@@ -1013,8 +1306,62 @@ export default {
|
|
|
})
|
|
|
})
|
|
|
break;
|
|
|
+ case '8': // 提取音频
|
|
|
+ task = new Promise((resolve,reject) =>{
|
|
|
+ let filePath = file.path;
|
|
|
+ let suffix = this.videoFormat;
|
|
|
+ let outPath = this.handleData.newPath + "\/" + file.name.slice(0, file.name.lastIndexOf('.')) + '.'+suffix;
|
|
|
+
|
|
|
+ let str = 'copy';
|
|
|
+ if(suffix == 'mp3'){
|
|
|
+ str = 'libmp3lame';
|
|
|
+ }
|
|
|
+
|
|
|
+ let params = [
|
|
|
+ '-i',
|
|
|
+ filePath,
|
|
|
+ '-vn',
|
|
|
+ '-acodec',
|
|
|
+ str,
|
|
|
+ outPath,
|
|
|
+ '-hide_banner',
|
|
|
+ '-y'
|
|
|
+ ];
|
|
|
+
|
|
|
+ electronApi.spawnExec(['ffmpeg.exe',...params],{
|
|
|
+ stderr:(data) =>{
|
|
|
+ let timeStr = regexTime.exec(data.toString());
|
|
|
+ if(timeStr && timeStr[1]){
|
|
|
+ file.percent = Math.ceil((this.getSs(timeStr[1])/file.duration).toFixed(2) * 100);
|
|
|
+ if(file.percent < 1){
|
|
|
+ file.percent = 1;
|
|
|
+ }
|
|
|
+ if(this.videoList[index]){ // 运行中的数据 删除后 防止重新添加
|
|
|
+ this.videoList.splice(index, 1, file);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }).then(res => {
|
|
|
+ file.percent = 100
|
|
|
+ if(this.videoList[index]){ // 运行中的数据 删除后 防止重新添加
|
|
|
+ this.videoList.splice(index, 1, file);
|
|
|
+ }
|
|
|
+ resolve(true);
|
|
|
+ }).catch(err =>{
|
|
|
+ if(this.videoList[index]){ // 运行中的数据 删除后 防止重新添加
|
|
|
+ file.percent = 0 // 失败则进度设置为0
|
|
|
+ this.videoList.splice(index, 1, file);
|
|
|
+ }
|
|
|
+ this.$notify.error({
|
|
|
+ title: '文件错误',
|
|
|
+ message: '可能参数有误,请稍后再试! '+ file.path,
|
|
|
+ });
|
|
|
+ reject(err);
|
|
|
+ })
|
|
|
+ })
|
|
|
+ break;
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
return task;
|
|
|
},
|
|
|
// 处理音频合成
|
|
@@ -1075,7 +1422,7 @@ export default {
|
|
|
|
|
|
let suffix = this.handleData.format;
|
|
|
let outPath = this.handleData.newPath + separator + '音频合并'+ this.formatNowDate() +'.'+suffix;
|
|
|
- let filelist = os.tmpdir() + separator + 'yoso_audio.txt';
|
|
|
+ let filelist = os.tmpdir() + separator + 'xy_audio.txt';
|
|
|
let options = {mode: 438, flag: 'w'};
|
|
|
fs.writeFileSync(filelist,filePathArr.join("\n"),options);
|
|
|
|
|
@@ -1151,11 +1498,16 @@ export default {
|
|
|
})
|
|
|
this.isShow = false;
|
|
|
}).catch(err =>{
|
|
|
- console.log('合并 ==',err);
|
|
|
+ console.log('合并 ==',err.stderr.toString());
|
|
|
this.isShow = false;
|
|
|
this.$message.error('操作失败,请重试!');
|
|
|
})
|
|
|
},
|
|
|
+ // 查看文件信息
|
|
|
+ showFile(rowIndex){
|
|
|
+ this.showIndex = rowIndex;
|
|
|
+ this.fileDetailModel = true;
|
|
|
+ },
|
|
|
// 删除文件
|
|
|
delFile(rowIndex){
|
|
|
this.$confirm('确认删除此音频吗?', '提示', {
|
|
@@ -1171,6 +1523,21 @@ export default {
|
|
|
|
|
|
});
|
|
|
},
|
|
|
+ // 删除文件
|
|
|
+ delVideoFile(rowIndex){
|
|
|
+ this.$confirm('确认删除此视频吗?', '提示', {
|
|
|
+ confirmButtonText: '确定',
|
|
|
+ cancelButtonText: '取消',
|
|
|
+ type: 'warning'
|
|
|
+ }).then(() => {
|
|
|
+ this.videoList.splice(rowIndex, 1);
|
|
|
+ if (this.videoList.length == 0) {
|
|
|
+ this.clearList();
|
|
|
+ }
|
|
|
+ }).catch(() => {
|
|
|
+
|
|
|
+ });
|
|
|
+ },
|
|
|
//文件排序
|
|
|
fileSort(type, index){
|
|
|
this.audioList.map((item, index) => {
|
|
@@ -1350,4 +1717,8 @@ export default {
|
|
|
.sort-btn{
|
|
|
padding: 7px !important;
|
|
|
}
|
|
|
+
|
|
|
+ .upload-img{
|
|
|
+ width: 220px;
|
|
|
+ }
|
|
|
</style>
|