feat: real EXIF extraction via adapters-exif crate
- MetadataExtractorPort in domain (bytes → StructuredData) - adapters-exif: NomExifExtractor using nom-exif, handles EXIF + TrackInfo - Worker's MetadataExtractorPlugin delegates to port, no longer knows nom-exif - Filters noisy binary tags (U8Array, Undefined, Unknown)
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
use crate::plugin_registry::InMemoryPluginRegistry;
|
||||
use crate::plugins::{MetadataExtractorPlugin, NoOpPlugin, SidecarSyncPlugin};
|
||||
use domain::ports::SidecarWriterPort;
|
||||
use domain::ports::{MetadataExtractorPort, SidecarWriterPort};
|
||||
use std::sync::Arc;
|
||||
|
||||
use super::Repos;
|
||||
@@ -9,6 +9,7 @@ pub fn build_plugin_registry(
|
||||
repos: &Repos,
|
||||
file_storage: Arc<dyn domain::ports::FileStoragePort>,
|
||||
sidecar_writer: Arc<dyn SidecarWriterPort>,
|
||||
extractor: Arc<dyn MetadataExtractorPort>,
|
||||
) -> InMemoryPluginRegistry {
|
||||
let mut registry = InMemoryPluginRegistry::new();
|
||||
|
||||
@@ -17,6 +18,7 @@ pub fn build_plugin_registry(
|
||||
repos.asset.clone(),
|
||||
file_storage,
|
||||
repos.metadata.clone(),
|
||||
extractor,
|
||||
)));
|
||||
|
||||
let export_handler = Arc::new(application::sidecar::ExportSidecarHandler::new(
|
||||
|
||||
@@ -51,7 +51,14 @@ async fn main() -> anyhow::Result<()> {
|
||||
event_transport::CompositeEventPublisher::new(nats_publisher, event_store),
|
||||
);
|
||||
|
||||
let registry = Arc::new(build_plugin_registry(&repos, file_storage, sidecar_writer));
|
||||
let extractor: Arc<dyn domain::ports::MetadataExtractorPort> =
|
||||
Arc::new(adapters_exif::NomExifExtractor);
|
||||
let registry = Arc::new(build_plugin_registry(
|
||||
&repos,
|
||||
file_storage,
|
||||
sidecar_writer,
|
||||
extractor,
|
||||
));
|
||||
let process_next = Arc::new(build_process_next_handler(
|
||||
&repos,
|
||||
registry,
|
||||
|
||||
@@ -2,7 +2,10 @@ use async_trait::async_trait;
|
||||
use domain::{
|
||||
entities::{AssetMetadata, MetadataSource},
|
||||
errors::DomainError,
|
||||
ports::{AssetMetadataRepository, AssetRepository, FileStoragePort, PluginExecutor},
|
||||
ports::{
|
||||
AssetMetadataRepository, AssetRepository, FileStoragePort, MetadataExtractorPort,
|
||||
PluginExecutor,
|
||||
},
|
||||
value_objects::{MetadataValue, StructuredData, SystemId},
|
||||
};
|
||||
use std::sync::Arc;
|
||||
@@ -12,6 +15,7 @@ pub struct MetadataExtractorPlugin {
|
||||
asset_repo: Arc<dyn AssetRepository>,
|
||||
file_storage: Arc<dyn FileStoragePort>,
|
||||
metadata_repo: Arc<dyn AssetMetadataRepository>,
|
||||
extractor: Arc<dyn MetadataExtractorPort>,
|
||||
}
|
||||
|
||||
impl MetadataExtractorPlugin {
|
||||
@@ -19,11 +23,13 @@ impl MetadataExtractorPlugin {
|
||||
asset_repo: Arc<dyn AssetRepository>,
|
||||
file_storage: Arc<dyn FileStoragePort>,
|
||||
metadata_repo: Arc<dyn AssetMetadataRepository>,
|
||||
extractor: Arc<dyn MetadataExtractorPort>,
|
||||
) -> Self {
|
||||
Self {
|
||||
asset_repo,
|
||||
file_storage,
|
||||
metadata_repo,
|
||||
extractor,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -52,17 +58,16 @@ impl PluginExecutor for MetadataExtractorPlugin {
|
||||
|
||||
let path = &asset.source_reference.relative_path;
|
||||
let data = self.file_storage.read_file(path).await?;
|
||||
let file_size = data.len() as i64;
|
||||
|
||||
let mut extracted = StructuredData::new();
|
||||
extracted.insert("file_size_bytes", MetadataValue::Integer(file_size));
|
||||
let mut extracted = self.extractor.extract(&data)?;
|
||||
extracted.insert("file_size_bytes", MetadataValue::Integer(data.len() as i64));
|
||||
extracted.insert("mime_type", MetadataValue::String(asset.mime_type.clone()));
|
||||
|
||||
let metadata =
|
||||
AssetMetadata::new(asset_id, MetadataSource::ExifExtracted, extracted.clone());
|
||||
self.metadata_repo.save(&metadata).await?;
|
||||
|
||||
info!(asset_id = %asset_id, file_size, "extracted basic metadata");
|
||||
info!(asset_id = %asset_id, tags = extracted.len(), "extracted metadata");
|
||||
Ok(extracted)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user