Skip to content

Commit

Permalink
Merge pull request #149 from caorushizi/fix/addForm
Browse files Browse the repository at this point in the history
feat: ✨  支持直播视频下载
  • Loading branch information
caorushizi authored May 21, 2024
2 parents e79af1f + 7655aeb commit dd9de54
Show file tree
Hide file tree
Showing 18 changed files with 143 additions and 103 deletions.
1 change: 1 addition & 0 deletions .cspell/custom-words.txt
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,4 @@ acodec
KHTML
svgz
stylelint
consola
2 changes: 0 additions & 2 deletions .env
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,3 @@ APP_NAME=mediago
APP_ID=mediago.ziying.site
APP_COPYRIGHT=caorushizi
APP_VERSION=2.2.0-beta.3

APP_SERVER_PORT=8433
1 change: 1 addition & 0 deletions packages/main/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
"@typescript-eslint/eslint-plugin": "6.21.0",
"@typescript-eslint/parser": "6.21.0",
"chokidar": "^3.5.3",
"consola": "^3.2.3",
"cross-env": "^7.0.3",
"dotenv": "^16.3.2",
"electron": "^28.2.6",
Expand Down
9 changes: 5 additions & 4 deletions packages/main/scripts/dev.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@ import { ChildProcessWithoutNullStreams, spawn } from "child_process";
import electron from "electron";
import * as esbuild from "esbuild";
import chokidar from "chokidar";
import { loadDotEnvRuntime, mainResolve, log, copyResource } from "./utils";
import { loadDotEnvRuntime, mainResolve, copyResource } from "./utils";
import { external } from "./config";
import consola from "consola";

let electronProcess: ChildProcessWithoutNullStreams | null = null;

Expand Down Expand Up @@ -46,11 +47,11 @@ function startElectron() {
electronProcess = spawn(String(electron), args);

electronProcess.stdout.on("data", (data) => {
log(String(data));
consola.log(String(data));
});

electronProcess.stderr.on("data", (data) => {
log(String(data));
consola.log(String(data));
});
}

