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
+
+
+
+
+
+
+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),