Skip to content

Videos played from content uri stores and loads wrong progress position save file #542

Closed

Description

@YanceyChiew

Important information

Android version: 12

mpv-android version: 2022-03-23 release

Description

When loading a video document from a content provider, I often encounter situations where the player quits immediately or cannot properly read valid data from the provider because the current position exceeds the total video duration.

Or sometimes the video player automatically quits in the middle of playing, and it doesn't look like it crashes when it encounters an error. The postion when quitting is always as long as the total duration of the previous video.

  • Use the following commands to generate 3 video files for testing
mkdir /sdcard/test
cd test
ffmpeg -f lavfi -i nullsrc=s=256x256:d=1800 test30min.mp4
ffmpeg -f lavfi -i nullsrc=s=256x256:d=600 test10min.mp4
ffmpeg -f lavfi -i nullsrc=s=256x256:d=180 test3min.mp4

Opening them through a traditional file browser, mpv handles the saving progress position normally, however, when opened by the content provider (ie. com.google.android.documentsui) , mpv's handling of the save position is confusing.

Log output

Since there is too much output, I only filter key messages, and mpv doesn't output the open watch_later filename every time it plays. mpv has uid 10667 in my device

logcat -c && logcat --uid 10667|grep -C2 -E "Resolving|watch_later|'start'|Exiting"

I opened the 10-minute version first, dragged the progress to the end, exited and opened the 30-minute version, then exited and opened the 3-minute version, and finally reopened the 10-minute version.

  • Below is the output
ar && logcat --uid 10667|grep -C1 -E "Resolving|watch_later|'start'|Exiting"                                    <
05-29 04:34:27.211 17273 17273 E Toast   : setGravity() shouldn't be called on text toasts, the values won't be used
05-29 04:34:27.212 17273 17273 V mpv     : Resolving content URI: content://com.android.externalstorage.documents/document/primary%3Atest%2Ftest10min.mp4
05-29 04:34:27.239 17273 17273 V mpv     : Display 0 reports FPS of 60.000004
--
05-29 04:34:32.033 17273 19054 V mpv     : [cplayer:v] Set property: vo="null" -> 1
05-29 04:34:32.042 17273 17273 V mpv     : Exiting.
05-29 04:34:37.432 17273 17688 D AppScoutStateMachine: 17273-ScoutStateMachinecreated
--
05-29 04:34:37.446 17273 17273 E Toast   : setGravity() shouldn't be called on text toasts, the values won't be used
05-29 04:34:37.446 17273 17273 V mpv     : Resolving content URI: content://com.android.externalstorage.documents/document/primary%3Atest%2Ftest30min.mp4
05-29 04:34:37.465 17273 17273 V mpv     : Display 0 reports FPS of 60.000004
--
05-29 04:34:37.504 17273 19111 V mpv     : [cplayer:info] Resuming playback. This behavior can be disabled with --no-resume-playback.
05-29 04:34:37.504 17273 19111 V mpv     : [cplayer:v] Loading config '/data/user/0/is.xyz.mpv/files/watch_later/1D6DF7821937FF351A892E5977534E83'
05-29 04:34:37.504 17273 19111 V mpv     : [cplayer:v] Reading config file /data/user/0/is.xyz.mpv/files/watch_later/1D6DF7821937FF351A892E5977534E83
05-29 04:34:37.504 17273 19111 V mpv     : [cplayer:v] Applying profile 'default'...
05-29 04:34:37.506 17273 19111 V mpv     : [cplayer:v] Setting option 'start' = '566.720000' (flags = 36)
05-29 04:34:37.506 17273 19111 V mpv     : [cplayer:v] Running hook: ytdl_hook/on_load
--
05-29 04:34:39.912 17273 19111 V mpv     : [cplayer:v] Set property: vo="null" -> 1
05-29 04:34:39.919 17273 17273 V mpv     : Exiting.
05-29 04:34:41.370 17273 17879 D AppScoutStateMachine: 17273-ScoutStateMachinecreated
--
05-29 04:34:41.392 17273 17273 E Toast   : setGravity() shouldn't be called on text toasts, the values won't be used
05-29 04:34:41.392 17273 17273 V mpv     : Resolving content URI: content://com.android.externalstorage.documents/document/primary%3Atest%2Ftest3min.mp4
05-29 04:34:41.409 17273 17273 V mpv     : Display 0 reports FPS of 60.000004
--
05-29 04:34:41.450 17273 19173 V mpv     : [cplayer:info] Resuming playback. This behavior can be disabled with --no-resume-playback.
05-29 04:34:41.450 17273 19173 V mpv     : [cplayer:v] Loading config '/data/user/0/is.xyz.mpv/files/watch_later/1D6DF7821937FF351A892E5977534E83'
05-29 04:34:41.450 17273 19173 V mpv     : [cplayer:v] Reading config file /data/user/0/is.xyz.mpv/files/watch_later/1D6DF7821937FF351A892E5977534E83
05-29 04:34:41.450 17273 19173 V mpv     : [cplayer:v] Applying profile 'default'...
05-29 04:34:41.450 17273 19173 V mpv     : [cplayer:v] Setting option 'start' = '568.600000' (flags = 36)
05-29 04:34:41.450 17273 19173 V mpv     : [cplayer:v] Running hook: ytdl_hook/on_load
--
05-29 04:34:41.931 17273 19173 V mpv     : [cplayer:v] Set property: vo="null" -> 1
05-29 04:34:41.936 17273 17273 V mpv     : Exiting.
05-29 04:34:43.847 17273 17879 D AppScoutStateMachine: 17273-ScoutStateMachinecreated
--
05-29 04:34:43.859 17273 17273 E Toast   : setGravity() shouldn't be called on text toasts, the values won't be used
05-29 04:34:43.860 17273 17273 V mpv     : Resolving content URI: content://com.android.externalstorage.documents/document/primary%3Atest%2Ftest10min.mp4
05-29 04:34:43.884 17273 17273 V mpv     : Display 0 reports FPS of 60.000004
--
05-29 04:34:45.964 17273 19227 V mpv     : [cplayer:v] Set property: vo="null" -> 1
05-29 04:34:45.973 17273 17273 V mpv     : Exiting.

