返回

优雅结合 Electron + Vite + Vue3 + Ts,构建 MP4 转换器

后端

打造一款高效的 MP4 转换器:使用 Electron、Vite、Vue3 和 TypeScript

随着数字媒体的蓬勃发展,我们经常需要将视频转换为不同的格式以适应不同设备和平台。MP4 作为一种通用视频格式,凭借其广泛的兼容性、较高的压缩率和清晰的画质,成为当今最受欢迎的视频格式之一。

本文将指导你使用 Electron、Vite、Vue3 和 TypeScript 构建一款简洁高效的 MP4 转换器。这款转换器不仅可以在 Windows、Mac 和 Linux 等不同操作系统上运行,而且操作简单,功能强大,能够满足大多数用户的需求。

技术栈简介

Electron

Electron 是一种跨平台的应用程序框架,它允许我们使用 HTML、CSS 和 JavaScript 构建桌面应用程序。Electron 集成了 Chromium 和 Node.js,使得我们可以轻松访问本地操作系统资源,并使用 JavaScript 处理各种任务。

Vite

Vite 是一个前端构建工具,它采用模块化的开发方式,可以大幅提升开发效率。Vite 还内置了对 TypeScript 的支持,使得我们可以轻松地使用 TypeScript 开发 Electron 应用程序。

Vue3

Vue3 是一个渐进式 JavaScript 框架,它拥有轻量级、易于学习和强大的响应式系统等优点。Vue3 非常适合构建用户界面,特别是在开发单页应用程序时,Vue3 可以帮助我们快速构建出功能强大、交互丰富的应用程序。

TypeScript

TypeScript 是一种强类型的编程语言,它扩展了 JavaScript,增加了类型系统和其它一些特性。TypeScript 可以帮助我们编写更加健壮的代码,并减少运行时错误。

实现步骤

1. 创建项目

使用 Electron CLI 工具创建新的 Electron 项目:

npx create-electron-app my-mp4-converter

2. 安装依赖

cd my-mp4-converter
npm install electron-vite vite @vitejs/plugin-vue vue vue-router @vueuse/core ts-node-dev ffmpeg-static

3. 配置 Vite

vite.config.ts 文件中添加:

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'

export default defineConfig({
  plugins: [vue()],
  build: {
    sourcemap: true
  }
})

4. 编写代码

main.ts

import { app, BrowserWindow, Menu, MenuItem, dialog } from 'electron'
import { createRouter } from 'vue-router'
import { createApp } from 'vue'

const isMac = process.platform === 'darwin'

const appMenu = new Menu()
appMenu.append(new MenuItem({
  label: 'File',
  submenu: [
    {
      label: 'Open',
      click: async () => {
        const { filePaths } = await dialog.showOpenDialog({
          properties: ['openFile'],
          filters: [
            { name: 'Videos', extensions: ['mp4', 'mov', 'avi', 'mkv'] }
          ]
        })
        if (filePaths.length > 0) {
          // TODO: Handle filePaths
        }
      }
    }
  ]
}))

const menu = Menu.buildFromTemplate([
  ...(isMac ? [{
    label: app.getName(),
    submenu: [
      { role: 'about' },
      { type: 'separator' },
      { role: 'quit' }
    ]
  }] : []),
  {
    label: 'File',
    submenu: [
      { role: 'quit' }
    ]
  },
  {
    label: 'View',
    submenu: [
      { role: 'reload' },
      { role: 'forcereload' },
      { role: 'toggledevtools' },
      { type: 'separator' },
      { role: 'resetzoom' },
      { role: 'zoomin' },
      { role: 'zoomout' },
      { type: 'separator' },
      { role: 'togglefullscreen' }
    ]
  },
  appMenu
])
Menu.setApplicationMenu(menu)

function createWindow() {
  const win = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
      nodeIntegration: true,
      contextIsolation: false,
      enableRemoteModule: true
    }
  })

  win.loadFile('index.html')

  win.on('closed', () => {
    win = null
  })
}

app.whenReady().then(() => {
  createWindow()

  app.on('activate', () => {
    if (BrowserWindow.getAllWindows().length === 0) createWindow()
  })
})

app.on('window-all-closed', () => {
  if (process.platform !== 'darwin') app.quit()
})

index.html

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    
    <link
      href="https://unpkg.com/element-plus/dist/index.css"
      rel="stylesheet"
    />
  </head>
  <body>
    <div id="app"></div>
    <script type="module" src="./src/main.js"></script>
  </body>
</html>

main.js

import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import ElementPlus from 'element-plus'

const app = createApp(App)

app.use(router)
app.use(ElementPlus)

app.mount('#app')

App.vue

<template>
  <div>
    <h1>MP4 Converter</h1>
    <el-button @click="selectFile">Select File</el-button>
    <el-input v-model="file" placeholder="No file selected" disabled></el-input>
    <el-button v-if="file" @click="convert">Convert</el-button>
  </div>
</template>

<script>
import { ref } from 'vue'
import { ipcRenderer } from 'electron'

export default {
  setup() {
    const file = ref(null)

    const selectFile = () => {
      ipcRenderer.send('open-file-dialog')
    }

    const convert = () => {
      // TODO: Handle conversion
    }

    ipcRenderer.on('selected-file', (event, filePaths) => {
      file.value = filePaths[0]
    })

    return {
      file,
      selectFile,
      convert
    }
  }
}
</script>

router.js

import { createRouter, createWebHistory } from 'vue-router'

const router = createRouter({
  history: createWebHistory(),
  routes: [
    {
      path: '/',
      name: 'home',
      component: () => import('./views/Home.vue')
    },
    {
      path: '/about',
      name: 'about',
      component: () => import('./views/About.vue')
    }
  ]
})

export default router

5. 运行程序

npm run dev

常见问题解答

1. 我可以在哪些平台上运行这款转换器?

这款转换器可以在 Windows、Mac 和 Linux 等不同操作系统上运行。

2. 我可以转换哪些格式的视频?

目前,这款转换器支持将视频转换为 MP4 格式。

3. 我可以同时转换多个视频吗?

目前,这款转换器一次只能转换一个视频。

4. 我可以自定义转换设置吗?

目前,这款转换器尚未提供自定义转换设置的功能。

5. 如果遇到问题,如何获得帮助?

你可以通过 GitHub 上的 issue tracker 来报告问题或寻求帮助。