add 获取视频长度及测试用按钮与请求地址

This commit is contained in:
SummerTail 2023-06-30 20:49:07 +08:00
parent 768bdcc2af
commit fe815b455d
4 changed files with 185 additions and 134 deletions

View File

@ -1,13 +1,19 @@
const Router = require("koa-router") const Router = require("koa-router")
const { getQqListData } = require("../util/getList/qq") const {getQqListData} = require("../util/getList/qq")
const {getVideoTotalLength} = require("../util/utils")
const KoaSSEStream = require('koa-sse-stream'); const KoaSSEStream = require('koa-sse-stream');
const { dowload } = require("../util/download"); const {dowload} = require("../util/download");
const { addDownList, getDownList, setDownState } = require("../util/sql/download"); const {addDownList, getDownList, setDownState} = require("../util/sql/download");
const dayjs = require("dayjs") const dayjs = require("dayjs")
const router = new Router() const router = new Router()
// const dowloadlist = [] // const dowloadlist = []
router.get("/getQqList",async (ctx)=>{ router.get("/test", async (ctx) => {
let url = ctx.query.url
ctx.body = getVideoTotalLength(url)
})
router.get("/getQqList", async (ctx) => {
let url = ctx.query.url let url = ctx.query.url
let videoid = url.split("/") let videoid = url.split("/")
for(let i in videoid){ for(let i in videoid){
@ -20,7 +26,7 @@ router.get("/getQqList",async (ctx)=>{
ctx.body = list ctx.body = list
}) })
router.get("/startDown",async (ctx)=>{ router.get("/startDown", async (ctx) => {
let title = ctx.query.title let title = ctx.query.title
let url = ctx.query.url let url = ctx.query.url
let save = ctx.query.save let save = ctx.query.save
@ -28,10 +34,10 @@ router.get("/startDown",async (ctx)=>{
// title,url,save // title,url,save
// }) // })
// startDown() // startDown()
addDownList(title,url,save,new Date().getTime(),0) addDownList(title, url, save, new Date().getTime(), 0)
ctx.body={ ctx.body = {
code:0, code: 0,
msg:"添加成功" msg: "添加成功"
} }
}) })
// 连接池 // 连接池
@ -44,33 +50,35 @@ const SSE_CONF = {
router.get('/msg', KoaSSEStream(SSE_CONF), ctx => { router.get('/msg', KoaSSEStream(SSE_CONF), ctx => {
// 每次连接会进行一个 push // 每次连接会进行一个 push
clientList.push(ctx.sse); clientList.push(ctx.sse);
if(clientList.length > 5){ if (clientList.length > 5) {
// 超过5个删除最开始的一个 // 超过5个删除最开始的一个
// todo 浏览器关闭后自动检测删除 // todo 浏览器关闭后自动检测删除
clientList.shift() clientList.shift()
} }
}) })
let start = false let start = false
function startDown(data){
function startDown(data) {
start = true start = true
dowload(data,async (data2,isok)=>{ dowload(data, async (data2, isok) => {
let name = data2.title let name = data2.title
clientList.forEach((i)=>{ clientList.forEach((i) => {
i.send(isok ? `${name}下载完成` : data2 ) i.send(isok ? `${name}下载完成` : data2)
}) })
if(isok){ if (isok) {
// dowloadlist.shift() // dowloadlist.shift()
await setDownState(data.id,1) await setDownState(data.id, 1)
start = false start = false
} }
}) })
} }
setInterval(async ()=>{
setInterval(async () => {
let dowloadlist = await getDownList() let dowloadlist = await getDownList()
if(dowloadlist.length != 0 && !start){ if (dowloadlist.length != 0 && !start) {
startDown(dowloadlist[0]) startDown(dowloadlist[0])
}else if(dowloadlist.length == 0){ } else if (dowloadlist.length == 0) {
start = false start = false
} }
},1000) }, 1000)
module.exports = router module.exports = router

View File

@ -1,27 +1,52 @@
const { spawn } = require('child_process'); const {spawn} = require('child_process');
function seep(time){ function seep(time) {
return new Promise((res)=>{ return new Promise((res) => {
setTimeout(()=>{ setTimeout(() => {
res() res()
},time) }, time)
}) })
} }
function dow(info,callback){
const lux = spawn("./bin/yt-dlp.exe", ['--cookies-from-browser', 'chrome', '-P', info.save, '-o', info.title + '.mp4', info.url]) /**
lux.stdout.on('data', (data) => { * 获取视频长度
console.log(String(data)) * @param {String} filePath 文件绝对路径
callback(String(data),false) * @returns {number} 时长()
}); */
lux.on('close', (code) => { function getVideoTotalLength(filePath) {
console.log("结束")
callback(code,true) const lux = spawn("./bin/ffmpeg.exe", ['-i', filePath, '-show_entries', 'format=duration', '-v', 'quiet', '-of', 'csv="p=0"'])
}); console.log("join")
lux.stdout.on('data', (data) => {
console.log("开始")
console.log(data)
});
lux.on('close', (code) => {
console.log("结束")
console.log(code.toString())
});
return 0;
} }
function dow(info, callback) {
const lux = spawn("./bin/yt-dlp.exe", ['--cookies-from-browser', 'chrome', '-P', info.save, '-o', info.title + '.mp4', info.url])
lux.stdout.on('data', (data) => {
console.log(String(data))
callback(String(data), false)
});
lux.on('close', (code) => {
console.log("结束")
callback(code, true)
});
}
module.exports = { module.exports = {
seep, seep,
dow dow,
getVideoTotalLength
} }

View File

@ -5,8 +5,8 @@
<link rel="icon" type="image/svg+xml" href="./vite.svg" /> <link rel="icon" type="image/svg+xml" href="./vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite + Vue</title> <title>Vite + Vue</title>
<script type="module" crossorigin src="./assets/index-ec9a45aa.js"></script> <script type="module" crossorigin src="./assets/index-ea8b965c.js"></script>
<link rel="stylesheet" href="./assets/index-6ef103ac.css"> <link rel="stylesheet" href="./assets/index-e0450ab1.css">
</head> </head>
<body> <body>
<div id="app"></div> <div id="app"></div>

View File

@ -1,126 +1,144 @@
<template> <template>
<div class="url"> <div class="url">
<el-form-item label="视频地址"> <el-form-item label="视频地址">
<div style="display: flex;width: 100%;"> <div style="display: flex;width: 100%;">
<el-input style="width: 100%;" v-model="form.name" /> <el-input style="width: 100%;" v-model="form.name"/>
<el-button style="flex-shrink: 0;margin: 0 10px;" @click="getlist" type="primary">获取</el-button> <el-button style="flex-shrink: 0;margin: 0 10px;" @click="getList" type="primary">获取</el-button>
</div> </div>
</el-form-item> </el-form-item>
<el-form-item label="第几集开始"> <el-form-item label="第几集开始">
<div style="display: flex;"> <div style="display: flex;">
<el-input v-model="form.start" /> <el-input v-model="form.start"/>
<el-button style="flex-shrink: 0;margin: 0 10px;" @click="setlist" type="primary">设置</el-button> <el-button style="flex-shrink: 0;margin: 0 10px;" @click="setList" type="primary">设置</el-button>
</div> <el-button style="flex-shrink: 0;margin: 0 10px;" @click="test" type="primary">测试按钮</el-button>
</div>
</el-form-item> </el-form-item>
<el-form-item label="下载保存地址"> <el-form-item label="下载保存地址">
<div style="display: flex;"> <div style="display: flex;">
<el-input v-model="form.save" /> <el-input v-model="form.save"/>
<el-button style="flex-shrink: 0;margin: 0 10px;" @click="dow" type="primary">下载</el-button> <el-button style="flex-shrink: 0;margin: 0 10px;" @click="dow" type="primary">下载</el-button>
<el-button style="flex-shrink: 0;margin: 0 10px;" @click="showmsg" type="primary">查看进度</el-button> <el-button style="flex-shrink: 0;margin: 0 10px;" @click="showMsg" type="primary">查看进度</el-button>
</div>
</el-form-item> </div>
<el-table ref="table" :data="tableData" style="width: 100%">
<el-table-column type="selection" width="55" />
<el-table-column label="title" prop="title">
</el-table-column>
<el-table-column label="url" prop="url" />
</el-table>
<el-dialog :fullscreen="true" v-model="dialogVisible" title="Tips" width="30%">
<div style="width: 100%;height: 100%;overflow-y: auto;">
<div v-for="i in msg">{{ i }}</div>
</div>
</el-dialog> </el-form-item>
</div> <el-table ref="table" :data="tableData" style="width: 100%">
<el-table-column type="selection" width="55"/>
<el-table-column label="title" prop="title">
</el-table-column>
<el-table-column label="url" prop="url"/>
</el-table>
<el-dialog :fullscreen="true" v-model="dialogVisible" title="Tips" width="30%">
<div style="width: 100%;height: 100%;overflow-y: auto;">
<div v-for="i in msg">{{ i }}</div>
</div>
</el-dialog>
</div>
</template> </template>
<script setup> <script setup>
import { ref } from 'vue'; import {ref} from 'vue';
import { ElLoading, ElMessage } from 'element-plus' import {ElLoading, ElMessage} from 'element-plus'
import axios from 'axios'; import axios from 'axios';
const dialogVisible = ref(false) const dialogVisible = ref(false)
const form = ref({ const form = ref({
name: "https://v.qq.com/x/cover/mzc002007vp35qj.html", name: "https://v.qq.com/x/cover/mzc002007vp35qj.html",
start: 1, start: 1,
save: localStorage.getItem("save") save: localStorage.getItem("save")
}) })
const tableData = ref([]) const tableData = ref([])
const table = ref() const table = ref()
function getlist() {
// let load = ElLoading.service() function getList() {
// window.getlist(form.value.name).then((res) => { // let load = ElLoading.service()
// console.log(res) // window.getlist(form.value.name).then((res) => {
// tableData.value = res // console.log(res)
// load.close() // tableData.value = res
// }) // load.close()
axios.get("/getQqList", { // })
params: { url: form.value.name } axios.get("/getQqList", {
}).then((r) => { params: {url: form.value.name}
tableData.value = r.data }).then((r) => {
}) tableData.value = r.data
})
} }
function setlist() {
table.value.clearSelection() function setList() {
for (let i = form.value.start - 1; i < tableData.value.length; i++) { table.value.clearSelection()
console.log(i) for (let i = form.value.start - 1; i < tableData.value.length; i++) {
table.value.toggleRowSelection(tableData.value[i], undefined) console.log(i)
} table.value.toggleRowSelection(tableData.value[i], undefined)
}
} }
const msg = ref([]) const msg = ref([])
async function dow() { async function dow() {
let list = table.value.getSelectionRows() let list = table.value.getSelectionRows()
if (list.length == 0) { if (list.length === 0) {
ElMessage({
showClose: true,
message: '请选择要下载的剧集',
type: 'error',
})
return
}
if (!form.value.save) {
ElMessage({
showClose: true,
message: '请填写下载位置',
type: 'error',
})
return
}
dialogVisible.value = true
localStorage.setItem("save",form.value.save)
for (let i of list) {
await axios.get("/startDown", {
params: {
...i,
save: form.value.save + "/" + i.title.split(" ")[0]
}
})
}
// dialogVisible.value = false
ElMessage({ ElMessage({
showClose: true, showClose: true,
message: '添加完成', message: '请选择要下载的剧集',
type: 'success', type: 'error',
}) })
return
}
if (!form.value.save) {
ElMessage({
showClose: true,
message: '请填写下载位置',
type: 'error',
})
return
}
dialogVisible.value = true
localStorage.setItem("save", form.value.save)
for (let i of list) {
await axios.get("/startDown", {
params: {
...i,
save: form.value.save + "/" + i.title.split(" ")[0]
}
})
}
// dialogVisible.value = false
ElMessage({
showClose: true,
message: '添加完成',
type: 'success',
})
} }
const source = new EventSource(`/msg`); const source = new EventSource(`/msg`);
source.onmessage = event => { source.onmessage = event => {
// //
if (msg.value.length > 200) { if (msg.value.length > 200) {
msg.value.splice(200) msg.value.splice(200)
} }
msg.value.unshift(event.data) msg.value.unshift(event.data)
} }
function showmsg() {
dialogVisible.value = true function showMsg() {
dialogVisible.value = true
} }
function test() {
axios.get("/test", {
params: {url: form.value.name}
}).then((r) => {
console.log(r.data);
})
}
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.url {} .url {
}
</style> </style>