When the 30-minute version is opened, the progress automatically jumps to a position close to 10 minutes. It is not the playback progress of the 10-minute version, but very close. When the 3-minute version is opened, because the progress position exceeds the video duration, it immediately exits and resets the saved progress postion.

Additional information

When the document content provider obtains data from the network, mpv does not always exit immediately when attempting to read a video from a position that exceeds its total duration. You can see that mpv-android displays the total duration of the previous video in current interface in this situation. And if the previous video is shorter than the current one, then mpv may quit when it reaches the progress of the total duration of the previous video, but this is not easy to reproduce and report, and the source of the problem should be the same as above.

This should probably be broken down into two problems, namely that mpv does not correctly generate a watch_later file corresponding to the unique content uri, and the total duration displayed on the interface and something deeper will be preferentially affected by factors other than the metadata of the current video itself.

Activity

  1. sfan5 commented on May 29, 2022

    @sfan5
    Member

    This is an issue but not easy to fix because mpv can't see the actual URIs.

  2. YanceyChiew commented on May 29, 2022

    @YanceyChiew
    Author

    This is an issue but not easy to fix because mpv can't see the actual URIs.

    For mpv-android, although the file strict path itself cannot be parsed, at least we can see the whole picture of the content uri, which probably contains the file name, and is expected to be unique.

    But this information is lost when the fd is submitted to libmpv for processing, leaving only the file descriptor.

    The fd protocol of mpv does not contain a real file name, it‘s stream structure only contains a fd number cropped from url as path, which cannot be used to uniquely identify a video. It seems reasonable. So the question is, can we figure out a way to pass the real path to mpv to make it not only handle saving the playback progress correctly, but also display the filename as the title of the video?

    It seems easy to deal with the latter only by send a set_property command, but that doesn't help the former, and the latter will be solved naturally after the former is dealt with. I don't know, maybe a new private uri protocol support could be added to mpv's stream_file?

  3. sfan5 commented on May 31, 2022

    @sfan5
    Member

    It's possible to let mpv see the original URI via hooks. See here for a very old implementation: d6af5ea

  4. YanceyChiew commented on May 31, 2022

    @YanceyChiew
    Author

    Yes, there may still be a way to see the path of the file pointed to by the content link, but this will only get harder as the Android system version is upgraded, not to mention the case where the file itself does not exist in the local storage, then see the original link doesn't help either.

    Now that the mandatory popularization of content providers has become an inevitable trend, and there are indeed benefits in a sense, I think providing better support for content provider links rather than trying to bypass restrictions on conversions should also be considered.

    At present, the processing of content link is to open the file to get the fd and then pass the fd to mpv. What I want to say is, why not pass the other information extracted from the uri at the same time?

    For example, design a new uri protocol such like this:

    contentfd://<fd>/<flags ie. close=8, with orgin extenstion=4, encoded=2, hashed=1>/<uri_decoded_without_protocol_not_after_last_:_or_/_in_base64_or md5>/<uri_docoded_after_last_:_or_/_as_filename>.<origin_extension_or_from_mimetype_if_need>
    

    If a content link was opened in mpv-android as fd=85, with orginal extension and uri not need to be hasded (too long or be protected away form lua script), like this:

    content://com.android.externalstorage.documents/document/primary%3Atest%2Ftest3min.mp4
    

    Considering possible compatibility issues, the front part of the path was base64 encoded, Then libmpv will see this:

    contentfd://85/14/Y29tLmFuZHJvaWQuZXh0ZXJuYWxzdG9yYWdlLmRvY3VtZW50cy9kb2N1bWVudC9wcmltYXJ5Og==/test/test3min.mp4
    

    Then add code to stream_file to process it, extract the path and filename, they were previously set to null, now they can make sense.

    I'm not sure if this will work, just an idea. When mpv streams the link of the http protocol, it will take out the part after the protocol header as the path, and use the processed path when saving and restoring the playback status and options, and obviously the path of http does not really exist on the local storage, so I think just manually specifying the path to the stream will most likely work.

  5. YanceyChiew commented on May 31, 2022

    @YanceyChiew
    Author

    The above idea has not been carefully thought out, and there are many omissions, except that it is uncertain whether there is other logic coupled with the path and file name when mpv is streaming, it is also possible that there is no file name in the content uri. Perhaps the display name should be directly obtained as the file name, and then the whole original content uri should be encoded or hashed as the path.

  6. changed the title [-]Videos played from content uri may stores and loads wrong progress position save file[/-] [+]Videos played from content uri stores and loads wrong progress position save file[/+] on Sep 25, 2023
  7. sfan5 commented on Sep 25, 2023

    @sfan5
    Member

    Opening the legacy file picker will ask for those permissions, that it fixes this case is a coincidence (sort of).

    The real solution is making mpv deal with content URI loaded paths correctly.

  8. YanceyChiew commented on Sep 30, 2023

    @YanceyChiew
    Author

    Wait, I've just read the mpv documentation and it looks like watch-later indexes are already based on file's md5 checksum.

    Are you sure? I didn't find such a description in the mpv manual. Also, this doesn’t seem to make sense. To calculate md5sum, you need to read the file completely first, which is a huge IO overhead. Moreover, the URI does not necessarily point to a local file, and may even point to a live stream that does not have a clear length.

    As of the last time I read the MPV source code, MPV logs watch-later files based on file paths or URLs, and has special handling of http protocol URLs to ignore their host/domain name parts. Attach the filename to fdclose:// currently used by MPV-android, and simply modifying the invalid judgment assertion of fdclose can make watch-later work to a certain extent. But because fd is a dynamically generated number and the entire URL will change with it, this approach is not reliable. It wouldn't take much effort to improve it further so that the fd itself is ignored like the hostname of the http URL, but based on the previous discussion, maybe this solution is not a best practice that both MPV and MPV-android are happy to accept. There are Mentioned that the best solution is to re-implement a new protocol.

    As for your mention of generating watch-later based on file md5, I think this may be a misunderstanding. The watch-later file name itself is the md5sum of the string path or URL of the video, not the md5sum of the video content itself.

  9. syphyr commented on Sep 30, 2023

    @syphyr
    Contributor

    Try clearing out all the orphaned watch later files.
    #715

  10. added theissue type on Mar 1, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions