Open Nojevah opened 2 years ago
Thank you for sharing that MultiMonitorTool program with me, it actually does solve the biggest obstacle I had with implementing that feature which was to link monitor display names to the display IDs that mpv uses. I am interested in doing a complete rewrite of this script to make everything work better, but it's a pretty large job and I'm not sure when I'll have time. I may work on a way to implement this beforehand though. I will ping this thread if/when I do.
I've read in aonther ticket that you wanted to rewrite it, but if indeed you managed to insert this functionality in the actual (not that bad to me) script, it would be great and I could use the "auto" option. But I understand you have other priorities. I'll just hope and wait !
Ok I have a solution for you. I have written a very basic script called display-name. What it does is track what display the mpv window is currently open on and updates a shared_script_property with the actual name of the monitor instead of the horrible ID that mpv uses. It requires that MultiMonitorTool.exe
be available in the system path, so just put it in the same place as nircmd.exe
.
Once you have that script installed and have updated change-refresh with the latest commits I made just earlier you should be good to go.
What you need to do is create conditional auto-profiles in mpv.conf for the display you want to use, for example:
[PC]
profile-cond=shared_script_properties['display_name'] ~= 'SAMSUNG'
script-opts-append=changerefresh-auto=no
[TV]
profile-cond=shared_script_properties['display_name'] == 'SAMSUNG'
script-opts-append=changerefresh-auto=yes
This will automatically automatically switch the TV if you open the video on it's display or move it to the TVs display during playback.
You could also use profile restoration instead as well (though there are a few caveats so if things start acting weird try the other way) for example:
[TV]
profile-cond=shared_script_properties['display_name'] == 'SAMSUNG'
profile-restore=copy-equal
script-opts-append=changerefresh-auto=yes
And naturally if you have multiple displays you want to switch on you can just add more profiles.
If you're not sure what the names of your displays are you can run mpv --script-opts=display_names=yes
to get a list printed for you by the script. Edit: the name you want to use is the one on the right.
You can also use --script-opts-append=changerefresh-rates=23;24...
in the profiles to set custom rates for individual displays.
Thanks for your work ! For now I don't manage to have _mpv --script-opts=displaynames=yes list my displays.
I'm not sure where MultiMonitorTool should be. For nircmd, I use a personalized path. For MMT, I've tried all these without success: the same personalized path as nircmd; C:\Windows\System32; "mpv Profile"\; "mpv_Profile"\scripts\; mpv.exe folder.
I have display-name.lua in "scripts" folder, with (updated) change-refresh.lua. I've also tried to create a file named display-name.conf in script-opts with display_names=yes in it, also without success.
FWIW, there's another tool using cmd only, called "DisplayChanger" (dccmd.exe) if it's better to use/integrate (there's also regedit info on its webpage) ? Also another thing it'd be cool to have: don't launch .exe if the frequency is already what we want (for now, there's just a quick black flash fortunately). But I'm going off-topic, it's just for where you'll find motivation to rewrite it.
I also have errors when I launch a file.
For now I don't manage to have mpv --script-opts=display_names=yes list my displays.
Sorry I made a mistake, you need to use: mpv --script-opts=display_names=yes --idle=once
.
I also have errors when I launch a file.
I have uploaded a new version of display-name.lua
that should print some more useful error messages. Most probably you don't have MultiMonitorTool.exe in the correct location.
FWIW, I've ended editing your script in order to suit my need:
local var = {
video_fps = 0,
display_hz = 0
}
-- change refresh rate based on video fps and monitor
function matchVideo()
var.video_fps = mp.get_property_number('estimated-vf-fps', 0)
var.video_fps_trunc = math.floor(var.video_fps)
var.display_hz = mp.get_property_number('display-fps')
if (var.video_fps_trunc ~= math.floor(var.display_hz) and var.display_hz < 90) then
mp.set_property_bool("pause", true)
local process2 = mp.command_native({
name = 'subprocess',
playback_only = false,
capture_stdout = true,
args = {
"C:\\PLB\\Common\\Apps\\Display_Changer_x64\\dccmd.exe",
"-monitor=SamsungTV",
"-refresh=" .. var.video_fps_trunc
}
})
if (string.match(process2.stdout, "There is no monitor with that name")) then
mp.osd_message("!! Monitor not found !!",5)
else
mp.add_timeout(2, function()
var.video_fps = mp.get_property_number('estimated-vf-fps', 0)
var.display_hz = mp.get_property_number('display-fps')
if (math.floor(var.video_fps) ~= math.floor(var.display_hz)) then
mp.osd_message("!!!! PROBLEM !!!!! Video: " .. var.video_fps .. "fps Display: " .. var.display_hz .. "Hz",8)
else
mp.osd_message("Video: " .. var.video_fps .. "fps Display: " .. var.display_hz .. "Hz",5)
mp.set_property_bool("pause", false)
end
end)
end
end
end
mp.add_timeout(0.2, matchVideo)
mp.add_key_binding("f10", "match-video", matchVideo)
It works because I have a monitor with 120+ Hz. But it can be adapted to a 60 Hz monitor:
local var = {
video_fps = 0,
display_hz = 0
}
-- change refresh rate based on video fps and monitor name
function matchVideo()
var.video_fps = mp.get_property_number('estimated-vf-fps', 0)
var.video_fps_trunc = math.floor(var.video_fps)
var.display_hz = mp.get_property_number('display-fps')
if (var.video_fps_trunc ~= math.floor(var.display_hz)) then
local process = mp.command_native({
name = 'subprocess',
playback_only = false,
capture_stdout = true,
args = {
"C:\\PLB\\Common\\Apps\\Display_Changer_x64\\dccmd.exe",
"-monitor=SamsungTV"
}
})
if (string.match(process.stdout, "There is no monitor with that name")) then
print("Monitor not found")
else
mp.set_property_bool("pause", true)
local process2 = mp.command_native({
name = 'subprocess',
playback_only = false,
capture_stdout = true,
args = {
"C:\\PLB\\Common\\Apps\\Display_Changer_x64\\dccmd.exe",
"-monitor=SamsungTV",
"-refresh=" .. var.video_fps_trunc
}
})
mp.add_timeout(2, function()
var.video_fps = mp.get_property_number('estimated-vf-fps', 0)
var.display_hz = mp.get_property_number('display-fps')
if (math.floor(var.video_fps) ~= math.floor(var.display_hz)) then
mp.osd_message("!!!! PROBLEM !!!!! Video: " .. var.video_fps .. "fps Display: " .. var.display_hz .. "Hz",8)
else
mp.osd_message("Video: " .. var.video_fps .. "fps Display: " .. var.display_hz .. "Hz",5)
mp.set_property_bool("pause", false)
end
end)
end
end
end
mp.add_timeout(0.2, matchVideo)
mp.add_key_binding("f10", "match-video", matchVideo)
It's far less powerful than your script, but it's easier to maintain to me. Thanks for you useful script which helped a lot !
Cool, I'm glad you've found a solution.
Would it be possible to detect monitor when executing script ? I'd like the script not to go further (don't change refresh rate) depending on monitor. If I'm on my main monitor, I'd prefer not to change refresh rate. But when I launch mpv on my TV (in single monitor mode) I want this script to do its magic.
Active monitor can be found in regedit I think (from what I see in MultiMonitorTool from Nirsoft too).