From d94b4157ea929d05d7d1d58a395a8647c532e485 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E4=BC=8D=E8=BD=BB=E9=B8=A3?=
Date: Mon, 4 Mar 2024 16:27:35 +0800
Subject: [PATCH] dev merge (#18)
* test: add get videos list test error
* remove rs action
* doc: update
* feat: try add web ui and web server
---
.github/workflows/release_rs.yml | 15 --
README.md | 2 -
docs/ffmpeg.md | 100 ++++---
docs/ffmpeg_rs.md | 94 -------
garage-ui/package.json | 4 +-
garage-ui/src/App.vue | 5 +
garage-ui/src/api/user.ts | 12 +-
garage-ui/src/components/HelloWorld.vue | 12 +
garage-ui/src/layout/DashboardLayout.vue | 36 ++-
garage-ui/src/main.ts | 7 +
garage-ui/src/theme.ts | 19 ++
garage-ui/src/utils/http.ts | 56 ++--
garage-ui/vite.config.ts | 13 +-
garage-ui/yarn.lock | 202 ++++++++++----
garage_cmd/crawl_jav.go | 26 +-
garage_cmd/ffmpeg.go | 228 +++++++---------
garage_cmd/main.go | 10 +-
garage_di/app.go | 22 ++
garage_ffmpeg/ffmpeg.go | 327 ++++++++++++-----------
garage_ffmpeg/ffmpeg_test.go | 48 +++-
garage_jav/javbus.go | 237 ++++++++--------
garage_jav/model.go | 1 +
go.mod | 2 +
go.sum | 10 +
taskfile.yaml | 2 +
utils/config.go | 15 +-
utils/logger.go | 65 +++--
27 files changed, 837 insertions(+), 733 deletions(-)
delete mode 100644 .github/workflows/release_rs.yml
delete mode 100644 docs/ffmpeg_rs.md
create mode 100644 garage-ui/src/theme.ts
diff --git a/.github/workflows/release_rs.yml b/.github/workflows/release_rs.yml
deleted file mode 100644
index 0054d7d..0000000
--- a/.github/workflows/release_rs.yml
+++ /dev/null
@@ -1,15 +0,0 @@
-name: Release Rust
-
-on:
- push:
-
-jobs:
- build:
- name: cargo test
- runs-on: ubuntu-latest
- steps:
- - name: Check out code
- uses: actions/checkout@v4
- - name: Add Rust
- uses: dtolnay/rust-toolchain@stable
- - run: cargo version
diff --git a/README.md b/README.md
index 6a27774..c864d48 100644
--- a/README.md
+++ b/README.md
@@ -4,8 +4,6 @@
# Garage
-Unstable version,change to rust
-
`garage`是一个命令行工具,提供爬虫和批处理等功能。
[更新日志](./CHANGELOG.md)
diff --git a/docs/ffmpeg.md b/docs/ffmpeg.md
index 106391d..a82bf82 100644
--- a/docs/ffmpeg.md
+++ b/docs/ffmpeg.md
@@ -4,11 +4,42 @@
使用 FFMPEG 对多个视频快速转码或其他操作
+- [x] convert 批量视频转码
+- [x] add_sub 批量视频添加字幕
+- [x] add_fonts 批量视频添加字体
+
```shell
-# 视频批量转码
-$ garage ffmpeg-batch convert
-# 视频批量添加字幕和字体
-$ garage ffmpeg-batch add-sub
+# 子命令
+convert batch video convert other format
+add_sub batch video add one suffix subtittle
+add_fonts batch video add fonts from dir
+```
+
+## 视频转码
+
+```shell
+# 硬件加速 https://trac.ffmpeg.org/wiki/HWAccelIntro#VideoToolbox
+# h264 转码
+ffmpeg.exe -i input.mp4 -c:v h264_nvenc output.mkv
+# h265 cpu 10bit 转码
+ffmpeg -i INPUT.mp4 -c:v libx265 -crf 20 -pix_fmt yuv420p10le OUTPUT.mkv
+# h265 nvida加速 10bit 转码
+ffmpeg -i INPUT.mp4 -c:v hevc_nvenc -pix_fmt p010le -rc vbr -cq:v 27 OUTPUT.mkv
+# h264/h265 apple silicon 硬件加速转码
+# q:v 1-100 1 lowest, 100 highest
+ffmpeg -i INPUT.mp4 -c:v h264_videotoolbox -pix_fmt yuv444p -cq:v 27 OUTPUT.mkv
+ffmpeg -i INPUT.mp4 -c:v hevc_videotoolbox -pix_fmt yuv444p -cq:v 27 OUTPUT.mkv
+```
+
+```shell
+$ ffmpeg-batch convert --help
+
+--input_path <> input directory path
+--input_format <> input directory path [default: mp4]
+--output_path <> output directory path [default: ./dest]
+--output_format <> output directory path [default: mkv]
+--advance <> advance string
+--exec exec command
```
## 字幕添加
@@ -18,16 +49,23 @@ $ garage ffmpeg-batch add-sub
```shell
## ffmpeg 对应命令
ffmpeg.exe -i INPUT -c copy -i INPUT.ass -sub_charenc UTF-8 -c copy -map 0 -map -0:s -map 1 -metadata:s:s:0 language=chi -metadata:s:s:0 title="jp&sc" OUTPUT
+```
+
+```shell
## garage 对应命令
-garage ffmpeg-batch add-sub \
---input-path="queue" \
---input-type=".mkv" \
---input-sub-suffix=".ass" \
---output-path="result/" \
---exec=true
+$ garage ffmpeg-batch add-sub
+
+--input_path input directory path
+--input_format input directory path [default: mkv]
+--sub_suffix sub suffix and extension [default: ass]
+--sub_number sub number [default: 0]
+--output_path output directory path [default: ./dest]
+--output_format output directory path [default: mkv]
+--advance <> advance string
+--exec exec command
```
-添加字幕同时添加多个字体
+## 添加多个字体
```shell
## ffmpeg 对应命令
@@ -43,46 +81,6 @@ garage ffmpeg-batch add-sub \
--exec=true
```
-## 视频转码
-
-```shell
-## ffmpeg 对应命令
-ffmpeg.exe -i input.mp4 -c:v h264_nvenc output.mkv
-
-## garage 对应命令
-garage.exe ffmpeg-batch convert --input-path="queue" \
---input-type=".mp4" \
---output-path="result/" \
---output-type=".mkv" \
---advance="-c:v h264_nvenc" --exec
-```
-
-h256_10bit 转码
-
-```shell
-ffmpeg -i INPUT.mp4 -c:v libx265 -crf 20 -pix_fmt yuv420p10le OUTPUT.mkv
-
-## garage 对应命令
-garage.exe ffmpeg-batch convert --input-path="queue" \
---input-type=".mp4" \
---output-path="result/" \
---output-type=".mkv" \
---advance="-c:v libx265 -crf 20 -pix_fmt yuv420p10le" --exec
-```
-
-h256_10bit 转码 nvdia 硬件加速
-
-```shell
-ffmpeg -i INPUT.mp4 -c:v hevc_nvenc -pix_fmt p010le -rc vbr -cq:v 27 OUTPUT.mkv
-
-## garage 对应命令
-garage.exe ffmpeg-batch convert --input-path="queue" \
---input-type=".mp4" \
---output-path="result/" \
---output-type=".mkv" \
---advance="-c:v hevc_nvenc -pix_fmt p010le -rc vbr -cq:v 25" --exec
-```
-
## 切割视频 && 导出字幕文件
推荐使用 [Lossless Cut](https://github.com/mifi/lossless-cut)软件
diff --git a/docs/ffmpeg_rs.md b/docs/ffmpeg_rs.md
deleted file mode 100644
index f294145..0000000
--- a/docs/ffmpeg_rs.md
+++ /dev/null
@@ -1,94 +0,0 @@
-# 视频批量处理
-
-> 系统环境中需要预先安装 ffmpeg
-
-使用 FFMPEG 对多个视频快速转码或其他操作
-
-- [x] convert 批量视频转码
-- [ ] add_sub 批量视频添加字幕
-- [ ] addfonts 批量视频添加字体
-
-```shell
-# 子命令
-convert batch video convert other format
-add_sub batch video add one suffix subtittle
-add_fonts batch video add fonts from dir
-```
-
-## 视频转码
-
-```shell
-# 硬件加速 https://trac.ffmpeg.org/wiki/HWAccelIntro#VideoToolbox
-# h264 转码
-ffmpeg.exe -i input.mp4 -c:v h264_nvenc output.mkv
-# h265 cpu 10bit 转码
-ffmpeg -i INPUT.mp4 -c:v libx265 -crf 20 -pix_fmt yuv420p10le OUTPUT.mkv
-# h265 nvida加速 10bit 转码
-ffmpeg -i INPUT.mp4 -c:v hevc_nvenc -pix_fmt p010le -rc vbr -cq:v 27 OUTPUT.mkv
-# h264/h265 apple silicon 硬件加速转码
-# q:v 1-100 1 lowest, 100 highest
-ffmpeg -i INPUT.mp4 -c:v h264_videotoolbox -pix_fmt yuv444p -cq:v 27 OUTPUT.mkv
-ffmpeg -i INPUT.mp4 -c:v hevc_videotoolbox -pix_fmt yuv444p -cq:v 27 OUTPUT.mkv
-```
-
-```shell
-$ ffmpeg-batch convert --help
-
---input_path <> input directory path
---input_format <> input directory path [default: mp4]
---output_path <> output directory path [default: ./dest]
---output_format <> output directory path [default: mkv]
---advance <> advance string
---exec exec command
-```
-
-## 字幕添加
-
-添加字幕文件替换掉已有字幕, 只支持插入单条字幕。
-
-```shell
-## ffmpeg 对应命令
-ffmpeg.exe -i INPUT -c copy -i INPUT.ass -sub_charenc UTF-8 -c copy -map 0 -map -0:s -map 1 -metadata:s:s:0 language=chi -metadata:s:s:0 title="jp&sc" OUTPUT
-```
-
-```shell
-## garage 对应命令
-$ garage ffmpeg-batch add-sub
-
---input_path input directory path
---input_format input directory path [default: mkv]
---sub_suffix sub suffix and extension [default: ass]
---sub_number sub number [default: 0]
---output_path output directory path [default: ./dest]
---output_format output directory path [default: mkv]
---advance <> advance string
---exec exec command
-```
-
-## 添加多个字体
-
-```shell
-## ffmpeg 对应命令
-ffmpeg.exe -i INPUT -c copy -attach INPUT_FONT -metadata:s:t:0 mimetype=application/x-truetype-font
-
-## garage 对应命令
-garage ffmpeg-batch add-sub \
---input-path="queue" \
---input-type=".mkv" \
---input-sub-suffix=".ass" \
---input-fonts-path="fonts" \
---output-path="result/" \
---exec=true
-```
-
-## 切割视频 && 导出字幕文件
-
-推荐使用 [Lossless Cut](https://github.com/mifi/lossless-cut)软件
-
-```shell
-ffmpeg -i input.wmv -ss 00:00:30.0 -c copy -t 00:00:10.0 output.wmv
-```
-
-```shell
-ffmpeg -i input.mkv -map 0:s:0 subs.ass
-```
diff --git a/garage-ui/package.json b/garage-ui/package.json
index 0634ebf..2ad1257 100644
--- a/garage-ui/package.json
+++ b/garage-ui/package.json
@@ -6,10 +6,11 @@
"scripts": {
"dev": "vite",
"build": "vue-tsc && vite build",
+ "build:report": "vue-tsc && vite build",
"preview": "vite preview"
},
"dependencies": {
- "axios": "^1.6.7",
+ "ky": "^1.2.0",
"pinia": "^2.1.7",
"vue": "^3.4.15",
"vue-router": "^4.2.5",
@@ -20,6 +21,7 @@
"@types/node": "^20.11.19",
"@vitejs/plugin-vue": "^5.0.3",
"less": "^4.2.0",
+ "rollup-plugin-visualizer": "^5.12.0",
"typescript": "^5.2.2",
"vite": "^5.1.0",
"vite-plugin-vuetify": "^2.0.1",
diff --git a/garage-ui/src/App.vue b/garage-ui/src/App.vue
index edcdd1b..bdee649 100644
--- a/garage-ui/src/App.vue
+++ b/garage-ui/src/App.vue
@@ -1,8 +1,13 @@
diff --git a/garage-ui/src/api/user.ts b/garage-ui/src/api/user.ts
index 3ea67b2..7f9a778 100644
--- a/garage-ui/src/api/user.ts
+++ b/garage-ui/src/api/user.ts
@@ -1,5 +1,9 @@
-import http from "@/utils/http";
-import { AxiosResponse } from "axios";
+import { httpv2 } from "@/utils/http";
-export const userLogin = (): Promise> =>
- http.get("/user/logion");
+const userLogin = () => httpv2.get("user/logion");
+
+const testApi = () => {
+ return httpv2.get("api");
+};
+
+export { userLogin, testApi };
diff --git a/garage-ui/src/components/HelloWorld.vue b/garage-ui/src/components/HelloWorld.vue
index 68afb24..226e502 100644
--- a/garage-ui/src/components/HelloWorld.vue
+++ b/garage-ui/src/components/HelloWorld.vue
@@ -13,6 +13,18 @@ const count = ref(0);
Edit
components/HelloWorld.vue
to test HMR
+
+
diff --git a/garage-ui/src/layout/DashboardLayout.vue b/garage-ui/src/layout/DashboardLayout.vue
index e5fa3ad..217ff55 100644
--- a/garage-ui/src/layout/DashboardLayout.vue
+++ b/garage-ui/src/layout/DashboardLayout.vue
@@ -10,28 +10,34 @@
-
- Application Bar
-
+
+
+
+
+
-
-
+
@@ -41,4 +47,8 @@ import { useLayoutStore } from "@/stores/layout";
const layoutStore = useLayoutStore();
-
+
diff --git a/garage-ui/src/main.ts b/garage-ui/src/main.ts
index 4ec9d0c..af0a0d3 100644
--- a/garage-ui/src/main.ts
+++ b/garage-ui/src/main.ts
@@ -8,6 +8,7 @@ import "vuetify/styles";
import { createVuetify } from "vuetify";
import { aliases, mdi } from "vuetify/iconsets/mdi";
import "@mdi/font/css/materialdesignicons.css";
+import theme from "./theme";
const vuetify = createVuetify({
icons: {
@@ -15,6 +16,12 @@ const vuetify = createVuetify({
aliases,
sets: { mdi },
},
+ theme: {
+ defaultTheme: "myCustomLightTheme",
+ themes: {
+ myCustomLightTheme: theme,
+ },
+ },
});
const pinia = createPinia();
diff --git a/garage-ui/src/theme.ts b/garage-ui/src/theme.ts
new file mode 100644
index 0000000..e36a8fb
--- /dev/null
+++ b/garage-ui/src/theme.ts
@@ -0,0 +1,19 @@
+import { type ThemeDefinition } from "vuetify";
+
+const myCustomLightTheme: ThemeDefinition = {
+ dark: false,
+ colors: {
+ background: "#FAFAFA",
+ surface: "#F5F5F5",
+ primary: "#6200EE",
+ "primary-darken-1": "#3700B3",
+ secondary: "#03DAC6",
+ "secondary-darken-1": "#018786",
+ error: "#B00020",
+ info: "#2196F3",
+ success: "#4CAF50",
+ warning: "#FB8C00",
+ },
+};
+
+export default myCustomLightTheme;
diff --git a/garage-ui/src/utils/http.ts b/garage-ui/src/utils/http.ts
index a64ecd7..551bab8 100644
--- a/garage-ui/src/utils/http.ts
+++ b/garage-ui/src/utils/http.ts
@@ -1,33 +1,39 @@
-import axios from "axios";
-import { InternalAxiosRequestConfig, AxiosResponse } from "axios";
+import ky from "ky";
-const http = axios.create({
- baseURL: "",
+const httpv2 = ky.create({
+ prefixUrl: "https://example.com/api",
timeout: 5000,
headers: {
"Content-Type": "application/json",
},
-});
-
-http.interceptors.request.use(
- (config: InternalAxiosRequestConfig) => {
- console.log(config.baseURL);
- return config;
- },
- (error: any) => {
- console.error(error);
- return Promise.reject(error);
- }
-);
+ retry: 1,
+ hooks: {
+ beforeRequest: [
+ (options) => {
+ console.log("before request", options);
+ },
+ ],
+ beforeRetry: [
+ async ({ error }) => {
+ console.log("before retry", error);
+ },
+ ],
+ beforeError: [
+ (error) => {
+ console.log("before error:", error);
-http.interceptors.response.use(
- (resp: AxiosResponse) => {
- return resp;
+ return error;
+ },
+ ],
+ afterResponse: [
+ (request, _options, response) => {
+ console.log("after reponse:", response.status);
+ console.log("after reponse:", request.headers);
+ return new Response("A different response", { status: 200 });
+ },
+ ],
},
- (error: any) => {
- console.error("resp error: ", error);
- return Promise.reject(error);
- }
-);
+ throwHttpErrors: false,
+});
-export default http;
+export { httpv2 };
diff --git a/garage-ui/vite.config.ts b/garage-ui/vite.config.ts
index 089ef6e..25dc95b 100644
--- a/garage-ui/vite.config.ts
+++ b/garage-ui/vite.config.ts
@@ -3,10 +3,21 @@ import { splitVendorChunkPlugin } from "vite";
import vuetify from "vite-plugin-vuetify";
import vue from "@vitejs/plugin-vue";
import path from "path";
+import { visualizer } from "rollup-plugin-visualizer";
+
+const buildReportplugin =
+ process.env.npm_lifecycle_event === "build:report"
+ ? visualizer({
+ open: true,
+ brotliSize: true,
+ gzipSize: true,
+ filename: "dist/report.html",
+ })
+ : null;
// https://vitejs.dev/config/
export default defineConfig({
- plugins: [vue(), vuetify(), splitVendorChunkPlugin()],
+ plugins: [vue(), vuetify(), splitVendorChunkPlugin(), buildReportplugin],
server: {
host: "0.0.0.0",
port: 3000,
diff --git a/garage-ui/yarn.lock b/garage-ui/yarn.lock
index 077ec87..b49c438 100644
--- a/garage-ui/yarn.lock
+++ b/garage-ui/yarn.lock
@@ -342,19 +342,17 @@
dependencies:
upath "^2.0.1"
-asynckit@^0.4.0:
- version "0.4.0"
- resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
- integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==
+ansi-regex@^5.0.1:
+ version "5.0.1"
+ resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304"
+ integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==
-axios@^1.6.7:
- version "1.6.7"
- resolved "https://registry.yarnpkg.com/axios/-/axios-1.6.7.tgz#7b48c2e27c96f9c68a2f8f31e2ab19f59b06b0a7"
- integrity sha512-/hDJGff6/c7u0hDkvkGxR/oy6CbCs8ziCsC7SqmhjfozqiJGc8Z11wrv9z9lYfY4K8l+H9TpjcMDX0xOZmx+RA==
+ansi-styles@^4.0.0:
+ version "4.3.0"
+ resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937"
+ integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==
dependencies:
- follow-redirects "^1.15.4"
- form-data "^4.0.0"
- proxy-from-env "^1.1.0"
+ color-convert "^2.0.1"
balanced-match@^1.0.0:
version "1.0.2"
@@ -368,12 +366,26 @@ brace-expansion@^2.0.1:
dependencies:
balanced-match "^1.0.0"
-combined-stream@^1.0.8:
- version "1.0.8"
- resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f"
- integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==
+cliui@^8.0.1:
+ version "8.0.1"
+ resolved "https://registry.yarnpkg.com/cliui/-/cliui-8.0.1.tgz#0c04b075db02cbfe60dc8e6cf2f5486b1a3608aa"
+ integrity sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==
dependencies:
- delayed-stream "~1.0.0"
+ string-width "^4.2.0"
+ strip-ansi "^6.0.1"
+ wrap-ansi "^7.0.0"
+
+color-convert@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3"
+ integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==
+ dependencies:
+ color-name "~1.1.4"
+
+color-name@~1.1.4:
+ version "1.1.4"
+ resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2"
+ integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
computeds@^0.0.1:
version "0.0.1"
@@ -404,10 +416,15 @@ debug@^4.3.3:
dependencies:
ms "2.1.2"
-delayed-stream@~1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619"
- integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==
+define-lazy-prop@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz#3f7ae421129bcaaac9bc74905c98a0009ec9ee7f"
+ integrity sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==
+
+emoji-regex@^8.0.0:
+ version "8.0.0"
+ resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37"
+ integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==
entities@^4.5.0:
version "4.5.0"
@@ -450,30 +467,26 @@ esbuild@^0.19.3:
"@esbuild/win32-ia32" "0.19.12"
"@esbuild/win32-x64" "0.19.12"
+escalade@^3.1.1:
+ version "3.1.2"
+ resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.2.tgz#54076e9ab29ea5bf3d8f1ed62acffbb88272df27"
+ integrity sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==
+
estree-walker@^2.0.2:
version "2.0.2"
resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-2.0.2.tgz#52f010178c2a4c117a7757cfe942adb7d2da4cac"
integrity sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==
-follow-redirects@^1.15.4:
- version "1.15.5"
- resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.5.tgz#54d4d6d062c0fa7d9d17feb008461550e3ba8020"
- integrity sha512-vSFWUON1B+yAw1VN4xMfxgn5fTUiaOzAJCKBwIIgT/+7CuGy9+r+5gITvP62j3RmaD5Ph65UaERdOSRGUzZtgw==
-
-form-data@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452"
- integrity sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==
- dependencies:
- asynckit "^0.4.0"
- combined-stream "^1.0.8"
- mime-types "^2.1.12"
-
fsevents@~2.3.2, fsevents@~2.3.3:
version "2.3.3"
resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6"
integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==
+get-caller-file@^2.0.5:
+ version "2.0.5"
+ resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e"
+ integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==
+
graceful-fs@^4.1.2:
version "4.2.11"
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3"
@@ -496,11 +509,33 @@ image-size@~0.5.0:
resolved "https://registry.yarnpkg.com/image-size/-/image-size-0.5.5.tgz#09dfd4ab9d20e29eb1c3e80b8990378df9e3cb9c"
integrity sha512-6TDAlDPZxUFCv+fuOkIoXT/V/f3Qbq8e37p+YOiYrUv3v9cc3/6x78VdfPgFVaB9dZYeLUfKgHRebpkm/oP2VQ==
+is-docker@^2.0.0, is-docker@^2.1.1:
+ version "2.2.1"
+ resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.2.1.tgz#33eeabe23cfe86f14bde4408a02c0cfb853acdaa"
+ integrity sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==
+
+is-fullwidth-code-point@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d"
+ integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==
+
is-what@^3.14.1:
version "3.14.1"
resolved "https://registry.yarnpkg.com/is-what/-/is-what-3.14.1.tgz#e1222f46ddda85dead0fd1c9df131760e77755c1"
integrity sha512-sNxgpk9793nzSs7bA6JQJGeIuRBQhAaNGG77kzYQgMkrID+lS6SlK07K5LaptscDlSaIgH+GPFzf+d75FVxozA==
+is-wsl@^2.2.0:
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-2.2.0.tgz#74a4c76e77ca9fd3f932f290c17ea326cd157271"
+ integrity sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==
+ dependencies:
+ is-docker "^2.0.0"
+
+ky@^1.2.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/ky/-/ky-1.2.0.tgz#698be7d2c48cf875d2d4721fc4c69b681877a112"
+ integrity sha512-dnPW+T78MuJ9tLAiF/apJV7bP7RRRCARXQxsCmsWiKLXqGtMBOgDVOFRYzCAfNe/OrRyFyor5ESgvvC+QWEqOA==
+
less@^4.2.0:
version "4.2.0"
resolved "https://registry.yarnpkg.com/less/-/less-4.2.0.tgz#cbefbfaa14a4cd388e2099b2b51f956e1465c450"
@@ -540,18 +575,6 @@ make-dir@^2.1.0:
pify "^4.0.1"
semver "^5.6.0"
-mime-db@1.52.0:
- version "1.52.0"
- resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70"
- integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==
-
-mime-types@^2.1.12:
- version "2.1.35"
- resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a"
- integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==
- dependencies:
- mime-db "1.52.0"
-
mime@^1.4.1:
version "1.6.0"
resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1"
@@ -587,6 +610,15 @@ needle@^3.1.0:
iconv-lite "^0.6.3"
sax "^1.2.4"
+open@^8.4.0:
+ version "8.4.2"
+ resolved "https://registry.yarnpkg.com/open/-/open-8.4.2.tgz#5b5ffe2a8f793dcd2aad73e550cb87b59cb084f9"
+ integrity sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==
+ dependencies:
+ define-lazy-prop "^2.0.0"
+ is-docker "^2.1.1"
+ is-wsl "^2.2.0"
+
parse-node-version@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/parse-node-version/-/parse-node-version-1.0.1.tgz#e2b5dbede00e7fa9bc363607f53327e8b073189b"
@@ -602,6 +634,11 @@ picocolors@^1.0.0:
resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c"
integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==
+picomatch@^2.3.1:
+ version "2.3.1"
+ resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42"
+ integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==
+
pify@^4.0.1:
version "4.0.1"
resolved "https://registry.yarnpkg.com/pify/-/pify-4.0.1.tgz#4b2cd25c50d598735c50292224fd8c6df41e3231"
@@ -624,16 +661,26 @@ postcss@^8.4.33, postcss@^8.4.35:
picocolors "^1.0.0"
source-map-js "^1.0.2"
-proxy-from-env@^1.1.0:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2"
- integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==
-
prr@~1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476"
integrity sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw==
+require-directory@^2.1.1:
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42"
+ integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==
+
+rollup-plugin-visualizer@^5.12.0:
+ version "5.12.0"
+ resolved "https://registry.yarnpkg.com/rollup-plugin-visualizer/-/rollup-plugin-visualizer-5.12.0.tgz#661542191ce78ee4f378995297260d0c1efb1302"
+ integrity sha512-8/NU9jXcHRs7Nnj07PF2o4gjxmm9lXIrZ8r175bT9dK8qoLlvKTwRMArRCMgpMGlq8CTLugRvEmyMeMXIU2pNQ==
+ dependencies:
+ open "^8.4.0"
+ picomatch "^2.3.1"
+ source-map "^0.7.4"
+ yargs "^17.5.1"
+
rollup@^4.2.0:
version "4.12.0"
resolved "https://registry.yarnpkg.com/rollup/-/rollup-4.12.0.tgz#0b6d1e5f3d46bbcf244deec41a7421dc54cc45b5"
@@ -683,11 +730,32 @@ source-map-js@^1.0.2:
resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c"
integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==
+source-map@^0.7.4:
+ version "0.7.4"
+ resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.4.tgz#a9bbe705c9d8846f4e08ff6765acf0f1b0898656"
+ integrity sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==
+
source-map@~0.6.0:
version "0.6.1"
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==
+string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3:
+ version "4.2.3"
+ resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
+ integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
+ dependencies:
+ emoji-regex "^8.0.0"
+ is-fullwidth-code-point "^3.0.0"
+ strip-ansi "^6.0.1"
+
+strip-ansi@^6.0.0, strip-ansi@^6.0.1:
+ version "6.0.1"
+ resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
+ integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
+ dependencies:
+ ansi-regex "^5.0.1"
+
tslib@^2.3.0:
version "2.6.2"
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.2.tgz#703ac29425e7b37cd6fd456e92404d46d1f3e4ae"
@@ -773,7 +841,39 @@ vuetify@^3.5.4:
resolved "https://registry.yarnpkg.com/vuetify/-/vuetify-3.5.4.tgz#f919c5194995a123815c277a95812bc230e33464"
integrity sha512-fHgfWMI7+z/UtbVPOezX+O1MNBOOMBW9HnKejcBIyQQ7jFRnTHbDQmbINf25FK0wrg/zkjfzyOmWWREKW39eXg==
+wrap-ansi@^7.0.0:
+ version "7.0.0"
+ resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
+ integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
+ dependencies:
+ ansi-styles "^4.0.0"
+ string-width "^4.1.0"
+ strip-ansi "^6.0.0"
+
+y18n@^5.0.5:
+ version "5.0.8"
+ resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55"
+ integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==
+
yallist@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72"
integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==
+
+yargs-parser@^21.1.1:
+ version "21.1.1"
+ resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35"
+ integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==
+
+yargs@^17.5.1:
+ version "17.7.2"
+ resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.2.tgz#991df39aca675a192b816e1e0363f9d75d2aa269"
+ integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==
+ dependencies:
+ cliui "^8.0.1"
+ escalade "^3.1.1"
+ get-caller-file "^2.0.5"
+ require-directory "^2.1.1"
+ string-width "^4.2.3"
+ y18n "^5.0.5"
+ yargs-parser "^21.1.1"
diff --git a/garage_cmd/crawl_jav.go b/garage_cmd/crawl_jav.go
index 430b1f0..e81ebe1 100644
--- a/garage_cmd/crawl_jav.go
+++ b/garage_cmd/crawl_jav.go
@@ -2,7 +2,6 @@ package main
import (
"github.com/gsxhnd/garage/garage_jav"
- "github.com/gsxhnd/garage/utils"
"github.com/urfave/cli/v2"
)
@@ -35,9 +34,6 @@ var javCodeCmd = &cli.Command{
javOutputFlag,
},
Action: func(ctx *cli.Context) error {
- var (
- logger = utils.GetLogger()
- )
opt := &garage_jav.JavCrawlConfig{
Code: ctx.Args().Get(0),
DownloadMagent: ctx.Bool("magnet"),
@@ -47,12 +43,12 @@ var javCodeCmd = &cli.Command{
c, err := garage_jav.NewJavbusCrawl(logger, opt)
if err != nil {
- logger.Panic("client init error: " + err.Error())
+ logger.Panicw("client init error: " + err.Error())
return err
}
if err := c.StartCrawlJavbusMovie(); err != nil {
- logger.Panic("crawl error: " + err.Error())
+ logger.Panicw("crawl error: " + err.Error())
return err
}
@@ -75,7 +71,6 @@ var javPrefixCmd = &cli.Command{
&cli.IntFlag{Name: "prefix-max", Value: 5, Usage: "番号结束编号"},
},
Action: func(ctx *cli.Context) error {
- var logger = utils.GetLogger()
opt := &garage_jav.JavCrawlConfig{
Proxy: ctx.String("proxy"),
@@ -88,12 +83,12 @@ var javPrefixCmd = &cli.Command{
c, err := garage_jav.NewJavbusCrawl(logger, opt)
if err != nil {
- logger.Panic("client init error: " + err.Error())
+ logger.Panicw("client init error: " + err.Error())
return err
}
if err := c.StartCrawlJavbusMovieByPrefix(); err != nil {
- logger.Panic("crawl error: " + err.Error())
+ logger.Panicw("crawl error: " + err.Error())
return err
}
return nil
@@ -111,9 +106,6 @@ var javStarCodeCmd = &cli.Command{
&cli.StringFlag{Name: "star-code", Value: "vfn", Usage: "演员番号"},
},
Action: func(ctx *cli.Context) error {
- var (
- logger = utils.GetLogger()
- )
opt := &garage_jav.JavCrawlConfig{
DownloadMagent: ctx.Bool("magnet"),
@@ -124,12 +116,12 @@ var javStarCodeCmd = &cli.Command{
c, err := garage_jav.NewJavbusCrawl(logger, opt)
if err != nil {
- logger.Panic("client init error: " + err.Error())
+ logger.Panicw("client init error: " + err.Error())
return err
}
if err := c.StartCrawlJavbusMovieByStar(); err != nil {
- logger.Panic("crawl error: " + err.Error())
+ logger.Panicw("crawl error: " + err.Error())
return err
}
return nil
@@ -146,8 +138,6 @@ var javStarCodeFromDirCmd = &cli.Command{
&cli.StringFlag{Name: "input", Required: true},
},
Action: func(ctx *cli.Context) error {
- var logger = utils.GetLogger()
-
opt := &garage_jav.JavCrawlConfig{
DownloadMagent: ctx.Bool("magnet"),
Proxy: ctx.String("proxy"),
@@ -156,12 +146,12 @@ var javStarCodeFromDirCmd = &cli.Command{
c, err := garage_jav.NewJavbusCrawl(logger, opt)
if err != nil {
- logger.Panic("client init error: " + err.Error())
+ logger.Panicw("client init error: " + err.Error())
return err
}
if err := c.StartCrawlJavbusMovieByFilepath(ctx.String("input")); err != nil {
- logger.Panic("crawl error: " + err.Error())
+ logger.Panicw("crawl error: " + err.Error())
return err
}
return nil
diff --git a/garage_cmd/ffmpeg.go b/garage_cmd/ffmpeg.go
index 403e9ab..395290a 100644
--- a/garage_cmd/ffmpeg.go
+++ b/garage_cmd/ffmpeg.go
@@ -1,77 +1,66 @@
package main
import (
+ "context"
+
"github.com/gsxhnd/garage/garage_ffmpeg"
- "github.com/gsxhnd/garage/utils"
"github.com/urfave/cli/v2"
"go.uber.org/zap"
)
-var (
- ffmpegBatchInputPathFlag = &cli.StringFlag{
- Name: "input-path",
- Value: "./",
- Usage: "源视频路径",
- }
- ffmpegBatchInputTypeFlag = &cli.StringFlag{
- Name: "input-type",
- Value: ".mkv",
- Usage: "源视频后缀",
- }
- ffmpegBatchInputSubSuffixFlag = &cli.StringFlag{
- Name: "input-sub-suffix",
- Value: ".ass",
- Usage: "添加的字幕后缀",
- }
- ffmpegBatchInputSubNoFlag = &cli.IntFlag{
- Name: "input-sub-no",
- Value: 0,
- Usage: "添加的字幕所处流的位置",
- }
- ffmpegBatchInputSubLangFlag = &cli.StringFlag{
- Name: "input-sub-lang",
- Value: "chi",
- Usage: "添加的字幕语言缩写其他语言请参考ffmpeg",
- }
- ffmpegBatchInputSubTitleFlag = &cli.StringFlag{
- Name: "input-sub-title",
- Value: "Chinese",
- Usage: "添加的字幕标题",
- }
- ffmpegBatchInputFontsPathFlag = &cli.StringFlag{
- Name: "input-fonts-path",
- Usage: "添加的字体文件夹",
- }
- ffmpegBatchOutputDestPathFlag = &cli.StringFlag{
- Name: "output-path",
- Value: "./result/",
- Usage: "转换后文件存储位置",
- }
- ffmpegBatchOutputTypeFlag = &cli.StringFlag{
- Name: "output-type",
- Value: ".mkv",
- Usage: "转换后的视频后缀",
- }
- ffmpegBatchAdvanceFlag = &cli.StringFlag{
- Name: "advance",
- Value: "",
- Usage: "高级自定义参数",
- }
- ffmpegBatchExecFlag = &cli.BoolFlag{
- Name: "exec",
- Value: false,
- Usage: "是否执行批处理命令False时仅打印命令",
- }
-)
+type garage_ffmpeg_option string
var ffmpegBatchCmd = &cli.Command{
- Name: "ffmpeg-batch",
+ Name: "ffmpeg_batch",
Description: "ffmpeg视频批处理工具,支持视频格式转换、字幕添加和字体添加",
+ Flags: []cli.Flag{
+ &cli.StringFlag{
+ Name: "input_path",
+ Value: "./",
+ Usage: "源视频路径",
+ }, &cli.StringFlag{
+ Name: "input_format",
+ Value: ".mkv",
+ Usage: "源视频后缀",
+ },
+ &cli.StringFlag{
+ Name: "output_path",
+ Value: "./result/",
+ Usage: "转换后文件存储位置",
+ },
+ &cli.StringFlag{
+ Name: "output_format",
+ Value: ".mkv",
+ Usage: "转换后的视频后缀",
+ },
+ &cli.StringFlag{
+ Name: "advance",
+ Value: "",
+ Usage: "高级自定义参数",
+ },
+ &cli.BoolFlag{
+ Name: "exec",
+ Value: false,
+ Usage: "是否执行批处理命令False时仅打印命令",
+ },
+ },
Subcommands: []*cli.Command{
ffmpegBatchConvertCmd,
ffmpegBatchAddSubCmd,
ffmpegBatchAddFontCmd,
},
+ Before: func(ctx *cli.Context) error {
+ var opt = garage_ffmpeg.VideoBatchOption{
+ InputPath: ctx.String("input_path"),
+ InputFormat: ctx.String("input_format"),
+ OutputPath: ctx.String("output_path"),
+ OutputFormat: ctx.String("output_format"),
+ Advance: ctx.String("advance"),
+ Exec: ctx.Bool("exec"),
+ }
+ ctx.Context = context.WithValue(ctx.Context, garage_ffmpeg_option("opt"), opt)
+ return nil
+ },
}
var ffmpegBatchConvertCmd = &cli.Command{
@@ -79,27 +68,13 @@ var ffmpegBatchConvertCmd = &cli.Command{
Aliases: nil,
Usage: "视频转换批处理",
UsageText: "",
- Flags: []cli.Flag{
- ffmpegBatchInputPathFlag,
- ffmpegBatchInputTypeFlag,
- ffmpegBatchOutputDestPathFlag,
- ffmpegBatchOutputTypeFlag,
- ffmpegBatchAdvanceFlag,
- ffmpegBatchExecFlag,
- },
Action: func(c *cli.Context) error {
var (
- logger = utils.GetLogger()
- // inputPath = c.String("input-path")
- // inputType = c.String("input-type")
- // outputPath = c.String("output-path")
- // outputType = c.String("output-type")
- // advance = c.String("advance")
+ opt = c.Context.Value(garage_ffmpeg_option("opt")).(garage_ffmpeg.VideoBatchOption)
)
-
- vb, err := garage_ffmpeg.NewVideoBatch(logger, nil)
+ vb, err := garage_ffmpeg.NewVideoBatch(&opt)
if err != nil {
- logger.Panic("Create dest path error", zap.Error(err))
+ logger.Panicf("Create dest path error", zap.Error(err))
return err
}
return vb.StartConvertBatch()
@@ -107,87 +82,68 @@ var ffmpegBatchConvertCmd = &cli.Command{
}
var ffmpegBatchAddSubCmd = &cli.Command{
- Name: "add-sub",
+ Name: "add_sub",
Aliases: nil,
Usage: "视频添加字幕批处理",
UsageText: "",
Flags: []cli.Flag{
- ffmpegBatchInputPathFlag,
- ffmpegBatchInputTypeFlag,
- ffmpegBatchInputSubSuffixFlag,
- ffmpegBatchInputSubNoFlag,
- ffmpegBatchInputSubTitleFlag,
- ffmpegBatchInputSubLangFlag,
- ffmpegBatchInputFontsPathFlag,
- ffmpegBatchOutputDestPathFlag,
- ffmpegBatchExecFlag,
+ &cli.StringFlag{
+ Name: "input_fonts_path",
+ Usage: "添加的字体文件夹",
+ },
+ &cli.StringFlag{
+ Name: "input_sub_suffix",
+ Value: ".ass",
+ Usage: "添加的字幕后缀",
+ },
+ &cli.IntFlag{
+ Name: "input_sub_no",
+ Value: 0,
+ Usage: "添加的字幕所处流的位置",
+ },
+ &cli.StringFlag{
+ Name: "input_sub_lang",
+ Value: "chi",
+ Usage: "添加的字幕语言缩写其他语言请参考ffmpeg",
+ },
+ &cli.StringFlag{
+ Name: "input_sub_title",
+ Value: "Chinese",
+ Usage: "添加的字幕标题",
+ },
},
- Action: func(c *cli.Context) error {
- var (
- logger = utils.GetLogger()
- // inputPath = c.String("input-path")
- // inputType = c.String("input-type")
- // inputSubNo = c.Int("input-sub-no")
- // inputSubSuffix = c.String("input-sub-suffix")
- // inputSubLang = c.String("input-sub-lang")
- // inputSubTitle = c.String("input-sub-title")
- // inputFontsPath = c.String("input-fonts-path")
- // outputPath = c.String("output-path")
- )
- vb, err := garage_ffmpeg.NewVideoBatch(logger, nil)
+ Action: func(ctx *cli.Context) error {
+ var opt = ctx.Context.Value(garage_ffmpeg_option("opt")).(garage_ffmpeg.VideoBatchOption)
+ opt.FontsPath = ctx.String("input_fonts_path")
+ vb, err := garage_ffmpeg.NewVideoBatch(&opt)
if err != nil {
- logger.Panic("Create dest path error", zap.Error(err))
+ logger.Panicf("Create dest path error", zap.Error(err))
return err
}
return vb.StartAddSubtittleBatch()
- // if err != nil {
- // logger.Panic("Get add subtitle batch error", zap.Error(err))
- // }
- // logger.Info("Get all videos, starting add subtitle")
- // for _, cmd := range batch {
- // if !c.Bool("exec") {
- // logger.Sugar().Infof("cmd: %v", cmd)
- // } else {
- // startTime := time.Now()
- // logger.Sugar().Infof("Start add subtitle into video, cmd: %v", cmd)
- // cmd := exec.Command("powershell", cmd)
- // cmd.Stdout = os.Stdout
- // cmd.Stderr = os.Stderr
- // err := cmd.Run()
- // if err != nil {
- // logger.Sugar().Errorf("cmd errror: %v", err)
- // }
- // logger.Sugar().Infof("Finished add subtitle into video")
- // logger.Sugar().Infof("Finished convert video, spent time: %v sec", time.Since(startTime).Seconds())
- // }
- // }
},
}
var ffmpegBatchAddFontCmd = &cli.Command{
- Name: "add-fonts",
+ Name: "add_fonts",
Aliases: nil,
Usage: "视频添加字体批处理",
UsageText: "",
Flags: []cli.Flag{
- ffmpegBatchInputPathFlag,
- ffmpegBatchInputTypeFlag,
- ffmpegBatchInputFontsPathFlag,
- ffmpegBatchOutputDestPathFlag,
- ffmpegBatchExecFlag,
+ &cli.StringFlag{
+ Name: "input_fonts_path",
+ Usage: "添加的字体文件夹",
+ Required: true,
+ },
},
- Action: func(c *cli.Context) error {
- var (
- logger = utils.GetLogger()
- // inputPath = c.String("input-path")
- // inputType = c.String("input-type")
- // inputFontsPath = c.String("input-fonts-path")
- // outputPath = c.String("output-path")
- )
- vb, err := garage_ffmpeg.NewVideoBatch(logger, nil)
+ Action: func(ctx *cli.Context) error {
+ var opt = ctx.Context.Value(garage_ffmpeg_option("opt")).(garage_ffmpeg.VideoBatchOption)
+ opt.FontsPath = ctx.String("input_fonts_path")
+ vb, err := garage_ffmpeg.NewVideoBatch(&opt)
+
if err != nil {
- logger.Panic("Create dest path error", zap.Error(err))
+ logger.Panicf("Create dest path error", zap.Error(err))
return err
}
diff --git a/garage_cmd/main.go b/garage_cmd/main.go
index 81e0dbe..7285c2e 100644
--- a/garage_cmd/main.go
+++ b/garage_cmd/main.go
@@ -6,12 +6,20 @@ import (
"log"
"os"
+ "github.com/gsxhnd/garage/utils"
"github.com/urfave/cli/v2"
_ "github.com/glebarez/go-sqlite"
)
-var RootCmd = cli.NewApp()
+var (
+ RootCmd = cli.NewApp()
+ logger = utils.NewLogger(&utils.Config{
+ Log: utils.LogConfig{
+ Level: "debug",
+ },
+ })
+)
func init() {
RootCmd.HideVersion = true
diff --git a/garage_di/app.go b/garage_di/app.go
index 7418d24..d5ad74f 100644
--- a/garage_di/app.go
+++ b/garage_di/app.go
@@ -1,9 +1,12 @@
package garage_di
import (
+ "fmt"
"io/fs"
"log"
"net/http"
+ "os/exec"
+ "runtime"
"github.com/gin-gonic/gin"
garage_ui "github.com/gsxhnd/garage/garage-ui"
@@ -15,6 +18,23 @@ type Application struct {
router *routes.Routes
}
+// Open calls the OS default program for uri
+func Open(uri string) error {
+ var commands = map[string]string{
+ "windows": "cmd /c start",
+ "darwin": "open",
+ "linux": "xdg-open",
+ }
+
+ run, ok := commands[runtime.GOOS]
+ if !ok {
+ return fmt.Errorf("don't know how to open things on %s platform", runtime.GOOS)
+ }
+
+ cmd := exec.Command(run, uri)
+ return cmd.Start()
+}
+
func NewApplication(r *routes.Routes) *Application {
r.Init()
return &Application{
@@ -41,6 +61,8 @@ func (a *Application) Run() error {
return a.router.Engine.Run("0.0.0.0:8080")
})
+ Open("http://localhost:8081")
+
if err := g.Wait(); err != nil {
return err
} else {
diff --git a/garage_ffmpeg/ffmpeg.go b/garage_ffmpeg/ffmpeg.go
index d78198a..477745e 100644
--- a/garage_ffmpeg/ffmpeg.go
+++ b/garage_ffmpeg/ffmpeg.go
@@ -1,16 +1,12 @@
package garage_ffmpeg
import (
+ "errors"
"fmt"
"os"
"os/exec"
"path"
"path/filepath"
- "strconv"
- "strings"
- "time"
-
- "go.uber.org/zap"
)
type VideoBatchOption struct {
@@ -28,139 +24,234 @@ type VideoBatchOption struct {
}
type VideoBatcher interface {
- createDestDir() error // 创建输出后的文件夹
- getVideosList() error // 获取视频列表
- getFontsList() error // 获取字体列表
- getFontsParams() (string, error) // 获取字体列表
- StartAddSubtittleBatch() error // 添加字幕
- StartAddFontsBatch() error // 添加字体
- StartConvertBatch() error // 转换视频
- GetConvertBatch() error // 转换视频
+ createDestDir() error // 创建输出后的文件夹
+ GetVideosList() ([]string, error) // 获取视频列表s
+ GetFontsList() ([]string, error) // 获取字体列表
+ GetFontsParams() (string, error) // 获取字体列表
+ GetConvertBatch() ([]string, error) // 获取转换视频命令
+ StartConvertBatch() error // 转换视频
+ GetAddFontsBatch() ([]string, error) // 获取添加字体命令
+ StartAddFontsBatch() error // 添加字体
+ GetAddSubtittleBatch() ([]string, error) //
+ StartAddSubtittleBatch() error // 添加字幕
executeBatch() error
}
type videoBatch struct {
- option *VideoBatchOption
- videosList []string
- fontsList []string
- fontsParams string
- cmdBatch []string
- logger *zap.Logger
+ option *VideoBatchOption
+ cmdBatch []string
}
+var FONT_EXT = []string{".ttf", ".otf", ".ttc"}
+
const CONVERT_TEMPLATE = `ffmpeg.exe -i "%v" %v "%v"`
const ADD_SUB_TEMPLATE = `ffmpeg.exe -i "%s" -sub_charenc UTF-8 -i "%s" -map 0 -map 1 -metadata:s:s:%v language=%v -metadata:s:s:%v title="%v" -c copy %s "%v"`
const ADD_FONT_TEMPLATE = `ffmpeg.exe -i "%s" -c copy %s "%v"`
const FONT_TEMPLATE = `-attach "%s" -metadata:s:t:%v mimetype=application/x-truetype-font `
-func NewVideoBatch(l *zap.Logger, opt *VideoBatchOption) (VideoBatcher, error) {
- client := &videoBatch{
- logger: l,
- option: opt,
- videosList: make([]string, 0),
- fontsList: make([]string, 0),
- fontsParams: "",
- cmdBatch: make([]string, 0),
+func NewVideoBatch(opt *VideoBatchOption) (VideoBatcher, error) {
+ // if err := client.createDestDir(); err != nil {
+ // return nil, err
+ // }
+ return &videoBatch{
+ option: opt,
+ cmdBatch: make([]string, 0),
+ }, nil
+}
+
+func (vb *videoBatch) GetVideosList() ([]string, error) {
+ var videosList []string = make([]string, 0)
+ if err := filepath.Walk(vb.option.InputPath, func(path string, fi os.FileInfo, err error) error {
+ if err != nil {
+ return err
+ }
+
+ if fi.IsDir() {
+ return nil
+ }
+
+ filename := fi.Name()
+ fileExt := filepath.Ext(filename)
+ // vb.logger.Debug("get video filename: " + filename)
+
+ if fileExt == "."+vb.option.InputFormat {
+ videosList = append(videosList, path)
+ return nil
+ }
+ return nil
+ }); err != nil {
+ return nil, err
+ } else {
+ return videosList, nil
}
+}
- if err := client.createDestDir(); err != nil {
+func (vb *videoBatch) GetFontsList() ([]string, error) {
+ var fontsList []string = make([]string, 0)
+ if err := filepath.Walk(vb.option.FontsPath, func(path string, fi os.FileInfo, err error) error {
+ if err != nil {
+ return err
+ }
+
+ if fi.IsDir() {
+ return nil
+ }
+
+ filename := fi.Name()
+ fileExt := filepath.Ext(filename)
+
+ for _, b := range FONT_EXT {
+ if fileExt == b {
+ fontsList = append(fontsList, filename)
+ }
+ }
+ return nil
+ }); err != nil {
return nil, err
+ } else {
+ return fontsList, nil
}
- return client, nil
}
-func (vb *videoBatch) GetConvertBatch() error {
- if err := vb.getVideosList(); err != nil {
- return err
+func (vb *videoBatch) GetFontsParams() (string, error) {
+ var fontsParams = ""
+ fontsList, err := vb.GetFontsList()
+ if err != nil {
+ return "", nil
}
- for _, v := range vb.videosList {
+ for i, v := range fontsList {
+ fontPath := filepath.Join(vb.option.FontsPath, v)
+ fontsParams += fmt.Sprintf(FONT_TEMPLATE, fontPath, i)
+ }
+
+ return fontsParams, nil
+}
+
+func (vb *videoBatch) GetConvertBatch() ([]string, error) {
+ videosList, err := vb.GetVideosList()
+ if err != nil {
+ return nil, err
+ }
+
+ for _, v := range videosList {
inputVideo := filepath.Join(vb.option.InputPath, v+vb.option.InputFormat)
outputVideo := filepath.Join(vb.option.OutputPath, v+vb.option.OutputFormat)
s := fmt.Sprintf(CONVERT_TEMPLATE, inputVideo, vb.option.Advance, outputVideo)
vb.cmdBatch = append(vb.cmdBatch, s)
}
- return nil
+ return vb.cmdBatch, nil
}
func (vb *videoBatch) StartConvertBatch() error {
- vb.GetConvertBatch()
+ _, err := vb.GetConvertBatch()
+ if err != nil {
+ return err
+ }
return vb.executeBatch()
}
-func (vb *videoBatch) StartAddSubtittleBatch() error {
- if err := vb.getVideosList(); err != nil {
- return err
+func (vb *videoBatch) GetAddFontsBatch() ([]string, error) {
+ videosList, err := vb.GetVideosList()
+ if err != nil {
+ return nil, err
}
- vb.logger.Debug("Source videos directory: " + vb.option.InputPath)
- vb.logger.Debug("Get matching video count: " + strconv.Itoa(len(vb.videosList)))
- vb.logger.Debug("Target video's subtitle stream number: " + strconv.Itoa(vb.option.InputSubNo))
- vb.logger.Debug("Target video's subtitle language: " + vb.option.InputSubLang)
- vb.logger.Debug("Target video's subtitle title: " + vb.option.InputSubTitle)
-
- if vb.option.FontsPath != "" {
- if err := vb.getFontsList(); err != nil {
- return err
- }
- vb.logger.Info("Target video's font paths: " + vb.option.FontsPath)
- vb.logger.Info(fmt.Sprintf("Attach fonts parameters: %v", vb.fontsParams))
- } else {
- vb.logger.Info("Target video's font paths not set, skip.")
+ fontsParams, err := vb.GetFontsParams()
+ if err != nil {
+ return nil, err
}
- vb.logger.Info("Dest video directory: " + vb.option.OutputPath)
- template := `ffmpeg.exe -i "%s" -sub_charenc UTF-8 -i "%s" -map 0 -map 1 -metadata:s:s:%v language=%v -metadata:s:s:%v title="%v" -c copy %s "%v"`
- for _, v := range vb.videosList {
+ for _, v := range videosList {
sourceVideo := filepath.Join(vb.option.InputPath, v+vb.option.InputFormat)
- sourceSubtitle := filepath.Join(vb.option.InputPath, v+vb.option.InputSubSuffix)
destVideo := filepath.Join(vb.option.OutputPath, v+vb.option.InputFormat)
- s := fmt.Sprintf(template,
- sourceVideo, sourceSubtitle, vb.option.InputSubNo,
- vb.option.InputSubLang, vb.option.InputSubNo, vb.option.InputSubTitle,
- vb.fontsParams, destVideo)
+ s := fmt.Sprintf(ADD_FONT_TEMPLATE, sourceVideo, fontsParams, destVideo)
vb.cmdBatch = append(vb.cmdBatch, s)
}
- vb.logger.Info("Get all videos, starting convert")
- if vb.option.Exec {
+ return vb.cmdBatch, nil
+}
+
+func (vb *videoBatch) StartAddFontsBatch() error {
+ // if fontsList, err := vb.GetFontsList(); err != nil {
+ // return err
+ // }
+
+ // vb.logger.Info("Source videos directory: " + vb.option.InputPath)
+ // vb.logger.Info("Get matching video count: " + strconv.Itoa(len(vb.videosList)))
+ // vb.logger.Info("Target video's font paths: " + vb.option.FontsPath)
+ // vb.logger.Info(fmt.Sprintf("Attach fonts parameters: %v", vb.fontsParams))
+ // vb.logger.Info("Dest video directory: " + vb.option.OutputPath)
+
+ if !vb.option.Exec {
return nil
+ } else {
+ _, err := vb.GetConvertBatch()
+ if err != nil {
+ return err
+ }
+ return vb.executeBatch()
}
- return nil
}
-func (vb *videoBatch) StartAddFontsBatch() error {
- if err := vb.getVideosList(); err != nil {
- return err
+func (vb *videoBatch) GetAddSubtittleBatch() ([]string, error) {
+ videosList, err := vb.GetVideosList()
+ if err != nil {
+ return nil, err
}
- if err := vb.getFontsList(); err != nil {
- return err
+ // if vb.option.FontsPath != "" {
+ // }
+
+ fontsParams, err := vb.GetFontsParams()
+ if err != nil {
+ return nil, err
}
- vb.logger.Info("Source videos directory: " + vb.option.InputPath)
- vb.logger.Info("Get matching video count: " + strconv.Itoa(len(vb.videosList)))
- vb.logger.Info("Target video's font paths: " + vb.option.FontsPath)
- vb.logger.Info(fmt.Sprintf("Attach fonts parameters: %v", vb.fontsParams))
- vb.logger.Info("Dest video directory: " + vb.option.OutputPath)
- template := `ffmpeg.exe -i "%s" -c copy %s "%v"`
- for _, v := range vb.videosList {
+ for _, v := range videosList {
sourceVideo := filepath.Join(vb.option.InputPath, v+vb.option.InputFormat)
+ sourceSubtitle := filepath.Join(vb.option.InputPath, v+vb.option.InputSubSuffix)
destVideo := filepath.Join(vb.option.OutputPath, v+vb.option.InputFormat)
- s := fmt.Sprintf(template, sourceVideo, vb.fontsParams, destVideo)
+ s := fmt.Sprintf(ADD_SUB_TEMPLATE,
+ sourceVideo, sourceSubtitle, vb.option.InputSubNo,
+ vb.option.InputSubLang, vb.option.InputSubNo, vb.option.InputSubTitle,
+ fontsParams, destVideo)
vb.cmdBatch = append(vb.cmdBatch, s)
}
- if vb.option.Exec {
+ return vb.cmdBatch, nil
+}
+
+func (vb *videoBatch) StartAddSubtittleBatch() error {
+
+ // vb.logger.Debug("Source videos directory: " + vb.option.InputPath)
+ // vb.logger.Debug("Get matching video count: " + strconv.Itoa(len(vb.videosList)))
+ // vb.logger.Debug("Target video's subtitle stream number: " + strconv.Itoa(vb.option.InputSubNo))
+ // vb.logger.Debug("Target video's subtitle language: " + vb.option.InputSubLang)
+ // vb.logger.Debug("Target video's subtitle title: " + vb.option.InputSubTitle)
+
+ // vb.logger.Info("Target video's font paths: " + vb.option.FontsPath)
+ // vb.logger.Info(fmt.Sprintf("Attach fonts parameters: %v", vb.fontsParams))
+ // vb.logger.Info("Target video's font paths not set, skip.")
+ // vb.logger.Info("Dest video directory: " + vb.option.OutputPath)
+
+ // vb.logger.Info("Get all videos, starting convert")
+
+ if !vb.option.Exec {
return nil
+ } else {
+ _, err := vb.GetAddSubtittleBatch()
+ if err != nil {
+ return err
+ }
+ return vb.executeBatch()
}
- return nil
}
func (vb *videoBatch) createDestDir() error {
destDir := path.Join(vb.option.OutputPath)
- vb.logger.Info("Start creating destination directory: " + destDir)
+ // vb.logger.Info("Start creating destination directory: " + destDir)
if fi, err := os.Stat(destDir); err != nil {
if os.IsNotExist(err) {
os.MkdirAll(destDir, os.ModePerm)
@@ -169,94 +260,32 @@ func (vb *videoBatch) createDestDir() error {
}
} else {
if fi.IsDir() {
- vb.logger.Info("Destination directory already exists")
+ return errors.New("destination directory already exists")
+ // vb.logger.Info("Destination directory already exists")
}
}
- vb.logger.Info("Destination directory created")
+ // vb.logger.Info("Destination directory created")
return nil
}
-func (vb *videoBatch) getVideosList() error {
- err := filepath.Walk(vb.option.InputPath, func(path string, fi os.FileInfo, err error) error {
- if fi == nil {
- if err != nil {
- return err
- }
- return nil
- }
- if fi.IsDir() {
- return nil
- }
- filename := fi.Name()
- vb.logger.Debug("get video filename: " + filename)
- fileExt := filepath.Ext(filename)
- if fileExt == vb.option.InputFormat {
- fileName := strings.TrimSuffix(filename, fileExt)
- vb.videosList = append(vb.videosList, fileName)
- return nil
- }
- return nil
- })
- return err
-}
-
-func (vb *videoBatch) getFontsList() error {
- fontExts := []string{".ttf", ".otf", ".ttc"}
-
- err := filepath.Walk(vb.option.FontsPath, func(path string, fi os.FileInfo, err error) error {
- if fi == nil {
- if err != nil {
- return err
- }
- return nil
- }
- if fi.IsDir() {
- return nil
- }
- filename := fi.Name()
- fileExt := filepath.Ext(filename)
-
- for _, b := range fontExts {
- if fileExt == b {
- vb.fontsList = append(vb.fontsList, filename)
- }
- }
- return nil
- })
- return err
-}
-
-func (vb *videoBatch) getFontsParams() (string, error) {
- if err := vb.getFontsList(); err != nil {
- return "", nil
- }
- var fontsParams = ""
-
- for i, v := range vb.fontsList {
- fontPath := filepath.Join(vb.option.FontsPath, v)
- fontsParams += fmt.Sprintf(FONT_TEMPLATE, fontPath, i)
- }
- return fontsParams, nil
-}
-
func (vb *videoBatch) executeBatch() error {
for _, cmd := range vb.cmdBatch {
if vb.option.Exec {
- vb.logger.Sugar().Infof("cmd: %v", cmd)
+ // vb.logger.Sugar().Infof("cmd: %v", cmd)
return nil
}
- startTime := time.Now()
- vb.logger.Sugar().Infof("Start convert video cmd: %v", cmd)
+ // startTime := time.Now()
+ // vb.logger.Sugar().Infof("Start convert video cmd: %v", cmd)
cmd := exec.Command("powershell", cmd)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
err := cmd.Run()
if err != nil {
- vb.logger.Sugar().Errorf("cmd error: %v", err)
+ // vb.logger.Sugar().Errorf("cmd error: %v", err)
return err
}
- vb.logger.Sugar().Infof("Finished convert video, spent time: %v sec", time.Since(startTime).Seconds())
+ // vb.logger.Sugar().Infof("Finished convert video, spent time: %v sec", time.Since(startTime).Seconds())
}
return nil
}
diff --git a/garage_ffmpeg/ffmpeg_test.go b/garage_ffmpeg/ffmpeg_test.go
index 98f2963..97b64d0 100644
--- a/garage_ffmpeg/ffmpeg_test.go
+++ b/garage_ffmpeg/ffmpeg_test.go
@@ -1,41 +1,61 @@
package garage_ffmpeg
import (
+ "strconv"
"testing"
- "github.com/gsxhnd/garage/utils"
"github.com/stretchr/testify/assert"
)
-var logger = utils.GetLogger()
+func createCorrectVideos(inputPath, formart string) []string {
+ var a = make([]string, 0)
+ for i := 1; i < 5; i++ {
+ for j := 1; j < 6; j++ {
+ a = append(a, inputPath+"/"+strconv.Itoa(i)+"/"+strconv.Itoa(j)+"."+formart)
+ }
+ }
+ return a
+}
func Test_videoBatch_getVideosList(t *testing.T) {
type args struct {
- inputPath string
+ InputPath string
InputFormat string
}
+
tests := []struct {
name string
args args
want []string
wantErr bool
}{
- {"test_mkv", args{inputPath: "../testdata", InputFormat: ".mkv"}, []string{"1", "2", "3", "4", "5"}, false},
- {"test_mp4", args{inputPath: "../testdata", InputFormat: ".mp4"}, []string{"1", "2", "3", "4", "5"}, false},
- // {"test_err", args{sourceRootPath: "../../testdata", sourceVideoType: ".mp4"}, []string{}, false},
+ {"test_mkv", args{InputPath: "../testdata", InputFormat: "mkv"}, []string{}, false},
+ {"test_mp4", args{InputPath: "../testdata", InputFormat: "mp4"}, []string{}, false},
+ {"test_err", args{InputPath: "../111", InputFormat: "mp4"}, []string{}, true},
+ {"test_err", args{InputPath: "../111", InputFormat: "mp4"}, []string{}, true},
}
+
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
vb := &videoBatch{
- logger: logger,
option: &VideoBatchOption{
- InputPath: tt.args.inputPath,
+ InputPath: tt.args.InputPath,
InputFormat: tt.args.InputFormat,
},
}
- err := vb.getVideosList()
- t.Log(vb.videosList)
- assert.Nil(t, err)
+
+ videosList, err := vb.GetVideosList()
+ t.Log(videosList)
+
+ if tt.wantErr {
+ assert.NotNil(t, err)
+ } else {
+ var cList = createCorrectVideos(tt.args.InputPath, tt.args.InputFormat)
+ t.Log(cList)
+
+ assert.Nil(t, err)
+ assert.Equal(t, videosList, cList)
+ }
})
}
}
@@ -52,14 +72,14 @@ func Test_videoBatch_getFontsParams(t *testing.T) {
}{
// TODO: Add test cases.
}
+
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
vb := &videoBatch{
option: tt.fields.option,
-
- logger: logger,
}
- got, err := vb.getFontsParams()
+
+ got, err := vb.GetFontsParams()
if (err != nil) != tt.wantErr {
t.Errorf("videoBatch.getFontsParams() error = %v, wantErr %v", err, tt.wantErr)
return
diff --git a/garage_jav/javbus.go b/garage_jav/javbus.go
index 5243430..b9d8133 100644
--- a/garage_jav/javbus.go
+++ b/garage_jav/javbus.go
@@ -16,52 +16,41 @@ import (
"github.com/antchfx/htmlquery"
"github.com/go-gota/gota/dataframe"
+ "github.com/go-resty/resty/v2"
"github.com/gocolly/colly/v2"
"github.com/gocolly/colly/v2/queue"
+ "github.com/gsxhnd/garage/utils"
"github.com/inhies/go-bytesize"
- "go.uber.org/zap"
)
-type JavbusCrawl interface { // 通过番号爬取对应的电影信息
- StartCrawlJavbusMovie() error
- // 通过番号前缀爬取对应的电影信息
- StartCrawlJavbusMovieByPrefix() error
- // 通过演员ID爬取对应的电影信息
- StartCrawlJavbusMovieByStar() error
- // 访问文件夹下的视频列表爬取电影信息
- StartCrawlJavbusMovieByFilepath(inputPath string) error
- // 创建输出目录
- mkAllDir() error
- getJavMovieInfoByJavbus(element *colly.HTMLElement)
+type JavbusCrawl interface {
+ StartCrawlJavbusMovie() error // 通过番号爬取对应的电影信息
+ GetJavbusMovie(code string) (*JavMovie, error) // 通过番号爬取对应的电影信息
+ StartCrawlJavbusMovieByPrefix() error // 通过番号前缀爬取对应的电影信息
+ StartCrawlJavbusMovieByStar() error // 通过演员ID爬取对应的电影信息
+ StartCrawlJavbusMovieByFilepath(inputPath string) error // 访问文件夹下的视频列表爬取电影信息
+ mkAllDir() error // 创建输出目录
+ savejavInfos() error // 保存CSV格式的电影信息
+ saveCovers(coverPath, name string) error // 下载电影封面
+ saveMagents() error // 下载磁力列表
+ Save() error
+ getJavMovieInfowByJavbus(element *colly.HTMLElement)
getJavMovieMagnetByJavbus(e *colly.HTMLElement)
getJavStarMovieByJavbus(e *colly.HTMLElement)
-
- // 保存CSV格式的电影信息
- saveJavInfos() error
- // 下载电影封面
- saveCovers(coverPath, name string) error
- // 下载磁力列表
- saveMagents() error
}
type javbusCrawl struct {
- logger *zap.Logger
+ logger utils.Logger
option *JavCrawlConfig
collector *colly.Collector
+ collectorQueue *queue.Queue
pageCollector *colly.Collector
httpClient *http.Client
+ requestClient *resty.Client
maxDepth int
javbusUrl string
javInfos []JavMovie
javMagnets []string
- downloadMagent bool
- destPath string
- starCode string
- starPage int
- prefixCode string
- prefixMinNo int
- prefixMaxNo int
- javQueue *queue.Queue
}
type CrawlOptions struct {
@@ -74,7 +63,7 @@ type CrawlOptions struct {
PrefixMaxNo int
}
-func NewJavbusCrawl(logger *zap.Logger, option *JavCrawlConfig) (JavbusCrawl, error) {
+func NewJavbusCrawl(logger utils.Logger, option *JavCrawlConfig) (JavbusCrawl, error) {
collector := colly.NewCollector()
collector.ParseHTTPErrorResponse = true
collector.SetRedirectHandler(func(req *http.Request, via []*http.Request) error {
@@ -85,7 +74,7 @@ func NewJavbusCrawl(logger *zap.Logger, option *JavCrawlConfig) (JavbusCrawl, er
RandomDelay: 5 * time.Second,
})
collector.OnRequest(func(r *colly.Request) {
- logger.Info("Visiting: " + r.URL.String())
+ logger.Infow("Visiting: " + r.URL.String())
})
q, _ := queue.New(1, &queue.InMemoryQueueStorage{MaxSize: 10000})
@@ -107,22 +96,60 @@ func NewJavbusCrawl(logger *zap.Logger, option *JavCrawlConfig) (JavbusCrawl, er
}
return &javbusCrawl{
- logger: logger,
- option: option,
- collector: collector,
- pageCollector: nil,
- httpClient: httpClient,
- maxDepth: 100,
- javbusUrl: "https://www.javbus.com",
- javInfos: make([]JavMovie, 0),
- javMagnets: make([]string, 0),
- starPage: 2,
- javQueue: q,
+ logger: logger,
+ option: option,
+ collector: collector,
+ collectorQueue: q,
+ pageCollector: nil,
+ httpClient: httpClient,
+ requestClient: resty.New(),
+ maxDepth: 100,
+ javbusUrl: "https://www.javbus.com",
+ javInfos: make([]JavMovie, 0),
+ javMagnets: make([]string, 0),
}, nil
}
+func (cc *javbusCrawl) StartCrawlJavbusMovie() error {
+ cc.logger.Infow("Download Infow: " + cc.option.Code)
+
+ if cc.option.DownloadMagent {
+ cc.collector.OnHTML("body", cc.getJavMovieMagnetByJavbus)
+ }
+ cc.collector.OnHTML(".container", cc.getJavMovieInfowByJavbus)
+
+ if err := cc.collector.Visit(cc.javbusUrl + "/" + cc.option.Code); err != nil {
+ return err
+ }
+ cc.collector.Wait()
+
+ if len(cc.javInfos) == 0 {
+ return nil
+ }
+
+ if err := cc.savejavInfos(); err != nil {
+ return err
+ }
+ for _, v := range cc.javInfos {
+ err := cc.saveCovers(v.Cover, v.Code)
+ if err != nil {
+ return err
+ }
+ }
+ cc.saveMagents()
+ return nil
+}
+
+func (cc *javbusCrawl) GetJavbusMovie(code string) (*JavMovie, error) {
+ return nil, nil
+}
+
+func (cc *javbusCrawl) Save() error {
+ return nil
+}
+
func (cc *javbusCrawl) mkAllDir() error {
- fullPath := filepath.Join(cc.destPath, "cover")
+ fullPath := filepath.Join(cc.option.DestPath, "cover")
_, err := os.Stat(fullPath)
if err != nil {
if os.IsNotExist(err) {
@@ -139,39 +166,39 @@ func (cc *javbusCrawl) mkAllDir() error {
return nil
}
-func (cc *javbusCrawl) getJavMovieInfoByJavbus(e *colly.HTMLElement) {
- var info = &JavMovie{}
- info.Title = e.ChildText("h3")
- info.Cover = e.ChildAttr(".screencap img", "src")
- e.ForEach(".info p", func(i int, element *colly.HTMLElement) {
+func (cc *javbusCrawl) getJavMovieInfowByJavbus(e *colly.HTMLElement) {
+ var Infow = &JavMovie{}
+ Infow.Title = e.ChildText("h3")
+ Infow.Cover = e.ChildAttr(".screencap img", "src")
+ e.ForEach(".Infow p", func(i int, element *colly.HTMLElement) {
key := element.ChildText("span")
switch i {
case 0:
- info.Code = element.ChildTexts("span")[1]
+ Infow.Code = element.ChildTexts("span")[1]
}
switch key {
case "發行日期:":
pd := element.Text
- info.PublishDate = strings.Split(pd, " ")[1]
+ Infow.PublishDate = strings.Split(pd, " ")[1]
case "長度:":
pd := element.Text
p := strings.Split(pd, " ")[1]
- info.Length = strings.Split(p, "分鐘")[0]
+ Infow.Length = strings.Split(p, "分鐘")[0]
case "導演:":
- info.Director = element.ChildText("a")
+ Infow.Director = element.ChildText("a")
case "製作商:":
- info.ProduceCompany = element.ChildText("a")
+ Infow.ProduceCompany = element.ChildText("a")
case "發行商:":
- info.PublishCompany = element.ChildText("a")
+ Infow.PublishCompany = element.ChildText("a")
case "系列:":
- info.Series = element.ChildText("a")
+ Infow.Series = element.ChildText("a")
}
})
e.ForEach("ul li .star-name a", func(i int, element *colly.HTMLElement) {
star := element.Attr("title")
- info.Stars += star + ";"
+ Infow.Stars += star + ";"
})
- cc.javInfos = append(cc.javInfos, *info)
+ cc.javInfos = append(cc.javInfos, *Infow)
}
func (cc *javbusCrawl) getJavMovieMagnetByJavbus(e *colly.HTMLElement) {
@@ -188,33 +215,33 @@ func (cc *javbusCrawl) getJavMovieMagnetByJavbus(e *colly.HTMLElement) {
param = strings.Replace(param, ";", "&", -1)
param = strings.Replace(param, "'", "", -1)
urlS := "https://www.javbus.com/ajax/uncledatoolsbyajax.php?" + param + "lang=zh&floor=442"
- cc.logger.Info("Get magnet url: " + urlS)
+ cc.logger.Infow("Get magnet url: " + urlS)
r, _ := http.NewRequest("GET", urlS, nil)
r.Header.Add("Referer", e.Request.URL.Scheme+"://"+e.Request.URL.Host+e.Request.URL.Path)
res, err := cc.httpClient.Do(r)
if err != nil {
- cc.logger.Error("http client error: " + err.Error())
+ cc.logger.Errorw("http client error: " + err.Error())
return
}
body, err := io.ReadAll(res.Body)
if err != nil {
- cc.logger.Error("http read response error: " + err.Error())
+ cc.logger.Errorw("http read response error: " + err.Error())
return
}
defer res.Body.Close()
doc, err := htmlquery.Parse(strings.NewReader(""))
if err != nil {
- cc.logger.Error("html query error: " + err.Error())
+ cc.logger.Errorw("html query error: " + err.Error())
}
list, err := htmlquery.QueryAll(doc, "//tr")
if err != nil {
- cc.logger.Error("html query tr error: " + err.Error())
+ cc.logger.Errorw("html query tr error: " + err.Error())
}
if len(list) == 0 {
- cc.logger.Info("当前无磁力连接")
+ cc.logger.Infow("当前无磁力连接")
return
}
@@ -270,7 +297,7 @@ func (cc *javbusCrawl) getJavMovieMagnetByJavbus(e *colly.HTMLElement) {
func (cc *javbusCrawl) getJavStarMovieByJavbus(e *colly.HTMLElement) {
e.ForEach("#waterfall > div", func(i int, element *colly.HTMLElement) {
- cc.javQueue.AddURL(element.ChildAttr("a", "href"))
+ cc.collectorQueue.AddURL(element.ChildAttr("a", "href"))
})
e.ForEach("div.text-center.hidden-xs > ul", func(i int, element *colly.HTMLElement) {
page := element.ChildAttr("a#next", "href")
@@ -280,54 +307,24 @@ func (cc *javbusCrawl) getJavStarMovieByJavbus(e *colly.HTMLElement) {
})
}
-func (cc *javbusCrawl) StartCrawlJavbusMovie() error {
- cc.logger.Info("Download info: " + cc.option.Code)
-
- if cc.downloadMagent {
- cc.collector.OnHTML("body", cc.getJavMovieMagnetByJavbus)
- }
- cc.collector.OnHTML(".container", cc.getJavMovieInfoByJavbus)
-
- if err := cc.collector.Visit(cc.javbusUrl + "/" + cc.option.Code); err != nil {
- return err
- }
- cc.collector.Wait()
-
- if len(cc.javInfos) == 0 {
- return nil
- }
-
- if err := cc.saveJavInfos(); err != nil {
- return err
- }
- for _, v := range cc.javInfos {
- err := cc.saveCovers(v.Cover, v.Code)
- if err != nil {
- return err
- }
- }
- cc.saveMagents()
- return nil
-}
-
func (cc *javbusCrawl) StartCrawlJavbusMovieByPrefix() error {
q, _ := queue.New(1, &queue.InMemoryQueueStorage{MaxSize: 10000})
- for i := cc.prefixMinNo; i <= cc.prefixMaxNo; i++ {
- code := fmt.Sprintf("%s-%03d", cc.prefixCode, i)
+ for i := cc.option.PrefixMinNo; i <= cc.option.PrefixMaxNo; i++ {
+ code := fmt.Sprintf("%s-%03d", cc.option.PrefixCode, i)
q.AddURL(cc.javbusUrl + "/" + code)
}
- if cc.downloadMagent {
+ if cc.option.DownloadMagent {
cc.collector.OnHTML("body", cc.getJavMovieMagnetByJavbus)
}
- cc.collector.OnHTML(".container", cc.getJavMovieInfoByJavbus)
+ cc.collector.OnHTML(".container", cc.getJavMovieInfowByJavbus)
q.Run(cc.collector)
cc.collector.Wait()
- cc.saveJavInfos()
+ cc.savejavInfos()
cc.saveMagents()
for _, v := range cc.javInfos {
err := cc.saveCovers(v.Cover, v.Code)
@@ -340,7 +337,7 @@ func (cc *javbusCrawl) StartCrawlJavbusMovieByPrefix() error {
func (cc *javbusCrawl) StartCrawlJavbusMovieByStar() error {
starCode := cc.option.StarCode
- cc.logger.Debug("Getting star code: " + starCode)
+ cc.logger.Debugw("Getting star code: " + starCode)
cc.pageCollector = cc.collector.Clone()
cc.pageCollector.OnHTML("body", cc.getJavStarMovieByJavbus)
@@ -349,23 +346,23 @@ func (cc *javbusCrawl) StartCrawlJavbusMovieByStar() error {
return err
}
cc.pageCollector.Wait()
- if cc.javQueue.IsEmpty() {
+ if cc.collectorQueue.IsEmpty() {
return nil
}
- infoCrawlClient := cc.collector.Clone()
- infoCrawlClient.OnRequest(func(r *colly.Request) {
- cc.logger.Info("Visiting: " + r.URL.String())
+ InfowCrawlClient := cc.collector.Clone()
+ InfowCrawlClient.OnRequest(func(r *colly.Request) {
+ cc.logger.Infow("Visiting: " + r.URL.String())
})
- if cc.downloadMagent {
- infoCrawlClient.OnHTML("body", cc.getJavMovieMagnetByJavbus)
+ if cc.option.DownloadMagent {
+ InfowCrawlClient.OnHTML("body", cc.getJavMovieMagnetByJavbus)
}
- infoCrawlClient.OnHTML(".container", cc.getJavMovieInfoByJavbus)
- cc.javQueue.Run(infoCrawlClient)
+ InfowCrawlClient.OnHTML(".container", cc.getJavMovieInfowByJavbus)
+ cc.collectorQueue.Run(InfowCrawlClient)
cc.collector.Wait()
- cc.saveJavInfos()
+ cc.savejavInfos()
cc.saveMagents()
for _, v := range cc.javInfos {
err := cc.saveCovers(v.Cover, v.Code)
@@ -402,12 +399,12 @@ func (cc *javbusCrawl) StartCrawlJavbusMovieByFilepath(inputPath string) error {
return err
}
- cc.collector.OnHTML(".container", cc.getJavMovieInfoByJavbus)
+ cc.collector.OnHTML(".container", cc.getJavMovieInfowByJavbus)
q.Run(cc.collector)
cc.collector.Wait()
- cc.saveJavInfos()
+ cc.savejavInfos()
for _, v := range cc.javInfos {
err := cc.saveCovers(v.Cover, v.Code)
if err != nil {
@@ -418,13 +415,13 @@ func (cc *javbusCrawl) StartCrawlJavbusMovieByFilepath(inputPath string) error {
return nil
}
-func (cc *javbusCrawl) save() {}
+// func (cc *javbusCrawl) save() {}
-func (cc *javbusCrawl) saveJavInfos() error {
+func (cc *javbusCrawl) savejavInfos() error {
df := dataframe.LoadStructs(cc.javInfos)
- f, err := os.OpenFile(path.Join(cc.destPath, time.Now().Local().Format("2006-01-02-15-04-05")+"-jav_info.csv"), os.O_RDWR|os.O_CREATE|os.O_TRUNC, os.ModePerm)
+ f, err := os.OpenFile(path.Join(cc.option.DestPath, time.Now().Local().Format("2006-01-02-15-04-05")+"-jav_Infow.csv"), os.O_RDWR|os.O_CREATE|os.O_TRUNC, os.ModePerm)
if err != nil {
- cc.logger.Error("Save jav info file failed error: %s" + err.Error())
+ cc.logger.Errorw("Save jav Infow file failed error: %s" + err.Error())
return err
}
defer f.Close()
@@ -436,9 +433,9 @@ func (cc *javbusCrawl) saveMagents() error {
return nil
}
- f, err := os.OpenFile(path.Join(cc.destPath, time.Now().Local().Format("2006-01-02-15-04-05")+"-jav_magnet.text"), os.O_RDWR|os.O_CREATE|os.O_TRUNC, os.ModePerm)
+ f, err := os.OpenFile(path.Join(cc.option.DestPath, time.Now().Local().Format("2006-01-02-15-04-05")+"-jav_magnet.text"), os.O_RDWR|os.O_CREATE|os.O_TRUNC, os.ModePerm)
if err != nil {
- cc.logger.Error("Save jav info file failed error: %s" + err.Error())
+ cc.logger.Errorw("Save jav Infow file failed error: %s" + err.Error())
return err
}
defer f.Close()
@@ -453,7 +450,7 @@ func (cc *javbusCrawl) saveCovers(coverPath, code string) error {
var urlImg = ""
u, err := url.ParseRequestURI(coverPath)
if err != nil {
- cc.logger.Error("parse cover path failed error: %s" + err.Error())
+ cc.logger.Errorw("parse cover path failed error: %s" + err.Error())
return err
}
if u.Host == "" {
@@ -462,16 +459,16 @@ func (cc *javbusCrawl) saveCovers(coverPath, code string) error {
urlImg = coverPath
}
- cc.logger.Info("downloading coverage url: " + urlImg)
+ cc.logger.Infow("downloading coverage url: " + urlImg)
ext := path.Ext(urlImg)
resp, err := cc.httpClient.Get(urlImg)
if err != nil {
- cc.logger.Error("downloading coverage error: " + err.Error())
+ cc.logger.Errorw("downloading coverage error: " + err.Error())
return err
}
body, _ := ioutil.ReadAll(resp.Body)
- f, err := os.OpenFile(path.Join(cc.destPath, "cover", code+ext), os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0666)
+ f, err := os.OpenFile(path.Join(cc.option.DestPath, "cover", code+ext), os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0666)
if err != nil {
return err
}
diff --git a/garage_jav/model.go b/garage_jav/model.go
index 9585be9..d8fe647 100644
--- a/garage_jav/model.go
+++ b/garage_jav/model.go
@@ -28,6 +28,7 @@ type JavMovie struct {
PublishCompany string `json:"publish_company"`
Series string `json:"series"`
Stars string `json:"stars"`
+ Magnets []JavMovieMagnet
}
type JavMovieMagnet struct {
diff --git a/go.mod b/go.mod
index b0d6dd0..216d785 100644
--- a/go.mod
+++ b/go.mod
@@ -7,6 +7,7 @@ require (
github.com/gin-gonic/gin v1.9.1
github.com/glebarez/go-sqlite v1.22.0
github.com/go-gota/gota v0.12.0
+ github.com/go-resty/resty/v2 v2.11.0
github.com/gocolly/colly/v2 v2.1.0
github.com/google/wire v0.6.0
github.com/inhies/go-bytesize v0.0.0-20220417184213-4913239db9cf
@@ -14,6 +15,7 @@ require (
github.com/urfave/cli/v2 v2.27.1
go.uber.org/zap v1.26.0
golang.org/x/sync v0.6.0
+ gopkg.in/natefinch/lumberjack.v2 v2.2.1
)
require (
diff --git a/go.sum b/go.sum
index acd021e..c58a829 100644
--- a/go.sum
+++ b/go.sum
@@ -66,6 +66,8 @@ github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJn
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
github.com/go-playground/validator/v10 v10.18.0 h1:BvolUXjp4zuvkZ5YN5t7ebzbhlUtPsPm2S9NAZ5nl9U=
github.com/go-playground/validator/v10 v10.18.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM=
+github.com/go-resty/resty/v2 v2.11.0 h1:i7jMfNOJYMp69lq7qozJP+bjgzfAzeOhuGlyDrqxT/8=
+github.com/go-resty/resty/v2 v2.11.0/go.mod h1:iiP/OpA0CkcL3IGt1O0+/SIItFUbkkyw5BGXiVdTu+A=
github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y=
github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8=
github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
@@ -178,6 +180,7 @@ golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8U
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
+golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg=
golang.org/x/crypto v0.19.0 h1:ENy+Az/9Y1vSrlrvBSyna3PITt4tiZLf7sgCjZBX7Wo=
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
@@ -224,6 +227,7 @@ golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws=
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
+golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY=
golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4=
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
@@ -252,6 +256,7 @@ golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y=
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
@@ -261,6 +266,7 @@ golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU=
+golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U=
golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
@@ -274,6 +280,8 @@ golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
+golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4=
+golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
@@ -323,6 +331,8 @@ google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7
google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc=
+gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
diff --git a/taskfile.yaml b/taskfile.yaml
index 2c45970..bb76f03 100644
--- a/taskfile.yaml
+++ b/taskfile.yaml
@@ -7,6 +7,8 @@ tasks:
- rm -rvf testdata/
- mkdir -p testdata/{1,2,3,4}
- touch ./testdata/{1,2,3,4}/{1,2,3,4,5}.{mkv,mp4,ass,ttf}
+ - mkdir ./garage-ui/dist
+ - touch ./garage-ui/dist/index.html
- ls -al ./testdata
clean:
cmds:
diff --git a/utils/config.go b/utils/config.go
index 5aad48e..23cac90 100644
--- a/utils/config.go
+++ b/utils/config.go
@@ -1,9 +1,18 @@
package utils
type Config struct {
- Dev bool `env:"DEV" envDefault:"true"`
- Debug bool `env:"DEBUG" envDefault:"true"`
- LogLevel string `env:"LOG_LEVEL" envDefault:"info"`
+ Dev bool `env:"DEV" envDefault:"true"`
+ Debug bool `env:"DEBUG" envDefault:"true"`
+ Log LogConfig `json:"log,omitempty"`
+ LogLevel string `env:"LOG_LEVEL" envDefault:"info"`
+}
+
+type LogConfig struct {
+ Level string
+ Filename string
+ MaxSize int
+ MaxAge int
+ MaxBackups int
TraceEnable bool `env:"TRACE_ENABLE" envDefault:"false"`
TraceUrl string `env:"TRACE_URL"`
}
diff --git a/utils/logger.go b/utils/logger.go
index c310e74..a904d8f 100644
--- a/utils/logger.go
+++ b/utils/logger.go
@@ -6,6 +6,7 @@ import (
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
+ "gopkg.in/natefinch/lumberjack.v2"
)
type Logger interface {
@@ -17,6 +18,8 @@ type Logger interface {
Warnw(template string, keysAndValues ...interface{})
Errorf(template string, args ...interface{})
Errorw(template string, keysAndValues ...interface{})
+ Panicf(template string, args ...interface{})
+ Panicw(template string, keysAndValues ...interface{})
}
type logger struct {
@@ -56,30 +59,33 @@ var (
)
func NewLogger(cfg *Config) Logger {
- var encode zapcore.Encoder
- var level zapcore.Level
+ var (
+ level zapcore.Level
+ core zapcore.Core
+ )
- if cfg.Dev {
- encode = devEncoder
- } else {
- encode = prodEncoder
- }
- if cfg.LogLevel == "debug" {
- level = zap.DebugLevel
- } else if cfg.LogLevel == "info" {
+ if cfg.Log.Level == "info" {
level = zap.InfoLevel
- } else {
+ } else if cfg.Log.Level == "warn" {
level = zap.WarnLevel
+ } else {
+ level = zap.DebugLevel
}
- var core = zapcore.NewTee(
- zapcore.NewCore(encode, os.Stdout, level),
- )
- zapLogger := zap.New(core, zap.AddCaller(), zap.AddCallerSkip(1))
+ if !cfg.Dev {
+ core = zapcore.NewCore(prodEncoder, zapcore.AddSync(&lumberjack.Logger{
+ Filename: cfg.Log.Filename,
+ MaxSize: cfg.Log.MaxSize,
+ MaxBackups: cfg.Log.MaxBackups,
+ MaxAge: cfg.Log.MaxAge,
+ },
+ ), level)
+ } else {
+ core = zapcore.NewCore(devEncoder, os.Stdout, level)
+ }
return &logger{
- // Logger: zapLogger,
- Suger: zapLogger.Sugar(),
+ Suger: zap.New(core, zap.AddCaller(), zap.AddCallerSkip(1)).Sugar(),
}
}
@@ -119,22 +125,11 @@ func (l *logger) Errorw(template string, keysAndValues ...interface{}) {
l.Suger.Errorw(template, keysAndValues...)
}
-func GetLogger() *zap.Logger {
- debugEncoder := zapcore.NewConsoleEncoder(zapcore.EncoderConfig{
- MessageKey: "msg",
- LevelKey: "level",
- TimeKey: "ts",
- EncodeLevel: zapcore.CapitalColorLevelEncoder,
- EncodeTime: func(t time.Time, enc zapcore.PrimitiveArrayEncoder) {
- enc.AppendString(t.UTC().Format("2006-01-02T15:04:05.000000-07:00"))
- },
- EncodeCaller: zapcore.ShortCallerEncoder,
- EncodeDuration: func(d time.Duration, enc zapcore.PrimitiveArrayEncoder) {
- enc.AppendInt64(int64(d) / 1000000)
- },
- })
- var core = zapcore.NewTee(
- zapcore.NewCore(debugEncoder, os.Stdout, zap.DebugLevel),
- )
- return zap.New(core, zap.AddCaller(), zap.AddCallerSkip(1))
+func (l *logger) Panicf(template string, args ...interface{}) {
+ defer l.Suger.Sync()
+ l.Suger.Panicf(template, args...)
+}
+func (l *logger) Panicw(template string, keysAndValues ...interface{}) {
+ defer l.Suger.Sync()
+ l.Suger.Panicw(template, keysAndValues...)
}