Skip to content

Commit

Permalink
feat: check Media Overlays total duration consistency
Browse files Browse the repository at this point in the history
EPUB 3.3 now recommends that the total MO duration equals the sum of
individual MO durations.

This commit:
- implements this check by inspecting metadata in the OPF
checker, using the `SmilClock` class to sum the durations.
- tweak existing tests to make their declared total duration matching
the individual durations

Fix #1217
  • Loading branch information
rdeltour committed Jan 24, 2022
1 parent bf9bce1 commit ee9c720
Show file tree
Hide file tree
Showing 9 changed files with 80 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@ private void initialize()
severities.put(MessageId.MED_013, Severity.ERROR);
severities.put(MessageId.MED_014, Severity.ERROR);
severities.put(MessageId.MED_015, Severity.USAGE);
severities.put(MessageId.MED_016, Severity.WARNING);

// NAV
severities.put(MessageId.NAV_001, Severity.ERROR);
Expand Down
1 change: 1 addition & 0 deletions src/main/java/com/adobe/epubcheck/messages/MessageId.java
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@ public enum MessageId implements Comparable<MessageId>
MED_013("MED_013"),
MED_014("MED_014"),
MED_015("MED_015"),
MED_016("MED_016"),

// Epub3 based table of content errors
NAV_001("NAV-001"),
Expand Down
9 changes: 9 additions & 0 deletions src/main/java/com/adobe/epubcheck/opf/MetadataSet.java
Original file line number Diff line number Diff line change
Expand Up @@ -353,6 +353,15 @@ public Set<Metadata> getRefiners()
{
return refiners;
}

/**
* Whether this is a primary metadata expression (as opposed to a refining
* expression)
* @return <code>true</code> if and only if this is a primary metadata expression
*/
public boolean isPrimary() {
return !refines.isPresent();
}

@Override
public String toString()
Expand Down
33 changes: 33 additions & 0 deletions src/main/java/com/adobe/epubcheck/opf/OPFChecker30.java
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,12 @@
import com.adobe.epubcheck.opf.MetadataSet.Metadata;
import com.adobe.epubcheck.opf.ResourceCollection.Roles;
import com.adobe.epubcheck.overlay.OverlayTextChecker;
import com.adobe.epubcheck.overlay.SmilClock;
import com.adobe.epubcheck.util.EPUBVersion;
import com.adobe.epubcheck.util.FeatureEnum;
import com.adobe.epubcheck.util.PathUtil;
import com.adobe.epubcheck.vocab.DCMESVocab;
import com.adobe.epubcheck.vocab.MediaOverlaysVocab;
import com.adobe.epubcheck.vocab.PackageVocabs;
import com.google.common.base.Optional;
import com.google.common.base.Predicate;
Expand Down Expand Up @@ -77,6 +79,7 @@ protected boolean checkContent()
super.checkContent();
checkLinkedResources();
checkCollections();
checkMediaOverlaysDuration();
return true;
}

Expand Down Expand Up @@ -408,6 +411,36 @@ private void checkLinkedResources()
}
}
}

// Checks that the total MO duration equals the sum of durations
private void checkMediaOverlaysDuration() {
MetadataSet metadata = ((OPFHandler30) opfHandler).getMetadata();
// search total durations metadata expressions
Set<Metadata> totalDurationExpressions = metadata.getPrimary(MediaOverlaysVocab.VOCAB.get(MediaOverlaysVocab.PROPERTIES.DURATION));
if (!totalDurationExpressions.isEmpty()) {
try
{
// the total duration is the first primary duration found
SmilClock totalDuration = new SmilClock(totalDurationExpressions.iterator().next().getValue());
// sum all the individual durations (non-primary metadata expressions)
SmilClock sumDuration = new SmilClock();
Set<Metadata> allDurations = metadata.getAny(MediaOverlaysVocab.VOCAB.get(MediaOverlaysVocab.PROPERTIES.DURATION));
for (Metadata durationExpression : allDurations)
{
if (!durationExpression.isPrimary()) {
sumDuration = sumDuration.addTime(new SmilClock(durationExpression.getValue()));
}
}
// report if the sum and total don't match
if (!totalDuration.equals(sumDuration)) {
report.message(MessageId.MED_016, EPUBLocation.create(path));
}
} catch (NumberFormatException e)
{
return; // Abort sum check. Invalid values are reported by the schema.
}
}
}

