mediac 1.8.0 → 1.8.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/cmd/cmd_compress.js +45 -21
- package/cmd/cmd_dcim.js +2 -1
- package/cmd/cmd_decode.js +15 -15
- package/cmd/cmd_ffmpeg.js +200 -97
- package/cmd/cmd_moveup.js +1 -0
- package/cmd/cmd_prefix.js +17 -5
- package/cmd/cmd_remove.js +130 -74
- package/cmd/cmd_rename.js +107 -71
- package/cmd/cmd_shared.js +21 -9
- package/cmd/cmd_zipu.js +2 -2
- package/lib/core.js +34 -1
- package/lib/encoding.js +2 -1
- package/lib/exif.js +3 -3
- package/lib/ffmpeg_presets.js +69 -23
- package/lib/file.js +7 -7
- package/lib/helper.js +8 -4
- package/lib/media_parser.js +293 -0
- package/lib/mediainfo.js +139 -0
- package/lib/shared.js +0 -2
- package/lib/tryfp.js +5 -7
- package/package.json +2 -1
- package/lib/ffprobe.js +0 -205
package/cmd/cmd_compress.js
CHANGED
|
@@ -24,8 +24,8 @@ import * as core from '../lib/core.js'
|
|
|
24
24
|
import * as log from '../lib/debug.js'
|
|
25
25
|
import * as mf from '../lib/file.js'
|
|
26
26
|
import * as helper from '../lib/helper.js'
|
|
27
|
-
import tryfp from '../lib/tryfp.js'
|
|
28
|
-
import { calculateScale, compressImage } from "./cmd_shared.js"
|
|
27
|
+
import * as tryfp from '../lib/tryfp.js'
|
|
28
|
+
import { applyFileNameRules, calculateScale, compressImage } from "./cmd_shared.js"
|
|
29
29
|
|
|
30
30
|
//
|
|
31
31
|
export { aliases, builder, command, describe, handler }
|
|
@@ -40,11 +40,11 @@ const WIDTH_DEFAULT = 6000
|
|
|
40
40
|
|
|
41
41
|
const builder = function addOptions(ya, helpOrVersionSet) {
|
|
42
42
|
return ya
|
|
43
|
-
.option("
|
|
43
|
+
.option("delete-source-files", {
|
|
44
44
|
alias: "p",
|
|
45
45
|
type: "boolean",
|
|
46
46
|
default: false,
|
|
47
|
-
description: "
|
|
47
|
+
description: "Delete original image files after compress",
|
|
48
48
|
})
|
|
49
49
|
// 输出目录,默认输出文件与原文件同目录
|
|
50
50
|
.option("output", {
|
|
@@ -52,6 +52,32 @@ const builder = function addOptions(ya, helpOrVersionSet) {
|
|
|
52
52
|
describe: "Folder store ouput files",
|
|
53
53
|
type: "string",
|
|
54
54
|
})
|
|
55
|
+
// 正则,包含文件名规则
|
|
56
|
+
.option("include", {
|
|
57
|
+
alias: "I",
|
|
58
|
+
type: "string",
|
|
59
|
+
description: "filename include pattern",
|
|
60
|
+
})
|
|
61
|
+
//字符串或正则,不包含文件名规则
|
|
62
|
+
// 如果是正则的话需要转义
|
|
63
|
+
.option("exclude", {
|
|
64
|
+
alias: "E",
|
|
65
|
+
type: "string",
|
|
66
|
+
description: "filename exclude pattern ",
|
|
67
|
+
})
|
|
68
|
+
// 默认启用正则模式,禁用则为字符串模式
|
|
69
|
+
.option("regex", {
|
|
70
|
+
alias: 're',
|
|
71
|
+
type: "boolean",
|
|
72
|
+
default: true,
|
|
73
|
+
description: "match filenames by regex pattern",
|
|
74
|
+
})
|
|
75
|
+
// 需要处理的扩展名列表,默认为常见视频文件
|
|
76
|
+
.option("extensions", {
|
|
77
|
+
alias: "e",
|
|
78
|
+
type: "string",
|
|
79
|
+
describe: "include files by extensions (eg. .wav|.flac)",
|
|
80
|
+
})
|
|
55
81
|
// 压缩后的文件后缀,默认为 _Z4K
|
|
56
82
|
.option("suffix", {
|
|
57
83
|
alias: "S",
|
|
@@ -59,10 +85,10 @@ const builder = function addOptions(ya, helpOrVersionSet) {
|
|
|
59
85
|
type: "string",
|
|
60
86
|
default: "_Z4K",
|
|
61
87
|
})
|
|
62
|
-
.option("
|
|
88
|
+
.option("delete-source-files-only", {
|
|
63
89
|
type: "boolean",
|
|
64
90
|
default: false,
|
|
65
|
-
description: "Just delete original image files only",
|
|
91
|
+
description: "Just delete original image files only, no compression",
|
|
66
92
|
})
|
|
67
93
|
// 是否覆盖已存在的压缩后文件
|
|
68
94
|
.option("force", {
|
|
@@ -118,12 +144,7 @@ const handler = cmdCompress
|
|
|
118
144
|
async function cmdCompress(argv) {
|
|
119
145
|
const testMode = !argv.doit
|
|
120
146
|
const logTag = "cmdCompress"
|
|
121
|
-
const root =
|
|
122
|
-
assert.strictEqual("string", typeof root, "root must be string")
|
|
123
|
-
if (!root || !(await fs.pathExists(root))) {
|
|
124
|
-
log.error(logTag, `Invalid Input: '${root}'`)
|
|
125
|
-
throw new Error(`Invalid Input: ${root}`)
|
|
126
|
-
}
|
|
147
|
+
const root = await helper.validateInput(argv.input)
|
|
127
148
|
if (!testMode) {
|
|
128
149
|
log.fileLog(`Root:${root}`, logTag)
|
|
129
150
|
log.fileLog(`Argv:${JSON.stringify(argv)}`, logTag)
|
|
@@ -133,8 +154,8 @@ async function cmdCompress(argv) {
|
|
|
133
154
|
const quality = argv.quality || QUALITY_DEFAULT
|
|
134
155
|
const minFileSize = (argv.size || SIZE_DEFAULT) * 1024
|
|
135
156
|
const maxWidth = argv.width || WIDTH_DEFAULT
|
|
136
|
-
const purgeOnly = argv.
|
|
137
|
-
const purgeSource = argv.
|
|
157
|
+
const purgeOnly = argv.deleteSourceFilesOnly || false
|
|
158
|
+
const purgeSource = argv.deleteSourceFiles || false
|
|
138
159
|
log.show(`${logTag} input:`, root)
|
|
139
160
|
// 如果有force标志,就不过滤文件名
|
|
140
161
|
const RE_THUMB = argv.force ? /@_@/ : /Z4K|P4K|M4K|feature|web|thumb$/i
|
|
@@ -152,8 +173,10 @@ async function cmdCompress(argv) {
|
|
|
152
173
|
log.showYellow(logTag, "no files found, abort.")
|
|
153
174
|
return
|
|
154
175
|
}
|
|
176
|
+
// 应用文件名过滤规则
|
|
177
|
+
files = await applyFileNameRules(files, argv)
|
|
155
178
|
log.show(logTag, `total ${files.length} files found (all)`)
|
|
156
|
-
if (files.length === 0) {
|
|
179
|
+
if (!files || files.length === 0) {
|
|
157
180
|
log.showYellow("Nothing to do, abort.")
|
|
158
181
|
return
|
|
159
182
|
}
|
|
@@ -317,10 +340,11 @@ async function preCompress(f) {
|
|
|
317
340
|
} else {
|
|
318
341
|
if (im?.exif) {
|
|
319
342
|
log.info(logTag, "force:", fileDst)
|
|
320
|
-
const
|
|
343
|
+
const [err, iexif] = tryfp.tryCatch(exif)(im.exif)
|
|
321
344
|
// 跳过以前由mediac压缩过的图片,避免重复压缩
|
|
322
|
-
if (!f.force) {
|
|
323
|
-
|
|
345
|
+
if (!f.force && iexif?.Image) {
|
|
346
|
+
const md = iexif?.Image
|
|
347
|
+
if (md?.Copyright?.includes("mediac")
|
|
324
348
|
|| md.Software?.includes("mediac")
|
|
325
349
|
|| md.Artist?.includes("mediac") && !f.force) {
|
|
326
350
|
log.info(logTag, "skip:", fileDst)
|
|
@@ -339,12 +363,12 @@ async function preCompress(f) {
|
|
|
339
363
|
}
|
|
340
364
|
|
|
341
365
|
if (err) {
|
|
342
|
-
log.warn(logTag, "sharp",
|
|
343
|
-
log.fileLog(`SharpErr: ${f.index} <${fileSrc}> sharp:${
|
|
366
|
+
log.warn(logTag, "sharp", err.message, fileSrc)
|
|
367
|
+
log.fileLog(`SharpErr: ${f.index} <${fileSrc}> sharp:${err.message}`, logTag)
|
|
344
368
|
return
|
|
345
369
|
}
|
|
346
370
|
|
|
347
|
-
const { dstWidth, dstHeight } =
|
|
371
|
+
const { dstWidth, dstHeight } = calculateScale(im.width, im.height, maxWidth)
|
|
348
372
|
if (f.total < 1000 || f.index > f.total - 1000) {
|
|
349
373
|
log.show(logTag, `${f.index}/${f.total}`,
|
|
350
374
|
helper.pathShort(fileSrc),
|
package/cmd/cmd_dcim.js
CHANGED
|
@@ -11,7 +11,7 @@ import fs from 'fs-extra'
|
|
|
11
11
|
import inquirer from "inquirer"
|
|
12
12
|
import path from "path"
|
|
13
13
|
|
|
14
|
-
import { renameFiles } from "./cmd_shared.js"
|
|
14
|
+
import { addEntryProps, renameFiles } from "./cmd_shared.js"
|
|
15
15
|
|
|
16
16
|
import * as log from '../lib/debug.js'
|
|
17
17
|
import * as exif from '../lib/exif.js'
|
|
@@ -136,6 +136,7 @@ const handler = async function cmdRename(argv) {
|
|
|
136
136
|
log.showYellow(LOG_TAG, "Nothing to do, exit now.")
|
|
137
137
|
return
|
|
138
138
|
}
|
|
139
|
+
files = addEntryProps(files)
|
|
139
140
|
log.show(
|
|
140
141
|
LOG_TAG,
|
|
141
142
|
`Total ${files.length} media files ready to rename by exif`,
|
package/cmd/cmd_decode.js
CHANGED
|
@@ -60,7 +60,7 @@ const handler = async function cmdDecode(argv) {
|
|
|
60
60
|
}
|
|
61
61
|
const fromEnc = argv.fromEnc?.length > 0 ? [argv.fromEnc] : ENC_LIST
|
|
62
62
|
const toEnc = argv.toEnc?.length > 0 ? [argv.toEnc] : ENC_LIST
|
|
63
|
-
const threhold = log.isVerbose() ?
|
|
63
|
+
const threhold = log.isVerbose() ? 0 : 50
|
|
64
64
|
log.show(logTag, `Input:`, strArgs)
|
|
65
65
|
log.show(logTag, `fromEnc:`, JSON.stringify(fromEnc))
|
|
66
66
|
log.show(logTag, `toEnc:`, JSON.stringify(toEnc))
|
|
@@ -88,19 +88,19 @@ function showResults(r) {
|
|
|
88
88
|
let cr = chardet.analyse(Buffer.from(str))
|
|
89
89
|
cr = cr.filter(ct => ct.confidence >= 70)
|
|
90
90
|
cr?.length > 0 && print('Encoding', cr)
|
|
91
|
-
print('String', Array.from(str))
|
|
92
|
-
print('Unicode', Array.from(str).map(c => c.codePointAt(0).toString(16)))
|
|
93
|
-
const badUnicode = enc.checkBadUnicode(str)
|
|
91
|
+
// print('String', Array.from(str))
|
|
92
|
+
// print('Unicode', Array.from(str).map(c => c.codePointAt(0).toString(16)))
|
|
93
|
+
const badUnicode = enc.checkBadUnicode(str, true)
|
|
94
94
|
badUnicode?.length > 0 && log.show('badUnicode:', badUnicode)
|
|
95
|
-
log.info(`MESSY_UNICODE=${enc.REGEX_MESSY_UNICODE.test(str)}`,
|
|
96
|
-
|
|
97
|
-
log.info(`OnlyJapanese=${unicode.strOnlyJapanese(str)}`,
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
)
|
|
101
|
-
log.info(`HasHangul=${unicode.strHasHangul(str)}`,
|
|
102
|
-
|
|
103
|
-
log.info(`HasChinese=${unicode.strHasChinese(str)}`,
|
|
104
|
-
|
|
105
|
-
|
|
95
|
+
// log.info(`MESSY_UNICODE=${enc.REGEX_MESSY_UNICODE.test(str)}`,
|
|
96
|
+
// `MESSY_CJK=${enc.REGEX_MESSY_CJK.test(str)}`)
|
|
97
|
+
// log.info(`OnlyJapanese=${unicode.strOnlyJapanese(str)}`,
|
|
98
|
+
// `OnlyJpHan=${unicode.strOnlyJapaneseHan(str)}`,
|
|
99
|
+
// `HasHiraKana=${unicode.strHasHiraKana(str)}`
|
|
100
|
+
// )
|
|
101
|
+
// log.info(`HasHangul=${unicode.strHasHangul(str)}`,
|
|
102
|
+
// `OnlyHangul=${unicode.strOnlyHangul(str)}`)
|
|
103
|
+
// log.info(`HasChinese=${unicode.strHasChinese(str)}`,
|
|
104
|
+
// `OnlyChinese=${unicode.strOnlyChinese(str)}`,
|
|
105
|
+
// `OnlyChn3500=${enc.RE_CHARS_MOST_USED.test(str)}`)
|
|
106
106
|
}
|