Episode: 4585 Title: mpv util scripts Source: https://hub.hackerpublicradio.org/ccdn.php?filename=/eps/hpr4585/hpr4585.mp3 Transcribed: 2026-07-31 16:14:30 (official HPR transcript) --- This is Hacker Public Radio Episode 4585, for 2026-02-27 Today's show is entitled, "mpv util scripts" The host is candycanearter and the duration is 00:11:55 The flag is Clean, and the license is CC-BY-SA The summary is "a collection of hand-written scripts for mpv and explaining how the mpv api works" There are some programs that act as a cornerstone, a little next to meody, like Vim or Emacs, deserve some publicity and high levels of extendability. One of these options is really better, but today we're talking about a different program that I think deserves more attention for its flexibility. That program isn't baby-y, simply described as a media player in its documentation. Despite the name, it has tons of support for everything from DVDs to HLS streams to even YouTube support and has been fantastic for my daily use cases. I wanted it to show off some scripts I had written in order to display how I took advantage of the flexibility and to potentially provide a starting point for others who MPV the poor scripts in three different languages, being Lua, JavaScript, and C. Regardless of which language you're using, the underlying framework is similar. The cornerstone of scripting an MPV is properties. Nearly every feature of MPV is exposed through some property or another, and it can be things that first termed a video, setting, or even state flags. There's also a dedicated property and for you to find a global, that can be written to by any script, and it's liberally not touched by the player. The generalization of many different pieces of info to his property to them makes scripting much easier as all data can be forced through to think where and point. Property is probably able to be affirmed. This is done through the of variable property function, which calls the given function whenever the property is updated through any source. This can be used for anything from when the player goes into a certain state from when the mouse is moved thanks to the flexible property system. Register event runs the given function on a global event. This is for state changes that like a fouling started or stopped or thinking operations, and it's generally a more live away to detect such global state tuned over using a property. Added hook is an experimental feature, but it is required for certain cases. Unlike other hooks, it is blocking, which can be important for preventing waste conditions. Register script message, expose that a user-thread function under the given name and can be activated from the command line or through a key bind. Added time out an ad periodic timer are the most basic hooks, calling the function once or repeatedly for a given number of time. The other command that are important are get and set property native, which read and write two properties. Command, which runs the command within the MPV console syntax, LST method, which displays a message to the user on the top left. These nine functions make up the majority of the interaction with the MPV core. So we have the button blocks. Let's see what we can do with them. A and a square profit that Lua doesn't do much on the phone, but it sets up properties for other scripts to use. In particular, it watches for when the path and play time remaining, property of or being written to, parses the data out of it, and then writes the data to user data properties that can be used by other scripts. Getting into this script selects to do stuff A and a square aspect ratio at Lua. MPV by default has the geometry property, which may written to you to change the window size. However, did geometry either set to the value, whenever any fellow said it, which can be annoying if you would previously resize the window. Wet the script is doing its useful. First, it watches a geometry variable and make sure it is of a specified aspect ratio. This allows you to do things that like specify the geometry as the percent of the screen without having to be calculated by use manually. It also resets a geometry value to the current window size, whenever new fellow voted, in order to prevent random recitals. First, the target aspect ratio is stored in local variables. This technically should be described off system, but for a personal script, I didn't want to go through the treble of implementing it. The reset gem function is simply gets the current dimensions of the window, and writes it to the geometry. The dimension hop function does a heavy lifting of calculating the aspect ratio in writing a new geometry 5 if needed. Then the function are just registered to the corresponding properties and events to make it work. Next, the audiovisual. By default, MPV only displays a black screen when playing audio files of no associated video track, which is lame. Fortunately, MPV also supports assigning an arbitrary FFM pedic photographs, so we can rectify that. Due to FFM pedic limitations of every input having to be filled, this program actually requires a default cover file with the name covered up PNG to be put either in your home directory or in the MPV config directory. The one that I drill and made will be in the show notes. The script is split in the two different functions. That being one that handled adding the missing cover is needed, and one that actually assigns the filter graph. First, a look-up table of images to the main is put in the top of the function. This is the useful for network streams that do not provide a cover image, such as this podcast for some reason. Because the command to add the image stream returns a false value if the image can't be found, we can use a suit check whether the given image exists and provide a fault that option is not. You also try to add the FFM from the domain, but this will most likely fail. Since there is no way to parse HTML, we simply try to access FFM.itio into domain root. Finally, it just adds the cover image if all other methods have failed. Inject needed, it's a function that actually does most of the work. First, it scans your all the tracks in the track list, and if there is a video track, then it simply returns without doing anything. If there is no image track present, then it calls resolve within cover with the domain paths that we have assigned in a props.lua. Finally, it writes the filter graph. Now, this isn't a filter tutorial, but in essence, what is this doing is scaling the image up to 250 thick by 250 thick if it's smaller, using nearest neighbor, and then scaling it to a width of 720. This width is big enough that the element on the screen do not look too blurry. We'll also be following us that doesn't overload the RAM. Then it calls it's a built-in audio visual either, and overlay it with the image. This uses ad hook since the function needs to be run after the tracks have been parsed, but before the videos are playing, then the F event will crash if it's missing a source. A and F are playing with that lua, it's just um, either function I defined it in order to help with playlists ordering. The full clear is simply clear is a playlists and resets MPV to an idle site is, and playlists next to last simply moves at the next element in the playlists to the end of it. A, R, C, Fill, dot lua, or relative cash fill. This makes the winning for cash state a little bit more dynamic. By default, when the network screen runs out of cash, MPV will simply wait for one second of the cash to be filled before playing again. In most cases, this is fine, when playing a flow stream, it's a constant starting and stopping and can be distracting. This script changes how much cash the cash waits for before playing again, based on the current cash speed, the bit rate, and the speed. The audio and video bit rate are thumbed and multiplied by the current playback speed, and then multiplied by 3 in order to give some extra room for the cash. That's then divided by the current download speed, and they clamped to 20 seconds maximum, and are supervented from rating forever. Then, erase the cash cause of the weight property and deflate an OSB message. Also note that it writes to a file local options instead of the default cash cause weight. This means that it's reset after the file is loaded. Jump to E-Cash is another either hub or function that sets a playback to 5 seconds before the cash is done. This is very useful for things like live streams. Last and thirdly not least, is a ton of art at the wall, which writes to the title bar. By default, MPV uses the title property in order to set what the title bar displays, which uses property expansion. For update expansion, define special characters that expand to whatever the property of fallen. By default, property expansion contains some logical operations that like checking if a property is set to a third value, but with scripting, we can go further and make it even more dynamic. When the function is first started on startup, it writes the current value of the title property to a special user data variable. This is thought that the user can still set a title bar for things like the idle state. Everything related to updating the title dynamically is handled by a function title update. First, the media title property is checked, and if it's not that, that no file is currently loaded. So, we set the title to the previously saved default title and return. Next, the current playlist position is retrieved, and if it's not negative one, the subtracted it from the current playlist count to get the number of files remaining in the playlist. Negative one is a special case, meaning no playlist is loaded. Next, the play time remaining at property if retrieved, and if it's not set, we assume that we're currently loading the file. So, we just display the currently loading title, and one left a number of files remaining in the playlist if it was set. And earlier return. Everything produced by on is for contracting the title bar, for a file that's currently being played. The progress number is the most dynamic part of the script. By default, it displays the current position in the file from 0 to 100%. However, after it's less than 100 seconds left of playback, then it instead displays the number of seconds until the file is over. It also uses the prepping doubts that up in a underscore props. Apparently, it's also displayed the number of seconds behind real time a livestream at being played, since those were by constantly updating the end time of the file. Finally, if the player is popular cash, then it displays the percentage of cash until it'll start playing again. If the the MOOC's are the network property is set, then it also displays the cash speed or download speed of the file. Finally, if the domain path, which we set in a underscore props, is set, we also display the host name of the file being played. Finally, we set title to the concatenation of all of the different variables, and we're done. Thankfully, Louis isn't as strict as, say, JavaScript, or a fee yet about 5-inch signatures. So, we can assign a title update function to a myriad of different properties and events, as well as a periodic timer, just in case. Title update only shows the template of the title, not how fast the values in the title are being updated. Keep that in mind if you want to extend this one. Hopefully, this episode aspires you to try out MPB and try your hand out the wascripting. Even if you're not an expert in coding, Louis is one of the easiest languages to get into. And crafting your own customized media player is a surprisingly easy goal to achieve for even for a first timer. You just have to be patient. Happy MPB-Aing and have some good. You have been listening to the Hacker Public Radio podcast, at hackerpublicradio.org. Today's show was contributed by a HPR listener like yourself. If you ever thought of recording a podcast, then visit the HPR site to find out how easy it really is. Hosting for HPR has been kindly provided by anhonesthost.com, the Internet Archive, rsync.net, and the HPR Community Content Delivery Network. Unless otherwise stated, today's show is released under a Creative Commons Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.