Skip to content

Commit f1a7a7b

Browse files
committed
更新课程
1 parent 77fc778 commit f1a7a7b

File tree

7 files changed

+109
-37
lines changed

7 files changed

+109
-37
lines changed

videoMerge/src/main/ffmpeg.ts

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,26 +2,29 @@ import ffmpegPath from '@ffmpeg-installer/ffmpeg'
22
import ffprobePath from '@ffprobe-installer/ffprobe'
33
import ffmpeg from 'fluent-ffmpeg'
44
import { promisify } from 'util'
5+
import { IFile } from './ipc'
56
ffmpeg.setFfmpegPath(ffmpegPath.path)
67
ffmpeg.setFfprobePath(ffprobePath.path)
78

89
class VideoMerge {
910
private ffmpeg: ffmpeg.FfmpegCommand
10-
private files: string[] = []
11+
private files: IFile = { file: '', endVideo: '', preVideo: '' }
1112
private totalTime = 0
1213

1314
constructor() {
1415
this.ffmpeg = ffmpeg()
1516
}
1617

17-
videos(files: string[]) {
18-
this.files = files
19-
return this
20-
}
18+
// private videos(files: IFile) {
19+
// this.files = files
20+
// return this
21+
// }
2122

2223
private async getTotalTime() {
24+
const files = Object.values(this.files).filter((f) => f)
25+
// console.log(files)
2326
const nums = await Promise.all(
24-
this.files.map(async (file) => {
27+
files.map(async (file) => {
2528
const {
2629
format: { duration }
2730
} = (await promisify(ffmpeg.ffprobe)(file)) as ffmpeg.FfprobeData
@@ -32,7 +35,10 @@ class VideoMerge {
3235
}
3336

3437
private videosAdd() {
35-
this.files.forEach((file) => this.ffmpeg.mergeAdd(file))
38+
if (this.files.preVideo) this.ffmpeg.mergeAdd(this.files.preVideo)
39+
this.ffmpeg.mergeAdd(this.files.file)
40+
if (this.files.endVideo) this.ffmpeg.mergeAdd(this.files.endVideo)
41+
// this.files.forEach((file) => this.ffmpeg.mergeAdd(file))
3642
}
3743

3844
private progress(progress: any) {
@@ -41,16 +47,18 @@ class VideoMerge {
4147
times.forEach((time, index) => {
4248
runTotalTime += Math.pow(60, 2 - index) * time
4349
})
50+
//文件名 进度数值
4451
console.log((runTotalTime / this.totalTime) * 100)
4552
}
46-
async run() {
47-
await this.getTotalTime()
53+
async run(files: IFile) {
54+
this.files = files
4855

56+
await this.getTotalTime()
4957
this.videosAdd()
5058
this.ffmpeg
5159
.on('progress', this.progress.bind(this))
5260
.on('error', (err) => {
53-
// console.log(err)
61+
console.log(err)
5462
})
5563
.on('end', function () {
5664
// console.log('转换完成')
@@ -62,10 +70,10 @@ class VideoMerge {
6270
.save('/Users/hd/live/v2023/videoMerge/b.mp4')
6371
}
6472
}
65-
const files = ['/Users/hd/live/v2023/videoMerge/a1.mp4', '/Users/hd/live/v2023/videoMerge/a2.mp4']
73+
// const files = ['/Users/hd/live/v2023/videoMerge/a1.mp4', '/Users/hd/live/v2023/videoMerge/a2.mp4']
6674

67-
const instance = new VideoMerge()
68-
instance.videos(files).run()
75+
export default new VideoMerge()
76+
// instance.videos(files).run()
6977
// ffmpeg()
7078
//获取多个视频的总时长
7179
// Promise.all(

videoMerge/src/main/index.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,16 @@ import { app, shell, BrowserWindow } from 'electron'
22
import { join } from 'path'
33
import { electronApp, optimizer, is } from '@electron-toolkit/utils'
44
import icon from '../../resources/icon.png?asset'
5-
import './ffmpeg'
6-
5+
import './ipc'
76
function createWindow(): void {
87
// Create the browser window.
98
const mainWindow = new BrowserWindow({
109
width: 400,
11-
height: 700,
10+
height: 500,
1211
minWidth: 400,
1312
minHeight: 500,
1413
x: 1900,
15-
y: 180,
14+
y: 150,
1615
// resizable: false,
1716
show: false,
1817
frame: false,

videoMerge/src/main/ipc.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import { IpcMainEvent, ipcMain } from 'electron'
2+
import ffmpeg from './ffmpeg'
3+
export interface IFile {
4+
file: string
5+
preVideo?: string
6+
endVideo?: string
7+
}
8+
ipcMain.on('videoMerge', (event: IpcMainEvent, files: IFile) => {
9+
ffmpeg.run(files)
10+
})

videoMerge/src/preload/index.d.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
1+
import { IFile } from './../main/ipc'
12
import { ElectronAPI } from '@electron-toolkit/preload'
23

34
declare global {
45
interface Window {
56
electron: ElectronAPI
6-
api: unknown
7+
api: {
8+
videoMerge: (files: IFile) => void
9+
}
710
}
811
}

videoMerge/src/preload/index.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,13 @@
1-
import { contextBridge } from 'electron'
1+
import { contextBridge, ipcRenderer } from 'electron'
22
import { electronAPI } from '@electron-toolkit/preload'
3+
import { IFile } from '../main/ipc'
34

45
// Custom APIs for renderer
5-
const api = {}
6+
const api = {
7+
videoMerge: (files: IFile) => {
8+
ipcRenderer.send('videoMerge', files)
9+
}
10+
}
611

712
// Use `contextBridge` APIs to expose Electron APIs to
813
// renderer only if context isolation is enabled, otherwise

videoMerge/src/renderer/src/components/VideoList.vue

Lines changed: 21 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,8 @@
11
<script setup lang="ts">
2-
import { Plus, UpdateRotation, CloseOne } from '@icon-park/vue-next'
3-
import { ElMessage, UploadRequestOptions } from 'element-plus'
4-
import { ref } from 'vue'
5-
const files = ref<string[]>([])
6-
const httpRequest = (options: UploadRequestOptions) => {
7-
const file = options.file.path.split('/').pop()!
8-
const isExists = files.value.some((f) => f == file)
9-
if (isExists) {
10-
ElMessage.error(`${file}已存在`)
11-
} else files.value?.push(file)
12-
}
2+
import { CloseOne, Plus, UpdateRotation } from '@icon-park/vue-next'
3+
import useVideo from '@renderer/composables/useVideo'
134
14-
const removeVideo = (index: number) => {
15-
files.value.splice(index, 1)
16-
}
5+
const { files, httpRequest, removeVideo, isRun, run } = useVideo()
176
</script>
187

198
<template>
@@ -25,8 +14,14 @@ const removeVideo = (index: number) => {
2514

2615
<div
2716
class="w-20 h-20 bg-white flex justify-center items-center rounded-md border border-gray-200 cursor-pointer"
17+
@click="run"
2818
>
29-
<update-rotation theme="outline" size="48" class="text-gray-600 animate-spin" />
19+
<update-rotation
20+
theme="outline"
21+
size="48"
22+
class="text-gray-600"
23+
:class="{ 'animate-spin': isRun }"
24+
/>
3025
</div>
3126
</section>
3227
<section class="text-center text-white my-3 text-xs opacity-40 font-light">
@@ -40,9 +35,10 @@ const removeVideo = (index: number) => {
4035
<div
4136
v-for="(file, index) of files"
4237
:key="index"
43-
class="group bg-[#34495e] text-gray-300 opacity-80 py-1 px-3 my-2 rounded-md flex justify-between items-center hover:bg-white hover:text-[#2c3e50] hover:opacity-90 duration-300 cursor-pointer"
38+
class="group item bg-[#34495e] text-gray-300 opacity-80 py-1 px-3 my-2 rounded-md flex justify-between items-center hover:bg-white hover:text-[#2c3e50] hover:opacity-90 duration-300 cursor-pointer"
39+
:style="`--process:${file.process}%`"
4440
>
45-
<div class="text-xs opacity-70">{{ file }}</div>
41+
<div class="text-xs opacity-70">{{ file.name }}</div>
4642

4743
<close-one
4844
theme="outline"
@@ -66,6 +62,14 @@ const removeVideo = (index: number) => {
6662
:deep(.el-upload-dragger) {
6763
@apply w-20 h-20 flex justify-center items-center;
6864
}
65+
.item {
66+
@apply relative overflow-hidden;
67+
&::before {
68+
content: '';
69+
@apply bg-green-700 absolute left-0 top-0 bottom-0;
70+
width: var(--process);
71+
}
72+
}
6973
// .run {
7074
// animation: rotate 2s both infinite linear;
7175
// }
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import useConfigStore from '@renderer/store/useConfigStore'
2+
import { ElMessage, UploadRequestOptions } from 'element-plus'
3+
import { ref } from 'vue'
4+
interface IVideo {
5+
name: string
6+
path: string
7+
process: number
8+
}
9+
10+
export default () => {
11+
//配置项{片头,片尾}
12+
const { config } = useConfigStore()
13+
//文件列表
14+
const files = ref<IVideo[]>([])
15+
//是否正在合并
16+
const isRun = ref(false)
17+
//选择文件
18+
const httpRequest = (options: UploadRequestOptions) => {
19+
const filePath = options.file.path
20+
const fileName = filePath.split('/').pop()!
21+
const isExists = files.value.some((f) => f.path == filePath)
22+
if (isExists) {
23+
ElMessage.error(`${fileName}已存在`)
24+
} else files.value?.push({ path: filePath, name: fileName, process: 10 })
25+
}
26+
//删除视频
27+
const removeVideo = (index: number) => {
28+
files.value.splice(index, 1)
29+
}
30+
31+
//执行合并
32+
const run = () => {
33+
if (!files.value.length) return ElMessage.error({ message: '请选择视频' })
34+
const video = files.value[0]
35+
window.api.videoMerge({
36+
file: video.path,
37+
preVideo: config.preVideo,
38+
endVideo: config.endVideo
39+
})
40+
}
41+
42+
return { files, httpRequest, removeVideo, isRun, run }
43+
}

0 commit comments

Comments
 (0)