refactor: streamline logging in image processing and EXIF extraction

- Removed optional logger parameters in several functions, replacing them with global loggers for consistency.
- Updated logging statements to ensure they are always executed, enhancing the visibility of processing steps and errors.
- Cleaned up unused imports and commented-out code to improve code clarity and maintainability.

Signed-off-by: Innei <tukon479@gmail.com>
This commit is contained in:
Innei
2025-06-23 12:43:15 +08:00
parent 90e712373b
commit 0a17c01d5e
9 changed files with 33 additions and 77 deletions

View File

@@ -8,7 +8,7 @@ import { exiftool } from 'exiftool-vendored'
import type { Metadata } from 'sharp'
import sharp from 'sharp'
import type { Logger } from '../logger/index.js'
import { getGlobalLoggers } from '../photo/logger-adapter.js'
import type { PickedExif } from '../types/photo.js'
const baseImageBuffer = sharp({
@@ -26,28 +26,27 @@ const baseImageBuffer = sharp({
export async function extractExifData(
imageBuffer: Buffer,
originalBuffer?: Buffer,
exifLogger?: Logger['exif'],
): Promise<PickedExif | null> {
const log = exifLogger
const log = getGlobalLoggers().exif
try {
log?.info('开始提取 EXIF 数据')
log.info('开始提取 EXIF 数据')
// 首先尝试从处理后的图片中提取 EXIF
let metadata = await sharp(imageBuffer).metadata()
// 如果处理后的图片没有 EXIF 数据,且提供了原始 buffer尝试从原始图片提取
if (!metadata.exif && originalBuffer) {
log?.info('处理后的图片缺少 EXIF 数据,尝试从原始图片提取')
log.info('处理后的图片缺少 EXIF 数据,尝试从原始图片提取')
try {
metadata = await sharp(originalBuffer).metadata()
} catch (error) {
log?.warn('从原始图片提取 EXIF 失败,可能是不支持的格式:', error)
log.warn('从原始图片提取 EXIF 失败,可能是不支持的格式:', error)
}
}
if (!metadata.exif) {
log?.warn('未找到 EXIF 数据')
log.warn('未找到 EXIF 数据')
return null
}
@@ -89,21 +88,11 @@ export async function extractExifData(
const exifData = await exiftool.read(tempImagePath)
const result = handleExifData(exifData, metadata)
// const makerNote = exifReader(exifBuffer).Photo?.MakerNote
// if (makerNote) {
// const recipe = getRecipe(makerNote)
// if (recipe) {
// ;(exifData as any).FujiRecipe = recipe
// log?.info('检测到富士胶片配方信息')
// }
// }
await unlink(tempImagePath).catch(noop)
if (!exifData) {
log?.warn('EXIF 数据解析失败')
log.warn('EXIF 数据解析失败')
return null
}
@@ -112,12 +101,10 @@ export async function extractExifData(
delete exifData.warnings
delete exifData.errors
// const cleanedExifData = cleanExifData(exifData)
log?.success('EXIF 数据提取完成')
log.success('EXIF 数据提取完成')
return result
} catch (error) {
log?.error('提取 EXIF 数据失败:', error)
log.error('提取 EXIF 数据失败:', error)
return null
}
}

View File

@@ -6,6 +6,7 @@ import sharp from 'sharp'
import { HEIC_FORMATS } from '../constants/index.js'
import type { Logger } from '../logger/index.js'
import { getGlobalLoggers } from '../photo/logger-adapter.js'
import type { ImageMetadata } from '../types/photo.js'
// 获取图片元数据(复用 Sharp 实例)
@@ -86,9 +87,8 @@ export async function convertHeicToJpeg(
export async function preprocessImageBuffer(
buffer: Buffer,
key: string,
imageLogger?: Logger['image'],
): Promise<Buffer> {
const log = imageLogger
const log = getGlobalLoggers().image.originalLogger
const ext = path.extname(key).toLowerCase()
// 如果是 HEIC/HEIF 格式,先转换为 JPEG
@@ -135,9 +135,9 @@ export async function convertBmpToJpegSharpInstance(
// 创建 Sharp 实例
// Calculate the number of channels in the BMP image
const channels = bmpImage.data.length / (bmpImage.width * bmpImage.height);
const channels = bmpImage.data.length / (bmpImage.width * bmpImage.height)
if (channels !== 3 && channels !== 4) {
throw new Error(`Unsupported BMP channel count: ${channels}`);
throw new Error(`Unsupported BMP channel count: ${channels}`)
}
// Create Sharp instance with the correct channel count

View File

@@ -19,7 +19,6 @@ export type {
// S3 操作
export { generateBlurhash } from './image/blurhash.js'
export { extractExifData } from './image/exif.js'
export {
getImageMetadataWithSharp,
preprocessImageBuffer,

View File

@@ -63,7 +63,7 @@ export async function saveManifest(items: PhotoManifestItem[]): Promise<void> {
),
)
logger.fs.info(`📁 Manifest 保存至:${manifestPath}`)
logger.fs.info(`📁 Manifest 保存至: ${manifestPath}`)
}
// 检测并处理已删除的图片

View File

@@ -119,11 +119,7 @@ export async function processExifData(
const ext = path.extname(photoKey).toLowerCase()
const originalBuffer = HEIC_FORMATS.has(ext) ? rawImageBuffer : undefined
return await extractExifData(
imageBuffer,
originalBuffer,
loggers.exif.originalLogger,
)
return await extractExifData(imageBuffer, originalBuffer)
}
/**

View File

@@ -57,11 +57,7 @@ export async function preprocessImage(
// 预处理图片(处理 HEIC/HEIF 格式)
let imageBuffer: Buffer
try {
imageBuffer = await preprocessImageBuffer(
rawImageBuffer,
photoKey,
loggers.image.originalLogger,
)
imageBuffer = await preprocessImageBuffer(rawImageBuffer, photoKey)
} catch (error) {
loggers.image.error(`预处理图片失败:${photoKey}`, error)
return null
@@ -182,11 +178,7 @@ export async function executePhotoProcessingPipeline(
)
// 6. 提取照片信息
const photoInfo = extractPhotoInfo(
photoKey,
exifData,
loggers.image.originalLogger,
)
const photoInfo = extractPhotoInfo(photoKey, exifData)
// 7. 处理 Live Photo
const livePhotoResult = processLivePhoto(photoKey, livePhotoMap)

View File

@@ -2,18 +2,6 @@
export type { PhotoProcessorOptions } from './processor.js'
export { processPhoto } from './processor.js'
// 图片处理管道
export type {
PhotoProcessingContext,
ProcessedImageData,
} from './image-pipeline.js'
export {
executePhotoProcessingPipeline,
preprocessImage,
processImageWithSharp,
processPhotoWithPipeline,
} from './image-pipeline.js'
// 缓存管理
export type { CacheableData, ThumbnailResult } from './cache-manager.js'
export {
@@ -27,9 +15,6 @@ export {
export type { LivePhotoResult } from './live-photo-handler.js'
export { createLivePhotoMap, processLivePhoto } from './live-photo-handler.js'
// 信息提取
export { extractPhotoInfo } from './info-extractor.js'
// Logger 适配器
export type { PhotoLogger, PhotoProcessingLoggers } from './logger-adapter.js'
export {

View File

@@ -2,18 +2,17 @@ import path from 'node:path'
import { env } from '@env'
import type { Logger } from '../logger/index.js'
import type { PhotoInfo, PickedExif } from '../types/photo.js'
import { getGlobalLoggers } from './logger-adapter.js'
// 从文件名提取照片信息
export function extractPhotoInfo(
key: string,
exifData?: PickedExif | null,
imageLogger?: Logger['image'],
): PhotoInfo {
const log = imageLogger
const log = getGlobalLoggers().image
log?.debug(`提取照片信息:${key}`)
log.info(`提取照片信息:${key}`)
const fileName = path.basename(key, path.extname(key))
@@ -42,7 +41,7 @@ export function extractPhotoInfo(
.filter((part) => part.trim() !== '')
tags = pathParts.map((part) => part.trim())
log?.debug(`从路径提取标签:[${tags.join(', ')}]`)
log.info(`从路径提取标签:[${tags.join(', ')}]`)
}
}
@@ -54,7 +53,7 @@ export function extractPhotoInfo(
// 如果是 Date 对象,直接使用
if (dateTimeOriginal instanceof Date) {
dateTaken = dateTimeOriginal.toISOString()
log?.debug('使用 EXIF Date 对象作为拍摄时间')
log.info('使用 EXIF Date 对象作为拍摄时间')
} else {
log?.warn(
`未知的 DateTimeOriginal 类型:${typeof dateTimeOriginal}`,
@@ -72,7 +71,7 @@ export function extractPhotoInfo(
const dateMatch = fileName.match(/(\d{4}-\d{2}-\d{2})/)
if (dateMatch) {
dateTaken = new Date(dateMatch[1]).toISOString()
log?.debug(`从文件名提取拍摄时间:${dateMatch[1]}`)
log.info(`从文件名提取拍摄时间:${dateMatch[1]}`)
}
}
@@ -80,7 +79,7 @@ export function extractPhotoInfo(
const viewsMatch = fileName.match(/(\d+)views?/i)
if (viewsMatch) {
views = Number.parseInt(viewsMatch[1])
log?.debug(`从文件名提取浏览次数:${views}`)
log.info(`从文件名提取浏览次数:${views}`)
}
// 从文件名中提取标题(移除日期和浏览次数)
@@ -95,7 +94,7 @@ export function extractPhotoInfo(
title = path.basename(key, path.extname(key))
}
log?.debug(`照片信息提取完成:"${title}"`)
log.info(`照片信息提取完成:"${title}"`)
return {
title,

View File

@@ -4,7 +4,7 @@ import type { _Object } from '@aws-sdk/client-s3'
import { GetObjectCommand, ListObjectsV2Command } from '@aws-sdk/client-s3'
import { SUPPORTED_FORMATS } from '../../constants/index.js'
import type { Logger } from '../../logger/index.js'
import { logger } from '../../logger/index.js'
import { s3Client } from '../../s3/client.js'
import type { S3Config, StorageObject, StorageProvider } from '../interfaces'
@@ -25,11 +25,9 @@ export class S3StorageProvider implements StorageProvider {
this.config = config
}
async getFile(key: string, logger?: Logger['s3']): Promise<Buffer | null> {
const log = logger
async getFile(key: string): Promise<Buffer | null> {
try {
log?.info(`下载文件:${key}`)
logger.s3.info(`下载文件:${key}`)
const startTime = Date.now()
const command = new GetObjectCommand({
@@ -40,7 +38,7 @@ export class S3StorageProvider implements StorageProvider {
const response = await s3Client.send(command)
if (!response.Body) {
log?.error(`S3 响应中没有 Body: ${key}`)
logger.s3.error(`S3 响应中没有 Body: ${key}`)
return null
}
@@ -48,7 +46,7 @@ export class S3StorageProvider implements StorageProvider {
if (response.Body instanceof Buffer) {
const duration = Date.now() - startTime
const sizeKB = Math.round(response.Body.length / 1024)
log?.success(`下载完成:${key} (${sizeKB}KB, ${duration}ms)`)
logger.s3.success(`下载完成:${key} (${sizeKB}KB, ${duration}ms)`)
return response.Body
}
@@ -65,17 +63,17 @@ export class S3StorageProvider implements StorageProvider {
const buffer = Buffer.concat(chunks)
const duration = Date.now() - startTime
const sizeKB = Math.round(buffer.length / 1024)
log?.success(`下载完成:${key} (${sizeKB}KB, ${duration}ms)`)
logger.s3.success(`下载完成:${key} (${sizeKB}KB, ${duration}ms)`)
resolve(buffer)
})
stream.on('error', (error) => {
log?.error(`下载失败:${key}`, error)
logger.s3.error(`下载失败:${key}`, error)
reject(error)
})
})
} catch (error) {
log?.error(`下载失败:${key}`, error)
logger.s3.error(`下载失败:${key}`, error)
return null
}
}