-
Notifications
You must be signed in to change notification settings - Fork 11
Initial support for OPDS Progression #91
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
|
In the current examples, a fragment like
Suggestion: We could disambiguate by allowing fragments to optionally include the resource HREF as a prefix:
The resource HREF would match exactly what appears in the publication's reading order and must be a valid URL. Both forms could coexist in the same fragments array: "fragments": ["#t=849.250", "chapter3.mp3#t=32.250"]Additional considerations:
|
|
Thank you for your comment @mickael-menu, I think that this is one of the key discussion point for this draft PR. First of all, it's important to point out that we want to cover a wide range of publication formats:
For standalone formats, using a fragment on its own makes perfect sense and we need to make sure that we can support this use case. As we can see, there's a strong case to support standalone fragments, but we might want to identify which ones. For packaged publications and Web publications, one could argue that a URL or URL reference to one of its resource could also be considered a fragment. That's why I like your proposal of supporting references to these resources in Going back to your additional considerations:
I think so and I would extend this to full URLs in the case on Web Publications, not just a path into a container. I don't think that this needs to be renamed to Let's go back to the EPUB with Media Overlays example from the draft, this could be updated to: {
"modified": "2026-01-28T00:24:00Z",
"device": {
"id": "urn:uuid:019c0047-cc8d-7ec4-a3c3-938ccadc020a",
"name": "Ebook Reader (Pixel 10 Pro)"
},
"progression": 0.0174920,
"fragments": ["#t=40.274", "chapter1.html#par36&t=12.482"]
}Compared to the previous example:
Now let's use another example with an Audiobook available only as a RWPM: https://readium.org/webpub-manifest/examples/Flatland/manifest.json A Progression Document could look something like this for this example: {
"modified": "2026-01-28T00:24:00Z",
"device": {
"id": "urn:uuid:019c0047-cc8d-7ec4-a3c3-938ccadc089b",
"name": "Audio Player"
},
"progression": 0.027492,
"fragments": ["#t=1390", "http://www.archive.org/download/flatland_rg_librivox/flatland_2_abbott.mp3#t=21"]
}
That's always a risk, even without references to specific resources or URLs. We'll need processing rules for this, but as a rule of thumb we should go from the most specific one to the least specific one. It's also important to note, that what you can use may be contextual as well. For example, if I'm listening to an EPUB Media Overlay without displaying any text on screen, it's possible to a reading system might only be able to calculate a temporal dimension media fragment. Finally, it's also good to think of these fragments as a fallback chain. If I can't resolve the temporal dimension in an EPUB Media Overlay, I might still be capable of resolving an HTML ID. And if I can't, I might be able to resolve the |
Also replaced fragments with references
|
Updates so far:
|
|
Hello 👋 Thank you for your work pushing the OPDS progression spec forward! I have a little client application which implements the OPDS v2.0 draft, along with a progression implementation based off of this discussion. I had a quick question around I hope that makes sense! Thanks again for your work on this, excited to see OPDS evolve further. |
|
Hello @aaronleopold and thank you for your feeback! If you're targeting pre-paginated formats (PDF, CBZ and EPUB FXL) the good news is that they're much easier to handle than the other ones. I've included I'd like to keep
I'm surprised to learn that at least two clients have implemented what @mickael-menu documented in this issue as a private implementation, but the good news is that it should be fairly straightforward to move to the standardized way of handling progression. |
While I am slightly worried about potential floating-point issues going that route, I think this makes sense and likely will be fine. Thank you for clarifying! |
|
@aaronleopold for CBZ and EPUB you can also provide a path to the resource using Let's take a publication with 100 pages in CBZ and we're currently at page 10: {
"modified": "2025-12-25T12:00:00Z",
"device": {
"id": "urn:uuid:019c0049-6e8c-745c-adb1-5b03f8ad50c4",
"name": "Comic Reader"
},
"progression": 0.1,
"references": ["page10.jxl"]
}This is very much optional but can be useful to further disambiguate. |
|
I think in order for cross-client use of a floating-point number for progression, a recommendation should be provided on the math to be used for turning a floating progression into a page number - specifically, what rounding you use: 5000 / 10001 = 0.49995000499950004
0.49995000499950004 * 10001 = 5000
0.4999 * 10001 = 4999.4999 # If the decimals were truncated by a system for storageThere are many better examples of unlucky large floating point numbers that people happen to land on for novels, audiobooks, comics, that beg the question of whether it's the next page or the previous page you want to land on. |
|
I'd like to keep this sort of recommendations outside of the main draft/spec ideally. While there is clearly a risk with rounding errors on floating point numbers, I think that calculating progression for EPUB reflowable will require even more recommendations (see w3c/epub-specs#2892 (comment)). Rounding errors won't be as much of an issue with timestamps or even reflowable EPUB, since we don't need to round them to an integer in the same way. An error resulting in a few hundred milliseconds shift wouldn't impact the experience much. This is very much a draft at this stage, in addition to the use of a path in I'm reluctant to use Here's what the PDF spec says: |
|
I agree that Reintroducing |
|
I've re-added the reference to the PDF spec for I've also used this opportunity to add new examples for pre-paginated/FXL EPUB and CBZ. The draft is still missing better error handling:
Once I'm done with that, I will remove the draft status from this PR. I've mostly received private feedback for now, but mostly positive and from implementers that would use it for many different formats (comics, audiobooks, EPUB or even sync across various formats). |
Goal
Synchronizing progression using OPDS has been by far the most requested features over the last few years.
Wth this PR the goal is to provide a standardized solution that could work across many types of publications.
The document itself is fairly barebones and will be fleshed out once there's a general agreement on what it contains. The current approach is based on the minimum information required to make this work.
Links
Syntax
Looking at the required property, this currently means:
modified)device)progression)The timestamp is self-explanatory.
For the device, I went for two required values:
idmeant to uniquely identify a device (useful for clients/servers potentially) based on a URInamemeant to be displayed to the user using a stringIf I finished reading chapter 1 on device A, next time that my progression is synchronized on device B, it should tell the user that the progression has changed and mention that this information is coming from device A. That's what this information is for.
A client could also recognize itself using the
idand skip all of this.For the progression itself, a total progression in the publication in percentage (number between 0 and 1 in JSON) feels like the most universal thing.
How we calculate progression is a different story, one that could be handled through best practices as we flesh out the document further.
In addition, I've also added support for
referenceswhich open the door to media-specific fragments suche aspagefor PDF. A list of well-known fragments has also been included.I initially started working on this based on Readium Locators, but kept simplifying things until
progression(totalProgressionin Readium Locators) andreferenceswere the only two things left.Examples
Example 3: Progression in an EPUB
{ "modified": "2026-01-27T11:00:00Z", "device": { "id": "urn:uuid:019c0047-cc8d-7ec4-a3c3-938ccadc020a", "name": "Ebook Reader (Pixel 10 Pro)" }, "progression": 0.0174920 }Example 4: Progression in an EPUB with Media Overlays
{ "modified": "2026-01-28T00:24:00Z", "device": { "id": "urn:uuid:019c0047-cc8d-7ec4-a3c3-938ccadc020a", "name": "Ebook Reader (Pixel 10 Pro)" }, "progression": 0.0174920, "references": ["#t=40.274", "chapter1.html#par36"] }Example 5: Progression in a PDF using a Web Reader
{ "modified": "2026-01-28T19:00:00Z", "device": { "id": "https://reader.example.com", "name": "Web Reader" }, "progression": 0.048204 }Example 6: Progression in an audiobook
{ "modified": "2025-12-25T12:00:00Z", "device": { "id": "urn:uuid:019c0049-6e8c-745c-adb1-5b03f8ad50c4", "name": "Audiobook Player (Sonos Era 300)" }, "progression": 0.72370325, "references": ["#t=849.250"] }