benwiley4000 / cassette

📼 A flexible media player component library for React that requires no up-front config
https://benwiley4000.github.io/cassette/styleguide
MIT License
184 stars 28 forks source link

Snapshot not updating PlayerContextProvider state if playlist contains different track urls #438

Open robo220 opened 4 years ago

robo220 commented 4 years ago

In reference to https://github.com/benwiley4000/cassette/issues/437 I'm trying to ensure the player remembers the user's location in the playlist.

This works perfectly when using the playlist in this demo https://github.com/benwiley4000/cassette-demo-app located here https://github.com/benwiley4000/cassette-demo-app/blob/forward/src/playlist.js. However, if the track urls are different, for example have different url parameters, I believe the snapshot functionality resets the position to beginning of the playlist rather than continuing from the position saved in the snapshot. The track indexes will always be the same but the url pointing to the media may change.

Is there anyway around this? Thanks Ross

benwiley4000 commented 4 years ago

Hey Ross, just to be clear, could you give me an example of two URLs that are different but you consider to be pointing to the same piece of media? Is it a query string that is changing? I'm happy to think about a solution for a smarter "equivalence" check than strict url equality, but I hope it makes sense that you can't always assume that a track is the same as before just because the index in the loaded playlist is the same.

robo220 commented 4 years ago

@benwiley4000 thanks again for your quick reply!

To confirm, it is the query string that is changing rather than the url specifically. Two examples are shown below they do have an expiry date.

https://content.bookboon.com/audio-branding/2a98e7e1-559f-4be2-8df2-4fa1a35fe8c6/start?response-content-type=audio%2Fmp4&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=BV997TAV5RI6P88ZDTV8%2F20200504%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20200504T155104Z&X-Amz-SignedHeaders=host&X-Amz-Expires=86400&X-Amz-Signature=f7a8bdace9580136610e98c4a60d56ea8083a3f5cd8d324f4be28fffc808bbf1

https://content.bookboon.com/audio-branding/2a98e7e1-559f-4be2-8df2-4fa1a35fe8c6/start?response-content-type=audio%2Fmp4&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=BV997TAV5RI6P88ZDTV8%2F20200504%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20200504T154722Z&X-Amz-SignedHeaders=host&X-Amz-Expires=86400&X-Amz-Signature=12b495d80d62a6b79abc074ff8113651520b0cae54bf63b9f68093e9bcd9ebd8

benwiley4000 commented 4 years ago

I see! I think to solve this maybe we could have a new prop passable to the PlayerContextProvider that is called areTracksEqual or something, not sure what the best name is. It takes two tracks as arguments and returns true if the tracks are equivalent. In your case it could be:

function areTracksEqual(a, b) {
  const [pathnameA, pathnameB] = [a, b].map(track =>
    new URL(track.url || track.sources[0].src).pathname
  );
  return pathnameA === pathnameB;
}

Does that seem like it could work?

benwiley4000 commented 4 years ago

@robo220 Ok so finally this is what I came up with: https://github.com/benwiley4000/cassette/pull/439/files#diff-85f3673c9affae062acd5232f1e0243bR1387-R1430

This is what you would need to add to your Player or PlayerContextProvider:

function areTrackSourceUrlsEqual(urlA, urlB) {
  const [pathnameA, pathnameB] = [urlA, urlB].map(url => new URL(url).pathname);
  return pathnameA === pathnameB;
}
// ...
areTrackSourceUrlsEqual={areTrackSourceUrlsEqual}

Does this seem good?

robo220 commented 4 years ago

@benwiley4000 This seems good to me, thank you!