├── LICENSE ├── README.md ├── autoscaling ├── README.md └── auto_scaling.lua ├── autospeed ├── README.md └── autospeed.lua ├── autospeedwin ├── README.md └── autospeedwin.lua ├── maximize ├── README.md └── maximize.lua ├── mkvrg ├── README.md └── mkvrg.lua ├── perfstats ├── README.md └── perfstats.lua └── powermizer ├── README.md └── powermizer.lua /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc., 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Lesser General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | {description} 294 | Copyright (C) {year} {fullname} 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License along 307 | with this program; if not, write to the Free Software Foundation, Inc., 308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 309 | 310 | Also add information on how to contact you by electronic and paper mail. 311 | 312 | If the program is interactive, make it output a short notice like this 313 | when it starts in an interactive mode: 314 | 315 | Gnomovision version 69, Copyright (C) year name of author 316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 317 | This is free software, and you are welcome to redistribute it 318 | under certain conditions; type `show c' for details. 319 | 320 | The hypothetical commands `show w' and `show c' should show the appropriate 321 | parts of the General Public License. Of course, the commands you use may 322 | be called something other than `show w' and `show c'; they could even be 323 | mouse-clicks or menu items--whatever suits your program. 324 | 325 | You should also get your employer (if you work as a programmer) or your 326 | school, if any, to sign a "copyright disclaimer" for the program, if 327 | necessary. Here is a sample; alter the names: 328 | 329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 330 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 331 | 332 | {signature of Ty Coon}, 1 April 1989 333 | Ty Coon, President of Vice 334 | 335 | This General Public License does not permit incorporating your program into 336 | proprietary programs. If your program is a subroutine library, you may 337 | consider it more useful to permit linking proprietary applications with the 338 | library. If this is what you want to do, use the GNU Lesser General 339 | Public License instead of this License. 340 | 341 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # mpv_scripts 2 | Various scripts for [mpv](https://mpv.io/). 3 | 4 | [autospeed](https://github.com/kevinlekiller/mpv_scripts/tree/master/autospeed/): Tries to match up monitor / video speeds for smoother playback. (*nix) 5 | 6 | [autospeedwin](https://github.com/kevinlekiller/mpv_scripts/tree/master/autospeedwin/): Tries to match up monitor / video speeds for smoother playback. (Windows) 7 | 8 | [autoscaling](https://github.com/kevinlekiller/mpv_scripts/tree/master/autoscaling/): Disable video scaling if video is slightly smaller than window size. (*nix / Windows) 9 | 10 | [maximize](https://github.com/kevinlekiller/mpv_scripts/tree/master/maximize/): Keeps the mpv window maximized when not in fullscreen. (Windows) 11 | 12 | [mkvrg](https://github.com/kevinlekiller/mpv_scripts/tree/master/mkvrg/): Scans replaygain on mkv files with bs1770gain and applies with mkvpropedit. 13 | 14 | [perfstats](https://github.com/kevinlekiller/mpv_scripts/tree/master/perfstats/): Displays statistics on dropped frames and video output performance. 15 | 16 | [powermizer](https://github.com/kevinlekiller/mpv_scripts/tree/master/powermizer/): Sets max performance on Nvidia GPU's when starting mpv, sets back to adaptive when exiting. (*nix) 17 | 18 | ---- 19 | ## License: 20 | 21 | https://github.com/kevinlekiller/mpv_scripts/blob/master/LICENSE 22 | 23 | ---- 24 | ## Donations 25 | Bitcoin: 38XZrqgXc9sE2YnWtfXz8QFf9XnDND3RKm 26 | Ethereum: 0x36374ea9cC3B33BCC9267be9e18a81AABAf98bEf 27 | Litecoin: MM49Vu3jQ1S8b8H9FrCJ1wgQHKSBidwtWZ 28 | Zcash: t1YUxEy9R2j9FW3ci3HWyKZEVUvdH5nyDAW 29 | -------------------------------------------------------------------------------- /autoscaling/README.md: -------------------------------------------------------------------------------- 1 | # autoscaling 2 | 3 | [mpv](https://mpv.io/) script to disable video scaling if video is slightly smaller than window size. 4 | 5 | For example, your monitor is 1920x1080, the video is 1920x816 (2.35:1 aspect ratio), scaling is disabled. 6 | 7 | The "window-scale" will be set to 1 and "border" set to "no" if the video is within range, this is to simplify how the script functions. 8 | 9 | Edit the script settings at line ~35. 10 | 11 | Download link for the script: https://raw.githubusercontent.com/kevinlekiller/mpv_scripts/master/autoscaling/auto_scaling.lua 12 | 13 | ---- 14 | #License: 15 | 16 | https://github.com/kevinlekiller/mpv_scripts/blob/master/LICENSE 17 | -------------------------------------------------------------------------------- /autoscaling/auto_scaling.lua: -------------------------------------------------------------------------------- 1 | --[[ 2 | Disable video scaling if video is slightly smaller than window size. 3 | 4 | For example, your monitor is 1920x1080, the video is 1920x816 (2.35:1 aspect ratio), scaling is disabled. 5 | 6 | The "window-scale" will be set to 1 and "border" set to "no" if the video is within range, 7 | this is to simplify how the script functions. 8 | 9 | Edit the script settings at line ~35. 10 | 11 | https://github.com/kevinlekiller/mpv_scripts 12 | --]] 13 | --[[ 14 | Copyright (C) 2016-2017 kevinlekiller 15 | 16 | This program is free software; you can redistribute it and/or 17 | modify it under the terms of the GNU General Public License 18 | as published by the Free Software Foundation; either version 2 19 | of the License, or (at your option) any later version. 20 | 21 | This program is distributed in the hope that it will be useful, 22 | but WITHOUT ANY WARRANTY; without even the implied warranty of 23 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 24 | GNU General Public License for more details. 25 | 26 | You should have received a copy of the GNU General Public License 27 | along with this program; if not, write to the Free Software 28 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 29 | https://www.gnu.org/licenses/gpl-2.0.html 30 | --]] 31 | 32 | ----------------------------------------------------------------------------------------------------------------------------------- 33 | ------------------------------------------- Start of user settings ---------------------------------------------------------------- 34 | ----------------------------------------------------------------------------------------------------------------------------------- 35 | local settings = { 36 | -- Width of your monitor's resolution in pixels. 37 | width = 1920, 38 | -- Height of your monitor's resolution in pixels. 39 | height = 1080, 40 | -- How much smaller can a video be to the window size before enabling scaling? 41 | -- For example, the video is 1860x1020, window size is 1920x1080, 1920*0.93=1786, 1080*0.93=1004, 42 | -- the video is larger than 1786x1004 so scaling is turned off. 43 | deviation = 0.93, 44 | osd = { 45 | -- Enable OSD? 46 | enabled = false, 47 | -- How much time in seconds will the OSD message be on screen. 48 | time = 5, 49 | -- Keyboard key to print OSD message. 50 | key = ";" 51 | }, 52 | -- Add debug to OSD messages? 53 | debug = false 54 | } 55 | ----------------------------------------------------------------------------------------------------------------------------------- 56 | -------------------------------------------- End of user settings ----------------------------------------------------------------- 57 | ----------------------------------------------------------------------------------------------------------------------------------- 58 | 59 | local global = { 60 | scale = nil, 61 | osd = { 62 | start = mp.get_property_osd("osd-ass-cc/0"), 63 | stop = mp.get_property_osd("osd-ass-cc/1") 64 | }, 65 | debug = "" 66 | } 67 | 68 | function main() 69 | global.debug = "" 70 | global.scale = check_scaling() 71 | if (global.scale ~= nil) then 72 | if (global.scale == "yes") then 73 | mp.set_property("border", "no") 74 | mp.set_property("window-scale", 1) 75 | end 76 | mp.set_property("video-unscaled", global.scale) 77 | end 78 | end 79 | 80 | function osd() 81 | if (settings.osd.enabled == true and global.scale ~= nil) then 82 | local string = global.osd.start .. "{\\b1}Scaling disabled:{\\b0}\\h" .. global.scale .. "\\N" 83 | if (settings.debug == true) then 84 | string = string .. "{\\b1}Debug:{\\b0}\\h" .. global.debug .. "\\N" 85 | end 86 | mp.osd_message(string .. global.osd.stop, settings.osd.time); 87 | end 88 | end 89 | 90 | if (settings.osd.enabled == true) then 91 | mp.add_key_binding(settings.osd.key, "auto-scaling_osd", osd, {repeatable=true}) 92 | end 93 | 94 | function check_scaling() 95 | -- Get video dimensions. 96 | local video = { 97 | width = mp.get_property("video-out-params/dw"), 98 | height = mp.get_property("video-out-params/dh") 99 | } 100 | 101 | -- Get window size. 102 | local window = { 103 | width = tonumber(settings.width), 104 | height = tonumber(settings.height), 105 | } 106 | 107 | local error = "nil property unavailable" 108 | if (video.width == error or video.height == error) then 109 | global.debug = "Unable to get video dimensions." 110 | return nil 111 | end 112 | 113 | video.width = tonumber(video.width) 114 | video.height = tonumber(video.height) 115 | if (window.width == nil or video.width == nil) then 116 | global.debug = "Unable to get video or window dimensions." 117 | return nil 118 | end 119 | 120 | -- Minimum acceptable values. 121 | local min = { 122 | width = (window.width * settings.deviation), 123 | height = (window.height * settings.deviation) 124 | } 125 | 126 | if (settings.debug == true) then 127 | global.debug = "Video (" .. video.width .. "x" .. video.height .. ") is " 128 | end 129 | 130 | -- Video is bigger than monitor. 131 | if (video.width > window.width or video.height > window.height) then 132 | if (settings.debug == true) then 133 | global.debug = ( 134 | global.debug .. "larger than window size (" .. 135 | window.width .. "x" .. window.height .."), enable scaling." 136 | ) 137 | end 138 | return "no" 139 | end 140 | 141 | -- Video width is within acceptable range. 142 | if (video.width >= min.width) then 143 | if (settings.debug == true) then 144 | global.debug = ( 145 | global.debug .. "within acceptable width range of (" .. 146 | min.width .. " - " .. window.width .. "), disable scaling." 147 | ) 148 | end 149 | return "yes" 150 | end 151 | 152 | -- Video height is within acceptable range. 153 | if (video.height >= min.height) then 154 | if (settings.debug == true) then 155 | global.debug = ( 156 | global.debug .. "within acceptable height range of (" .. 157 | min.height .. " - " .. window.height .. "), disable scaling." 158 | ) 159 | end 160 | return "yes" 161 | end 162 | 163 | -- Video height and width are under acceptable range. Enable scaling. 164 | if (settings.debug == true) then 165 | global.debug = ( 166 | global.debug .. 167 | "under acceptable range of thresholds (" .. min.width .. 168 | "x" .. min.height .. ") and window size (" .. 169 | window.width .. "x" .. window.height .. "), enable scaling." 170 | ) 171 | end 172 | return "no" 173 | end 174 | 175 | mp.register_event("file-loaded", main) 176 | mp.register_event("video-reconfig", main) 177 | mp.observe_property("window-scale", "native", main) 178 | mp.observe_property("fullscreen", "native", main) 179 | -------------------------------------------------------------------------------- /autospeed/README.md: -------------------------------------------------------------------------------- 1 | # autospeed 2 | 3 | ######Lua script for [mpv](https://mpv.io/) to adjust monitor refresh rate and video speed for almost 1:1 playback. 4 | 5 | -------------- 6 | 7 | #####Notes: 8 | 9 | * This script is for *nix operating systems. [See here for the Microsoft Windows version](https://github.com/kevinlekiller/mpv_scripts/tree/master/autospeedwin). 10 | 11 | * Can use (recommended) [xrandr](http://www.x.org/wiki/Projects/XRandR/) To set your monitor refresh rate closer to the video playback speed based on which refresh rates your monitor supports for the current resolution. 12 | 13 | * By default mpv will adjust the audio pitch to match the speed difference. You can read the [mpv manual](http://mpv.io/manual/master/#options-audio-pitch-correction) for more information on this. 14 | 15 | * Works better with mpv's [`--video-sync=display-resample`](https://mpv.io/manual/master/#options-video-sync) 16 | If using mpv's [`--video-sync=display-resample`](https://mpv.io/manual/master/#options-video-sync), do not use `autospeed-speed=true` 17 | If you have issues with mpv's [`--video-sync=display-resample`](https://mpv.io/manual/master/#options-video-sync), you can use `--video-sync=audio` and `autospeed-speed=true`, which still produces acceptable results. 18 | 19 | -------------- 20 | 21 | #####Basic Description: 22 | 23 | Changes the monitor refresh rate to be closer to the video fps, then sets 24 | the speed of the video to be closer to the monitor refresh rate. 25 | 26 | Lower resource usage than using interpolation. 27 | 28 | -------------- 29 | 30 | #####Script options: 31 | 32 | The script can read options from mpv's [--script-opts](http://mpv.io/manual/master/#options-script-opts) option. 33 | 34 | Valid options (and examples): 35 | 36 | autospeed-xrandr=true 37 | Default: false 38 | true/false - Use xrandr. 39 | Xrandr will be used to change the refresh rate of your monitor based on available 40 | refresh rates for the current resolution. 41 | autospeed-speed=false 42 | Default: false 43 | true/false - Adjust speed of the video? 44 | If set to true, the mpv speed setting will be changed based on the video 45 | fps and display refresh rate. 46 | Do not use this with mpv's --video-sync=display-resample 47 | autospeed-display=auto 48 | Default: auto 49 | If set to "auto", the primary connected monitor will be used with xrandr. 50 | If set to your monitors name, tell xrandr to use the specified display 51 | when changing the refresh rate. 52 | Find your monitor name using this command: xrandr | grep -Poi '^.+connected' 53 | It should look something like "HDMI-0". 54 | autospeed-exitmode=auto 55 | Default: auto 56 | Sets the refresh rate of the monitor when exiting mpv. 57 | autospeed-exitmode=auto 58 | Sets the monitor refresh rate back to the original refresh rate when mpv started. 59 | autospeed-exitmode=false 60 | Does not change the monitor refresh rate when exiting mpv. 61 | If you do not set autospeed-exitmode then this is the default. 62 | autospeed-exitmode=0x123 63 | This will set a specified mode when exiting. 64 | Find a mode using this command: xrandr --verbose 65 | For example, "0x48" in the following string is the 66 | mode: 1920x1080 (0x48) 148.500MHz +HSync +VSync *current +preferred 67 | autospeed-interlaced=false 68 | Default: false 69 | true/false - If set to false, the script will ignore a refresh rate if 70 | it is interlaced. 71 | autospeed-interlaced=false Do not use interlaced modes. 72 | autospeed-interlaced=true Use interlaced modes (and non-interlaced modes). 73 | autospeed-mblacklist=false 74 | Default: false 75 | Modes in this list will be ignored. Find modes with xrandr --verbose 76 | If more than one mode is specified, seperate them by semicolon. 77 | Examples: 78 | autospeed-mblacklist="0x128;0x2fa" 79 | autospeed-mblacklist=0x38d 80 | autospeed-minspeed=0.92 81 | Default: 0.9 82 | Number - Minimum allowable speed to play video at. 83 | Does not change mpv's speed setting if the calculated speed is lower than this. 84 | This is to prevent the video looking like it is in slow motion. 85 | A value of 0.9 allows playing the video at minimum, 10% slower. 86 | autospeed-maxspeed=1.08 87 | Default: 1.1 88 | Number - Maximum allowable speed to play video at. 89 | Does not change mpv's speed setting if the calculated speed is higher than this. 90 | This is to prevent the video looking like it is in fast forward. 91 | A value of 1.1 allows playing the video at maximum, 10% faster. 92 | autospeed-osd=true 93 | Default: false 94 | true/false - Enable OSD. 95 | This enables/disables the other autospeed-osd settings. 96 | autospeed-osdtime=15 97 | Default: 10 98 | Number - How many seconds the OSD will be shown. 99 | autospeed-osdkey="ctrl+y" 100 | Default: y 101 | This follows the same standard as mpv's input.conf for keybindgs. 102 | Key to press to show the OSD. 103 | Pressing this key will display autospeed information on mpv's OSD. 104 | autospeed-estfps=false 105 | Default: false 106 | true/false - Calculate/change speed if a video has a variable frame rate 107 | at the cost of higher CPU usage. 108 | If a video has a variable frame rate (fps), 109 | calculate / set the mpv speed based on the current video frame rate. 110 | This option will do nothing for most videos because, only few of them have variable fps. 111 | For example, most (all?) bluray videos have variable frame rates. 112 | Since the speed calulation must be done every time the video fps changes, 113 | this increases CPU load slightly. 114 | On my computer, mpv goes from ~10% to ~16% CPU usage with this option enabled. 115 | autospeed-spause=4 116 | Default: false 117 | true/false - Pause video while switching display modes. 118 | true: This will pause the video before and after switching the mode. 119 | false: Disables this option. 120 | Number - This enables the pause like true and sleeps for this amount of seconds. 121 | If bigger than 0: After switching the mode, we will wait this amount 122 | of seconds before unpausing the video. 123 | If set to 0: It disables the option, like false. 124 | Before switching the display mode (refresh rate), pause the video, unpause after 125 | it is switched. This can be used if you don't want to miss 126 | some of the video while your display is blank (my display is blank for ~5 seconds 127 | while switching modes). 128 | 129 | Examples: 130 | Setting the options at the command line: 131 | mpv file.mkv --script-opts=autospeed-xrandr=true,autospeed-speed=false,autospeed-minspeed=0.8 132 | Setting the options in ~/.config/mpv/mpv.conf : 133 | script-opts=autospeed-xrandr=true,autospeed-speed=false,autospeed-display=auto,autospeed-exitmode=auto,autospeed-minspeed=0.9,autospeed-maxspeed=1.1,autospeed-osd=true,autospeed-osdtime=10,autospeed-osdkey=y,autospeed-estfps=true,autospeed-spause=4 134 | 135 | -------------- 136 | 137 | #####Installation: 138 | 139 | Put the file inside the mpv/scripts folder, see the [mpv man page](https://github.com/mpv-player/mpv/blob/master/DOCS/man/mpv.rst#files) for the correct path, by default this should be `~/.config/mpv/scripts/`. 140 | 141 | 142 | Download link: 143 | [autospeed.lua](https://raw.githubusercontent.com/kevinlekiller/mpv_scripts/master/autospeed/autospeed.lua) 144 | 145 | You can use programs like `wget` or `curl` to download from the command line. 146 | 147 | For example, to download using curl: 148 | 149 | `mkdir -p ~/.config/mpv/scripts && curl -o ~/.config/mpv/scripts/autospeed.lua https://raw.githubusercontent.com/kevinlekiller/mpv_scripts/master/autospeed/autospeed.lua` 150 | 151 | -------------- 152 | 153 | #####Detailed Description: 154 | 155 | This is roughly the order of events that happen: 156 | 157 | Fetches your monitor refresh rate and video fps from mpv. 158 | 159 | If you have xrandr enabled in the config file: 160 | 161 | The supported modes for your monitor and resolution will be parsed using 162 | your display name (`autospeed-display`), your monitor's 163 | refresh rate will be changed to the most appropriate one based on 164 | the video speed thresholds (`autospeed-minspeed` and `autospeed-maxspeed`). 165 | 166 | The speed is then calculated based on the video fps / display refresh rate. 167 | 168 | If the speed is within range of the thresholds (`autospeed-minspeed` and `autospeed-maxspeed`), 169 | the mpv speed property is set. 170 | 171 | When mpv exits, the mode will be set to a user specified mode (`autospeed-exitmode`). 172 | 173 | -------------- 174 | 175 | #####Examples: 176 | 177 | * > 178 | The display supports 72hz. 179 | The video is 23.97602397602398fps. 180 | The display is currently 60hz. 181 | The display is set to 72hz. 182 | The mpv speed setting is set to 1.001. 183 | The video now plays at 24fps (23.97602397602398fps * 1.001 = 24). 184 | Every frame is repeated 3 times, so 1:1 playback. 185 | 186 | * > 187 | The display supports 50hz. 188 | The video is 24.95fps. 189 | The display is currently 60hz. 190 | The display is set to 50hz. 191 | The mpv speed setting is set to 1.002004008016032. 192 | The video now plays at 25fps. 193 | 194 | * > 195 | The display supports 60hz. 196 | The display is currently 144hz. 197 | The video is 60fps. 198 | The display is set to 60hz. 199 | 200 | -------------- 201 | 202 | #####License: 203 | 204 | GPL V2 205 | See [LICENSE](https://github.com/kevinlekiller/mpv_scripts/blob/master/LICENSE) 206 | -------------------------------------------------------------------------------- /autospeed/autospeed.lua: -------------------------------------------------------------------------------- 1 | --[[ 2 | See script details on https://github.com/kevinlekiller/mpv_scripts 3 | 4 | Valid --script-opts are (they are all optional): 5 | autospeed-xrandr=false true/false - Use xrandr to change display refresh rate?. 6 | autospeed-speed=false true/false - Adjust speed of the video? 7 | autospeed-display=HDMI1 - Use specified xrandr display, find with xrandr -q, if set to "auto", uses the primary monitor. 8 | autospeed-exitmode=0x48 - Changes the monitor mode (refresh rate) when exiting mpv. 9 | autospeed-exitmode=false Don't change the mode when exiting. If autospeed-exitmode is not set, this is the default. 10 | autospeed-exitmode=auto Change the mode to the mode used when mpv started. 11 | autospeed-exitmode=0x48 Revert to specified mode when exiting mpv. Find a mode using xrandr --verbose (it should look something like 0x123). 12 | autospeed-interlaced=false true/false - Allow using a interlaced mode when switching refresh rates with xrandr? 13 | autospeed-mblacklist=false - List of modes to blacklist. 14 | Modes in this list will be ignored. 15 | If more than one mode is specified, seperate them by semicolon. 16 | Example: autospeed-mblacklist="0x128;0x2fa" 17 | autospeed-minspeed=0.9 Number - Minimum allowable speed to play video at. 18 | autospeed-maxspeed=1.1 Number - Maximum allowable speed to play video at. 19 | autospeed-osd=true true/false - Enable OSD. 20 | autospeed-osdtime=10 Number - How many seconds the OSD will be shown. 21 | autospeed-osdkey=y - Key to press to show the OSD. 22 | autospeed-estfps=false true/false - Calculate/change speed if a video has a variable fps at the cost of higher CPU usage (most videos have a fixed fps). 23 | autospeed-spause true/false - Pause video while switching display modes. 24 | Number - If you set this a number, it will pause for that amount of seconds. 25 | 26 | Example: mpv file.mkv --script-opts=autospeed-xrandr=true,autospeed-speed=false,autospeed-minspeed=0.8 27 | --]] 28 | --[[ 29 | Copyright (C) 2015-2017 kevinlekiller 30 | 31 | This program is free software; you can redistribute it and/or 32 | modify it under the terms of the GNU General Public License 33 | as published by the Free Software Foundation; either version 2 34 | of the License, or (at your option) any later version. 35 | 36 | This program is distributed in the hope that it will be useful, 37 | but WITHOUT ANY WARRANTY; without even the implied warranty of 38 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 39 | GNU General Public License for more details. 40 | 41 | You should have received a copy of the GNU General Public License 42 | along with this program; if not, write to the Free Software 43 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 44 | https://www.gnu.org/licenses/gpl-2.0.html 45 | --]] 46 | local _global = { 47 | osd_start = mp.get_property_osd("osd-ass-cc/0"), 48 | osd_end = mp.get_property_osd("osd-ass-cc/1"), 49 | utils = require 'mp.utils', 50 | modes = {}, 51 | modeCache = {}, 52 | lastDrr = 0, 53 | speedCache = {}, 54 | next = next, 55 | } 56 | 57 | function round(number) 58 | return math.floor(number + 0.5) 59 | end 60 | 61 | function osdEcho() 62 | if (_global.options["osd"] ~= true) then 63 | return 64 | end 65 | setOSD() 66 | if (_global.temp["output"] ~= nil) then 67 | mp.osd_message(_global.temp["output"], _global.options["osdtime"]) 68 | end 69 | end 70 | 71 | function getOptions() 72 | _global.options = { 73 | ["xrandr"] = false, 74 | ["speed"] = false, 75 | ["display"] = "auto", 76 | ["exitmode"] = "auto", 77 | ["interlaced"] = false, 78 | ["mblacklist"] = "false", 79 | ["minspeed"] = 0.9, 80 | ["maxspeed"] = 1.1, 81 | ["osd"] = false, 82 | ["osdtime"] = 10, 83 | ["osdkey"] = "y", 84 | ["estfps"] = false, 85 | ["spause"] = false, 86 | } 87 | for key, value in pairs(_global.options) do 88 | local opt = mp.get_opt("autospeed-" .. key) 89 | if (opt ~= nil) then 90 | if (key == "xrandr" or key == "osd" or key == "estfps" or key == "interlaced" or key == "speed") then 91 | if (opt == "true") then 92 | _global.options[key] = true 93 | end 94 | elseif (key == "minspeed" or key == "maxspeed" or key == "osdtime") then 95 | opt = tonumber(opt) 96 | if (opt ~= nil) then 97 | _global.options[key] = opt 98 | end 99 | elseif (key == "spause") then 100 | if (opt == "true") then 101 | _global.options[key] = 0 102 | else 103 | opt = tonumber(opt) 104 | if (opt ~= nil) then 105 | _global.options[key] = opt 106 | end 107 | end 108 | else 109 | _global.options[key] = opt 110 | end 111 | end 112 | end 113 | if (_global.options["mblacklist"] == "false") then 114 | _global.options["mblacklist"] = false 115 | else 116 | local tmp_blacklist = {} 117 | for blacklist in string.gmatch(_global.options["mblacklist"], '[0-9a-zA-Z]+') do 118 | tmp_blacklist[blacklist] = true 119 | end 120 | _global.options["mblacklist"] = tmp_blacklist 121 | end 122 | end 123 | getOptions() 124 | 125 | function main(name, fps) 126 | if (fps == nil) then 127 | return 128 | end 129 | _global.temp["fps"] = fps 130 | findRefreshRate() 131 | if (_global.options["speed"] == true) then 132 | determineSpeed() 133 | if (_global.temp["speed"] >= _global.options["minspeed"] and _global.temp["speed"] <= _global.options["maxspeed"]) then 134 | mp.set_property_number("speed", _global.temp["speed"]) 135 | else 136 | _global.temp["speed"] = _global.confSpeed 137 | end 138 | else 139 | _global.temp["speed"] = _global.confSpeed 140 | end 141 | end 142 | 143 | function setOSD() 144 | _global.temp["output"] = (_global.osd_start .. 145 | "{\\b1}Original monitor refresh rate{\\b0}\\h\\h" .. _global.temp["start_drr"] .. "Hz\\N" .. 146 | "{\\b1}Current monitor refresh rate{\\b0}\\h\\h" .. _global.temp["drr"] .. "Hz\\N" .. 147 | "{\\b1}Original video fps{\\b0}\\h\\h\\h\\h\\h\\h\\h\\h\\h\\h\\h\\h\\h\\h\\h\\h\\h\\h\\h\\h\\h" .. _global.temp["fps"] .. "fps\\N" .. 148 | "{\\b1}Current video fps{\\b0}\\h\\h\\h\\h\\h\\h\\h\\h\\h\\h\\h\\h\\h\\h\\h\\h\\h\\h\\h\\h\\h" .. (_global.temp["fps"] * _global.temp["speed"]) .. "fps\\N" .. 149 | "{\\b1}Original mpv speed setting{\\b0}\\h\\h\\h\\h\\h\\h" .. _global.confSpeed .. "x\\N" .. 150 | "{\\b1}Current mpv speed setting{\\b0}\\h\\h\\h\\h\\h\\h" .. _global.temp["speed"] .. "x" .. 151 | _global.osd_end 152 | ) 153 | end 154 | 155 | function determineSpeed() 156 | local id = _global.temp["drr"] .. _global.temp["fps"] 157 | if (_global.speedCache[id] ~= nil) then 158 | _global.temp["speed"] = _global.speedCache[id] 159 | return 160 | end 161 | if (_global.temp["drr"] > _global.temp["fps"]) then 162 | local difference = (_global.temp["drr"] / _global.temp["fps"]) 163 | if (difference >= 2) then 164 | -- fps = 24fps, drr = 60hz 165 | -- difference = 60hz/24fps = 3 rounded 166 | -- 24fps * 3 = 72fps 167 | -- 60hz / 72fps = 0.833333333333 speed 168 | -- 72fps * 0.833333333333 = 60fps 169 | _global.temp["speed"] = (_global.temp["drr"] / (_global.temp["fps"] * round(difference))) 170 | else 171 | -- fps = 50fps, drr = 60hz 172 | -- 60hz / 50fps = 1.2 speed 173 | -- 50fps * 1.2 speed = 60fps 174 | 175 | -- fps = 59.94fps, drr = 60hz 176 | -- 60hz / 59.94fps = 1.001001001001001 speed 177 | -- 59.94fps * 1.001001001001001 = 60fps 178 | _global.temp["speed"] = difference 179 | end 180 | elseif (_global.temp["drr"] < _global.temp["fps"]) then 181 | local difference = (_global.temp["fps"] / _global.temp["drr"]) 182 | if (difference >= 2) then 183 | -- fps = 120fps, drr = 25hz 184 | -- difference = 120fps/25hz = 5 rounded 185 | -- 120fps/5 = 24fps ; 25hz / 24fps = 1.04166666667 speed 186 | -- 24fps * 1.04166666667 speed = 25fps 187 | _global.temp["speed"] = (_global.temp["drr"] / (_global.temp["fps"] / round(difference))) 188 | else 189 | -- fps = 60fps, drr = 50hz 190 | -- difference = 50hz / 60fps = 0.833333333333 speed 191 | -- 60fps * 0.833333333333 speed = 50fps 192 | 193 | -- fps = 60fps, drr = 59.94hz 194 | -- difference = 59.94hz / 60fps = 0.999 speed 195 | -- 60fps * 0.999 speed = 59.94fps 196 | _global.temp["speed"] = (_global.temp["drr"] / _global.temp["fps"]) 197 | end 198 | elseif (_global.temp["drr"] == _global.temp["fps"]) then 199 | _global.temp["speed"] = 1 200 | end 201 | _global.speedCache[id] = _global.temp["speed"] 202 | end 203 | 204 | function findRefreshRate() 205 | -- This is to prevent a system call if the screen refresh / video fps has not changed. 206 | if (_global.temp["drr"] == _global.lastDrr) then 207 | return 208 | elseif (_global.modeCache[_global.temp["drr"]] ~= nil) then 209 | setXrandrRate(_global.modeCache[_global.temp["drr"]]) 210 | return 211 | end 212 | if (_global.options["xrandr"] ~= true or getXrandrModes() == false) then 213 | return 214 | end 215 | -- If the current monitor rate is already a multiple, don't change the mode. 216 | if (_global.temp["fps"] <= _global.temp["drr"] and _global.temp["drr"] % _global.temp["fps"] == 0) then 217 | return 218 | end 219 | local round_fps = round(_global.temp["fps"]) 220 | local iterator = 1 221 | if (_global.temp["maxclock"] > round_fps) then 222 | iterator = round(_global.temp["maxclock"] / round_fps) 223 | elseif (_global.temp["maxclock"] < round_fps) then 224 | iterator = round(round_fps / _global.temp["maxclock"]) 225 | else 226 | setXrandrRate(_global.modes[_global.temp["maxclock"]]) 227 | return 228 | end 229 | local smallest = 0 230 | local foundMode = false 231 | for rate, mode in pairs(_global.modes) do 232 | local min = (rate * _global.options["minspeed"]) 233 | local max = (rate * _global.options["maxspeed"]) 234 | for multiplier = 1, iterator do 235 | local multiplied_fps = (multiplier * round_fps) 236 | if (multiplied_fps >= min and multiplied_fps <= max) then 237 | if (multiplied_fps < rate) then 238 | local difference = (rate - multiplied_fps) 239 | if (smallest == 0 or difference < smallest) then 240 | smallest = difference 241 | foundMode = mode 242 | end 243 | elseif (multiplied_fps > rate) then 244 | local difference = (multiplied_fps - rate) 245 | if (smallest == 0 or difference < smallest) then 246 | smallest = difference 247 | foundMode = mode 248 | end 249 | else 250 | setXrandrRate(mode) 251 | return 252 | end 253 | end 254 | end 255 | end 256 | if (foundMode ~= false) then 257 | setXrandrRate(foundMode) 258 | end 259 | end 260 | 261 | function setXrandrRate(mode) 262 | if (mode == _global.temp["currentmode"]) then 263 | return 264 | end 265 | local vars = {vid = nil, time_pos = nil, vdpau = (mp.get_property("options/vo") == "vdpau" or mp.get_property("options/hwdec") == "vdpau")} 266 | if (_global.options["spause"]) then 267 | mp.set_property("pause", "yes") 268 | end 269 | if (vars.vdpau) then 270 | vars.vid = mp.get_property("vid") 271 | vars.time_pos = mp.get_property("time-pos") 272 | mp.set_property("vid", "no") 273 | end 274 | _global.utils.subprocess({["cancellable"] = false, ["args"] = {[1] = "xrandr", [2] = "--output", [3] = _global.options["display"], [4] = "--mode", [5] = mode,}}) 275 | if (_global.options["spause"]) then 276 | if (tonumber(_global.options["spause"]) ~= nil and _global.options["spause"] > 0) then 277 | _global.utils.subprocess({["cancellable"] = false, ["args"] = {[1] = "sleep", [2] = _global.options["spause"]}}) 278 | end 279 | mp.set_property("pause", "no") 280 | end 281 | if (vars.vdpau) then 282 | mp.set_property("vid", vars.vid) 283 | if (vars.time_pos ~= nil) then 284 | mp.commandv("seek", vars.time_pos, "absolute", "keyframes") 285 | end 286 | end 287 | _global.utils.subprocess({["cancellable"] = false, ["args"] = {[1] = "sleep", [2] = "0.5"}}) 288 | _global.temp["drr"] = mp.get_property_native("display-fps") 289 | _global.modeCache[_global.temp["drr"]] = mode 290 | _global.lastDrr = _global.temp["drr"] 291 | _global.temp["currentmode"] = mode 292 | end 293 | 294 | function getXrandrModes() 295 | if (_global.next(_global.modes) ~= nil) then 296 | return true 297 | end 298 | if not (_global.modes) then 299 | return false 300 | end 301 | local vars = { 302 | handle = assert(io.popen("xrandr --verbose")), 303 | foundDisp = false, 304 | foundRes = false, 305 | count = 0, 306 | resolution, 307 | } 308 | if (_global.options["display"] == "auto") then 309 | vars.disp = "^%S+%sconnected%sprimary" 310 | else 311 | vars.disp = "^" .. string.gsub(_global.options["display"], "%-", "%%-") 312 | end 313 | _global.temp["maxclock"] = 0 314 | for line in vars.handle:lines() do 315 | if (vars.foundDisp == false and string.match(line, vars.disp) ~= nil) then -- Check if the display name (ie HDMI1) matches the one in the config. 316 | if (string.find(line, "disconnected") ~= nil) then 317 | break -- Wrong display name was given. 318 | else 319 | local res = string.match(line, vars.disp .. "%D+([%dx]+)") -- Find current monitor resolution. 320 | if (res ~= nil and res ~= "") then 321 | if (_global.options["display"] == "auto") then 322 | _global.options["display"] = string.match(line, "^%S+") 323 | end 324 | vars.resolution = res 325 | vars.foundDisp = true 326 | else 327 | break -- Could not find display resolution. 328 | end 329 | end 330 | elseif (vars.foundDisp == true) then -- We found the display name. 331 | if (vars.foundRes == false and string.match(line, "^%s+" .. vars.resolution) ~= nil) then -- Check if mode uses current display resolution. 332 | vars.foundRes = true 333 | end 334 | if (vars.foundRes == true) then -- We found a matching screen resolution. 335 | vars.count = vars.count + 1 336 | if (vars.count == 1) then -- Log the mode name. 337 | vars.mode = string.match(line, "%((.+)%)%s+[%d.]+MHz") 338 | if (_global.temp["origmode"] == nil) then 339 | if (string.find(line, "%*current") ~= nil) then 340 | _global.temp["origmode"] = vars.mode 341 | _global.temp["currentmode"] = vars.mode 342 | end 343 | end 344 | vars.interlaced = false 345 | if (string.find(line, "Interlace") ~= nil) then 346 | vars.interlaced = true 347 | end 348 | elseif (vars.count == 2) then 349 | 350 | elseif (vars.count == 3) then 351 | if ((_global.options["interlaced"] == false and vars.interlaced == true) or (_global.options["mblacklist"] ~= false and _global.options["mblacklist"][vars.mode] ~= nil)) then 352 | -- ignore these modes 353 | else 354 | local clock = string.match(line, "total%s+%d+.+clock%s+([%d.]+)[KkHh]+z") 355 | clock = round(clock) 356 | if (_global.temp["maxclock"] < clock) then 357 | _global.temp["maxclock"] = clock 358 | end 359 | _global.modes[clock] = vars.mode 360 | end 361 | vars.count = 0 -- Reset variables to look for another matching resolution. 362 | vars.foundRes = false 363 | end 364 | elseif (string.match(line, "^%S") ~= nil) then 365 | break -- We reached the next display or EOF. 366 | end 367 | end 368 | end 369 | vars.handle:close() 370 | if (_global.next(_global.modes) == nil) then 371 | _global.modes = false 372 | return false 373 | end 374 | end 375 | 376 | function start() 377 | mp.unobserve_property(start) 378 | _global.temp = {} 379 | _global.temp["start_drr"] = mp.get_property_native("display-fps") 380 | if not (_global.temp["start_drr"]) then 381 | return 382 | end 383 | _global.temp["drr"] = _global.temp["start_drr"] 384 | if not (_global.confSpeed) then 385 | _global.confSpeed = mp.get_property_native("speed") 386 | end 387 | local test = mp.get_property("container-fps") 388 | if (test == nil or test == "nil property unavailable") then 389 | if (_global.options["estfps"] ~= true) then 390 | return 391 | end 392 | test = mp.get_property("estimated-vf-fps") 393 | if (test == nil or test == "nil property unavailable") then 394 | return 395 | end 396 | mp.observe_property("estimated-vf-fps", "number", main) 397 | else 398 | mp.observe_property("container-fps", "number", main) 399 | end 400 | mp.add_key_binding(_global.options["osdkey"], mp.get_script_name(), osdEcho, {repeatable=true}) 401 | if (_global.options["xrandr"] == true and _global.options.exitmode ~= "false") then 402 | function revertDrr() 403 | if (_global.options["display"] ~= "auto") then 404 | if (_global.options["exitmode"] == "auto" and _global.temp["origmode"] ~= nil) then 405 | os.execute("xrandr --output " .. _global.options["display"] .. " --mode " .. _global.temp["origmode"] .. " &") 406 | else 407 | os.execute("xrandr --output " .. _global.options["display"] .. " --mode " .. _global.options["exitmode"] .. " &") 408 | end 409 | end 410 | end 411 | mp.register_event("shutdown", revertDrr) 412 | end 413 | end 414 | 415 | -- Wait until we get a video fps. 416 | function check() 417 | mp.observe_property("estimated-vf-fps", "string", start) 418 | end 419 | 420 | mp.register_event("file-loaded", check) 421 | -------------------------------------------------------------------------------- /autospeedwin/README.md: -------------------------------------------------------------------------------- 1 | # autospeedwin 2 | 3 | ######Lua script for [mpv](https://mpv.io/) to adjust monitor refresh rate and video speed for almost 1:1 playback. 4 | 5 | -------------- 6 | 7 | #####Notes: 8 | 9 | * This script is for the Microsoft Windows operating systems, [see here for the *nix version](https://github.com/kevinlekiller/mpv_scripts/tree/master/autospeed). 10 | 11 | * Can use (recommended) [nircmd](http://www.nirsoft.net/utils/nircmd.html) To set your monitor refresh rate closer to the video playback speed. 12 | 13 | * By default mpv will adjust the audio pitch to match the speed difference. You can read the [mpv manual](http://mpv.io/manual/master/#options-audio-pitch-correction) for more information on this. 14 | 15 | * Works better with mpv's [`--video-sync=display-resample`](https://mpv.io/manual/master/#options-video-sync) 16 | If using mpv's [`--video-sync=display-resample`](https://mpv.io/manual/master/#options-video-sync), do not use `autospeed-speed=true` 17 | If you have issues with mpv's [`--video-sync=display-resample`](https://mpv.io/manual/master/#options-video-sync), you can use `--video-sync=audio` and `autospeed-speed=true`, which still produces acceptable results. 18 | 19 | -------------- 20 | 21 | #####Basic Description: 22 | 23 | Optionally changes the monitor refresh rate to be closer to the video fps, then sets 24 | the speed of the video to be closer to the monitor refresh rate. 25 | 26 | Lower resource usage than using interpolation. 27 | 28 | -------------- 29 | 30 | #####Script options: 31 | 32 | The script can read options from mpv's [--script-opts](http://mpv.io/manual/master/#options-script-opts) option. 33 | 34 | Valid options (and examples): 35 | 36 | autospeed-nircmd=false 37 | true/false - Use nircmd to change the refresh rate of your monitor. 38 | nircmd will be used to change the refresh rate of your monitor based on options listed below. 39 | autospeed-speed=false 40 | Default: false 41 | true/false - Adjust speed of the video? 42 | If set to true, the mpv speed setting will be changed based on the video 43 | fps and display refresh rate. 44 | Do not use this with mpv's --video-sync=display-resample 45 | autospeed-nircmdc="nircmdc" 46 | String - Path to nircmdc executable file. 47 | If not set, nircmdc will be searched in Windows PATH variable. 48 | If you set this "" or "nircmdc", Windows will look in your PATH for nircmdc, 49 | otherwise you can specify a path, for example "c:\programs\nircmdc.exe" 50 | autospeed-monitor=0 51 | Number - Which monitor (display) to set the refresh rate on. 52 | This will be sent to nircmd when setting the refresh rate. 53 | autospeed-dwidth=1920 54 | Number - Display width. 55 | This will be sent to nircmd when setting the refresh rate. 56 | autospeed-dheight=1080 57 | Number - Display height. 58 | This will be sent to nircmd when setting the refresh rate. 59 | autospeed-bdepth=32 60 | Number - Display bit depth. 32 is usually the default. 61 | This will be sent to nircmd when setting the refresh rate. 62 | autospeed-rates="60" 63 | String - String of refresh rates your monitor supports and you want 64 | to use, separated by semicolons. Nircmd seems to prefer rounded 65 | numbers, 72 instead of 71.92 for example. 66 | This is the list of refresh rates you want autospeed to use when it changes your monitor refresh rate. 67 | Examples: autospeed-rates="60" | autospeed-rates="50;60;72" 68 | Note: If you want a rate to be prefered over another, for example the video is 24hz 69 | and your rates are "100;120;144", but you want 144hz instead of 120hz for 24fps videos, change the 70 | order to autospeed-rates="100;144;120", then 144hz will take precendence over 120hz. 71 | autospeed-exitrate=60 72 | Number - Which refresh rate to set when exiting mpv. Set to 0 to ignore. 73 | When mpv exits, if you want your monitor to go back to a specific refresh rate. 74 | autospeed-minspeed=0.9 75 | Number - Minimum allowable speed to play video at. 76 | Does not change mpv's speed setting if the calculated speed is lower than this. 77 | This is to prevent the video looking like it is in slow motion. 78 | A value of 0.9 allows playing the video at minimum, 10% slower. 79 | autospeed-maxspeed=1.1 80 | Number - Maximum allowable speed to play video at. 81 | Does not change mpv's speed setting if the calculated speed is higher than this. 82 | This is to prevent the video looking like it is in fast forward. 83 | A value of 1.1 allows playing the video at maximum, 10% faster. 84 | autospeed-osd=false 85 | true/false - Enable OSD. 86 | This enables/disables the other autospeed-osd settings. 87 | autospeed-osdtime=10 88 | Number - How many seconds the OSD will be shown. 89 | autospeed-osdkey=y 90 | Key to press to show the OSD. 91 | This follows the same standard as mpv's input.conf for keybindgs. 92 | Pressing this key will display autospeed information on mpv's OSD. 93 | autospeed-estfps=false 94 | true/false - Calculate/change speed if a video has a variable fps 95 | at the cost of higher CPU usage. 96 | If a video has a variable frame rate (fps), 97 | calculate / set the mpv speed based on the current video frame rate. 98 | This option will do nothing for most videos because, only few of them have variable fps. 99 | For example, most (all?) bluray videos have variable frame rates. 100 | Since the speed calulation must be done every time the video fps changes, 101 | this increases CPU load slightly. 102 | autospeed-spause=4 103 | Default: false 104 | true/false - Pause video while switching display modes. 105 | true: This will pause the video before and after switching the mode. 106 | false: Disables this option. 107 | Number - This enables the pause like true and sleeps for this amount of seconds. 108 | If bigger than 0: After switching the mode, we will wait this amount 109 | of seconds before unpausing the video. 110 | If set to 0: It disables the option, like false. 111 | Before switching the display mode (refresh rate), pause the video, unpause after 112 | it is switched. This can be used if you don't want to miss 113 | some of the video while your display is blank (my display is blank for ~5 seconds 114 | while switching modes). 115 | 116 | Examples: 117 | Setting the options at the command line: 118 | mpv file.mkv --script-opts=autospeed-speed=true,autospeed-estfps=true,autospeed-minspeed=0.8 119 | Setting the options in %APPDATA%\mpv\mpv.conf: 120 | script-opts=autospeed-nircmd=true,autospeed-speed=false,autospeed-nircmdc="nircmdc",autospeed-monitor=0,autospeed-dwidth=1920,autospeed-dheight=1080,autospeed-bdepth=32,autospeed-rates="60;72",autospeed-exitrate=60,autospeed-minspeed=0.9,autospeed-maxspeed=1.1,autospeed-osd=true,autospeed-osdtime=10,autospeed-osdkey=y,autospeed-estfps=false,autospeed-spause=4 121 | 122 | -------------- 123 | 124 | #####Installation: 125 | 126 | Put the file inside the mpv\scripts folder, see the [mpv man page](https://github.com/mpv-player/mpv/blob/master/DOCS/man/mpv.rst#files) for the correct path, should be `%APPDATA%\mpv\scripts\`. 127 | 128 | 129 | Direct download link: 130 | [autospeedwin.lua](https://raw.githubusercontent.com/kevinlekiller/mpv_scripts/master/autospeedwin/autospeedwin.lua) 131 | 132 | -------------- 133 | 134 | #####Examples: 135 | 136 | * > 137 | The display supports 72hz. 138 | The video is 23.97602397602398fps. 139 | The display is currently 60hz. 140 | The display is set to 72hz. 141 | The mpv speed setting is set to 1.001. 142 | The video now plays at 24fps (23.97602397602398fps * 1.001 = 24). 143 | Every frame is repeated 3 times, so 1:1 playback. 144 | 145 | * > 146 | The display supports 50hz. 147 | The video is 24.95fps. 148 | The display is currently 60hz. 149 | The display is set to 50hz. 150 | The mpv speed setting is set to 1.002004008016032. 151 | The video now plays at 25fps. 152 | 153 | * > 154 | The display supports 60hz. 155 | The display is currently 144hz. 156 | The video is 60fps. 157 | The display is set to 60hz. 158 | 159 | -------------- 160 | 161 | #####License: 162 | 163 | GPL V2 164 | See [LICENSE](https://github.com/kevinlekiller/mpv_scripts/blob/master/LICENSE) 165 | -------------------------------------------------------------------------------- /autospeedwin/autospeedwin.lua: -------------------------------------------------------------------------------- 1 | --[[ 2 | See script details on https://github.com/kevinlekiller/mpv_scripts 3 | 4 | Valid --script-opts are (they are all optional): 5 | autospeed-nircmd=false true/false - Use nircmd to change the refresh rate of your monitor. 6 | autospeed-speed=false true/false - Adjust speed of the video?. 7 | autospeed-nircmdc="nircmdc" String - Path to nircmdc executable file. If not set, nircmdc will be searched in Windows PATH variable. 8 | autospeed-monitor=0 Number - Which monitor (display) to set the refresh rate on. 9 | autospeed-dwidth=1920 Number - Display width. 10 | autospeed-dheight=1080 Number - Display height. 11 | autospeed-bdepth=32 Number - Display bit depth. 12 | autospeed-rates="60" String - String of refresh rates your monitor supports and you want to use, separated by semicolons. 13 | Nircmd seems to prefer rounded numbers, 72 instead of 71.92 for example. 14 | Examples: autospeed-rates="60" | autospeed-rates="50;60;72" 15 | Note if you want a rate to be prefered over another, for example the video is 24hz 16 | and your rates are "100;120;144", but you want 144hz instead of 120hz for 24fps videos, change the 17 | order to autospeed-rates="100;144;120", then 144hz will take precendence over 120hz. 18 | autospeed-exitrate=60 Number - Which refresh rate to set when exiting mpv. Set to 0 to ignore. 19 | autospeed-minspeed=0.9 Number - Minimum allowable speed to play video at. 20 | autospeed-maxspeed=1.1 Number - Maximum allowable speed to play video at. 21 | autospeed-osd=true true/false - Enable OSD. 22 | autospeed-osdtime=10 Number - How many seconds the OSD will be shown. 23 | autospeed-osdkey=y - Key to press to show the OSD. 24 | autospeed-estfps=false true/false - Calculate/change speed if a video has a variable fps at the cost of higher CPU usage (most videos have a fixed fps). 25 | autospeed-spause true/false - Pause video while switching display modes. 26 | Number - If you set this a number, it will pause for that amount of seconds. 27 | 28 | Example: mpv file.mkv --script-opts=autospeed-nircmd=true,autospeed-minspeed=0.8 29 | --]] 30 | --[[ 31 | Copyright (C) 2016-2017 kevinlekiller 32 | 33 | This program is free software; you can redistribute it and/or 34 | modify it under the terms of the GNU General Public License 35 | as published by the Free Software Foundation; either version 2 36 | of the License, or (at your option) any later version. 37 | 38 | This program is distributed in the hope that it will be useful, 39 | but WITHOUT ANY WARRANTY; without even the implied warranty of 40 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 41 | GNU General Public License for more details. 42 | 43 | You should have received a copy of the GNU General Public License 44 | along with this program; if not, write to the Free Software 45 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 46 | https://www.gnu.org/licenses/gpl-2.0.html 47 | --]] 48 | local _global = { 49 | osd_start = mp.get_property_osd("osd-ass-cc/0"), 50 | osd_end = mp.get_property_osd("osd-ass-cc/1"), 51 | utils = require 'mp.utils', 52 | rateCache = {}, 53 | lastDrr = 0, 54 | speedCache = {}, 55 | next = next, 56 | } 57 | 58 | function round(number) 59 | return math.floor(number + 0.5) 60 | end 61 | 62 | function osdEcho() 63 | if (_global.options["osd"] ~= true) then 64 | return 65 | end 66 | setOSD() 67 | if (_global.temp["output"] ~= nil) then 68 | mp.osd_message(_global.temp["output"], _global.options["osdtime"]) 69 | end 70 | end 71 | 72 | function getOptions() 73 | _global.options = { 74 | ["nircmd"] = false, 75 | ["speed"] = false, 76 | ["nircmdc"] = "nircmdc", 77 | ["monitor"] = 0, 78 | ["dwidth"] = 1920, 79 | ["dheight"] = 1080, 80 | ["bdepth"] = 32, 81 | ["rates"] = "", 82 | ["exitrate"] = 0, 83 | ["minspeed"] = 0.9, 84 | ["maxspeed"] = 1.1, 85 | ["osd"] = false, 86 | ["osdtime"] = 10, 87 | ["osdkey"] = "y", 88 | ["estfps"] = false, 89 | ["spause"] = 0, 90 | } 91 | for key, value in pairs(_global.options) do 92 | local opt = mp.get_opt("autospeed-" .. key) 93 | if (opt ~= nil) then 94 | if ((key == "nircmd" or key == "speed" or key == "osd" or key == "estfps") and opt == "true") then 95 | _global.options[key] = true 96 | elseif (key == "minspeed" or key == "maxspeed" or key == "osdtime" or key == "monitor" or key == "dwidth" or key == "dheight" or key == "bdepth" or key == "exitrate" or key == "spause") then 97 | local test = tonumber(opt) 98 | if (test ~= nil) then 99 | _global.options[key] = test 100 | end 101 | else 102 | _global.options[key] = opt 103 | end 104 | end 105 | end 106 | end 107 | getOptions() 108 | 109 | function main(name, fps) 110 | if (fps == nil) then 111 | return 112 | end 113 | _global.temp["fps"] = fps 114 | findRefreshRate() 115 | determineSpeed() 116 | if (_global.options["speed"] == true and _global.temp["speed"] >= _global.options["minspeed"] and _global.temp["speed"] <= _global.options["maxspeed"]) then 117 | mp.set_property_number("speed", _global.temp["speed"]) 118 | else 119 | _global.temp["speed"] = _global.confSpeed 120 | end 121 | end 122 | 123 | function setOSD() 124 | _global.temp["output"] = (_global.osd_start .. 125 | "{\\b1}Original monitor refresh rate{\\b0}\\h\\h" .. _global.temp["start_drr"] .. "Hz\\N" .. 126 | "{\\b1}Current monitor refresh rate{\\b0}\\h\\h" .. _global.temp["drr"] .. "Hz\\N" .. 127 | "{\\b1}Original video fps{\\b0}\\h\\h\\h\\h\\h\\h\\h\\h\\h\\h\\h\\h\\h\\h\\h\\h\\h\\h\\h\\h\\h" .. _global.temp["fps"] .. "fps\\N" .. 128 | "{\\b1}Current video fps{\\b0}\\h\\h\\h\\h\\h\\h\\h\\h\\h\\h\\h\\h\\h\\h\\h\\h\\h\\h\\h\\h\\h" .. (_global.temp["fps"] * _global.temp["speed"]) .. "fps\\N" .. 129 | "{\\b1}Original mpv speed setting{\\b0}\\h\\h\\h\\h\\h\\h" .. _global.confSpeed .. "x\\N" .. 130 | "{\\b1}Current mpv speed setting{\\b0}\\h\\h\\h\\h\\h\\h" .. _global.temp["speed"] .. "x" .. 131 | _global.osd_end 132 | ) 133 | end 134 | 135 | function determineSpeed() 136 | local id = _global.temp["drr"] .. _global.temp["fps"] 137 | if (_global.speedCache[id] ~= nil) then 138 | _global.temp["speed"] = _global.speedCache[id] 139 | return 140 | end 141 | if (_global.temp["drr"] > _global.temp["fps"]) then 142 | local difference = (_global.temp["drr"] / _global.temp["fps"]) 143 | if (difference >= 2) then 144 | -- fps = 24fps, drr = 60hz 145 | -- difference = 60hz/24fps = 3 rounded 146 | -- 24fps * 3 = 72fps 147 | -- 60hz / 72fps = 0.833333333333 speed 148 | -- 72fps * 0.833333333333 = 60fps 149 | _global.temp["speed"] = (_global.temp["drr"] / (_global.temp["fps"] * round(difference))) 150 | else 151 | -- fps = 50fps, drr = 60hz 152 | -- 60hz / 50fps = 1.2 speed 153 | -- 50fps * 1.2 speed = 60fps 154 | 155 | -- fps = 59.94fps, drr = 60hz 156 | -- 60hz / 59.94fps = 1.001001001001001 speed 157 | -- 59.94fps * 1.001001001001001 = 60fps 158 | _global.temp["speed"] = difference 159 | end 160 | elseif (_global.temp["drr"] < _global.temp["fps"]) then 161 | local difference = (_global.temp["fps"] / _global.temp["drr"]) 162 | if (difference >= 2) then 163 | -- fps = 120fps, drr = 25hz 164 | -- difference = 120fps/25hz = 5 rounded 165 | -- 120fps/5 = 24fps ; 25hz / 24fps = 1.04166666667 speed 166 | -- 24fps * 1.04166666667 speed = 25fps 167 | _global.temp["speed"] = (_global.temp["drr"] / (_global.temp["fps"] / round(difference))) 168 | else 169 | -- fps = 60fps, drr = 50hz 170 | -- difference = 50hz / 60fps = 0.833333333333 speed 171 | -- 60fps * 0.833333333333 speed = 50fps 172 | 173 | -- fps = 60fps, drr = 59.94hz 174 | -- difference = 59.94hz / 60fps = 0.999 speed 175 | -- 60fps * 0.999 speed = 59.94fps 176 | _global.temp["speed"] = (_global.temp["drr"] / _global.temp["fps"]) 177 | end 178 | elseif (_global.temp["drr"] == _global.temp["fps"]) then 179 | _global.temp["speed"] = 1 180 | end 181 | _global.speedCache[id] = _global.temp["speed"] 182 | end 183 | 184 | function findRefreshRate() 185 | -- This is to prevent a system call if the screen refresh / video fps has not changed. 186 | if (_global.temp["drr"] == _global.lastDrr) then 187 | return 188 | elseif (_global.rateCache[_global.temp["drr"]] ~= nil) then 189 | setRate(_global.rateCache[_global.temp["drr"]]) 190 | return 191 | end 192 | if (_global.options["nircmd"] ~= true or _global.options["rates"] == "") then 193 | return 194 | end 195 | local floor_fps = math.floor(_global.temp["fps"]) 196 | if (_global.temp["maxrate"] == nil) then 197 | _global.temp["maxrate"] = 0 198 | for rate in string.gmatch(_global.options["rates"], "[%w.]+") do 199 | rate = tonumber(rate) 200 | if (rate > _global.temp["maxrate"]) then 201 | _global.temp["maxrate"] = rate 202 | end 203 | end 204 | if (_global.temp["maxrate"] == 0) then 205 | _global.options["rates"] = "" 206 | return 207 | end 208 | end 209 | local iterator = 1 210 | if (_global.temp["maxrate"] > floor_fps) then 211 | iterator = round(_global.temp["maxrate"] / floor_fps) 212 | elseif (_global.temp["maxrate"] < floor_fps) then 213 | iterator = round(floor_fps / _global.temp["maxrate"]) 214 | else 215 | setRate(_global.temp["maxrate"]) 216 | return 217 | end 218 | local smallest = 0 219 | local foundRate = false 220 | for rate in string.gmatch(_global.options["rates"], "[%w.]+") do 221 | rate = tonumber(rate) 222 | local min = (rate * _global.options["minspeed"]) 223 | local max = (rate * _global.options["maxspeed"]) 224 | for multiplier = 1, iterator do 225 | local multiplied_fps = (multiplier * floor_fps) 226 | if (multiplied_fps >= min and multiplied_fps <= max) then 227 | if (multiplied_fps < rate) then 228 | local difference = (rate - multiplied_fps) 229 | if (smallest == 0 or difference < smallest) then 230 | smallest = difference 231 | foundRate = rate 232 | end 233 | elseif (multiplied_fps > rate) then 234 | local difference = (multiplied_fps - rate) 235 | if (smallest == 0 or difference < smallest) then 236 | smallest = difference 237 | foundRate = rate 238 | end 239 | else 240 | setRate(rate) 241 | return 242 | end 243 | end 244 | end 245 | end 246 | if (foundRate ~= false) then 247 | setRate(foundRate) 248 | end 249 | end 250 | 251 | function setRate(rate) 252 | local paused = mp.get_property("pause") 253 | if (_global.options["spause"] > 0 and paused ~= "yes") then 254 | mp.set_property("pause", "yes") 255 | end 256 | _global.utils.subprocess({ 257 | ["cancellable"] = false, 258 | ["args"] = { 259 | [1] = _global.options["nircmdc"], 260 | [2] = "setdisplay", 261 | [3] = "monitor:" .. _global.options["monitor"], 262 | [4] = _global.options["dwidth"], 263 | [5] = _global.options["dheight"], 264 | [6] = _global.options["bdepth"], 265 | [7] = rate 266 | } 267 | }) 268 | if (_global.options["spause"] > 0 and paused ~= "yes") then 269 | --os.execute("ping -n " .. _global.options["spause"] .. " localhost > NUL") 270 | _global.utils.subprocess({ 271 | ["cancellable"] = false, 272 | ["args"] = { 273 | [1] = "ping", 274 | [2] = "-n", 275 | [3] = _global.options["spause"], 276 | [4] = "localhost", 277 | [5] = ">", 278 | [6] = "NUL" 279 | } 280 | }) 281 | mp.set_property("pause", "no") 282 | end 283 | --os.execute("ping -n 2 localhost > NUL") 284 | _global.utils.subprocess({ 285 | ["cancellable"] = false, 286 | ["args"] = { 287 | [1] = "ping", 288 | [2] = "-n", 289 | [3] = "2", 290 | [4] = "localhost", 291 | [5] = ">", 292 | [6] = "NUL" 293 | } 294 | }) 295 | _global.temp["drr"] = mp.get_property_native("display-fps") 296 | _global.rateCache[_global.temp["drr"]] = rate 297 | _global.lastDrr = _global.temp["drr"] 298 | end 299 | 300 | function start() 301 | mp.unobserve_property(start) 302 | _global.temp = {} 303 | _global.temp["start_drr"] = mp.get_property_native("display-fps") 304 | if not (_global.temp["start_drr"]) then 305 | return 306 | end 307 | _global.temp["drr"] = _global.temp["start_drr"] 308 | if not (_global.confSpeed) then 309 | _global.confSpeed = mp.get_property_native("speed") 310 | end 311 | local test = mp.get_property("container-fps") 312 | if (test == nil or test == "nil property unavailable") then 313 | if (_global.options["estfps"] ~= true) then 314 | return 315 | end 316 | test = mp.get_property("estimated-vf-fps") 317 | if (test == nil or test == "nil property unavailable") then 318 | return 319 | end 320 | mp.observe_property("estimated-vf-fps", "number", main) 321 | else 322 | mp.observe_property("container-fps", "number", main) 323 | end 324 | mp.add_key_binding(_global.options["osdkey"], mp.get_script_name(), osdEcho, {repeatable=true}) 325 | if (_global.options["nircmd"] == true and _global.options["exitrate"] > 0) then 326 | function revertDrr() 327 | _global.utils.subprocess({ 328 | ["cancellable"] = false, 329 | ["args"] = { 330 | [1] = _global.options["nircmdc"], 331 | [2] = "setdisplay", 332 | [3] = "monitor:" .. _global.options["monitor"], 333 | [4] = _global.options["dwidth"], 334 | [5] = _global.options["dheight"], 335 | [6] = _global.options["bdepth"], 336 | [7] = _global.options["exitrate"] 337 | } 338 | }) 339 | end 340 | mp.register_event("shutdown", revertDrr) 341 | end 342 | end 343 | 344 | -- Wait until we get a video fps. 345 | function check() 346 | mp.observe_property("estimated-vf-fps", "string", start) 347 | end 348 | 349 | mp.register_event("file-loaded", check) 350 | -------------------------------------------------------------------------------- /maximize/README.md: -------------------------------------------------------------------------------- 1 | # maximize 2 | 3 | Note: Microsoft Windows only. 4 | 5 | [mpv](https://mpv.io/) script for maximizing mpv when exiting full screen or startup on Microsoft Windows using [nircmd](http://www.nirsoft.net/utils/nircmd.html). 6 | 7 | Requires nircmdc.exe in PATH 8 | 9 | Download nircdm at the bottom of this page: http://www.nirsoft.net/utils/nircmd.html 10 | 11 | Download link for the script: https://raw.githubusercontent.com/kevinlekiller/mpv_scripts/master/maximize/maximize.lua 12 | 13 | ---- 14 | #License: 15 | 16 | https://github.com/kevinlekiller/mpv_scripts/blob/master/LICENSE 17 | -------------------------------------------------------------------------------- /maximize/maximize.lua: -------------------------------------------------------------------------------- 1 | --[[ 2 | Script to maximize mpv on start or fullscreen exit on Windows O/S using nircmd. 3 | Requires nircmdc.exe in PATH 4 | 5 | https://github.com/kevinlekiller/mpv_scripts 6 | --]] 7 | --[[ 8 | Copyright (C) 2015-2017 kevinlekiller 9 | 10 | This program is free software; you can redistribute it and/or 11 | modify it under the terms of the GNU General Public License 12 | as published by the Free Software Foundation; either version 2 13 | of the License, or (at your option) any later version. 14 | 15 | This program is distributed in the hope that it will be useful, 16 | but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with this program; if not, write to the Free Software 22 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 23 | https://www.gnu.org/licenses/gpl-2.0.html 24 | --]] 25 | 26 | -- This is better than os.execute since it doesn't pop up command prompts. 27 | mputils = require 'mp.utils' 28 | local command = {} 29 | command["args"] = {} 30 | command["args"][1] = "nircmdc" 31 | command["args"][2] = "win" 32 | command["args"][3] = "" 33 | command["args"][4] = "process" 34 | command["args"][5] = "mpv.exe" 35 | 36 | -- This is so we don't run maximize_no_fs 2 times on start. 37 | local start = true 38 | 39 | -- Maximize the window on start on Windows O/S using nircmd. 40 | function maximize_start() 41 | start = false 42 | if (mp.get_property("fullscreen") == "no") then 43 | command["args"][3] = "max" 44 | mputils.subprocess(command) 45 | end 46 | end 47 | mp.register_event("video-reconfig", maximize_start) 48 | 49 | -- Maximize the window when exiting fullscreen. 50 | function maximize_no_fs() 51 | if (start == false and mp.get_property("fullscreen") == "no") then 52 | -- This is kind of a hack to force it to maximize. 53 | command["args"][3] = "togglemax" 54 | mputils.subprocess(command) 55 | command["args"][3] = "max" 56 | mputils.subprocess(command) 57 | end 58 | end 59 | mp.observe_property("fullscreen", "string", maximize_no_fs) 60 | -------------------------------------------------------------------------------- /mkvrg/README.md: -------------------------------------------------------------------------------- 1 | # mkvrg 2 | 3 | When a file is loaded into [mpv](https://mpv.io/), this script will check if it's a local mkv file. 4 | 5 | If the file is missing replaygain tags, it will scan them with bs1770gain, using --ebu, --samplepeak (much faster than --truepeak) and --range options. 6 | 7 | While bs1770gain scans the file, the video is paused, the time it takes varies based on CPU power, the amount of audio channels / length of the audio track in the audio stream in the mkv file. 8 | 9 | On a laptop with a Intel Core i3, a 2 hour 6 audio channels mkv file can take around 2 minutes, while a desktop with a Intel Core i7 can take about 25 seconds. 10 | 11 | If bs1770gain succeeds, replaygain tags are applied using mkvpropedit. 12 | 13 | mpv will then see the replaygain tags, and use them if you have the appropriate setting : https://mpv.io/manual/master/#audio-filters-volume 14 | 15 | For example : `mpv --af=volume:replaygain-track:detach example.mkv` 16 | 17 | This script is based on https://github.com/kevinlekiller/mkvrg which can be used outside of mpv, so you can scan your files before playing them with mpv, avoiding the pause. 18 | 19 | ---- 20 | #Options 21 | 22 | You can enable mkvrg.lua OSD messages in mpv by passing the script-opts option mkvrg-osd=true, like this: `mpv --script-opts=mkvrg-osd=true example.mkv` 23 | 24 | ---- 25 | #Requirements: 26 | 27 | These programs are required for this script to function: 28 | 29 | bs1770gain : http://bs1770gain.sourceforge.net/ 30 | 31 | mkvpropedit : https://mkvtoolnix.download/ 32 | 33 | ---- 34 | #Download 35 | 36 | Download link for the script: https://raw.githubusercontent.com/kevinlekiller/mpv_scripts/master/mkvrg/mkvrg.lua 37 | 38 | ---- 39 | #License: 40 | 41 | https://github.com/kevinlekiller/mpv_scripts/blob/master/LICENSE 42 | -------------------------------------------------------------------------------- /mkvrg/mkvrg.lua: -------------------------------------------------------------------------------- 1 | --[[ 2 | https://github.com/kevinlekiller/mpv_scripts 3 | 4 | When a file is loaded into mpv, this script will check if it's a local mkv file. 5 | If the file is missing replaygain tags, it will scan them with bs1770gain, 6 | using --ebu, --samplepeak (much faster than --truepeak) and --range options. 7 | If bs1770gain succeeds, tags are applied using mkvpropedit. 8 | mpv will then see the replaygain tags, and use them if you have the 9 | appropriate setting : https://mpv.io/manual/master/#audio-filters-volume 10 | For example : mpv --af=volume:replaygain-track:detach 11 | 12 | You can enable mkvrg.lua OSD messages in mpv by passing the script-opts 13 | option mkvrg-osd=true, like this: mpv --script-opts=mkvrg-osd=true 14 | 15 | These programs are required for this script to function: 16 | bs1770gain : http://bs1770gain.sourceforge.net/ 17 | mkvpropedit : https://mkvtoolnix.download/ 18 | 19 | This script is based on https://github.com/kevinlekiller/mkvrg 20 | --]] 21 | --[[ 22 | Copyright (C) 2017 kevinlekiller 23 | 24 | This program is free software; you can redistribute it and/or 25 | modify it under the terms of the GNU General Public License 26 | as published by the Free Software Foundation; either version 2 27 | of the License, or (at your option) any later version. 28 | 29 | This program is distributed in the hope that it will be useful, 30 | but WITHOUT ANY WARRANTY; without even the implied warranty of 31 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 32 | GNU General Public License for more details. 33 | 34 | You should have received a copy of the GNU General Public License 35 | along with this program; if not, write to the Free Software 36 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 37 | https://www.gnu.org/licenses/gpl-2.0.html 38 | --]] 39 | 40 | local osd = mp.get_opt("mkvrg-" .. "osd") 41 | osd = (osd ~= nil and osd == "true") 42 | local utils = require 'mp.utils' 43 | local msg = require 'mp.msg' 44 | 45 | local function file_exists(path) 46 | local handle = io.open(path, "r") 47 | if handle ~= nil then 48 | handle:close() 49 | return true 50 | end 51 | return false 52 | end 53 | 54 | local function process() 55 | if mp.get_property("file-format") ~= "mkv" then 56 | msg.info("File is not mkv, skipping.") 57 | return 58 | end 59 | local tlist = mp.get_property_native("track-list") 60 | if type(tlist) ~= "table" then 61 | return 62 | end 63 | local ids = false 64 | for key,value in pairs(tlist) do 65 | if value["external"] then 66 | msg.info("File is not local. skipping.") 67 | break 68 | elseif (value["type"] == "audio" and value["selected"] == true) then 69 | if (value["replaygain-track-gain"] == nil and value["replaygain-track-peak"] == nil) then 70 | ids = {["ffid"] = value["ff-index"], ["id"] = value["id"]} 71 | msg.info("No replaygain found, processing file.") 72 | else 73 | msg.info("File already has replaygain info. skipping.") 74 | end 75 | break 76 | end 77 | end 78 | if type(ids) ~= "table" then 79 | return 80 | end 81 | local path = mp.get_property("working-directory") .. "/" .. mp.get_property("path") 82 | if not file_exists(path) then 83 | msg.warn("File not found: '" .. path .. "', skipping.") 84 | return 85 | end 86 | if osd then 87 | mp.osd_message("mkvrg: Scanning file for replaygain, this can take a few minutes.", 10) 88 | end 89 | local output = utils.subprocess({ 90 | ["cancellable"] = false, 91 | ["args"] = { 92 | [1] = "bs1770gain", 93 | [2] = "--ebu", 94 | [3] = "--audio", 95 | [4] = ids["ffid"], 96 | [5] = "-rp", 97 | [6] = path, 98 | } 99 | }) 100 | if osd then 101 | mp.osd_message("", 0) 102 | end 103 | if output["error"] ~= nil then 104 | msg.warn("Problem getting replaygain info from bs1770gain, skipping.") 105 | return 106 | end 107 | local rg = {["gain"] = false, ["range"] = false, ["peak"] = false} 108 | for line in string.gmatch(output["stdout"], "[^\r\n]+") do 109 | if (rg["gain"] and rg["range"] and rg["peak"]) then 110 | break 111 | end 112 | if (rg["gain"] == false and string.match(line, "integrated")) then 113 | rg["gain"] = string.gsub(line, "%s*integrated.*/%s+", "") 114 | rg["gain"] = string.gsub(rg["gain"], "%s+LU%s*", "") 115 | elseif (rg["range"] == false and string.match(line, "range")) then 116 | rg["range"] = string.gsub(line, "%s*range:%s*", "") 117 | rg["range"] = string.gsub(rg["range"], "%s*LUFS%s*", "") 118 | elseif (rg["peak"] == false and string.match(line, "peak")) then 119 | rg["peak"] = string.gsub(line, "%s*sample%s*peak.*/%s+", "") 120 | rg["peak"] = string.gsub(rg["peak"], "s*$", "") 121 | end 122 | end 123 | if not (rg["gain"] and rg["range"] and rg["peak"]) then 124 | msg.warn("Could not parse replaygain info for file, skipping.") 125 | return 126 | end 127 | local xml = [===[ 128 | 129 | 130 | 131 | 132 | 133 | 134 | REPLAYGAIN_ALGORITHM 135 | ITU-R BS.1770 136 | 137 | 138 | REPLAYGAIN_REFERENCE_LOUDNESS 139 | -23.0 140 | 141 | 142 | REPLAYGAIN_TRACK_GAIN 143 | ]===] .. rg["gain"] .. [===[ 144 | 145 | 146 | REPLAYGAIN_TRACK_RANGE 147 | ]===] .. rg["range"] .. [===[ 148 | 149 | 150 | REPLAYGAIN_TRACK_PEAK 151 | ]===] .. rg["peak"] .. [===[ 152 | 153 | 154 | ]===] 155 | 156 | local tmppath = os.tmpname() 157 | local handle = io.open(tmppath, "w") 158 | if handle == nil then 159 | msg.warn("Could not open '" .. tmppath .. "' for writing, skipping.") 160 | return 161 | end 162 | handle:write(xml) 163 | handle:close() 164 | if os.execute("mkvpropedit --tags track:" .. (tonumber(ids["ffid"]) + 1) .. ":" .. tmppath .. " " .. path) ~= 0 then 165 | msg.warn("Could not write replaygain tags to file with mkvpropedit.") 166 | end 167 | os.remove(tmppath) 168 | local index = mp.get_property("playlist-pos") 169 | mp.command("loadfile " .. path .. " append-play") 170 | mp.command("playlist-remove " .. index) 171 | end 172 | 173 | local function start() 174 | local paused = mp.get_property("pause") 175 | if paused == "no" then 176 | mp.set_property("pause", "yes") 177 | end 178 | process() 179 | if paused == "no" then 180 | mp.set_property("pause", "no") 181 | end 182 | end 183 | 184 | mp.register_event("file-loaded", start) 185 | -------------------------------------------------------------------------------- /perfstats/README.md: -------------------------------------------------------------------------------- 1 | # perfstats 2 | 3 | [mpv](https://mpv.io/) script for displaying statistics on dropped frames and video output performance. 4 | 5 | Default keybinding is ` (the key under Escape on US keyboards). 6 | 7 | Frames: 8 | Dropped: https://mpv.io/manual/master/#command-interface-decoder-frame-drop-count 9 | VO Dropped: https://mpv.io/manual/master/#command-interface-frame-drop-count 10 | Mistimed: https://mpv.io/manual/master/#command-interface-mistimed-frame-count 11 | VO Delayed: https://mpv.io/manual/master/#command-interface-vo-delayed-frame-count 12 | 13 | Video output performance (does not seem to function with the angle backend): 14 | upload: https://mpv.io/manual/master/#command-interface-upload 15 | render: https://mpv.io/manual/master/#command-interface-render 16 | present: https://mpv.io/manual/master/#command-interface-present 17 | Total: Combined amount of time of the above 3 (this should stay lower than 18 | your display frame time, if it goes higher, you will want to tweak 19 | mpv settings, however this probably depends on the fps of the video, 20 | if the video is 30fps and the display is 60hz, then you probably get 21 | 2x more time to work on a frame since the same frame is displayed twice). 22 | 23 | last: How much time it took for the last frame; https://mpv.io/manual/master/#command-interface-last 24 | average: How much time it took for the last few frames; https://mpv.io/manual/master/#command-interface-avg 25 | Note: Wait 5 to 10 seconds at the start of a video for the average to settle. 26 | peak: The highest amount of time it took to display a frame; https://mpv.io/manual/master/#command-interface-peak 27 | 28 | Refresh rate: 29 | How many times per second your monitor displays a new frame. 30 | Frame time: 31 | This is how much time your computer monitor spends displaying a single frame. 32 | 33 | Frame rate: 34 | Reported video fps by mpv. 35 | Frame time: 36 | How long in time a single frame of the video is. 37 | 38 | Note: All time measurements are in microseconds. 39 | 40 | Download link for the script: https://raw.githubusercontent.com/kevinlekiller/mpv_scripts/master/perfstats/perfstats.lua 41 | 42 | ---- 43 | #License: 44 | 45 | https://github.com/kevinlekiller/mpv_scripts/blob/master/LICENSE 46 | -------------------------------------------------------------------------------- /perfstats/perfstats.lua: -------------------------------------------------------------------------------- 1 | --[[ 2 | mpv script for displaying statistics on dropped frames and video output performance. 3 | 4 | Default keybinding is ` (the key under Escape on US keyboards). 5 | 6 | Frames: 7 | Dropped: https://mpv.io/manual/master/#command-interface-decoder-frame-drop-count 8 | VO Dropped: https://mpv.io/manual/master/#command-interface-frame-drop-count 9 | Mistimed: https://mpv.io/manual/master/#command-interface-mistimed-frame-count 10 | VO Delayed: https://mpv.io/manual/master/#command-interface-vo-delayed-frame-count 11 | 12 | Video output performance (does not seem to function with the angle backend): 13 | render: https://mpv.io/manual/master/#command-interface-render 14 | upload: https://mpv.io/manual/master/#command-interface-upload 15 | present: https://mpv.io/manual/master/#command-interface-present 16 | Total: Combined amount of time of the above 3 (this should stay lower than 17 | your display frame time, if it goes higher, you will want to tweak 18 | mpv settings, however this probably depends on the fps of the video, 19 | if the video is 30fps and the display is 60hz, then you probably get 20 | 2x more time to work on a frame since the same frame is displayed twice). 21 | 22 | last: How much time it took for the last frame; https://mpv.io/manual/master/#command-interface-last 23 | average: How much time it took for the last few frames; https://mpv.io/manual/master/#command-interface-avg 24 | Note: Wait 5 to 10 seconds at the start of a video for the average to settle. 25 | peak: The highest amount of time it took to display a frame; https://mpv.io/manual/master/#command-interface-peak 26 | 27 | Refresh rate: 28 | How many times per second your monitor displays a new frame. 29 | Frame time: 30 | This is how much time your computer monitor spends displaying a single frame. 31 | 32 | Frame rate: 33 | Reported video fps by mpv. 34 | Frame time: 35 | How long in time a single frame of the video is. 36 | 37 | Note: All time measurements are in microseconds. 38 | 39 | https://github.com/kevinlekiller/mpv_scripts 40 | --]] 41 | --[[ 42 | Copyright (C) 2016-2017 kevinlekiller 43 | This program is free software; you can redistribute it and/or 44 | modify it under the terms of the GNU General Public License 45 | as published by the Free Software Foundation; either version 2 46 | of the License, or (at your option) any later version. 47 | This program is distributed in the hope that it will be useful, 48 | but WITHOUT ANY WARRANTY; without even the implied warranty of 49 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 50 | GNU General Public License for more details. 51 | You should have received a copy of the GNU General Public License 52 | along with this program; if not, write to the Free Software 53 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 54 | https://www.gnu.org/licenses/gpl-2.0.html 55 | --]] 56 | 57 | local keybinding = "`" 58 | local font_size = 7 59 | -- Time in seconds to show the message on mpv's osd. 60 | local osd_time = 8 61 | 62 | ------------------------------------------------------------------------------------- 63 | ------------------------------------------------------------------------------------- 64 | local osdh = mp.get_property_osd("osd-ass-cc/0") 65 | local osdt = mp.get_property_osd("osd-ass-cc/1") 66 | local msg = require 'mp.msg' 67 | local properties0 = { 68 | ["Dropped"] = "decoder-frame-drop-count", 69 | ["VO Dropped:"] = "frame-drop-count", 70 | ["Mistimed:"] = "mistimed-frame-count", 71 | ["VO Delayed:"] = "vo-delayed-frame-count" 72 | } 73 | local properties1 = { 74 | "render", 75 | "upload", 76 | "present", 77 | } 78 | function perfstats() 79 | local out = osdh .. "{\\fs" .. font_size .. "}Frames:\\N" 80 | for key,property in pairs(properties0) do 81 | local prop = mp.get_property(property) 82 | if (prop == nil) then 83 | msg.warn("Got a nil value from mpv for property : " .. property) 84 | return 85 | end 86 | out = out .. key .. "\\h" .. prop .."\\N" 87 | end 88 | local totals = {["avg"] = 0, ["last"] = 0, ["peak"] = 0} 89 | for key,property in ipairs(properties1) do 90 | local propname = "vo-performance/" .. property .. "-" 91 | out = out .. "_________\\NVideo output performance (" .. property .. "):\\N" 92 | for k,name in pairs(totals) do 93 | local prop = mp.get_property(propname .. k) 94 | if (prop == nil) then 95 | msg.warn("Got a nil value from mpv for property : " .. propname .. k) 96 | return 97 | end 98 | totals[k] = totals[k] + prop 99 | out = out .. k .. ":\\h" .. prop .. "μs\\N" 100 | end 101 | end 102 | out = out .. "_________\\NVideo output performance (total):\\N" 103 | for key,total in pairs(totals) do 104 | out = out .. key .. ":\\h" .. total .. "μs\\N" 105 | end 106 | local prop = mp.get_property("display-fps") 107 | if (prop ~= nil) then 108 | out = out .. "_________\\NDisplay information:\\NRefresh rate:\\h" .. prop .. "Hz\\N" 109 | out = out .. "Frame time:\\h" .. (1000000 / prop) .. "μs\\N" 110 | end 111 | prop = mp.get_property("container-fps") 112 | if (prop ~= nil) then 113 | out = out .. "_________\\NVideo information:\\NFrame rate:\\h" .. prop .. "fps\\N" 114 | out = out .. "Frame time:\\h" .. (1000000 / prop) .. "μs\\N" 115 | end 116 | mp.osd_message(out .. osdt, osd_time) 117 | end 118 | mp.add_key_binding(keybinding, mp.get_script_name(), perfstats, {repeatable=true}) 119 | -------------------------------------------------------------------------------- /powermizer/README.md: -------------------------------------------------------------------------------- 1 | # powermizer 2 | 3 | [mpv](https://mpv.io/) script for setting the "PowerMizer" setting on Nvidia GPU's with the proprietary driver on *nix operating systems. 4 | 5 | It sets "PowerMizer" to "Prefer Maximum Performance" when mpv is playing. 6 | 7 | It sets "PowerMizer" to "Adaptive" when mpv is idle or exits. 8 | 9 | It will try to automatically detect your GPU. 10 | 11 | You can override this by passing the mpv command: `--script-opts=powermizer-gpu="[gpu:1]"` 12 | 13 | You can find your GPU with this command: `nvidia-settings -q gpus` 14 | 15 | Download link for the script: https://raw.githubusercontent.com/kevinlekiller/mpv_scripts/master/powermizer/powermizer.lua 16 | 17 | ---- 18 | #License: 19 | 20 | https://github.com/kevinlekiller/mpv_scripts/blob/master/LICENSE 21 | -------------------------------------------------------------------------------- /powermizer/powermizer.lua: -------------------------------------------------------------------------------- 1 | --[[ 2 | https://github.com/kevinlekiller/mpv_scripts 3 | 4 | Sets "PowerMizer" in Nvidia GPUs with the proprietary driver to 5 | "Maximum Performance" mode while mpv is playing. 6 | Sets "PowerMizer" back to "Adaptive" when mpv is idle or exits. 7 | 8 | The script will try to automatically detect a GPU. 9 | 10 | You can also manually set your GPU like this: --script-opts=powermizer-gpu="[gpu:1]" 11 | Find your GPU with this command: nvidia-settings -q gpus 12 | --]] 13 | --[[ 14 | Copyright (C) 2015-2017 kevinlekiller 15 | 16 | This program is free software; you can redistribute it and/or 17 | modify it under the terms of the GNU General Public License 18 | as published by the Free Software Foundation; either version 2 19 | of the License, or (at your option) any later version. 20 | 21 | This program is distributed in the hope that it will be useful, 22 | but WITHOUT ANY WARRANTY; without even the implied warranty of 23 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 24 | GNU General Public License for more details. 25 | 26 | You should have received a copy of the GNU General Public License 27 | along with this program; if not, write to the Free Software 28 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 29 | https://www.gnu.org/licenses/gpl-2.0.html 30 | --]] 31 | local test = os.execute("which nvidia-settings > /dev/null") 32 | if (test == 0 or test == true) then 33 | local gpu = mp.get_opt("powermizer-gpu") 34 | if (gpu ~= nil) then 35 | gpu = string.match(gpu, "%[gpu:%d+%]") 36 | end 37 | if (gpu == nil) then 38 | local handle = assert(io.popen("nvidia-settings -q gpus")) 39 | for line in handle:lines() do 40 | gpu = string.match(line, "%[gpu:%d+%]") 41 | if (gpu ~= nil) then 42 | break 43 | end 44 | end 45 | handle:close() 46 | if (gpu == nil) then 47 | gpu = "[gpu:0]" 48 | end 49 | end 50 | 51 | function switch(name, paused) 52 | -- If it's nil it's because of the "shutdown" event. 53 | if (paused == true or paused == nil) then 54 | os.execute("nvidia-settings -a " .. gpu .. "/GPUPowerMizerMode=0 > /dev/null") 55 | else 56 | os.execute("nvidia-settings -a " .. gpu .. "/GPUPowerMizerMode=1 > /dev/null") 57 | end 58 | end 59 | 60 | mp.observe_property("core-idle", "bool", switch) 61 | -- "core-idle" doesn't trigger when exiting mpv, use "shutdown" to set GPU back to adaptive. 62 | mp.register_event("shutdown", switch) 63 | end 64 | --------------------------------------------------------------------------------