Skip to content

Fix skip buttons missing for MP4 sources with empty seekable range - #119

Merged
francescopuglisi-dolby merged 3 commits into
mainfrom
bugfix/skip-buttons-missing-mp4
Jul 14, 2026
Merged

Fix skip buttons missing for MP4 sources with empty seekable range#119
francescopuglisi-dolby merged 3 commits into
mainfrom
bugfix/skip-buttons-missing-mp4

Conversation

@francescopuglisi-dolby

Copy link
Copy Markdown
Collaborator

Summary

Skip (forward/backward) buttons were not rendered for progressive MP4 sources, even though the content is seekable and the seek bar works. This was most visible with preload: 'none'/'metadata'.

Root cause

SkipButton gated its visibility on the player's seekable range:

if (seekable.length === 0) {
  return <></>;
}

For progressive MP4, player.seekable legitimately stays empty until data is buffered (unlike HLS/DASH, where the manifest populates it immediately), even after a finite duration is known. As a result the buttons never appeared, despite the media being seekable — the same situation SeekBar already handles via a duration fallback.

Fix

Treat the media as seekable when there is a seekable range or when a finite, positive duration is known — mirroring SeekBar's existing fallback:

const isSeekable = seekable.length > 0 || (isFinite(duration) && duration > 0);
if (!isSeekable) {
  return <></>;
}

Live/unbounded streams report duration === Infinity, so the isFinite guard keeps them correctly excluded.
Kept inline (rather than extracted into a shared hook) to keep the change minimal; centralizing the shared "effective seekability" logic with SeekBar is a possible follow-up.

Testing

Reproduced with the ticket's MP4 source (poster + sideloaded subtitles, preload: 'none', no autoplay) in the example app on iOS.

App.tsx

player.autoplay = false;
player.preload = 'auto';

player.source = {
  sources: [
    {
      src: 'https://cdn.theoplayer.com/video/elephants-dream.mp4',
      type: 'video/mp4',
    },
  ],
  poster: 'https://fastly.picsum.photos/id/93/200/300.jpg?hmac=_9xpriBgFwY9RX_KtR53oeWtaQaNroWVr-4a9aJ0g_4',
  metadata: {
    title: 'Elephants Dream',
    subtitle: 'MP4 - preload none',
    album: 'React-Native THEOplayer demos',
    mediaUri: 'https://theoplayer.com',
    artist: 'THEOplayer',
  },
  textTracks: [
    {
      kind: TextTrackKind.subtitles,
      src: 'https://cdn.theoplayer.com/video/sintel/chapters.vtt',
      format: 'webvtt',
      srclang: 'en',
      label: 'Test',
      default: true,
    },
  ],
};

Before

Skip buttons absent.

Before.mov

After

Skip buttons visible and functional once duration is known.

After.mov

Show skip buttons for sources with empty seekable range

SkipButton hid itself whenever player.seekable was empty. For progressive
sources such as MP4 (especially with preload 'none'/'metadata'), the
seekable range stays empty even once a finite duration is known, so the
forward/backward skip buttons never appeared.

Mirror the SeekBar fallback: treat the media as seekable when there is a
seekable range OR a finite, positive duration is known. Kept inline rather
than extracted into a shared hook to keep the change minimal.
@changeset-bot

changeset-bot Bot commented Jul 13, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: e386fd7

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@theoplayer/react-native-ui Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

Comment thread .changeset/rich-seals-grin.md Outdated
Comment thread .changeset/rich-seals-grin.md Outdated
@francescopuglisi-dolby
francescopuglisi-dolby merged commit bea5699 into main Jul 14, 2026
1 check passed
@francescopuglisi-dolby
francescopuglisi-dolby deleted the bugfix/skip-buttons-missing-mp4 branch July 14, 2026 07:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants