├── 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 |
--------------------------------------------------------------------------------