Skip to content

Commit

Permalink
Add batch dump support
Browse files Browse the repository at this point in the history
  • Loading branch information
the1812 committed Aug 5, 2023
1 parent 808f8c3 commit b0387bb
Show file tree
Hide file tree
Showing 7 changed files with 272 additions and 185 deletions.
73 changes: 61 additions & 12 deletions src/cli/batch.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { readdirSync } from 'fs'
import { join } from 'path'
import type { Options as OraOptions, Ora } from 'ora'
import { log } from '../core/debug'
import { getDefaultAlbumName } from './default-album-name'
import { cliOptions, metadataConfig } from './options'
Expand All @@ -16,26 +17,34 @@ const readFolder = (folder: string, depth: number): { name: string; path: string
}
return currentSubFolders.flatMap(subFolder => readFolder(join(folder, subFolder.name), depth - 1))
}
export const runBatchTagger = async (folder: string, depth: number) => {

const createBatchRun = async (config: {
folder: string
depth: number
oraOptions: OraOptions
onProcess: (context: {
currentAlbum: string
workingDir: string
spinner: Ora
index: number
}) => Promise<void>
}) => {
const { folder, depth, oraOptions, onProcess } = config
const albums = readFolder(folder, depth)
const albumCount = albums.length
const { CliTagger } = await import('./tagger')
const { default: ora } = await import('ora')
for (let index = 0; index < albumCount; index++) {
try {
const album = getDefaultAlbumName(albums[index].name)
const spinner = ora({
text: '搜索中',
spinner: {
interval: 500,
frames: ['. ', '.. ', '...'],
},
}).start()
const spinner = ora(oraOptions).start()
spinner.prefixText = `[${album}] (${index + 1}/${albumCount})`
log(`start processing album #${index + 1}`)
const tagger = new CliTagger(cliOptions, metadataConfig, spinner)
tagger.workingDir = albums[index].path
await tagger.run(album)
await onProcess({
currentAlbum: album,
workingDir: albums[index].path,
spinner,
index,
})
log(`processed album #${index + 1}`)
} catch (error) {
log('batch error:', error.message)
Expand All @@ -44,3 +53,43 @@ export const runBatchTagger = async (folder: string, depth: number) => {
}
process.exit()
}

export const runBatchTagger = async (folder: string, depth: number) => {
const { CliTagger } = await import('./tagger')
await createBatchRun({
folder,
depth,
oraOptions: {
text: '搜索中',
spinner: {
interval: 500,
frames: ['. ', '.. ', '...'],
},
},
onProcess: async ({ currentAlbum, workingDir, spinner }) => {
const tagger = new CliTagger(cliOptions, metadataConfig, spinner)
tagger.workingDir = workingDir
await tagger.run(currentAlbum)
},
})
}
export const runBatchDump = async (folder: string, depth: number) => {
const { CliDumper } = await import('./dumper')
await createBatchRun({
folder,
depth,
oraOptions: {
text: '提取中',
spinner: {
interval: 500,
frames: ['. ', '.. ', '...'],
},
},
onProcess: async ({ workingDir, spinner }) => {
const tagger = new CliDumper(cliOptions)
tagger.workingDir = workingDir
await tagger.run()
spinner.stop()
},
})
}
6 changes: 6 additions & 0 deletions src/cli/command-base.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import type { CliOptions } from './options'

export abstract class CliCommandBase {
workingDir = '.'
constructor(public cliOptions: CliOptions) {}
}
82 changes: 0 additions & 82 deletions src/cli/dump.ts

This file was deleted.

93 changes: 93 additions & 0 deletions src/cli/dumper.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import { Metadata } from '../core'
import { log } from '../core/debug'
import { simplifyMetadataInfo } from '../core/metadata/normalize/normalize'
import { CliCommandBase } from './command-base'
import { CliOptions, metadataConfig } from './options'

const handleBufferStringify = (key: string, value: any) => {
const isBuffer = typeof value === 'object' && value !== null && value.type === 'Buffer'
if (isBuffer) {
return `<Buffer length=${value.data?.length ?? 0}>`
}
return value
}
const dumpCover = async (metadatas: Metadata[]) => {
const { writeFileSync } = await import('fs')
const { resolve } = await import('path')
const metadata = metadatas.find(m => m.coverImage)
if (!metadata) {
return
}
const { default: imageType } = await import('image-type')
const type = imageType(metadata.coverImage)
if (!type) {
return
}
const coverFilename = resolve(process.cwd(), `cover.${type.ext}`)
log('cover file', coverFilename)
writeFileSync(coverFilename, metadata.coverImage)
}

export class CliDumper extends CliCommandBase {
constructor(cliOptions: CliOptions) {
super(cliOptions)
}

async run() {
const { glob } = await import('glob')
const { extname, resolve } = await import('path')
const { writeFileSync, readFileSync } = await import('fs')
const { readerMappings } = await import('../core/reader/reader-mappings')
const globTypes = Object.keys(readerMappings)
.map(readerType => readerType.replace(/^\./, ''))
.join('|')
const files = (
await glob(`./**/*.@(${globTypes})`, { posix: true, cwd: this.workingDir })
).sort()
log({ globTypes })
log(files)
if (files.length === 0) {
console.log('没有找到能够提取的音乐文件')
return
}
const results: { metadata: Metadata; rawTag: any }[] = await Promise.all(
files.map(async file => {
const type = extname(file)
const reader = readerMappings[type]
reader.config = metadataConfig
const buffer = readFileSync(resolve(this.workingDir, file))
const rawTag = await reader.readRaw(buffer)
const metadata = await reader.read(rawTag)
return {
rawTag,
metadata,
}
}),
)

const metadatas = results.map(it => it.metadata)
const rawTags = results.map(it => it.rawTag)
await simplifyMetadataInfo({
metadatas,
})
writeFileSync(
resolve(this.workingDir, 'metadata.json'),
JSON.stringify(
metadatas.map(({ coverImage, ...restParts }) => {
return restParts
}),
undefined,
2,
),
)
if (this.cliOptions.debug) {
writeFileSync(
resolve(this.workingDir, 'metadata.debug.json'),
JSON.stringify(rawTags, handleBufferStringify, 2),
)
}
if (this.cliOptions.cover) {
await dumpCover(metadatas)
}
}
}
Loading

0 comments on commit b0387bb

Please sign in to comment.