add 获取视频长度及测试用按钮与请求地址
This commit is contained in:
parent
768bdcc2af
commit
fe815b455d
@ -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
|
@ -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])
|
/**
|
||||||
|
* 获取视频长度
|
||||||
|
* @param {String} filePath 文件绝对路径
|
||||||
|
* @returns {number} 时长(秒)
|
||||||
|
*/
|
||||||
|
function getVideoTotalLength(filePath) {
|
||||||
|
|
||||||
|
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) => {
|
lux.stdout.on('data', (data) => {
|
||||||
console.log(String(data))
|
console.log("开始")
|
||||||
callback(String(data),false)
|
console.log(data)
|
||||||
});
|
});
|
||||||
lux.on('close', (code) => {
|
lux.on('close', (code) => {
|
||||||
console.log("结束")
|
console.log("结束")
|
||||||
callback(code,true)
|
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
|
||||||
}
|
}
|
4
view/dist/index.html
vendored
4
view/dist/index.html
vendored
@ -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>
|
||||||
|
@ -2,31 +2,33 @@
|
|||||||
<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>
|
||||||
|
<el-button style="flex-shrink: 0;margin: 0 10px;" @click="test" 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.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>
|
</div>
|
||||||
|
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-table ref="table" :data="tableData" style="width: 100%">
|
<el-table ref="table" :data="tableData" style="width: 100%">
|
||||||
<el-table-column type="selection" width="55" />
|
<el-table-column type="selection" width="55"/>
|
||||||
<el-table-column label="title" prop="title">
|
<el-table-column label="title" prop="title">
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="url" prop="url" />
|
<el-table-column label="url" prop="url"/>
|
||||||
</el-table>
|
</el-table>
|
||||||
<el-dialog :fullscreen="true" v-model="dialogVisible" title="Tips" width="30%">
|
<el-dialog :fullscreen="true" v-model="dialogVisible" title="Tips" width="30%">
|
||||||
<div style="width: 100%;height: 100%;overflow-y: auto;">
|
<div style="width: 100%;height: 100%;overflow-y: auto;">
|
||||||
@ -38,9 +40,10 @@
|
|||||||
</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",
|
||||||
@ -49,7 +52,8 @@ const form = ref({
|
|||||||
})
|
})
|
||||||
const tableData = ref([])
|
const tableData = ref([])
|
||||||
const table = ref()
|
const table = ref()
|
||||||
function getlist() {
|
|
||||||
|
function getList() {
|
||||||
// let load = ElLoading.service()
|
// let load = ElLoading.service()
|
||||||
// window.getlist(form.value.name).then((res) => {
|
// window.getlist(form.value.name).then((res) => {
|
||||||
// console.log(res)
|
// console.log(res)
|
||||||
@ -57,23 +61,25 @@ function getlist() {
|
|||||||
// load.close()
|
// load.close()
|
||||||
// })
|
// })
|
||||||
axios.get("/getQqList", {
|
axios.get("/getQqList", {
|
||||||
params: { url: form.value.name }
|
params: {url: form.value.name}
|
||||||
}).then((r) => {
|
}).then((r) => {
|
||||||
tableData.value = r.data
|
tableData.value = r.data
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
function setlist() {
|
|
||||||
|
function setList() {
|
||||||
table.value.clearSelection()
|
table.value.clearSelection()
|
||||||
for (let i = form.value.start - 1; i < tableData.value.length; i++) {
|
for (let i = form.value.start - 1; i < tableData.value.length; i++) {
|
||||||
console.log(i)
|
console.log(i)
|
||||||
table.value.toggleRowSelection(tableData.value[i], undefined)
|
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({
|
ElMessage({
|
||||||
showClose: true,
|
showClose: true,
|
||||||
message: '请选择要下载的剧集',
|
message: '请选择要下载的剧集',
|
||||||
@ -92,7 +98,7 @@ async function dow() {
|
|||||||
}
|
}
|
||||||
dialogVisible.value = true
|
dialogVisible.value = true
|
||||||
|
|
||||||
localStorage.setItem("save",form.value.save)
|
localStorage.setItem("save", form.value.save)
|
||||||
for (let i of list) {
|
for (let i of list) {
|
||||||
await axios.get("/startDown", {
|
await axios.get("/startDown", {
|
||||||
params: {
|
params: {
|
||||||
@ -108,6 +114,7 @@ async function dow() {
|
|||||||
type: 'success',
|
type: 'success',
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const source = new EventSource(`/msg`);
|
const source = new EventSource(`/msg`);
|
||||||
source.onmessage = event => {
|
source.onmessage = event => {
|
||||||
// 挂到载体上面
|
// 挂到载体上面
|
||||||
@ -116,11 +123,22 @@ source.onmessage = event => {
|
|||||||
}
|
}
|
||||||
msg.value.unshift(event.data)
|
msg.value.unshift(event.data)
|
||||||
}
|
}
|
||||||
function showmsg() {
|
|
||||||
|
function showMsg() {
|
||||||
dialogVisible.value = true
|
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>
|
Loading…
Reference in New Issue
Block a user