diff --git a/packages/metadata_attacher/src/fixtures/video_mediainfo_single_track.xml b/packages/metadata_attacher/src/fixtures/video_mediainfo_single_track.xml new file mode 100644 index 00000000..4156aa51 --- /dev/null +++ b/packages/metadata_attacher/src/fixtures/video_mediainfo_single_track.xml @@ -0,0 +1,77 @@ + + + + + + + +UUID +4a64ba7c-ceac-4547-ac13-c487b2711d5a + +test_video_upload-4a64ba7c-ceac-4547-ac13-c487b2711d5a + + + + + + + + + + +UUID +b3c97850-9697-451a-8ad5-9f085188e890 + + +0 + +sha256 +abc123def456789 + +5242880 + + +MPEG-4 Media File +2 + + +PRONOM +fmt/199 + + + +2024-05-20T08:45:00Z + + + +MediaInfoLib + + +300 +1 +General +General +0 +MPEG-4 +MPEG-4 +video/mp4 +5242880 +120.5 +2024-05-20 08:45:00 UTC + + + + + +video/mp4 + + + + +%transferDirectory%objects/4a64ba7c-ceac-4547-ac13-c487b2711d5a + + + + + + diff --git a/packages/metadata_attacher/src/index.test.ts b/packages/metadata_attacher/src/index.test.ts index fec2bc97..3db80e41 100644 --- a/packages/metadata_attacher/src/index.test.ts +++ b/packages/metadata_attacher/src/index.test.ts @@ -851,6 +851,68 @@ describe("handler", () => { expect(recordMetadata?.altText).toEqual(null); }); + test("should extract timestamp from video with a single MediaInfo track object", async () => { + const metsContent = await loadMetsFile("video_mediainfo_single_track.xml"); + mockS3Send.mockResolvedValue({ + Body: { + transformToString: jest.fn().mockResolvedValue(metsContent), + }, + }); + + const event = { + Records: [ + { + messageId: "1", + receiptHandle: "1", + body: JSON.stringify({ + Message: JSON.stringify({ + Records: [ + { + s3: { + bucket: { + name: "test-bucket", + }, + object: { + key: "access_copies/53f9/8c3d/a29e/4fbf/8a4a/4fd9/991e/313d/1_upload-4a64ba7c-ceac-4547-ac13-c487b2711d5a/METS.4a64ba7c-ceac-4547-ac13-c487b2711d5a.xml", + }, + }, + }, + ], + }), + }), + attributes: { + ApproximateReceiveCount: "1", + SentTimestamp: "1", + SenderId: "1", + ApproximateFirstReceiveTimestamp: "1", + }, + messageAttributes: {}, + md5OfBody: "1", + eventSource: "1", + eventSourceARN: "1", + awsRegion: "1", + }, + ], + }; + + await handler(event, mock(), jest.fn()); + + expect(mockS3Send).toHaveBeenCalledTimes(1); + + const recordMetadata = await getRecordMetadata("1"); + expect(recordMetadata).toBeDefined(); + expect(recordMetadata?.derivedTimestamp).toEqual( + new Date("2024-05-20T08:45:00.000Z"), + ); + expect(recordMetadata?.originalFileCreationTime).toEqual( + "2024-05-20T08:45:00Z", + ); + expect(recordMetadata?.displayName).toEqual("test_file.jpg"); + expect(recordMetadata?.description).toEqual(null); + expect(recordMetadata?.tags.length).toEqual(0); + expect(recordMetadata?.altText).toEqual(null); + }); + test("should handle video with no timestamp metadata", async () => { const metsContent = await loadMetsFile("video_no_timestamp.xml"); mockS3Send.mockResolvedValue({ diff --git a/packages/metadata_attacher/src/index.ts b/packages/metadata_attacher/src/index.ts index 109a74a0..22e32021 100644 --- a/packages/metadata_attacher/src/index.ts +++ b/packages/metadata_attacher/src/index.ts @@ -157,10 +157,13 @@ const getVideoMetadataFromMediaInfo = ( creationTimeInEdtf: string | undefined; } | undefined => { - const tracks = embeddedMetadata.MediaInfo?.media.track; - if (tracks === undefined) { + const tracksFromMediaInfo = embeddedMetadata.MediaInfo?.media.track; + if (tracksFromMediaInfo === undefined) { return undefined; } + const tracks = Array.isArray(tracksFromMediaInfo) + ? tracksFromMediaInfo + : [tracksFromMediaInfo]; const generalTracks = tracks.filter( (track: TrackMetadata) => track.StreamKind === "General", diff --git a/packages/metadata_attacher/src/models.ts b/packages/metadata_attacher/src/models.ts index 5446e702..516f7717 100644 --- a/packages/metadata_attacher/src/models.ts +++ b/packages/metadata_attacher/src/models.ts @@ -55,7 +55,7 @@ export interface EmbeddedMetadata { MediaInfo: | { media: { - track: TrackMetadata[]; + track: TrackMetadata[] | TrackMetadata; }; } | undefined; diff --git a/packages/metadata_attacher/src/validators.ts b/packages/metadata_attacher/src/validators.ts index 2ecc0996..01aaec1e 100644 --- a/packages/metadata_attacher/src/validators.ts +++ b/packages/metadata_attacher/src/validators.ts @@ -35,7 +35,9 @@ const embeddedMetadataSchema = Joi.object({ .unknown(true), MediaInfo: Joi.object({ media: Joi.object({ - track: Joi.array().items(trackMetadataSchema).required(), + track: Joi.alternatives() + .try(Joi.array().items(trackMetadataSchema), trackMetadataSchema) + .required(), }) .required() .unknown(true),