Expand Down Expand Up @@ -82,7 +83,7 @@ async function start() {
watcher.on("change", async () => {
await mainContext.rebuild();
await preloadContext.rebuild();
log("watch build succeed.");
consola.log("watch build succeed.");
restartElectron();
});

Expand Down
47 changes: 17 additions & 30 deletions packages/main/scripts/utils.ts
Original file line number Diff line number Diff line change
@@ -1,56 +1,43 @@
import { existsSync, cpSync, rmSync } from "fs";
import dotenv from "dotenv";
import { resolve } from "path";
import consola from "consola";

// FIXME: 有没有什么办法可以不用这么写?
const con = console;
export const log = con.log;

export const mainResolve = (...r: any[]) => resolve(__dirname, "..", ...r);
export const rootResolve = (...r: any[]) =>
export const mainResolve = (...r: string[]) => resolve(__dirname, "..", ...r);
export const rootResolve = (...r: string[]) =>
resolve(__dirname, "../../..", ...r);
const nodeEnv = process.env.NODE_ENV;
log("当前的环境是: ", nodeEnv);
consola.log("当前的环境是: ", nodeEnv);

function loadEnv(path: string) {
const result: Record<string, string> = {};

const _loadEnv = (path: string) => {
if (!existsSync(path)) {
return null;
}

const { error, parsed } = dotenv.config({ path });
if (error != null || !parsed) {
return null;
}
if (!existsSync(path)) {
return null;
}

Object.keys(parsed).forEach((key) => {
result[key] = parsed[key];
});
};
const { error, parsed } = dotenv.config({ path, override: true });
if (error != null || !parsed) {
return null;
}

_loadEnv(path);
_loadEnv(`${path}.local`);
Object.keys(parsed).forEach((key) => {
result[key] = parsed[key];
});

return result;
}

function loadDotEnv() {
const env = loadEnv(rootResolve(".env"));
const envMode = loadEnv(rootResolve(`.env.${nodeEnv}`));
const envModeLocal = loadEnv(rootResolve(`.env.${nodeEnv}.local`));

return { ...env, ...envMode };
return { ...env, ...envMode, ...envModeLocal };
}

export function loadDotEnvRuntime() {
const env = loadDotEnv();

Object.keys(env).forEach((key) => {
if (!process.env[key]) {
process.env[key] = env[key];
}
});
loadDotEnv();
}

export function loadDotEnvDefined() {
Expand Down
3 changes: 0 additions & 3 deletions packages/main/src/controller/DownloadController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,9 +77,6 @@ export default class DownloadController implements Controller {
async startDownload(e: IpcMainEvent, vid: number) {
// 查找将要下载的视频
const video = await this.videoRepository.findVideo(vid);
if (!video) {
return Promise.reject("没有找到该视频");
}
const { name, url, headers, type } = video;
const local = this.store.get("local");

Expand Down
8 changes: 4 additions & 4 deletions packages/main/src/controller/HomeController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ export default class HomeController implements Controller {
{
label: "拷贝链接地址",
click: () => {
clipboard.writeText(item?.url || "");
clipboard.writeText(item.url || "");
},
},
{
Expand Down Expand Up @@ -208,8 +208,8 @@ export default class HomeController implements Controller {
async convertToAudio(e: IpcMainEvent, id: number) {
const video = await this.videoRepository.findVideo(id);
const local = this.store.get("local");
const input = path.join(local, `${video?.name}.mp4`);
const output = path.join(local, `${video?.name}.mp3`);
const input = path.join(local, `${video.name}.mp4`);
const output = path.join(local, `${video.name}.mp3`);

const exist = await fs.exists(input);
if (exist) {
Expand Down Expand Up @@ -250,6 +250,6 @@ export default class HomeController implements Controller {
@handle("get-download-log")
async getDownloadLog(event: IpcMainEvent, id: number) {
const video = await this.videoRepository.findVideo(id);
return video?.log || "";
return video.log || "";
}
}
29 changes: 12 additions & 17 deletions packages/main/src/repository/VideoRepository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,9 +96,14 @@ export default class VideoRepository {
}

async findVideo(id: number) {
return this.db.appDataSource.getRepository(Video).findOneBy({
id,
});
const repository = this.db.appDataSource.getRepository(Video);
const video = await repository.findOneBy({ id });

if (!video) {
throw new Error("没有找到该视频");
}

return video;
}

async findVideoByName(name: string) {
Expand All @@ -117,14 +122,10 @@ export default class VideoRepository {
.execute();
}

async changeVideoIsLive(id: number | number[], isLive: boolean) {
const ids = !Array.isArray(id) ? [id] : id;
return this.db.appDataSource
.createQueryBuilder()
.update(Video)
.set({ isLive })
.where({ id: In(ids) })
.execute();
async changeVideoIsLive(id: number) {
const video = await this.findVideo(id);
video.isLive = true;
return this.db.manager.save(video);
}

async findWattingAndDownloadingVideos() {
Expand All @@ -147,18 +148,12 @@ export default class VideoRepository {

async appendDownloadLog(id: number, message: string) {
const video = await this.findVideo(id);
if (!video) {
throw new Error("视频不存在");
}
video.log = video.log ? `${video.log}\n${message}` : message;
return await this.db.manager.save(video);
}

async getDownloadLog(id: number) {
const video = await this.findVideo(id);
if (!video) {
throw new Error("视频不存在");
}
return video.log;
}
}
44 changes: 31 additions & 13 deletions packages/main/src/services/DownloadService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,21 @@ import { biliDownloaderBin, m3u8DownloaderBin } from "../helper";
import * as pty from "node-pty";
import stripAnsi from "strip-ansi";

interface DownloadContext {
// 是否为直播
isLive: boolean;
// 下载进度
percent: string;
// 下载速度
speed: string;
// 是否已经 ready
ready: boolean;
}

export interface DownloadOptions {
abortSignal: AbortController;
encoding?: string;
onMessage?: (ctx: any, message: string) => void;
onMessage?: (ctx: DownloadContext, message: string) => void;
id: number;
}

Expand Down Expand Up @@ -64,7 +75,7 @@ const processList: Schema[] = [
percent: "([\\d.]+)%",
speed: "([\\d.]+\\s[GMK]B/s)",
error: "ERROR",
start: "开始下载文件",
start: "开始下载文件|开始录制",
isLive: "识别为直播流, 开始录制",
},
},
Expand Down Expand Up @@ -269,7 +280,12 @@ export default class DownloadService extends EventEmitter {
});

if (onMessage) {
const ctx = {};
const ctx: DownloadContext = {
ready: false,
isLive: false,
percent: "",
speed: "",
};
ptyProcess.onData((data) => {
try {
this.emit("download-message", id, data);
Expand Down Expand Up @@ -347,7 +363,7 @@ export default class DownloadService extends EventEmitter {
const speedReg = RegExp(consoleReg.speed, "g");
const percentReg = RegExp(consoleReg.percent, "g");

const onMessage = (ctx: any, message: string) => {
const onMessage = (ctx: DownloadContext, message: string) => {
// 解析是否为直播资源
if (isLiveReg.test(message)) {
ctx.isLive = true;
Expand All @@ -367,25 +383,27 @@ export default class DownloadService extends EventEmitter {
callback({
id,
type: "ready",
isLive: !!ctx.isLive,
isLive: ctx.isLive,
speed: "",
percent: "",
});
ctx.ready = true;
return;
}

if (errorReg.test(message)) {
throw new Error(message);
}

// FIXME: 无法获取是否为直播流
callback({
id,
type: "progress",
percent: ctx.percent || "",
speed: ctx.speed || "",
isLive: !!ctx.isLive,
});
if (ctx.ready && (ctx.percent || ctx.speed)) {
callback({
id,
type: "progress",
percent: ctx.percent || "",
speed: ctx.speed || "",
isLive: ctx.isLive,
});
}
};

this.logger.debug("download params: ", spawnParams);
Expand Down
12 changes: 7 additions & 5 deletions packages/main/src/windows/MainWindow.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,11 @@ export default class MainWindow extends Window {
app.on("second-instance", this.secondInstance);
}

onDownloadReadyStart = ({ id, isLive }: { id: number; isLive: boolean }) => {
this.videoRepository.changeVideoIsLive(id, isLive);
this.send("change-video-is-live", { id, isLive });
onDownloadReadyStart = async ({ id, isLive }: DownloadProgress) => {
if (isLive) {
await this.videoRepository.changeVideoIsLive(id);
this.send("change-video-is-live", { id });
}
};

init(): void {
Expand Down Expand Up @@ -112,7 +114,7 @@ export default class MainWindow extends Window {

new Notification({
title: "下载成功",
body: `${video?.name} 下载成功`,
body: `${video.name} 下载成功`,
}).show();
}

Expand All @@ -126,7 +128,7 @@ export default class MainWindow extends Window {

new Notification({
title: "下载失败",
body: `${video?.name} 下载失败`,
body: `${video.name} 下载失败`,
}).show();
}
this.logger.error("下载失败:", err);
Expand Down
1 change: 1 addition & 0 deletions packages/renderer/src/components/DownloadForm/index.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
// empty
3 changes: 3 additions & 0 deletions packages/renderer/src/components/PageContainer/index.scss
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,21 @@
border-bottom: #f0f0f0 solid 1px;
background: #fff;
}

@media (prefers-color-scheme: dark) {
.page-container-header {
background: #141414;
border-bottom: #313131 solid 1px;
}
}

.page-container-inner {
overflow: auto;
flex: 1;
padding: 15px;
background: #fff;
}

@media (prefers-color-scheme: dark) {
.page-container-inner {
background: #141414;
Expand Down
1 change: 1 addition & 0 deletions packages/renderer/src/components/WebView/index.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
// empty
Loading

0 comments on commit dd9de54

Please sign in to comment.