private void checkPagination()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@ MED_012=The "media-overlay" attribute does not match the ID of the Media Overlay
MED_013=Media Overlay Document referenced from the "media-overlay" attribute does not contain a reference to this Content Document.
MED_014=A non-empty fragment identifier is required.
MED_015=Media overlay text references must be in reading order. Text target "%1$s" is before the previous link target in %2$s order.
MED_016=Media Overlays total duration should be the sum of the durations of all Media Overlays documents.

#NAV EPUB v3 Table of contents
NAV_001=The nav file is not supported for EPUB v2.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,17 @@
<dc:identifier id="uid">NOID</dc:identifier>
<meta property="dcterms:modified">2019-01-01T12:00:00Z</meta>
<meta property="media:duration">10min</meta>
<!--<meta refines="#media001" property="media:duration">10min</meta>-->
<meta refines="#media001" property="media:duration">10min</meta>
<!-- <meta refines="#media002" property="media:duration">10min</meta>-->
</metadata>
<manifest>
<item id="t001" href="contents.xhtml" properties="nav" media-type="application/xhtml+xml" media-overlay="media001"/>
<item id="media001" href="media001.smil" media-type="application/smil+xml" />
<item id="t001" href="nav.xhtml" properties="nav" media-type="application/xhtml+xml" media-overlay="media001"/>
<item id="t002" href="contents.xhtml" media-type="application/xhtml+xml" media-overlay="media002"/>
<item id="media001" href="media001.smil" media-type="application/smil+xml"/>
<item id="media002" href="media002.smil" media-type="application/smil+xml" />
</manifest>
<spine>
<itemref idref="t001"/>
<itemref idref="t002"/>
</spine>
</package>
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<package xmlns="http://www.idpf.org/2007/opf" version="3.0" unique-identifier="uid"
xmlns:dc="http://purl.org/dc/elements/1.1/">
<metadata>
<dc:title>Title</dc:title>
<dc:language>en</dc:language>
<dc:identifier id="uid">NOID</dc:identifier>
<meta property="dcterms:modified">2019-01-01T12:00:00Z</meta>
<!-- Media Overlays Duration Properties -->
<meta property="media:duration">10min</meta>
<meta refines="#mo001" property="media:duration">5min</meta>
<meta refines="#mo002" property="media:duration">0:05:00.200</meta>
</metadata>
<manifest>
<item id="t001" href="contents.xhtml" properties="nav" media-type="application/xhtml+xml"/>
<item id="mo001" href="mediaoverlay_001.smil" media-type="application/smil+xml"/>
<item id="mo002" href="mediaoverlay_002.smil" media-type="application/smil+xml"/>
</manifest>
<spine>
<itemref idref="t001"/>
</spine>
</package>
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<dc:identifier id="uid">NOID</dc:identifier>
<meta property="dcterms:modified">2019-01-01T12:00:00Z</meta>
<meta property="media:duration">0:32:00</meta>
<meta refines="#media001" property="media:duration">12min</meta>
<meta refines="#media001" property="media:duration">32min</meta>
</metadata>
<manifest>
<item id="t001" href="contents.xhtml" properties="nav" media-type="application/xhtml+xml" media-overlay="media001"/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,11 @@ Feature: EPUB 3 ▸ Media Overlays ▸ Package Document Checks
Then error RSC-005 is reported
And the message contains "item media:duration meta element not set"
And no other errors or warnings are reported


Scenario: the total duration should be the sum of all Media Overlay durations
When checking file 'mediaoverlays-duration-total-not-sum-warning.opf'
Then warning MED-016 is reported
And no other errors or warnings are reported


# C. Media Overlays Metadata Vocabulary
Expand Down

0 comments on commit ee9c720

Please sign in to comment.