Skip to content

Add a command to set multiple ab-loop of the same file #7975

Closed

Description

@SmootheSmooth

Hello,

currently I can only add an --ab-loop-a and ab-loop-b once for the same video file (for guitar learning).

How can I add a second or third ab-loop for the same video file?

Additional:
It should also be possible to set the order of the multiple ab-loop and use a shuffle function for ab-loop.

Activity

  1. SmootheSmooth commented on Aug 6, 2020

    @SmootheSmooth
    Author

    I tried again and found nothing.

    It's not supported. Currently I use this mpv version on Windows.
    https://sourceforge.net/projects/mpv-player-windows/files/64bit/mpv-x86_64-20200802-git-b238897.7z/download

    Therefore make this report a feature request.

  2. SmootheSmooth commented on Aug 6, 2020

    @SmootheSmooth
    Author

    Expected behavior of the wanted feature

    The expected behaviour could be to add new commands, like ab-loop-a-number=2 and ab-loop-b-number=2

    When use these commands, you can add up to 2x ab-loop-a and 2x ab-loop-b for the same video file.

  3. changed the title [-]How can I add a second ab-loop for the same file?[/-] [+]Add a command to set multiple ab-loop of the same file[/+] on Aug 6, 2020
  4. jgreco commented on Sep 17, 2020

    @jgreco
    Contributor

    Perhaps you could get this sort of effect using edit decision lists (EDLs, documented here: https://github.com/mpv-player/mpv/blob/master/DOCS/edl-mpv.rst). For instance you could create one EDL file for each segment you want to loop and put them into a shuffled mpv playlist. e.g. mpv --shuffle loop1.edl loop2.edl ...

    EDL files themselves are fairly straight forward, for your purposes an EDL file of a loop starting at the 150 second second mark including the next 5 seconds might look like:

    # mpv EDL v0
    /path/to/your/video.mp4,150,5
    

    These files may also contain many entries/lines, including duplicate entries, which you can reorder as you like. Each segment will be played back to back in the order they appear in the EDL file, or you could create multiple EDL files and manage their order as you would any other mpv playlist.

    (Note that if your video's filename contains a , character any EDL file for it will get a little bit more complicated. Writing these EDL files by hand is very far from ideal. It might be a good candidate for an mpv userscript though.)

  5. Akemi commented on Apr 30, 2021

    @Akemi
    Member

    yeah i think this is a case where EDL should be used. alternatively/additionally a script that writes such a file on the fly.

  6. guidocella commented on Dec 16, 2023

    @guidocella
    Contributor

    I generate them with this script. It is bound to g-e

    local utils = require 'mp.utils'
    local start
    
    mp.add_key_binding('g-e', 'generate-edl', function ()
        if start == nil then
            start = mp.get_property_native('time-pos')
            mp.osd_message('Saved start')
            return
        end
    
        local directory, filename = utils.split_path(mp.get_property('path'))
        local bookmarks_exist = utils.file_info(directory .. '/bookmarks.edl')
        local edl = io.open(directory .. '/bookmarks.edl', 'a')
        if not bookmarks_exist then
            edl:write('# mpv EDL v0\n')
        end
        edl:write(
            filename .. ',' .. start .. ',' .. mp.get_property_native('time-pos') - start .. '\n'
        )
        edl:close()
        start = nil
        mp.osd_message('EDL updated')
    end)

    Published to https://gist.github.com/guidocella/5f05794d0a8400b2393fe7a9995ebb43

  7. hrxn commented on Dec 16, 2023

    @hrxn
    Contributor

    What would this script look like if I wanted to use a binding in input.conf with script-binding?

  8. guidocella commented on Dec 16, 2023

    @guidocella
    Contributor

    I updated the script giving the binding a name. You can bind script-binding generate-edl, or just edit the key in the script.

  9. hrxn commented on Dec 16, 2023

    @hrxn
    Contributor

    Thanks!

    But this still binds a key from the script, no?
    What would I have to do? Use ignore as the param for mp.add_key_binding()?

    Or, another example, what if I change this script to this?

    local utils = require 'mp.utils'
    local start
    
    function generate_edl()
        if start == nil then
            start = mp.get_property_native('time-pos')
            mp.osd_message('Saved start')
            return
        end
    
        local directory, filename = utils.split_path(mp.get_property('path'))
        local bookmarks_exist = os.rename(directory .. '/bookmarks.edl', directory .. '/bookmarks.edl')
        local edl = io.open(directory .. '/bookmarks.edl', 'a')
        if not bookmarks_exist then
            edl:write('# mpv EDL v0\n')
        end
        edl:write(
            filename .. ',' .. start .. ',' .. mp.get_property_native('time-pos') - start .. '\n'
        )
        edl:close()
        start = nil
        mp.osd_message('EDL updated')
    end
  10. guidocella commented on Dec 16, 2023

    @guidocella
    Contributor
    mp.add_key_binding(nil, 'generate-edl', function ()

    or

    mp.register_script_message('generate-edl', function ()

    An existing function is passed with

    mp.register_script_message('generate-edl', generate_edl)
  11. hrxn commented on Dec 16, 2023

    @hrxn
    Contributor

    k, thanks!

  12. 9 remaining items

  13. guidocella commented on Jan 3, 2024

    @guidocella
    Contributor

    mp.get_property('platform')

  14. hrxn commented on Jan 3, 2024

    @hrxn
    Contributor

    Ah, thanks, just found it.

    Strange, Lua docs says

    A character class is used to represent a set of characters. The following combinations are allowed in describing a character class:
    
    - x: (where x is not one of the magic characters ^$()%.[]*+-?) represents the character x itself.
    

    So forward slash is not in the list of special characters. AI says I need to escape forward slash? Or is AI doing me dirty again?

  15. guidocella commented on Jan 3, 2024

    @guidocella
    Contributor

    You don't have to escape forward slashes in Lua patterns. It's getting confused with regular expressions using / as delimiters.

  16. hrxn commented on Jan 3, 2024

    @hrxn
    Contributor
    Score
    Docs 2
    AI 0

    Okay, it was actually also working with utils.getcwd(), but it's more clear and sane this way:

    local function prfx_path_is_absolute(pathval)
        local os_pltfr = mp.get_property('platform')
        local path_str = string.sub(pathval, 1, 2)
        if os_pltfr == 'windows' then
            if string.match(path_str, '%u:') then
                return true
            else
                return false
            end
        else
            if string.match(path_str, '/.') then
                return true
            else
                return false
            end
        end
    end

    I hope it's not too bad 😄

  17. guidocella commented on Jan 3, 2024

    @guidocella
    Contributor
    local function is_absolute(path)
        if mp.get_property('platform') == 'windows' then
            return path:find('^%u:')
        end
    
        return path:find('^/')
    end

    If you're trying to convert it to an absolute path you can use utils.join_path which returns paths as they are when already absolute.

    Edit: even shorter:

    local function is_absolute(path)
        return path:find(mp.get_property('platform') == 'windows' and '^%u:' or '^/')
    end
  18. hrxn commented on Jan 3, 2024

    @hrxn
    Contributor

    Nice, thanks. It's definitely shorter. But is it also faster? 😄

    Again, not familiar with Lua syntax (basically the first thing in Lua I've ever written), but is path:find(<pattern>) some special method? Or is it the same as string.find(path, <pattern>), basically? Just syntactic sugar?

    If you're trying to convert it to an absolute path you can use utils.join_path which returns paths as they are when already absolute.

    I've found that one in the manual actually, and it is what I've tried first.

    But I had one problem, where it did not work in a specific case. Might be a Windows specific issue again, not sure.

    Consider this:

    • Directory
      • D:\Example\Test
    • File
      • RandomClip-0001.mp4

    If I run mpv like this:

    mpv D:\Example\Test\RandomClip-0001.mp4
    

    utils.join_path (with the second parameter, just as described in the manual) returns the correct path, exactly as used on the command-line.
    Regardless of working directory in the terminal.


    With the terminal in the directory mentioned above

    mpv RandomClip-0001.mp4
    

    gets me D:\Example\Test/Random-Clip-0001.mp4. So it joins with the "wrong" path separator, but it's not really a big deal, the path still works.


    But on the other hand, again, same current location in terminal:

    mpv .\RandomClip-0001.mp4
    

    returns D:\Example\Test./Random-Clip-0001.mp4, which is a bit, well, dubious...

  19. guidocella commented on Jan 3, 2024

    @guidocella
    Contributor

    Nice, thanks. It's definitely shorter. But is it also faster? 😄

    Yes but there's nothing slow in either one.

    Again, not familiar with Lua syntax (basically the first thing in Lua I've ever written), but is path:find(<pattern>) some special method? Or is it the same as string.find(path, <pattern>), basically? Just syntactic sugar?

    Yes, path:find(pattern) is short for path.find(path, pattern).

    Yes, paths are a mess on Windows because mpv mixes both kinds of slashes, using different paths also breaks the watch later feature. If #12303 is merged and someone is willing to adapt it in on Windows, we can implement a normalize-path command to handle this for script writers.

  20. hrxn commented on Jan 3, 2024

    @hrxn
    Contributor

    @guidocella Such a normalize-path function seems very useful, I agree.

    Would this also address the issue which I just stumbled upon, namely, given the same directory structure from my comment above (i.e. terminal in D:\Example\Test), but I now play a file named unnamedvid.mp4 in the parent directory (so D:\Example), which works just fine with mpv (as well as with any other cli program). IOW, the command would be

    mpv ..\unnamedvid.mp4
    

    with local x, y = utils.split_path(mp.get_property('path')) I get this

    Variable Value
    x ..\
    y unnamedvid.mp4

    Which is perfectly fine and as expected. But the way I try to convert to absolute paths, I'll end up with this path here:

    D:\Example\Test\unnamedvid.mp4
    

    Which is just wrong, unnamedvid.mp is in Example, not in Test.

    But it's not because I do anything funny, this gives the same result:

    mp.osd_message(utils.join_path(mp.get_property('working-directory'), y))
    

    (Reusing y from utils.split_path() above)

    I checked the relevant parts of the manual again, and this is even expected behavior, as I understand it.

    Because both

    • utils.getcwd()
    • mp.get_property('working-directory')

    Return the working directory of the mpv process, or the directory from which mpv was launched from.
    Seems like the documentation is correct, but this leads me to the following questions:

    1. What's the point of having both of these functions, if they return the same thing? What is the difference?
    2. How can I get the working-directory of the currently active file?

    I also tried the playlist-path property, but I just get an lua error. Basically the wrong type, but I assume this just means that this property does not return anything useful. Maybe because if one opens a single file, it will maybe have an internal "playlist", but it is not a "real" playlist?
    I assume playlist/N/playlist-path won't make a difference here?

  21. guidocella commented on Jan 3, 2024

    @guidocella
    Contributor

    Would this also address the issue which I just stumbled upon...

    Yes.

    1. What's the point of having both of these functions, if they return the same thing? What is the difference?

    utils.getcwd() is older, then working-directory was added to access it from JSON IPC. There is no reason to keep using utils.getcwd() which just calls mp.get_property("working-directory").

    1. How can I get the working-directory of the currently active file?

    On Unix you call realpath with subprocess. I don't know if on Windows you can call GetFullPathNameW with Luajit's FFI.

    I also tried the playlist-path property, but I just get an lua error. Basically the wrong type, but I assume this just means that this property does not return anything useful. Maybe because if one opens a single file, it will maybe have an internal "playlist", but it is not a "real" playlist? I assume playlist/N/playlist-path won't make a difference here?

    That's the path of directories expanded at runtime, archives and m3u playlists.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions