马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
×
#1024步伐员节 | 征文#
目次
一、简介
二、音频素材页
2.1 功能形貌
搜索
添加
删除
2.2 结果展示
2.3 代码实现
前端
后端
三、视频素材页
3.1 功能形貌
搜索
添加
编辑
删除
3.2 结果展示
3.3 代码实现
前端
后端
四、分组管理页
4.1 功能形貌
搜索
添加
编辑
删除
4.2 结果展示
4.3 代码实现
前端
后端
五、视频混剪页
5.1 功能形貌
搜索
添加
删除
5.2 结果展示
5.3 代码实现
前端
后端
一、简介
此篇文章带来的是 利用 FFmpeg 实现视频混剪而且可以指定天生视频的数目以及天生视频的时长,此案例也是对前边几篇文章功能的综合。
阐明:
此案例中的代码部分,前端利用的是 Vue + ElementPlus + Vite、后端利用的是 Nodejs + FFmpeg + MySQL
下方提供的代码为每一部分的核心代码,假如须要案例的完备代码,可以在批评区留言我来私信你!!!
二、音频素材页
2.1 功能形貌
搜索
在搜索栏中输入 音频名称、上传时间 后点击搜索按钮即可,也可以只输入一个条件搜索。
添加
点击页面上的【添加音频】按钮,然后在弹出的上传音频对话框中输入 音频名称,并选择要上传的音频文件之后直接点击确定按钮即可完成音频文件的上传。
删除
点击表格中的【删除】按钮即可删除对应的音频文件
2.2 结果展示
音频素材页面 点击上一张图片中的添加音频按钮弹出的对话框 选择要上传的音频文件 2.3 代码实现
前端
- <template>
- <div>
- <el-button type="primary" @click="dialogVisible = true">添加音频</el-button>
- <el-row style="margin: 10px 0">
- <el-form v-model="queryParams" inline>
- <el-form-item label="音频名称">
- <el-input
- v-model="queryParams.name"
- placeholder="输入要查询的文件名称"
- style="width: 200px"
- ></el-input>
- </el-form-item>
- <el-form-item label="上传时间">
- <el-date-picker
- v-model="daterange"
- type="daterange"
- unlink-panels
- range-separator="至"
- start-placeholder="开始日期"
- end-placeholder="结束日期"
- :shortcuts="shortcuts"
- />
- </el-form-item>
- </el-form>
- <div style="margin-left: 20px">
- <el-button type="primary" @click="handleSearch">搜索</el-button>
- <el-button type="info" plain @click="handleReset">重置</el-button>
- </div>
- </el-row>
- <el-table
- :data="tableData"
- stripe
- border
- :style="{ height: tableHeight ? tableHeight + 'px' : '' }"
- >
- <el-table-column prop="id" label="ID" align="center" />
- <el-table-column prop="name" label="音频名称" align="center" />
- <el-table-column
- prop="path"
- label="音频文件"
- align="center"
- min-
- >
- <template #default="scope">
- <audio :src="scope.row.path" controls class="audioStyle"></audio>
- </template>
- </el-table-column>
- <el-table-column
- prop="type"
- label="音频类型"
- align="center"
-
- />
- <el-table-column prop="size" label="文件大小" align="center" >
- <template #default="scope"> {
-
- { scope.row.size }}M </template>
- </el-table-column>
- <el-table-column
- prop="upload_time"
- label="上传时间"
- align="center"
-
- />
- <el-table-column label="操作" align="center" fixed="right">
- <template #default="scope">
- <el-button
- v-if="choose"
- type="success"
- size="small"
- @click="handleChoose(scope.row)"
- >选择</el-button
- >
- <el-button
- v-else
- type="danger"
- size="small"
- @click="handleDelete(scope.row)"
- >删除</el-button
- >
- </template>
- </el-table-column>
- </el-table>
- <el-row style="margin-top: 10px; justify-content: end; align-items: center">
- <span style="margin-right: 20px; color: #606266">共 {
-
- { total }} 条</span>
- <el-pagination
- background
- layout="prev, pager, next"
- :page-size="queryParams.size"
- :total="total"
- @current-change="handleCurrentChange"
- ></el-pagination>
- </el-row>
- <!-- 添加音频对话框 -->
- <el-dialog v-model="dialogVisible" title="上传音频">
- <el-form :model="formData" :rules="rules" ref="ruleFormRef">
- <el-form-item label="音频名称" prop="name">
- <el-input
- v-model="formData.name"
- placeholder="请输入音频名称"
- ></el-input>
- </el-form-item>
- <el-form-item label="音频文件" prop="file">
- <el-input
- v-model="formData.path"
- placeholder="请选择音频文件"
- class="input-with-select"
- disabled
- >
- <template #append>
- <el-upload
- v-model:file-list="fileList"
- action=""
- :limit="1"
- :before-upload="beforeUpload"
- :show-file-list="false"
- accept="audio/*"
- >
- <el-button :icon="Upload" class="upload-btn">上传</el-button>
- </el-upload>
- </template>
- </el-input>
- </el-form-item>
- </el-form>
- <template #footer>
- <div class="dialog-footer">
- <el-button @click="handleCancel">取消</el-button>
- <el-button type="primary" @click="handleSubmit"> 确定 </el-button>
- </div>
- </template>
- </el-dialog>
- </div>
- </template>
- <script setup>
- import { onMounted, ref } from "vue";
- import { Upload } from "@element-plus/icons-vue";
- import { post, get, del } from "@/utils/http";
- import { useStore } from "@/store";
- const porp = defineProps(["choose"]);
- const store = useStore();
- const tableData = ref([]);
- const total = ref(0);
- // 查询条件
- const queryParams = ref({
- name: undefined,
- startTime: undefined,
- endTime: undefined,
- page: 1,
- size: 10,
- });
- const daterange = ref([]);
- const shortcuts = [
- {
- text: "最近一周",
- value: () => {
- const end = new Date();
- const start = new Date();
- start.setTime(start.getTime() - 3600 * 1000 * 24 * 7);
- return [start, end];
- },
- },
- {
- text: "最近一个月",
- value: () => {
- const end = new Date();
- const start = new Date();
- start.setTime(start.getTime() - 3600 * 1000 * 24 * 30);
- return [start, end];
- },
- },
- {
- text: "最近三个月",
- value: () => {
- const end = new Date();
- const start = new Date();
- start.setTime(start.getTime() - 3600 * 1000 * 24 * 90);
- return [start, end];
- },
- },
- ];
- // 获取音频列表
- const getList = () => {
- get("/audio/list", queryParams.value).then((res) => {
- tableData.value = res.data;
- total.value = res.total;
- });
- };
- // 搜索
- const handleSearch = () => {
- queryParams.value.startTime = daterange.value[0];
- queryParams.value.endTime = daterange.value[1];
- console.log(queryParams.value);
- getList();
- };
- // 重置
- const handleReset = () => {
- queryParams.value = {
- name: undefined,
- startTime: undefined,
- endTime: undefined,
- page: 1,
- size: 10,
- };
- daterange.value = [];
- getList();
- };
- // 切换页
- const handleCurrentChange = (page) => {
- queryParams.value.page = page;
- getList();
- };
- const dialogVisible = ref(false); //弹出对话框是否显示
- const fileList = ref([]);
- const ruleFormRef = ref(null);
- const formData = ref({
- name: "",
- path: "",
- file: "",
- });
- // 校验规则
- const rules = {
- name: [{ required: true, message: "请输入音频名称", trigger: "blur" }],
- file: [
- { required: true, message: "请选择要上传的音频文件", trigger: "blur" },
- ],
- };
- // 点击取消按钮
- const handleCancel = () => {
- dialogVisible.value = false;
- // 重置表单
- formData.value = {
- name: "",
- file: "",
- };
- };
- // 点击确定按钮
- const handleSubmit = () => {
- const data = new FormData();
- data.append("name", formData.value.name);
- data.append("audio", formData.value.file);
- console.log(formData.value);
- // 先进行表单的验证
- ruleFormRef.value.validate((valid) => {
- if (valid) {
- post("/audio/single/audio", data).then((res) => {
- ElMessage.success("上传成功");
- console.log("上传成功", res);
- dialogVisible.value = false;
- getList();
- });
- }
- });
- };
- // 上传文件之前
- const beforeUpload = (file) => {
- formData.value.path = URL.createObjectURL(file);
- formData.value.file = file;
- return false;
- };
- // 删除
- const handleDelete = (item) => {
- del(`/audio/delete/${item.id}`).then((res) => {
- ElMessage.success("删除成功");
- getList();
- });
- };
- // 选择音频
- const handleChoose = (item) => {
- store.chooseBgm(item);
- store.setAudioDialog();
- };
- onMounted(() => {
- getList();
- });
- </script>
- <style lang="scss" scoped>
- .el-table {
- margin-top: 10px;
- }
- .el-button.upload-btn {
- height: 100%;
- background: #f56c6c;
- color: #fff;
- &:hover {
- background: #f89898;
- color: #fff;
- }
- }
- .el-input-group__append > div {
- display: flex;
- }
- .audioStyle {
- width: 250px;
- height: 40px;
- }
- </style>
复制代码 后端
- var express = require('express');
- var router = express.Router();
- const multer = require('multer');
- const path = require('path');
- const connection = require('../config/db.config')
- const baseURL = 'http://localhost:3000'
- // 音频
- const uploadVoice = multer({
- dest: 'public/uploadVoice/',
- storage: multer.diskStorage({
- destination: function (req, file, cb) {
- cb(null, 'public/uploadVoice'); // 文件保存的目录
- },
- filename: function (req, file, cb) {
- // 提取原始文件的扩展名
- const ext = path.extname(file.originalname).toLowerCase(); // 获取文件扩展名,并转换为小写
- // 生成唯一文件名,并加上扩展名
- const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1E9);
- const fileName = uniqueSuffix + ext; // 新文件名
- cb(null, fileName); // 文件名
- }
- })
- });
- // 上传单个音频文件
- router.post('/single/audio', uploadVoice.single('audio'), (req, res) => {
- const audioPath = req.file.path.replace('public', '').replace(/\\/g, '/');
- const { name } = req.body
- const type = req.file.filename.split('.')[1]
- const size = (req.file.size / (1024 * 1024)).toFixed(2)
- console.log(req.file)
- console.log(name, audioPath, type, size)
- const insertSql = 'insert into audio (name,path,type,size) values (?,?,?,?)'
- const insertValues = [name, audioPath, type, size]
- connection.query(insertSql, insertValues, (err, results) => {
- if (err) {
- console.error('插入数据失败:', err.message);
- res.send({
- status: 500,
- msg: err.message
- })
- return;
- }
- console.log('音频插入成功');
- res.send({
- status: 200,
- msg: 'ok',
- path: audioPath// 返回新插入记录的ID
- })
- })
- })
- // 获取音频列表
- router.get('/list', (req, res) => {
- let { name, startTime, endTime, page, size, isAll } = req.query
- startTime = startTime ? (new Date(startTime)).toLocaleDateString() : ''
- endTime = endTime ? (new Date(endTime)).toLocaleDateString() : ''
- console.log({ name, startTime, endTime, page, size })
- let selectSql = ''
- // 按照名称查询并按照id进行倒序排列
- if (name && !startTime) {
- selectSql = `select * from audio where name like '%${name}%' order by id desc`
- } else if (!name && startTime) {
- // 按照上传时间并按照id进行倒序排列
- selectSql = `select * from audio where Date(upload_time) between '${startTime}' and '${endTime}' order by id desc`
- } else if (name && startTime) {
- // 按照时间时间和名称并按照id进行倒序排列
- selectSql = `select * from audio where name like '%${name}%' and Date(upload_time) between '${startTime}' and '${endTime}' order by id desc`
- } else {
- selectSql = 'select * from audio order by id desc'
- }
- connection.query(selectSql, (err, results) => {
- if (err) {
- console.error('查询数据失败:', err.message);
- res.send({
- status: 500,
- msg: err.message
- })
- return;
- }
- const data = results.map(item => {
- item.path = baseURL + item.path
- item['upload_time'] = item['upload_time'].toLocaleString()
- return item
- })
- res.send({
- status: 200,
- msg: 'ok',
- data: isAll ? data : data.slice((page - 1) * size, page * size),
- total: data.length
- })
- })
- })
- // 删除音频
- router.delete('/delete/:id', (req, res) => {
- const { id } = req.params
- const deleteSql = `delete from audio where id = ?`
- connection.query(deleteSql, [id], (err, results) => {
- if (err) {
- console.error('删除数据失败:', err.message);
- res.send({
- status: 500,
- msg: err.message
- })
- return;
- }
- console.log('音频删除成功')
- res.send({
- status: 200,
- msg: 'ok',
- })
- })
- })
- module.exports = router;
复制代码 三、视频素材页
3.1 功能形貌
搜索
在搜索栏中输入 视频名称、视频分组、上传时间 后点击搜索按钮即可,也可以只输入一个大概两个条件搜索。
添加
点击页面上的【上传视频】按钮,然后在弹出的上传视频对话框中输入 视频名称、选择 视频分组(选填),并选择要上传的视频文件之后,点击确定按钮即可完成视频文件的上传。
编辑
点击页面中的【编辑】按钮,即可在弹出的对话框中编辑该条视频的 名称和分组。
删除
点击页面中的【删除】按钮,即可删除对应的视频文件。
3.2 结果展示
视频素材页面 点击上一张图片中的上传视频按钮弹出的对话框 选择要上传的视频文件 3.3 代码实现
前端
- <template>
- <div>
- <el-button type="primary" @click="handleAdd">上传视频</el-button>
- <el-row style="margin-top: 10px">
- <el-form v-model="queryParams" inline>
- <el-form-item label="视频名称">
- <el-input
- v-model="queryParams.name"
- placeholder="输入要查询的文件名称"
- style="width: 200px"
- ></el-input>
- </el-form-item>
- <el-form-item label="视频分组">
- <el-select
- v-model="queryParams.group_id"
- clearable
- placeholder="请选择分组"
- style="width: 200px"
- >
- <el-option
- v-for="item in groups"
- :key="item.id"
- :label="item.group_name"
- :value="item.id"
- />
- </el-select>
- </el-form-item>
- <el-form-item label="上传时间">
- <el-date-picker
- v-model="daterange"
- type="daterange"
- unlink-panels
- range-separator="至"
- start-placeholder="开始日期"
- end-placeholder="结束日期"
- :shortcuts="shortcuts"
- />
- </el-form-item>
- </el-form>
- <div style="margin-left: 20px">
- <el-button type="primary" @click="handleSearch">搜索</el-button>
- <el-button type="info" plain @click="handleReset">重置</el-button>
- </div>
- </el-row>
- <el-button type="success" @click="handleChooseMul" v-if="choose"
- >选择</el-button
- >
- <el-table
- ref="tableRef"
- :data="tableData"
- stripe
- border
- @selection-change="handleSelectionChange"
- :style="{ height: tableHeight ? tableHeight + 'px' : '' }"
复制代码 |