Skip to content
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

On remote subtitle load error player errors out as well #1722

Closed
TheBeastLT opened this issue Sep 11, 2024 · 4 comments
Closed

On remote subtitle load error player errors out as well #1722

TheBeastLT opened this issue Sep 11, 2024 · 4 comments
Assignees
Labels

Comments

@TheBeastLT
Copy link

When a media item defines a remote url subtitles and when loading such a subtitle and error occurs it crashes the whole player, even tho you could argue that subtitles are not the most important part of the video and it could fail silently continuing to play the video, since potentially you could selected some other subtitle which would not fail.
Is this intentional behaviour or maybe there's some way to circumvent this to not crash the player?

@oceanjules
Copy link
Contributor

Hi @TheBeastLT, thanks for reporting the issue! Could you provide the error stack trace and/or media that causes the crash?

@TheBeastLT
Copy link
Author

Playback error
      androidx.media3.exoplayer.ExoPlaybackException: Source error
      at androidx.media3.exoplayer.ExoPlayerImplInternal.handleIoException(ExoPlayerImplInternal.java:736)
      at androidx.media3.exoplayer.ExoPlayerImplInternal.handleMessage(ExoPlayerImplInternal.java:708)
      at android.os.Handler.dispatchMessage(Handler.java:102)
      at android.os.Looper.loop(Looper.java:211)
      at android.os.HandlerThread.run(HandlerThread.java:65)
    Caused by: androidx.media3.datasource.HttpDataSource$InvalidResponseCodeException: Response code: 500
      at androidx.media3.datasource.DefaultHttpDataSource.open(DefaultHttpDataSource.java:397)
      at androidx.media3.datasource.DefaultDataSource.open(DefaultDataSource.java:275)
      at androidx.media3.datasource.StatsDataSource.open(StatsDataSource.java:86)
      at androidx.media3.exoplayer.source.ProgressiveMediaPeriod$ExtractingLoadable.load(ProgressiveMediaPeriod.java:1045)
      at androidx.media3.exoplayer.upstream.Loader$LoadTask.run(Loader.java:421)
      at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
      at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
      at java.lang.Thread.run(Thread.java:764)

This error code is from subtitles url, you can potentially replicate this by adding a subtitle configuration with url pointing to some non-existing file which would result in a 404. Ie:

SubtitleConfiguration.Builder("https://example.com/subtitle.srt".toUri())
                            .setId("my-id")
                            .setMimeType(MimeTypes.APPLICATION_SUBRIP)
                            .setLanguage("en")
                            .setLabel("English")
                            .build()

@oceanjules
Copy link
Contributor

Thanks! I could repro and do a bit of debugging

  • Given that we don't have a loadErrorHandlingPolicy, we rely on DefaultLoadErrorHandlingPolicy

ProgressiveMediaSource.Factory progressiveMediaSourceFactory =
new ProgressiveMediaSource.Factory(dataSourceFactory, extractorsFactory);
if (loadErrorHandlingPolicy != null) {
progressiveMediaSourceFactory.setLoadErrorHandlingPolicy(loadErrorHandlingPolicy);
}
mediaSources[i + 1] =
progressiveMediaSourceFactory.createMediaSource(
MediaItem.fromUri(subtitleConfigurations.get(i).uri.toString()));

  • We end up with loadErrorAction = RETRY

} else /* the load should be retried */ {
int extractedSamplesCount = getExtractedSamplesCount();
boolean madeProgress = extractedSamplesCount > extractedSamplesCountAtStartOfLoad;
loadErrorAction =
configureRetry(loadable, extractedSamplesCount)
? Loader.createRetryAction(/* resetErrorCount= */ madeProgress, retryDelayMs)
: Loader.DONT_RETRY;
}
boolean wasCanceled = !loadErrorAction.isRetry();
mediaSourceEventDispatcher.loadError(

  • Forcefully setting it to DONT_RETRY and cancelling the load results in a timeout. Even though the Loader should handle it gracefully for ACTION_TYPE_DONT_RETRY

case MSG_IO_EXCEPTION:
currentError = (IOException) msg.obj;
errorCount++;
LoadErrorAction action =
callback.onLoadError(loadable, nowMs, durationMs, currentError, errorCount);
if (action.type == ACTION_TYPE_DONT_RETRY_FATAL) {
fatalError = currentError;
} else if (action.type != ACTION_TYPE_DONT_RETRY) {
if (action.type == ACTION_TYPE_RETRY_AND_RESET_ERROR_COUNT) {
errorCount = 1;
}
start(
action.retryDelayMillis != C.TIME_UNSET
? action.retryDelayMillis
: getRetryDelayMillis());
}
break;

Assigning it to @icbaker who might know more on the issue

copybara-service bot pushed a commit that referenced this issue Oct 17, 2024
Use this for sideloaded subtitles, so preparation can still complete
despite an error from e.g. `DataSource.open`. In this case, no subtitle
tracks will be emitted.

Issue: #1722
PiperOrigin-RevId: 686888588
copybara-service bot pushed a commit that referenced this issue Oct 17, 2024
These events are always reported with the primary child period ID,
because this is the same ID used in the parent `MergingMediaSource`'s
Timeline.

This ensures that e.g. loading errors from sideloaded subtitles (which
uses `MergingMediaSource`) are now reported via
`AnalyticsListener.onLoadError`.

It results in non-error events being reported from these children too,
which will result in more `onLoadStarted` and `onLoadCompleted` events
being reported (one for each child).

Issue: #1722
PiperOrigin-RevId: 686901439
copybara-service bot pushed a commit that referenced this issue Oct 17, 2024
Before this change:

* With legacy subtitle decoding (at render time), load errors (e.g. HTTP
  404) would result playback completely failing, while parse errors
  (e.g. invalid  WebVTT data) would be silently ignored, so playback
  would continue without subtitles.
* With new subtitle decoding (at extraction time), both load and parse
  errors would result in playback completely failing.

This change means that now neither load nor parse errors in text or
metadata tracks stop playback from continuing. Instead the error'd track
is disabled until the end of the current period.

With new subtitle decoding, both load and parse errors happen during
loading/extraction, and so are emitted to the app via
`MediaSourceEventListener.onLoadError` and
`AnalyticsListener.onLoadError`. With legacy subtitle decoding, only
load errors are emitted via these listeners and parsing errors continue
to be silently ignored.

Issue: #1722
PiperOrigin-RevId: 686902979
@icbaker
Copy link
Collaborator

icbaker commented Oct 18, 2024

The changes linked above mean that errors from both loading and parsing subtitle (and metadata) are suppressed, allowing the rest of the playback to continue. This should work with both sideloaded subtitles (via MediaItem.SubtitleConfiguration) and in-stream subtitles (whether that's a track in an MP4 file, or configured through a DASH or HLS playlist).

These errors are logged when they're suppressed, and also propagated out via onLoadError callbacks on AnalyticsListener and MediaSourceEventListener.

@icbaker icbaker closed this as completed Oct 18, 2024
@androidx androidx locked and limited conversation to collaborators Dec 18, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

No branches or pull requests

3 participants