Skip to content

[Bug] Streaming publication using LCPL file #618

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

Closed
KaramYaaqba opened this issue Feb 18, 2025 · 12 comments
Closed

[Bug] Streaming publication using LCPL file #618

KaramYaaqba opened this issue Feb 18, 2025 · 12 comments
Labels
bug Something isn't working

Comments

@KaramYaaqba
Copy link

Describe the bug

I am trying to implement streaming for books and audiobooks using the Readium 3.0 toolkit, following the instructions in the documentation (https://github.com/readium/kotlin-toolkit/blob/develop/docs/guides/lcp.md) under the "Streaming an LCP protected package" section. However, I am getting a "Format Not Supported" error, which does not occur when I load the book from the LCPL file instead of streaming:

org.readium.r2.streamer.PublicationOpener$OpenError$FormatNotSupported@c128feb

Here is the code snippet I am using:

`
suspend fun importPublicationFromStorage(uri: Uri) {
// Instantiate the required components.
val context = app.applicationContext.applicationContext
val httpClient = DefaultHttpClient()
val assetRetriever = AssetRetriever(
contentResolver = context.contentResolver,
httpClient = httpClient
)
val publicationOpener = PublicationOpener(
publicationParser = DefaultPublicationParser(
context,
httpClient = httpClient,
assetRetriever = assetRetriever,
pdfFactory = PdfiumDocumentFactory(context)
)
)
val asset =
assetRetriever.retrieve(uri.toAbsoluteUrl()!!).getOrElse {
null
}

    // Open a `Publication` from the `Asset` which is LCPL file in this case.
    val publication = publicationOpener.open(asset!!, allowUserInteraction = true)
        .getOrElse {
            print("error" + it)
                    }

    print("Opened ${publication}")
}

`

How to reproduce?

1- Load the LCPL file using the provided code.
2- An exception will occur when you do so.

Readium version

3.0

Android API version

35

Additional context

No response

@KaramYaaqba KaramYaaqba added bug Something isn't working triage Triage needed by maintainers labels Feb 18, 2025
@qnga
Copy link
Member

qnga commented Feb 18, 2025

Please try to reproduce this on the testapp (I can't do it). I can help you enable LCP support on Slack if you need it.

@qnga
Copy link
Member

qnga commented Feb 18, 2025

Note that you don't pass aLcpContentProtection to the PublicationOpener, which is likely to result in a FormatNotSupported error, but that should happen when you open a downloaded book too.

NB: I agree that the documentation is a bit misleading, we'll fix it.

@KaramYaaqba
Copy link
Author

KaramYaaqba commented Feb 19, 2025

@qnga I need your help to enable LCP streaming, what is the best way to connect with you on Slack?

@qnga
Copy link
Member

qnga commented Feb 19, 2025

I sent to you instructions on the Readium Slack, as you seem to have access to it.

@hishampro5
Copy link

@qnga we are encounter same issue.
We are confused about the error FormatNotSupported why and how can fix it.

@hishampro5
Copy link

@KaramYaaqba did you get why this error occur

@KaramYaaqba
Copy link
Author

@hishampro5, the first issue in my case is that our backend server does not support the HEAD method. We are fixing it, but until then, we cannot stream publications.

@mickael-menu
Copy link
Member

mickael-menu commented Feb 26, 2025

Also don't forget to pass the LCP content protection when initializing the PublicationOpener, otherwise you might get this error as LCP files won't be recognized.

See the documentation for that: https://github.com/readium/kotlin-toolkit/blob/3.0.3/docs/guides/lcp.md#initializing-the-publicationopener

@qnga
Copy link
Member

qnga commented Mar 28, 2025

Any update on this?

@hishampro5
Copy link

hishampro5 commented Apr 22, 2025

i did same as doc but i get error => An error occurred while attempting to decode the content

on fun **doOpen()**
// Instantiate the required components.
val httpClient = DefaultHttpClient()
val assetRetriever = AssetRetriever(
  contentResolver = activity.contentResolver,
  httpClient = httpClient
)
val publicationOpener = PublicationOpener(
  publicationParser = DefaultPublicationParser(
   activity,
   httpClient = httpClient,
   assetRetriever = assetRetriever,
   null
  )
)

val url = File("/storage/emulated/0/Download/hisham-488150.lcpl").toUrl()
//		val url = File("/storage/emulated/0/Download/Steremingbook.lcpl").toUrl()
//		val url = File("/storage/emulated/0/Download/Steremingbook.lcpl").toUrl()
//		val url = File("/data/user/0/com.samawy.readerapp/files/encryptedFile.lcpl").toUrl()
//		val file = File(activity.filesDir, "encryptedFile.lcpl")
//		val url = file.toUrl()

		// get assetFile from url
		val asset = readium.assetRetriever.retrieve(
			url,
			book.mediaType
		).getOrElse {
			return Try.failure(
				OpeningError.PublicationError(
					com.samawy.readerapp.readium.testapp.domain.PublicationError(it)
				)
			)
		}

		val publication = publicationOpener.open(
			asset,
			allowUserInteraction = true,
			credentials = credentials
		).getOrElse {
			return Try.failure(
				OpeningError.PublicationError(
					com.samawy.readerapp.readium.testapp.domain.PublicationError(it)
				)
			)
		}

		// The publication is protected with a DRM and not unlocked.
		if (publication.isRestricted) {
			return Try.failure(
				OpeningError.RestrictedPublication(
					publication.protectionError
						?: DebugError("Publication is restricted.")
				)
			)
		}

		val initialLocator = book.progression
			?.let { Locator.fromJSON(JSONObject(it)) }

		val readerInitData = when {
			publication.conformsTo(Publication.Profile.AUDIOBOOK) ->
				openAudio(bookId, publication, initialLocator)

			publication.conformsTo(Publication.Profile.EPUB) || publication.readingOrder.allAreHtml ->
				openEpub(bookId, publication, initialLocator)

			publication.conformsTo(Publication.Profile.PDF) ->
				openPdf(bookId, publication, initialLocator)

			publication.conformsTo(Publication.Profile.DIVINA) ->
				openImage(bookId, publication, initialLocator)

			else ->
				Try.failure(
					OpeningError.CannotRender(
						DebugError("No navigator supports this publication.")
					)
				)
		}

		return readerInitData.map { it ->
			repository[bookId] = it

//			if (it is MediaReaderInitData) {
//				mediaServiceFacade.openSession(bookId, it.mediaNavigator)
//			}
		}

@qnga
Copy link
Member

qnga commented Apr 22, 2025

Once again, doc is misleading. You can't hope for that to work if you don't pass a ContentProtection to your PublicationOpener.

@mickael-menu
Copy link
Member

I fixed the documentation here: #645

But did you read the full LCP guide or just the streaming section? It was explained in details how to initialize the PublicationOpener in the section I shared before:
https://github.com/readium/kotlin-toolkit/blob/develop/docs/guides/lcp.md#initializing-the-publicationopener

@mickael-menu mickael-menu closed this as not planned Won't fix, can't repro, duplicate, stale Apr 22, 2025
@mickael-menu mickael-menu removed the triage Triage needed by maintainers label Apr 22, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

4 participants