Compare commits

...

53 Commits

Author SHA1 Message Date
6eadea6f00 update to fork 2025-09-08 14:36:43 -07:00
05adde2559 update link 2025-09-08 14:06:22 -07:00
7579628faf update input.conf 2025-09-08 14:04:55 -07:00
5581723522 revert back to fork 2025-09-08 14:04:39 -07:00
b6390baec6 update submodule 2025-09-07 15:40:24 -07:00
21998241ba update mpvacious submodule and add keybinds to input.conf 2025-09-03 20:37:53 -07:00
57f6a5db30 update 2025-09-03 20:20:32 -07:00
5a6ac4bb3a Remove mpvacious submodule 2025-09-03 20:14:37 -07:00
5f08f09b2c add ytdl-preload script-opts file 2025-08-19 00:24:59 -07:00
9819a64f01 add immersion tracker 2025-08-19 00:16:22 -07:00
73a305af0b update mpv config 2025-08-17 17:31:36 -07:00
9ac84aba18 update submodule paths 2025-08-17 17:31:31 -07:00
cfc6ac22e5 Stage new submodule locations 2025-08-17 16:59:41 -07:00
e4afe79832 Move submodules to submodules directory 2025-08-17 16:57:56 -07:00
ca0899d233 enable watch history 2025-05-27 00:30:17 -07:00
deb591481e update configs 2025-05-27 00:30:00 -07:00
472899b680 update mac conf 2025-05-26 04:32:13 -07:00
2f3ccc60fc update mac conf 2025-05-26 04:19:01 -07:00
02d3c00229 update anilist to submodule 2025-05-26 02:19:45 -07:00
f3a4afcf76 update 2025-05-26 01:32:12 -07:00
087f16dfd0 update subs2srs 2025-05-24 21:23:18 -07:00
0b9f814eca add back mpvacious 2025-05-02 01:07:28 -07:00
efb9737e14 remove mpvacious 2025-05-01 19:38:05 -07:00
56e477bff1 update modernz 2025-04-28 23:48:50 -07:00
04fabf6356 add other shaders 2025-04-12 01:18:10 -07:00
d9747459d8 update config 2025-04-10 17:44:19 -07:00
33ea15228e update 2025-04-08 23:46:52 -07:00
1cd68861f5 add prettier file 2025-04-06 23:02:51 -07:00
2c90b30993 add jimaku script and update subsync 2025-04-06 23:02:06 -07:00
382c29ba42 update to alass 2025-04-06 22:25:05 -07:00
37b67be69b update 2025-04-05 19:47:37 -07:00
2ed3918aca update config 2025-04-05 19:46:45 -07:00
f0237be035 update script to use virtual environment 2025-04-04 03:43:22 -07:00
5260564aaf add mpvacious 2025-04-04 00:23:45 -07:00
1c6904a8a5 Merge branch 'master' of gitea.suda.codes:sudacode/mpv 2025-04-03 21:31:33 -07:00
e0f195e0ee update colors 2025-04-03 21:31:29 -07:00
76ddb33630 add laptop 2025-03-27 22:01:13 -07:00
7df9682378 replace immersive with animecard 2025-03-27 21:11:03 -07:00
0c7677b6ab update immersive 2025-03-25 19:06:26 -07:00
1f74dad64a remove c file 2025-03-18 03:29:34 -07:00
fc734fcffe Merge branch 'master' of gitea.suda.codes:sudacode/mpv 2025-03-18 03:26:35 -07:00
3c8cc50e97 add mpris 2025-03-18 03:26:26 -07:00
cbdca67613 update config and add fontconfig 2025-03-17 00:15:16 -07:00
3f0308189d update 2025-03-14 18:02:01 -07:00
81471617f2 add mpv anilist 2025-03-11 01:57:43 -07:00
ksyasuda
c3555288a9 update immersive config 2025-03-10 17:57:26 -07:00
ksyasuda
c2e9ae47e1 update 2025-03-10 02:07:25 -07:00
ksyasuda
afa6c8e2c0 update 2025-03-07 21:07:39 -08:00
ksyasuda
8ded1b4f0c update 2025-03-06 02:00:38 -08:00
ksyasuda
9a193ac5c3 update 2025-03-04 22:00:59 -08:00
ksyasuda
6e64e0c70f add immersive 2025-03-04 02:25:17 -08:00
ksyasuda
f596071c87 update 2025-03-03 23:41:05 -08:00
ksyasuda
7904708a42 add mpv_websocket 2025-03-03 22:33:17 -08:00
50 changed files with 12713 additions and 2429 deletions

6
.gitignore vendored Normal file
View File

@@ -0,0 +1,6 @@
immersive-data
.ytdl_preload/
.ytdl-preload/
scripts/anilistUpdater/anilistToken.txt
.watch-later
state

27
.gitmodules vendored
View File

@@ -1,12 +1,31 @@
[submodule "mpv-youtube-upnext"]
path = mpv-youtube-upnext
path = submodules/mpv-youtube-upnext
url = https://github.com/ksyasuda/mpv-youtube-upnext
[submodule "mpv-youtube-queue"]
path = mpv-youtube-queue
path = submodules/mpv-youtube-queue
url = https://github.com/ksyasuda/mpv-youtube-queue
[submodule "ModernZ"]
path = ModernZ
path = submodules/ModernZ
url = git@github.com:Samillion/ModernZ.git
[submodule "ytdl-preload"]
path = ytdl-preload
path = submodules/ytdl-preload
url = git@gist.github.com:17d90e3deeb35b5f75e55adb19098f58.git
[submodule "mpv-anilist-updater"]
path = submodules/mpv-anilist-updater
url = git@github.com:AzuredBlue/mpv-anilist-updater.git
[submodule "thumbfast"]
path = submodules/thumbfast
url = git@github.com:po5/thumbfast.git
[submodule "submodules/autosubsync-mpv"]
path = submodules/autosubsync-mpv
url = git@github.com:joaquintorres/autosubsync-mpv.git
[submodule "submodules/immersion-tracker"]
path = submodules/immersion-tracker
url = git@gitea.suda.codes:sudacode/immersion-tracker.git
[submodule "submodules/mpvacious"]
path = submodules/mpvacious
url = git@github.com:ksyasuda/mpvacious.git
[submodule "submodules/animecards"]
path = submodules/animecards
url = git@github.com:ksyasuda/Anacreon-Script

2
.prettierrc Normal file
View File

@@ -0,0 +1,2 @@
trailingComma: "es5"
singleQuote: true

Submodule ModernZ deleted from 04bd74082d

View File

@@ -74,7 +74,7 @@
#Shift+PGUP seek 600
#Shift+PGDWN seek -600
[ add speed -0.05 # scale playback speed
] add speed 0.05
] add speed 0.05
#{ multiply speed 0.5
#} multiply speed 2.0
#BS set speed 1.0 # reset speed to normal
@@ -193,9 +193,89 @@ CTRL+1 no-osd change-list glsl-shaders set "~/.config/mpv/shaders/FSR.glsl"; sho
CTRL+2 no-osd change-list glsl-shaders set "~/.config/mpv/shaders/NVScaler.glsl"; show-text "NIS"
CTRL+3 no-osd change-list glsl-shaders set "~/.config/mpv/shaders/CAS-scaled.glsl"; show-text "CAS"
CTRL+4 no-osd change-list glsl-shaders set "~/.config/mpv/shaders/FSRCNNX.glsl"; show-text "FSRCNNX"
CTRL+5 no-osd change-list glsl-shaders set "~/.config/mpv/shaders/FSRCNNX.glsl:~/.config/mpv/shaders/CAS-scaled.glsl:~/.config/mpv/shaders/NVScaler.glsl"; show-text "ALL"
CTRL+5 no-osd change-list glsl-shaders set "~/.config/mpv/shaders/ArtCNN_C4F32.glsl"; show-text "ArtCNN"
CTRL+6 no-osd change-list glsl-shaders set "~/.config/mpv/shaders/ArtCNN_C4F16_DS.glsl"; show-text "ArtCNN"
CTRL+7 no-osd change-list glsl-shaders set "~/.config/mpv/shaders/ArtCNN_C4F16.glsl"; show-text "ArtCNN"
CTRL+0 no-osd change-list glsl-shaders clr ""; show-text "GLSL shaders cleared"
ctrl+K cycle-values keep-open "yes" "no"
ctrl+r script-binding reload-scripts
ctrl+s script_binding autosubsync-menu
# {{{ sponsorblock
ctrl+g script-binding sponsorblock/set_segment
ctrl+G script-binding sponsorblock/submit_segment
ctrl+< script-binding sponsorblock/upvote_setment
ctrl+> script-binding sponsorblock/downvote_segment
#}}}
# {{{ anilist
ctrl+A script-binding update_anilist
ctrl+B script-binding launch_anilist
ctrl+E script-binding open_folder
ctrl+V script-binding mpvacious-secondary-sid-toggle
# }}}
# {{{ mpvacious (subs2srs)
a script-binding mpvacious-menu-open
ctrl+g ignore # script-binding mpvacious-animated-snapshot-toggle
ctrl+N script-binding mpvacious-export-note
ctrl+b ignore # script-binding mpvacious-update-selected-note
ctrl+B ignore # script-binding mpvacious-overwrite-selected-note
ctrl+m ignore # script-binding mpvacious-update-last-note
ctrl+M ignore # script-binding mpvacious-overwrite-last-note
G script-binding mpvacious-quick-card-menu-open
alt+g script-binding mpvacious-quick-card-sel-menu-open
ctrl+c script-binding mpvacious-copy-primary-sub-to-clipboard
ctrl+C script-binding mpvacious-copy-secondary-sub-to-clipboard
ctrl+= script-binding mpvacious-autocopy-toggle
H script-binding mpvacious-sub-seek-back
L script-binding mpvacious-sub-seek-forward
alt+h script-binding mpvacious-sub-seek-back-pause
alt+l script-binding mpvacious-sub-seek-forward-pause
ctrl+h script-binding mpvacious-sub-rewind
ctrl+H script-binding mpvacious-sub-replay
ctrl+L script-binding mpvacious-sub-play-up-to-next
ctrl+V script-binding mpvacious-secondary-sid-toggle
ctrl+K script-binding mpvacious-secondary-sid-prev
ctrl+J script-binding mpvacious-secondary-sid-next
# }}}
# {{ animecards
ctrl+v script-binding animecards/update-anki-card
# }}
# {{{ mpv-youtube-queue
ctrl+a script-binding mpv_youtube_queue/add_to_queue
ctrl+n script-binding mpv_youtube_queue/play_next_in_queue
ctrl+p script-binding mpv_youtube_queue/play_previous_in_queue
ctrl+q script-binding mpv_youtube_queue/print_queue
ctrl+k script-binding mpv_youtube_queue/move_cursor_up
ctrl+j script-binding mpv_youtube_queue/move_cursor_down
ctrl+ENTER script-binding mpv_youtube_queue/play_selected_video
ctrl+o script-binding mpv_youtube_queue/open_video_in_browser
ctrl+P script-binding mpv_youtube_queue/print_current_video
ctrl+O script-binding mpv_youtube_queue/open_channel_in_browser
ctrl+d script-binding mpv_youtube_queue/download_current_video
ctrl+D script-binding mpv_youtube_queue/download_selected_video
ctrl+m script-binding mpv_youtube_queue/move_video
ctrl+x script-binding mpv_youtube_queue/delete_video
#}}}
#{{{ MPV SELECT
g ignore
g-a script-binding select/select-aid
g-b script-binding select/select-binding
g-c script-binding select/select-chapter
g-e script-binding select/select-edition
g-h script-binding select/select-watch-history
g-l script-binding select/select-subtitle-line
g-m script-binding select/menu
g-p script-binding select/select-playlist
g-r script-binding select/show-properties
g-s script-binding select/select-sid
g-S script-binding select/select-secondary-sid
g-t script-binding select/select-track
g-v script-binding select/select-vid
g-w script-binding select/select-watch-later
# }}}

243
mac.conf Normal file
View File

@@ -0,0 +1,243 @@
#
# Example mpv configuration file
#
# Warning:
#
# The commented example options usually do _not_ set the default values. Call
# mpv with --list-options to see the default values for most options. There is
# no builtin or example mpv.conf with all the defaults.
#
#
# Configuration files are read system-wide from /usr/local/etc/mpv.conf
# and per-user from ~~/mpv.conf, where per-user settings override
# system-wide settings, all of which are overridden by the command line.
#
# Configuration file settings and the command line options use the same
# underlying mechanisms. Most options can be put into the configuration file
# by dropping the preceding '--'. See the man page for a complete list of
# options.
#
# Lines starting with '#' are comments and are ignored.
#
# See the CONFIGURATION FILES section in the man page
# for a detailed description of the syntax.
#
# Profiles should be placed at the bottom of the configuration file to ensure
# that settings wanted as defaults are not restricted to specific profiles.
##################
# video settings #
##################
# Start in fullscreen mode by default.
#fs=yes
# force starting with centered window
# geometry=50%:50%
# don't allow a new window to have a size larger than 90% of the screen size
#autofit-larger=90%x90%
# Do not close the window on exit.
#keep-open=yes
# Do not wait with showing the video window until it has loaded. (This will
# resize the window once video is loaded. Also always shows a window with
# audio.)
#force-window=immediate
# Disable the On Screen Controller (OSC).
# osc=no
# Keep the player window on top of all other windows.
# window=scale=1.0
# Specify high quality video rendering preset (for --vo=gpu only)
# Can cause performance problems with some drivers and GPUs.
# profile=gpu-hq
# Force video to lock on the display's refresh rate, and change video and audio
# speed to some degree to ensure synchronous playback - can cause problems
# with some drivers and desktop environments.
#video-sync=display-resample
# Enable hardware decoding if available. Often, this does not work with all
# video outputs, but should work well with default settings on most systems.
# If performance or energy usage is an issue, forcing the vdpau or vaapi VOs
# may or may not help.
# discourged by mpv devs and not likely to make significant difference
# hwdec=auto-copy
# hwdec-codecs=all
##################
# audio settings #
##################
# Specify default audio device. You can list devices with: --audio-device=help
# The option takes the device string (the stuff between the '...').
#audio-device=alsa/default
# Do not filter audio to keep pitch when changing playback speed.
#audio-pitch-correction=no
# Output 5.1 audio natively, and upmix/downmix audio with a different format.
#audio-channels=5.1
# Disable any automatic remix, _if_ the audio output accepts the audio format.
# of the currently played file. See caveats mentioned in the manpage.
# (The default is "auto-safe", see manpage.)
#audio-channels=auto
##################
# other settings #
##################
# Pretend to be a web browser. Might fix playback with some streaming sites,
# but also will break with shoutcast streams.
# user-agent="Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36"
user-agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36"
# user-agent="Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.85 Safari/537.36"
# user-agent="Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Ubuntu Chromium/37.0.2062.94 Chrome/37.0.2062.94 Safari/537.36"
# user-agent="Chromium/37.0.2062.94 Chrome/37.0.2062.94 Safari/537.36"
# cache settings
#
# Use a large seekable RAM cache even for local input.
cache=yes
#
# Use extra large RAM cache (needs cache=yes to make it useful).
demuxer-max-bytes=500M
demuxer-max-back-bytes=100M
#
# Disable the behavior that the player will pause if the cache goes below a
# certain fill size.
cache-pause=no
#
# Store cache payload on the hard disk instead of in RAM. (This may negatively
# impact performance unless used for slow input such as network.)
#cache-dir=~/.cache/
#cache-on-disk=yes
# Display English subtitles if available.
#slang=en
# Play Finnish audio if available, fall back to English otherwise.
#alang=fi,en
# Change subtitle encoding. For Arabic subtitles use 'cp1256'.
# If the file seems to be valid UTF-8, prefer UTF-8.
# (You can add '+' in front of the codepage to force it.)
#sub-codepage=cp1256
# You can also include other configuration files.
#include=/path/to/the/file/you/want/to/include
############
# Profiles #
############
# The options declared as part of profiles override global default settings,
# but only take effect when the profile is active.
# The following profile can be enabled on the command line with: --profile=eye-cancer
#[eye-cancer]
#sharpen=5
sub-font="JetBrainsMono Nerd Font"
sub-font-size=45
# osd-font="Fluent System Icons"
border=no
geometry=50%
volume=50
# speed-step=0.05
# audio-spdif=ac3,eac3,dts-hd,truehd
# glsl-shaders="~~/shaders/Anime4K_Clamp_Highlights.glsl:~~/shaders/Anime4K_Restore_CNN_VL.glsl:~~/shaders/Anime4K_Upscale_CNN_x2_VL.glsl:~~/shaders/Anime4K_AutoDownscalePre_x2.glsl:~~/shaders/Anime4K_AutoDownscalePre_x4.glsl:~~/shaders/Anime4K_Upscale_CNN_x2_M.glsl"
glsl-shaders="~~/shaders/ArtCNN_C4F16.glsl"
# glsl-shaders="~~/shaders/FSR.glsl"
# Can fix stuttering in some cases, in other cases probably causes it. Try it if you experience stuttering.
opengl-early-flush=no
video-sync=display-resample
osc=no
no-border
ytdl-raw-options=sub-langs=en.*,write-auto-subs=
ytdl-format=bestvideo+bestaudio/best
# get subtitles for videos automatically
sub-auto=fuzzy
slang=en,eng
# CATPPUCCIN MACHIATTO
# Main mpv options
background-color='#24273a'
osd-back-color='#181926'
osd-border-color='#181926'
osd-color='#cad3f5'
osd-shadow-color='#24273a'
# Stats script options
# Options are on separate lines for clarity
# Colors are in #BBGGRR format
script-opts-append=stats-border_color=30201e
script-opts-append=stats-font_color=f5d3ca
script-opts-append=stats-plot_bg_border_color=f8bdb7
script-opts-append=stats-plot_bg_color=30201e
script-opts-append=stats-plot_color=f8bdb7
# profile=svp
profile=gpu-hq
# GPU OPTIONS
vo=gpu-next
# hwdec=nvdec-copy
hwdec=videotoolbox
scale=bicubic
dscale=bicubic
cscale=bicubic
tscale=oversample
interpolation=yes
interpolation-preserve=no
input-ipc-server=/tmp/mpvsocket
# ao=pule,pipewire
# ao=pipewire,pulse
ontop=yes
ao=coreaudio
save-position-on-quit
watch-later-dir="~~.watch-later"
resume-playback=yes
save-watch-history
watch-history-path="~~state/watch_history.jsonl"
vd-lavc-threads=0
gpu-api=vulkan
gpu-context=macvk
opengl-pbo=yes
[svp]
input-ipc-server=/tmp/mpvsocket # Receives input from SVP
hr-seek-framedrop=no # Fixes audio desync
resume-playback=no # Not compatible with SVP
[Idle]
profile-cond=p["idle-active"]
profile-restore=copy-equal
title=' '
keepaspect=no
[immersion]
cookies=yes
cookies-file=/Volumes/sudacode/japanese/cookies.Japanese.txt
ytdl-raw-options=mark-watched=,write-auto-subs=,sub-langs=ja.*
ytdl-raw-options-append=cookies=/Volumes/sudacode/japanese/cookies.Japanese.txt
ytdl-raw-options-append=sponsorblock-mark=all
ytdl-raw-options-append=sponsorblock-remove=sponsor
ytdl-format=bestvideo+bestaudio/best
# get subtitles for videos automatically
sub-auto=fuzzy
slang=ja,jpn
alang=ja,jpn
vlang=ja,jpn

18
mpv-fonts.conf Normal file
View File

@@ -0,0 +1,18 @@
<?xml version="1.0"?>
<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
<fontconfig>
<dir>/home/sudacode/.config/mpv/fonts</dir>
<include ignore_missing="yes">/etc/fonts/fonts.conf</include>
<include ignore_missing="yes">/etc/fonts/conf.d</include>
<alias>
<family>sans-serif</family>
<prefer>
<family>JetBrainsMono Nerd Font</family>
<family>Fluent System Icons</family>
<family>Noto Sans CJK JP</family>
<family>Noto Sans</family>
<family>Open Sans</family>
</prefer>
</alias>
</fontconfig>

274
mpv.conf
View File

@@ -1,162 +1,21 @@
#
# Example mpv configuration file
#
# Warning:
#
# The commented example options usually do _not_ set the default values. Call
# mpv with --list-options to see the default values for most options. There is
# no builtin or example mpv.conf with all the defaults.
#
#
# Configuration files are read system-wide from /usr/local/etc/mpv.conf
# and per-user from ~~/mpv.conf, where per-user settings override
# system-wide settings, all of which are overridden by the command line.
#
# Configuration file settings and the command line options use the same
# underlying mechanisms. Most options can be put into the configuration file
# by dropping the preceding '--'. See the man page for a complete list of
# options.
#
# Lines starting with '#' are comments and are ignored.
#
# See the CONFIGURATION FILES section in the man page
# for a detailed description of the syntax.
#
# Profiles should be placed at the bottom of the configuration file to ensure
# that settings wanted as defaults are not restricted to specific profiles.
##################
# video settings #
##################
# Start in fullscreen mode by default.
#fs=yes
# force starting with centered window
# geometry=50%:50%
# don't allow a new window to have a size larger than 90% of the screen size
#autofit-larger=90%x90%
# Do not close the window on exit.
#keep-open=yes
# Do not wait with showing the video window until it has loaded. (This will
# resize the window once video is loaded. Also always shows a window with
# audio.)
#force-window=immediate
# Disable the On Screen Controller (OSC).
# osc=no
# Keep the player window on top of all other windows.
#ontop=yes
# window=scale=1.0
# Specify high quality video rendering preset (for --vo=gpu only)
# Can cause performance problems with some drivers and GPUs.
# profile=gpu-hq
# Force video to lock on the display's refresh rate, and change video and audio
# speed to some degree to ensure synchronous playback - can cause problems
# with some drivers and desktop environments.
#video-sync=display-resample
# Enable hardware decoding if available. Often, this does not work with all
# video outputs, but should work well with default settings on most systems.
# If performance or energy usage is an issue, forcing the vdpau or vaapi VOs
# may or may not help.
# discourged by mpv devs and not likely to make significant difference
# hwdec=auto-copy
# hwdec-codecs=all
##################
# audio settings #
##################
# Specify default audio device. You can list devices with: --audio-device=help
# The option takes the device string (the stuff between the '...').
#audio-device=alsa/default
# Do not filter audio to keep pitch when changing playback speed.
#audio-pitch-correction=no
# Output 5.1 audio natively, and upmix/downmix audio with a different format.
#audio-channels=5.1
# Disable any automatic remix, _if_ the audio output accepts the audio format.
# of the currently played file. See caveats mentioned in the manpage.
# (The default is "auto-safe", see manpage.)
#audio-channels=auto
##################
# other settings #
##################
# Pretend to be a web browser. Might fix playback with some streaming sites,
# but also will break with shoutcast streams.
# user-agent="Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36"
user-agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36"
# user-agent="Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.85 Safari/537.36"
# user-agent="Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Ubuntu Chromium/37.0.2062.94 Chrome/37.0.2062.94 Safari/537.36"
# user-agent="Chromium/37.0.2062.94 Chrome/37.0.2062.94 Safari/537.36"
# cache settings
#
# Use a large seekable RAM cache even for local input.
cache=yes
#
# Use extra large RAM cache (needs cache=yes to make it useful).
demuxer-max-bytes=500M
demuxer-max-back-bytes=100M
#
# Disable the behavior that the player will pause if the cache goes below a
# certain fill size.
cache-pause=no
#
# Store cache payload on the hard disk instead of in RAM. (This may negatively
# impact performance unless used for slow input such as network.)
#cache-dir=~/.cache/
#cache-on-disk=yes
# Display English subtitles if available.
#slang=en
# Play Finnish audio if available, fall back to English otherwise.
#alang=fi,en
# Change subtitle encoding. For Arabic subtitles use 'cp1256'.
# If the file seems to be valid UTF-8, prefer UTF-8.
# (You can add '+' in front of the codepage to force it.)
#sub-codepage=cp1256
# You can also include other configuration files.
#include=/path/to/the/file/you/want/to/include
############
# Profiles #
############
# The options declared as part of profiles override global default settings,
# but only take effect when the profile is active.
# The following profile can be enabled on the command line with: --profile=eye-cancer
#[eye-cancer]
#sharpen=5
sub-font=JetBrainsMono Nerd Font
sub-font-size=50
osd-font=JetBrainsMono Nerd Font
ontop=yes
sub-font="JetBrainsMono Nerd Font"
sub-font-size=45
# osd-font="Fluent System Icons"
border=no
geometry=50%
volume=50
# speed-step=0.05
audio-spdif=ac3,eac3,dts-hd,truehd
# geometry=50%
autofit=50%
volume=75
audio-spdif=ac3,dts-hd,truehd
# glsl-shaders="~~/shaders/Anime4K_Clamp_Highlights.glsl:~~/shaders/Anime4K_Restore_CNN_VL.glsl:~~/shaders/Anime4K_Upscale_CNN_x2_VL.glsl:~~/shaders/Anime4K_AutoDownscalePre_x2.glsl:~~/shaders/Anime4K_AutoDownscalePre_x4.glsl:~~/shaders/Anime4K_Upscale_CNN_x2_M.glsl"
glsl-shaders="~~/shaders/FSRCNNX.glsl:~~/shaders/FSR.glsl:~~/shaders/NVScaler.glsl:~~/shaders/CAS-scaled.glsl"
# glsl-shaders="~~/shaders/FSR.glsl"
# glsl-shaders="~~/shaders/FSRCNNX.glsl:~~/shaders/FSR.glsl:~~/shaders/NVScaler.glsl:~~/shaders/CAS-scaled.glsl"
# glsl-shaders="~~/shaders/ArtCNN_C4F32_DS.glsl"
glsl-shaders="~~/shaders/ArtCNN_C4F32.glsl"
# Can fix stuttering in some cases, in other cases probably causes it. Try it if you experience stuttering.
opengl-early-flush=no
@@ -165,47 +24,85 @@ video-sync=display-resample
osc=no
no-border
ytdl-raw-options=ignore-config=,sub-lang=en,write-auto-sub=
ytdl-raw-options=sub-langs=en.*,write-auto-subs=
ytdl-format=bestvideo+bestaudio/best
# get subtitles for videos automatically
# sub-auto=fuzzy
sub-auto=fuzzy
slang=en,eng
# disable subtitles by default = no
sid=no
video-sync=display-resample
# CATPPUCCIN MACHIATTO
# Main mpv options
background-color='#24273a'
osd-back-color='#181926'
osd-border-color='#181926'
osd-color='#cad3f5'
osd-shadow-color='#24273a'
# Stats script options
# Options are on separate lines for clarity
# Colors are in #BBGGRR format
script-opts-append=stats-border_color=30201e
script-opts-append=stats-font_color=f5d3ca
script-opts-append=stats-plot_bg_border_color=f8bdb7
script-opts-append=stats-plot_bg_color=30201e
script-opts-append=stats-plot_color=f8bdb7
# profile=svp
profile=gpu-hq
profile=high-quality
blend-subtitles=video
# GPU OPTIONS
vo=gpu-next
hwdec=nvdec-copy
scale=bicubic
dscale=bicubic
hwdec=nvdec
gpu-api=vulkan
scale=ewa_lanczossharp
dscale=catmull_rom
cscale=bicubic
tscale=oversample
interpolation=yes
interpolation-preserve=no
# fruit: 8-Bit/8-Bit+FRC display
# ordered: true 10-Bit/12-Bit display
# error-diffusion: high-end GPUs
dither=error-diffusion
dither-depth=auto
error-diffusion=sierra-lite # uncomment if not 'error-diffusion'
###### Antiring
scale-antiring=0.5
dscale-antiring=0.5
cscale-antiring=0.5
# laptop
# vo=gpu
# gpu-api=opengl
# gpu-context=wayland
# profile=opengl-hq
gpu-context=waylandvk
gpu-api=vulkan
vulkan-swap-mode=mailbox
swapchain-depth=2
vulkan-async-compute=no
vd-lavc-threads=0
opengl-pbo=yes
vd-lavc-film-grain=gpu
input-ipc-server=/tmp/mpvsocket
# ao=pule,pipewire
ao=pipewire,pulse
deband=yes
deband-iterations=4
deband-threshold=35
deband-range=16
deband-grain=4
subs-with-matching-audio=no
sub-fix-timing=yes
sub-ass-override=scale
#Some settings fixing VOB/PGS subtitles (creating blur & changing yellow subs to gray)
sub-gauss=1.0
sub-gray=yes
###### High-quality screenshots
screenshot-format=webp
screenshot-webp-lossless=yes
screenshot-high-bit-depth=yes
screenshot-sw=no
screenshot-directory="/truenas/sudacode/pictures/mpv"
screenshot-template="%f-%wH.%wM.%wS.%wT-#%#00n"
save-position-on-quit
watch-later-dir="~~/.watch-later"
resume-playback=yes
save-watch-history
watch-history-path="~~/state/watch_history.jsonl"
target-colorspace-hint=yes
[hdr]
target-colorspace-hint=yes
@@ -222,4 +119,21 @@ profile-cond=p["idle-active"]
profile-restore=copy-equal
title=' '
keepaspect=no
# background=1
[immersion]
cookies=yes
cookies-file=/truenas/sudacode/japanese/cookies.Japanese.txt
ytdl-raw-options=mark-watched=,write-auto-subs=,sub-langs=ja.*
ytdl-raw-options-append=cookies=/truenas/sudacode/japanese/cookies.Japanese.txt
ytdl-raw-options-append=sponsorblock-mark=all
ytdl-raw-options-append=sponsorblock-remove=sponsor
ytdl-format=bestvideo+bestaudio/best
# get subtitles for videos automatically
sub-auto=fuzzy
slang=ja,jpn,JA,JPN,ja.hi,ja.*
alang=ja,jpn
vlang=ja,jpn
sub-font="Noto Sans CJK JP"
sub-border-size=1
sub-shadow-color=0.0/0.0/0.0/0.50
sub-shadow-offset=2

BIN
mpv_websocket Executable file

Binary file not shown.

BIN
mpv_websocket-mac Executable file

Binary file not shown.

View File

@@ -0,0 +1,11 @@
# Use 'yes' or 'no' for boolean options below
# Example for multiple directories (comma or semicolon separated):
# DIRECTORIES=D:/Torrents,D:/Anime
# or
# DIRECTORIES=D:/Torrents;D:/Anime
DIRECTORIES=/truenas/jellyfin/anime
UPDATE_PERCENTAGE=85
SET_COMPLETED_TO_REWATCHING_ON_FIRST_EPISODE=no
UPDATE_PROGRESS_WHEN_REWATCHING=yes
SET_TO_COMPLETED_AFTER_LAST_EPISODE_CURRENT=yes
SET_TO_COMPLETED_AFTER_LAST_EPISODE_REWATCHING=yes

107
script-opts/animecards.conf Normal file
View File

@@ -0,0 +1,107 @@
# =================================================
# Anacreon Script (Animecards) Config for MPV
# =================================================
# ⚠ WARNING:
# Use only yes/no (not true/false) in boolean options
# =================================================
# Anki Field Names
# These must match the field names in your Anki note type
# =================================================
FRONT_FIELD=Expression
SENTENCE_FIELD=Sentence
IMAGE_FIELD=Picture
SENTENCE_AUDIO_FIELD=SentenceAudio
# =================================================
# Behavior Settings
# =================================================
# [Not recommended] Copy subtitles to clipboard enabled by default? (yes/no)
# The more modern and recommended alternative is to use the websocket.
ENABLE_SUBS_TO_CLIP=no
# Ask before overwriting existing cards? (yes/no)
# Recommended to set yes unless you know what you are doing
ASK_TO_OVERWRITE=yes
# [Dangerous] Max cards that can be overwritten at once (-1 = unlimited)
OVERWRITE_LIMIT=8
# Keep bold formatting added by yomitan? (yes/no)
HIGHLIGHT_WORD=no
# Use MPV's built-in clipboard API (requires v0.40+)? (yes/no)
# Alternative clipboard method that may reduce latency on Windows.
# Supported on macOS and Wayland as well. Not supported on X11.
USE_MPV_CLIPBOARD_API=no
# ==========================================================
# Audio Settings
# ==========================================================
# [Optional] Padding and fade settings in seconds. (0 = disable)
# Padding grabs extra audio around your selected subs.
# Fade does a volume fade in/out effect.
AUDIO_CLIP_PADDING=0.75
AUDIO_CLIP_FADE=0.2
# Always create mono audio? (yes/no)
AUDIO_MONO=yes
# [Optional] Use MPV's current volume for card audio? (yes/no)
USE_MPV_VOLUME=no
# [Optional] Play sentence audio after updating the card? (yes/no)
AUTOPLAY_AUDIO=no
# =================================================
# Image Settings
# =================================================
# Format of screenshots: png, jpg or webp
# ⚠ Use png or jpg for iOS/Mac compatibility
# (webp won't display on iOS/Mac)
IMAGE_FORMAT=png
# Resize image to this height (in pixels).
# Preserves aspect ratio. (0 = keep original resolution)
IMAGE_HEIGHT=480
# [JPG only] Quality: from 0 (worst) to 100 (best)
JPG_QUALITY=88
# =================================================
# Animated Image Settings
# =================================================
# Enable animated export for the selected subtitle segment (yes/no)
ANIMATED_IMAGE_ENABLED=yes
# Animated format: webp or avif
ANIMATED_IMAGE_FORMAT=avif
# Resize animated image to this height (in pixels). (0 = keep original)
ANIMATED_IMAGE_HEIGHT=480
# Frames per second for animated export (1-30)
ANIMATED_IMAGE_FPS=24
# Quality 0-100 (mapped to CRF for avif)
ANIMATED_IMAGE_QUALITY=69
# =================================================
# Misc Info - Extra metadata for cards
# =================================================
# [Optional] Save extra metadata (filename, timestamp, etc.) to a field
WRITE_MISCINFO=yes
# Field to store the extra info (only used if WRITE_MISCINFO=yes)
MISCINFO_FIELD=MiscInfo
# Pattern for the Misc Info content:
# %f = filename (without extension)
# %F = filename (with extension)
# %t = timestamp (HH:MM:SS)
# %T = timestamp with milliseconds (HH:MM:SS:MLS)
# <br> = Next line tag
# Examples:
# MISCINFO_PATTERN %f (%t)
# MISCINFO_PATTERN=File: %F<br>Timestamp: %T
MISCINFO_PATTERN=[Anacreon Script] %f (%t)

View File

@@ -0,0 +1,33 @@
# Absolute paths to the executables, if needed:
# 1. ffmpeg
ffmpeg_path=/usr/bin/ffmpeg
# 2. ffsubsync
ffsubsync_path=/usr/bin/ffsubsync
# 3. alass
alass_path=/usr/bin/alass
# Preferred retiming tool. Allowed options: 'ffsubsync', 'alass', 'ask'.
# If set to 'ask', the add-on will ask to choose the tool every time:
# 1. Preferred tool for syncing to audio.
# audio_subsync_tool=ask
audio_subsync_tool=ffsubsync
# audio_subsync_tool=alass
# 2. Preferred tool for syncing to another subtitle.
# altsub_subsync_tool=ask
# altsub_subsync_tool=ffsubsync
altsub_subsync_tool=alass
# Unload old subs (yes,no)
# After retiming, tell mpv to forget the original subtitle track.
unload_old_sub=yes
# unload_old_sub=no
# Overwrite the original subtitle file.
# Replace the old subtitle file with the retimed file.
# overwrite_old_sub=yes
overwrite_old_sub=no

View File

@@ -0,0 +1,22 @@
start_tracking_key=ctrl+t
data_dir=/home/sudacode/.config/mpv/scripts/immersion-tracker/data
csv_file=/truenas/sudacode/japanese/immersion_tracker.csv
session_file=/home/sudacode/.config/mpv/scripts/immersion-tracker/data/current_session.json
min_session_duration=30
save_interval=10
enable_debug_logging=no
backup_sessions=no
max_backup_files=10
use_title=yes
use_filename=no
custom_prefix=[Immersion]
max_title_length = 100
export_csv=yes
export_json=no
export_html=no
backup_csv=yes
show_session_start=yes
show_session_end=yes
show_progress_milestones=no
milestone_percentages=25507590

View File

@@ -102,9 +102,9 @@ raise_subtitle_amount=125
# show the jump backward and forward buttons
jump_buttons=yes
# change the jump amount in seconds
jump_amount=10
jump_amount=1
# change the jump amount in seconds when right-clicking jump buttons and shift-clicking chapter skip buttons
jump_more_amount=60
jump_more_amount=5
# show different icon when jump_amount is set to 5, 10, or 30
jump_icon_number=yes
# seek mode for jump buttons
@@ -175,47 +175,47 @@ zoom_out_min=-1
# Colors and style
# accent color of the OSC and title bar
osc_color=#000000
osc_color=#181926
# color of the title in borderless/fullscreen mode
window_title_color=#FFFFFF
window_title_color=#A5ADCB
# color of the window controls (close, minimize, maximize) in borderless/fullscreen mode
window_controls_color=#FFFFFF
window_controls_color=#A5ADCB
# color of close window control on hover
windowcontrols_close_hover=#F45C5B
windowcontrols_close_hover=#ED8796
# color of maximize window controls on hover
windowcontrols_max_hover=#F8BC3A
windowcontrols_max_hover=#EED49F
# color of minimize window controls on hover
windowcontrols_min_hover=#43CB44
windowcontrols_min_hover=#A6DA95
# color of the title (above seekbar)
title_color=#FFFFFF
title_color=#CAD3F5
# color of the cache information
cache_info_color=#FFFFFF
cache_info_color=#CAD3F5
# color of the seekbar progress and handle
seekbarfg_color=#FB8C00
seekbarfg_color=#C6A0F6
# color of the remaining seekbar
seekbarbg_color=#94754F
seekbarbg_color=#B7BDF8
# color of the cache ranges on the seekbar
seekbar_cache_color=#918F8E
seekbar_cache_color=#A5ADCB
# match volume bar color with seekbar color (ignores side_buttons_color)
volumebar_match_seek_color=no
# color of the timestamps (below seekbar)
time_color=#FFFFFF
time_color=#CAD3F5
# color of the chapter title next to timestamp (below seekbar)
chapter_title_color=#FFFFFF
chapter_title_color=#A5ADCB
# color of the side buttons (audio, subtitles, playlist, etc.)
side_buttons_color=#FFFFFF
side_buttons_color=#A5ADCB
# color of the middle buttons (skip, jump, chapter, etc.)
middle_buttons_color=#FFFFFF
middle_buttons_color=#A5ADCB
# color of the play/pause button
playpause_color=#FFFFFF
playpause_color=#A5ADCB
# color of the element when held down (pressed)
held_element_color=#999999
# color of a hovered button when hover_effect includes "color"
hover_effect_color=#FB8C00
hover_effect_color=#C6A0F6
# color of the border for thumbnails (with thumbfast)
thumbnail_border_color=#111111
thumbnail_border_color=#181926
# color of the border outline for thumbnails
thumbnail_border_outline=#404040
thumbnail_border_outline=#363A4F
# alpha of the OSC background box
fade_alpha=130

View File

@@ -16,8 +16,8 @@ save_queue=ctrl+s
save_full_queue=ctrl+S
remove_from_queue=ctrl+x
play_selected_video=ctrl+ENTER
browser=firefox
clipboard_command=wl-paste -p
browser=zen-browser
clipboard_command=wl-paste
cursor_icon=➤
display_limit=10
download_directory=~/videos/YouTube

1
script-opts/stats.conf Normal file
View File

@@ -0,0 +1 @@
plot_tonemapping_lut=yes

331
script-opts/subs2srs.conf Normal file
View File

@@ -0,0 +1,331 @@
###
### Main mpvacious configuration file.
### Save this file to ~/.config/mpv/script-opts/subs2srs.conf
###
##
## General settings
##
# Anki deck for new cards. Subdecks are supported.
deck_name=Minecraft
# Model names are listed in `Tools -> Manage note types` menu in Anki.
# If you don't have a model for Japanese, get it from
# https://tatsumoto.neocities.org/blog/setting-up-anki.html#import-an-example-mining-deck
model_name=Lapis
# Field names as they appear in the selected note type.
# If you set `audio_field` or `image_field` empty,
# the corresponding media file will not be created.
audio_field=SentenceAudio
image_field=Picture
sentence_field=Expression
secondary_field=SelectionText
# The tag(s) added to new notes. Spaces separate multiple tags.
# Leave nothing after `=` to disable tagging completely.
# The following substitutions are supported:
# %n - the name of the video
# %t - timestamp
# %d - episode number (if none, returns nothing)
# %e - SUBS2SRS_TAGS environment variable (if you have it set)
# note_tag=subs2srs
note_tag=%n-E%d %t
#note_tag=
# Size and name of the font used in the menu
menu_font_size=24
menu_font_name=Noto Serif CJK JP
# AnkiConnect server address
# The default address for a server on the same device is http://127.0.0.1:8765.
# If Anki is running and AnkiConnect is installed, opening this URL should
# open a page showing the current version of AnkiConnect.
# Change this if you have changed webBindAddress in AnkiConnect's settings.
ankiconnect_url=127.0.0.1:8765
##
## Toggleables.
## Possible values: `yes` or `no`.
# Use FFmpeg encoder instead of mpv encoder
# If mpvacious encounters problems creating audio and images for Anki cards,
# setting this to `yes` should fix them.
#
# You need to install ffmpeg and add it to the PATH first.
# https://wiki.archlinux.org/title/FFmpeg
# https://www.ffmpeg.org/download.html
#
# FFmpeg encoder is unable to create audio and images from remote content (like YouTube videos).
use_ffmpeg=yes
# Automatically create the deck for new cards (see deck_name option)
create_deck=no
# Allow making notes with the same sentence field.
allow_duplicates=no
# When mpv starts, automatically copy subs to the clipboard as they appear on screen.
# This option can be also toggled in the addon's OSD menu.
autoclip=no
# Possible options:
# "disabled" - autocopy is disabled
# "clipboard" - copy to the system clipboard (e.g. uses xclip)
# "goldendict" - send the subtitle string to goldendict (goldendict-ng).
# "custom_command" - run any custom command specified in `autoclip_custom_args`.
autoclip_method=custom_command
# Command to run when autoclip is enabled and set to "custom_command".
# If empty, nothing will be done.
# If set, calls the external program.
# The following substitutions are supported:
# %MPV_PRIMARY% - primary subtitle line
# %MPV_SECONDARY% - secondary subtitle line
autoclip_custom_args=wl-copy %MPV_PRIMARY%
# Remove all spaces from the primary subtitle text.
# Set this to "yes" for languages without spaces like Japanese.
# However, if mpvacious detects any latin characters in the string, spaces will not be removed.
nuke_spaces=yes
# if set to `yes`, the volume of the outputted audio file
# depends on the volume of the player at the time of export
tie_volumes=no
# This is used when selecting cards in Anki to update, it wont let you
# overwrite more than the value specified below
# Just remember that having multiple cards with the same sentence
# and the same audio recording is usually bad practice.
card_overwrite_safeguard = 1
# Remove text in parentheses and leading/trailing spaces or
# newlines that may interfere with Rikaitan before copying
# subtitles to the clipboard
clipboard_trim_enabled=yes
# Add media to fields before or after existing data
append_media=yes
# Remove text in brackets before substituting %n into tag
tag_nuke_brackets=yes
# Remove text in parentheses before substituting %n into tag
tag_nuke_parentheses=no
# Remove the episode number before substituting %n into tag
tag_del_episode_num=yes
# Remove everything after the episode number before substituting %n into tag
# Does nothing if the previous option tag_del_episode_num is disabled.
tag_del_after_episode_num=yes
# Convert filename to lowercase for tagging.
tag_filename_lowercase=no
# Lets you disable anki browser manipulation by mpvacious.
disable_gui_browse=no
# Play audio clip automatically in background
# after note creation (or note update) to ensure that the audio is correctly cut.
preview_audio=yes
# When selecting subtitle lines, print them on the screen.
show_selected_text=yes
# For convenience, read config file from disk before a card is made.
# Useful if you change your config often since you won't have to restart mpv every time,
# but reading from disk takes some time.
reload_config_before_card_creation=yes
##
## Image settings
##
# Snapshot format.
# Do not switch to `jpg` unless your computer doesn't support `webp` or `avif`.
snapshot_format=avif
# snapshot_format=webp
#snapshot_format=jpg
# Quality of produced image files. 0 = lowest, 100=highest.
snapshot_quality=88
# Image dimensions
# If either (but not both) of the width or height parameters is -2,
# the value will be calculated preserving the aspect-ratio.
snapshot_width=-2
snapshot_height=400
# Screenshot (yes, no)
# Usually not required.
# When making Anki cards, create a screenshot (by calling 'screenshot-to-file') instead of a snapshot.
# If set to yes, image dimensions and quality cannot be controlled due to mpv limitations.
# 'snapshot_format' is still respected.
# When using this, a custom sync server is recommended, e.g. https://github.com/ankicommunity/anki-sync-server
screenshot=yes
# The exact image template used when exporting to Anki's image field.
# Adding data-editor-shrink="true" makes the image smaller by default within the Anki viewer
# on versions 2.1.53+ (equivalent of double-clicking on the image).
# You likely would not want to change this unless you know what you are doing.
image_template=<img alt="snapshot" src="%s">
#image_template=<img alt="snapshot" data-editor-shrink="true" src="%s">
# Similar to image_template but with audio.
# Normally, the user doesn't need to change this setting,
# but it may be needed for audio files to be playable on AnkiWeb.
audio_template=[sound:%s]
#audio_template=<audio controls="" src="%s"></audio>
##
## Animated snapshots
## Animated snapshots will capture the video from the start to the end times selected when using mpvacious.
##
# If enabled, generates animated snapshots (something like GIFs) instead of static snapshots.
animated_snapshot_enabled=yes
# Animated snapshot format. Like "snapshot_format" but for animated images. Can be either avif or webp.
animated_snapshot_format=avif
# animated_snapshot_format=webp
# Number of frame per seconds, a value between 0 and 30 (30 included)
# Higher values will increase both quality and file size, lower values will do the opposite
animated_snapshot_fps=24
# Animated snapshot dimensions
# If either (but not both) of the width or height parameters is -2,
# the value will be calculated preserving the aspect-ratio.
animated_snapshot_width=-2
animated_snapshot_height=400
# Quality of the produced animation, 0 = lowest, 100 = highest
animated_snapshot_quality=69
##
## Audio settings
##
# Audio format.
# Opus is the recommended format.
audio_format=opus
# audio_format=mp3
# Container for opus files.
# It may be required to use a different container for Opus.
# This is the case on certain computers or devices
# which are running proprietary operating systems, e.g. AnkiMobile. Using them is discouraged.
# ・ Ogg/Opus play everywhere except AnkiWeb in Safari and AnkiMobile.
# ・ M4A (iOS 17.2 and probably even earlier) and WEBM (since iOS 17.4) play everywhere.
# ・ Opus in CAF can be used with older iOS. CAF plays only on Anki Desktop, Safari and AnkiMobile.
# ・ (iOS Lockdown Mode disables Opus support completely,
# though you may try to add an exception for AnkiMobile.)
# opus_container=ogg
#opus_container=opus
opus_container=m4a
# opus_container=webm
#opus_container=caf
# Sane values are 16k-32k for opus, 64k-128k for mp3.
audio_bitrate=32k
# Set a pad to the dialog timings. 0.5 = half a second.
# Pads are never applied to manually set timings.
audio_padding=0.0
#audio_padding=0.5
##
## Forvo support (Rikaitan users only)
##
# yes - fetch audio from Forvo if Rikaitan couldn't find the audio (default)
# always - always fetch audio from Forvo and replace the audio added by Rikaitan
# no - never use Forvo
use_forvo=yes
# Vocab field should be equal to {expression} field in Rikaitan
vocab_field=Expression
# Vocab Audio field should be equal to {audio} field in Rikaitan
vocab_audio_field=ExpressionAudio
##
## Misc info
## Various context information that can be written on your cards in a specified field.
##
# yes to enable or no to disable.
miscinfo_enable=yes
# Field name
miscinfo_field=ExtraInfo
# Format string used to fill the misc info field.
# It supports the same substitutions as `note_tag`. HTML is supported.
miscinfo_format=%n EP%d (%t)
#miscinfo_format=From <b>mpvacious</b> %n at %t.
##
## Secondary subtitles
## Mpvacious can try automatically loading secondary subtitles that will appear at the top.
## For example, you may want to load English subs alongside Japanese subs.
##
## Secondary subtitles should be present in the container.
## But if you manually set secondary sid from the command line, mpvacious won't change it.
##
# Load secondary subtitle track automatically when a file is opened.
secondary_sub_auto_load=yes
# Language of secondary subs. This is your native language or a language you know well.
# If you leave this parameter empty, secondary subs will NOT be automatically loaded.
secondary_sub_lang=eng,en
#secondary_sub_lang=
# Hover area.
# Proportion of the top part of the mpv window where the secondary subtitles are visible when hovered over.
# Possible values: from 0.0 to 1.0
secondary_sub_area=0.15
# Visibility state
# Can be set to: 'auto', 'never', 'always'.
# If set to 'never' or 'always', secondary_sub_area has no effect.
# If set to 'auto', visibility behaves according to the value of secondary_sub_area.
# Default binding to cycle this value: Ctrl+v.
secondary_sub_visibility=auto
# Perform two-pass loudness normalization.
# Parameter explanation can be found e.g. at:
# https://auphonic.com/blog/2013/01/07/loudness-targets-mobile-audio-podcasts-radio-tv/
# https://auphonic.com/blog/2019/08/19/dynamic-range-processing/
# MAKE SURE TO REMOVE loudnorm FROM CUSTOM ARGS BEFORE ENABLING.
loudnorm=no
loudnorm_target=-16
loudnorm_range=11
loudnorm_peak=-1.5
##
## Custom audio encoding arguments
## These arguments are added to the command line.
## `mpv` and `ffmpeg` accept slightly different parameters.
## Feel free to experiment for yourself, but be careful or media creation might stop working.
##
# loudnorm IN CUSTOM ARGS IS LEFT FOR BACKWARD COMPATIBILITY.
# MAKE SURE TO REMOVE ALL MENTIONS OF loudnorm FROM CUSTOM ARGS
# (E.G. SET TO EMPTY STRINGS) BEFORE ENABLING TWO-PASS loudnorm.
# ENABLING loudnorm BOTH THROUGH THE SWITCH AND THROUGH CUSTOM ARGS
# CAN LEAD TO UNPREDICTABLE RESULTS.
# Ffmpeg
ffmpeg_audio_args=-af loudnorm=I=-16:TP=-1.5:LRA=11:dual_mono=true
#ffmpeg_audio_args=
#ffmpeg_audio_args=-af silenceremove=1:0:-50dB
# mpv
# mpv accepts each filter as a separate argument, e.g. --af-append=1 --af-append=2
mpv_audio_args=--af-append=loudnorm=I=-16:TP=-1.5:LRA=11:dual_mono=true
#mpv_audio_args=
#mpv_audio_args=--af-append=silenceremove=1:0:-50dB

View File

@@ -0,0 +1 @@
temp=/tmp/ytdl-preload

View File

@@ -0,0 +1 @@
../../submodules/mpv-anilist-updater/anilistUpdater/anilistUpdater.py

View File

@@ -0,0 +1 @@
../../submodules/mpv-anilist-updater/anilistUpdater/main.lua

1
scripts/animecards Symbolic link
View File

@@ -0,0 +1 @@
../submodules/animecards/animecards

1
scripts/autosubsync-mpv Symbolic link
View File

@@ -0,0 +1 @@
../submodules/autosubsync-mpv

1
scripts/immersion-tracker Symbolic link
View File

@@ -0,0 +1 @@
../submodules/immersion-tracker

388
scripts/jimaku.js Normal file
View File

@@ -0,0 +1,388 @@
// Go to https://jimaku.cc/login and create a new account.
// Then go to https://jimaku.cc/account and click the `Generate` button to create a new API key
// Click the `Copy` button and paste it below
var API_KEY = "";
// Configuration options
var CONFIG = {
// Filter the response to only have the specified episode
prompt_episode: true,
// Subtitle suffix (e.g., ".JA" for Japanese subtitles)
subtitle_suffix: ".JA",
// Preferred subtitle format (order matters, first is most preferred)
preferred_formats: ["ass", "srt", "vtt"],
// Automatically load the subtitle after download
auto_load: true,
// Default subtitle delay in seconds (can be positive or negative)
default_delay: 0,
// Default subtitle font size
default_font_size: 16,
// Automatically rename the subtitle file after download
auto_rename: true,
// Automatically run autosubsync-mpv after downloading the subtitle
run_auto_subsync: true
};
// Keybindings
// var MANUAL_SEARCH_KEY = "g";
var FILENAME_AUTO_SEARCH_KEY = "ctrl+J";
var PARENT_FOLDER_AUTO_SEARCH_KEY = "n";
function api(url, extraArgs) {
var baseArgs = [
"curl",
"-s",
"--url",
url,
"--header",
"Authorization: " + API_KEY
];
var args = Array.prototype.concat.apply(baseArgs, extraArgs);
var res = mp.command_native({
name: "subprocess",
playback_only: false,
capture_stdout: true,
capture_stderr: true,
args: args
});
if (res.stdout) return JSON.parse(res.stdout);
}
function downloadSub(sub) {
return api(sub.url, ["--output", sub.name]);
}
function showMessage(message, persist) {
var ass_start = mp.get_property_osd("osd-ass-cc/0");
var ass_stop = mp.get_property_osd("osd-ass-cc/1");
mp.osd_message(
ass_start + "{\\fs16}" + message + ass_stop,
persist ? 999 : 2
);
}
// The timeout is neccessary due to a weird bug in mpv
function inputGet(args) {
mp.input.terminate();
setTimeout(function () {
mp.input.get(args);
}, 1);
}
// The timeout is neccessary due to a weird bug in mpv
function inputSelect(args) {
mp.input.terminate();
setTimeout(function () {
mp.input.select(args);
}, 1);
}
// Taken from mpv-subversive
// https://github.com/nairyosangha/mpv-subversive/blob/master/backend/backend.lua#L146
function sanitize(text) {
var subPatterns = [
/\.[a-zA-Z]+$/, // extension
/\./g,
/-/g,
/_/g,
/\[[^\]]+\]/g, // [] bracket
/\([^\)]+\)/g, // () bracket
/720[pP]/g,
/480[pP]/g,
/1080[pP]/g,
/[xX]26[45]/g,
/[bB]lu[-]?[rR]ay/g,
/^[\s]*/,
/[\s]*$/,
/1920x1080/g,
/1920X1080/g,
/Hi10P/g,
/FLAC/g,
/AAC/g
];
var result = text;
subPatterns.forEach(function (subPattern) {
var newResult = result.replace(subPattern, " ");
if (newResult.length > 0) {
result = newResult;
}
});
return result;
}
// Adapted from mpv-subversive
// https://github.com/nairyosangha/mpv-subversive/blob/master/backend/backend.lua#L164
function extractTitle(text) {
var matchers = [
{ regex: /^([\w\s\d]+)[Ss]\d+[Ee]?\d+/, group: 1 },
{ regex: /^([\w\s\d]+)-[\s]*\d+[\s]*[^\w]*$/, group: 1 },
{ regex: /^([\w\s\d]+)[Ee]?[Pp]?[\s]+\d+$/, group: 1 },
{ regex: /^([\w\s\d]+)[\s]\d+.*$/, group: 1 },
{ regex: /^\d+[\s]*(.+)$/, group: 1 }
];
for (var i = 0; i < matchers.length; i++) {
var matcher = matchers[i];
var match = text.match(matcher.regex);
if (match) {
return match[matcher.group].trim();
}
}
return text;
}
function getNames(results) {
return results.map(function (item) {
return item.name;
});
}
function runAutoSubSyncMPV() {
try {
mp.command_native(["script-binding", "autosubsync-menu"]);
} catch (e) {
showMessage("autosubsync-mpv not installed");
return;
}
}
function selectSub(selectedSub) {
showMessage("Downloading: " + selectedSub.name);
try {
downloadSub(selectedSub);
// Get current video filename without extension
var videoPath = mp.get_property("path");
if (!videoPath) {
throw new Error("No video file is currently playing");
}
var videoName = videoPath.substring(0, videoPath.lastIndexOf("."));
// Get subtitle extension
var subExt = selectedSub.name.substring(selectedSub.name.lastIndexOf("."));
var newSubName = selectedSub.name;
if (CONFIG.auto_rename) {
// Create new subtitle filename
newSubName = videoName + CONFIG.subtitle_suffix + subExt;
// Rename the downloaded subtitle file
var renameResult = mp.command_native({
name: "subprocess",
playback_only: false,
args: ["mv", selectedSub.name, newSubName]
});
if (renameResult.error) {
throw new Error(
"Failed to rename subtitle file: " + renameResult.error
);
}
showMessage(newSubName + " downloaded and renamed");
} else {
showMessage(newSubName + " downloaded");
}
if (CONFIG.auto_load) {
mp.commandv("sub_add", newSubName);
showMessage(newSubName + " added");
// Apply subtitle settings if configured
if (CONFIG.default_delay !== 0) {
mp.commandv("sub_delay", CONFIG.default_delay);
}
if (CONFIG.default_font_size !== 16) {
mp.commandv("sub_font_size", CONFIG.default_font_size);
}
}
if (CONFIG.run_auto_subsync) {
runAutoSubSyncMPV();
}
mp.set_property("pause", "no");
} catch (error) {
showMessage("Error: " + error.message, true);
mp.set_property("pause", "no");
}
}
function sortByPreferredFormat(files) {
return files.sort(function (a, b) {
var extA = a.name.substring(a.name.lastIndexOf(".") + 1).toLowerCase();
var extB = b.name.substring(b.name.lastIndexOf(".") + 1).toLowerCase();
var indexA = CONFIG.preferred_formats.indexOf(extA);
var indexB = CONFIG.preferred_formats.indexOf(extB);
if (indexA === -1) return 1;
if (indexB === -1) return -1;
return indexA - indexB;
});
}
function selectEpisode(anime, episode) {
mp.input.terminate();
var episodeResults;
if (episode) {
showMessage("Fetching subs for: " + anime.name + " episode " + episode);
episodeResults = api(
"https://jimaku.cc/api/entries/" + anime.id + "/files?episode=" + episode
);
} else {
showMessage("Fetching all subs for: " + anime.name);
episodeResults = api(
"https://jimaku.cc/api/entries/" + anime.id + "/files"
);
}
if (episodeResults.error) {
showMessage("Error: " + animeResults.error);
return;
}
if (episodeResults.length === 0) {
showMessage("No results found");
return;
}
// Sort results by preferred format
episodeResults = sortByPreferredFormat(episodeResults);
if (episodeResults.length === 1) {
var selectedEpisode = episodeResults[0];
selectSub(selectedEpisode);
return;
}
var items = getNames(episodeResults);
inputSelect({
prompt: "Select episode: ",
items: items,
submit: function (id) {
var selectedEpisode = episodeResults[id - 1];
selectSub(selectedEpisode);
}
});
}
function onAnimeSelected(anime) {
if (CONFIG.prompt_episode) {
inputGet({
prompt: "Episode (leave blank for all): ",
submit: function (episode) {
selectEpisode(anime, episode);
}
});
} else {
selectEpisode(anime);
}
}
function search(searchTerm, isAuto) {
mp.input.terminate();
showMessage('Searching for: "' + searchTerm + '"');
var animeResults = api(
encodeURI(
"https://jimaku.cc/api/entries/search?anime=true&query=" + searchTerm
)
);
if (animeResults.error) {
showMessage("Error: " + animeResults.error);
return;
}
if (animeResults.length === 0) {
showMessage("No results found");
if (isAuto) {
manualSearch(searchTerm);
}
return;
}
if (animeResults.length === 1) {
var selectedAnime = animeResults[0];
onAnimeSelected(selectedAnime);
return;
}
var items = getNames(animeResults);
inputSelect({
prompt: "Select anime: ",
items: items,
submit: function (id) {
var selectedAnime = animeResults[id - 1];
showMessage(selectedAnime.name, true);
onAnimeSelected(selectedAnime);
}
});
}
function manualSearch(defaultText) {
inputGet({
prompt: "Search term: ",
submit: search,
default_text: defaultText
});
mp.set_property("pause", "yes");
showMessage("Manual Jimaku Search", true);
}
function autoSearch() {
var filename = mp.get_property("filename");
var sanitizedFilename = sanitize(filename);
var currentAnime = extractTitle(sanitizedFilename);
mp.set_property("pause", "yes");
search(currentAnime, true);
}
function autoSearchParentFolder() {
var path = mp.get_property("stream-open-filename");
var pathSplit = path.split(path.indexOf("/") >= 0 ? "/" : "\\");
var filename =
pathSplit.length === 1 ? pathSplit[0] : pathSplit[pathSplit.length - 2];
var sanitizedFilename = sanitize(filename);
var currentAnime = extractTitle(sanitizedFilename);
mp.set_property("pause", "yes");
search(currentAnime, true);
}
// mp.add_key_binding(MANUAL_SEARCH_KEY, "jimaku-manual-search", manualSearch);
mp.add_key_binding(
FILENAME_AUTO_SEARCH_KEY,
"jimaku-filename-auto-search",
autoSearch
);
mp.add_key_binding(
PARENT_FOLDER_AUTO_SEARCH_KEY,
"jimaku-parent-folder-auto-search",
autoSearchParentFolder
);

View File

@@ -1 +1 @@
../ModernZ/modernz.lua
../submodules/ModernZ/modernz.lua

View File

@@ -1 +1 @@
../mpv-youtube-queue/mpv-youtube-queue.lua
../submodules/mpv-youtube-queue/mpv-youtube-queue.lua

View File

@@ -0,0 +1,83 @@
-- mpv_websocket
-- https://github.com/kuroahna/mpv_websocket
local utils = require("mp.utils")
local platform = mp.get_property_native("platform")
local config_file_path = mp.find_config_file("mpv.conf")
local config_folder_path, config_file = utils.split_path(config_file_path)
local mpv_websocket_path =
utils.join_path(config_folder_path, platform == "windows" and "mpv_websocket.exe" or "mpv_websocket")
local initialised_websocket
local _, err = utils.file_info(config_file_path)
if err then
error("failed to open mpv config file `" .. config_file_path .. "`")
end
local _, err = utils.file_info(mpv_websocket_path)
if err then
error("failed to open mpv_websocket")
end
local function find_mpv_socket(config_file_path)
local file = io.open(config_file_path, "r")
if file == nil then
error("failed to read mpv config file `" .. config_file_path .. "`")
end
local mpv_socket
for line in file:lines() do
mpv_socket = line:match("^input%-ipc%-server%s*=%s*(%g+)%s*")
if mpv_socket then
break
end
end
file:close()
if not mpv_socket then
error("input-ipc-server option does not exist in `" .. config_file_path .. "`")
end
return mpv_socket
end
local mpv_socket = find_mpv_socket(config_file_path)
if platform == "windows" then
mpv_socket = "\\\\.\\pipe" .. mpv_socket:gsub("/", "\\")
end
local function start_websocket()
initialised_websocket = mp.command_native_async({
name = "subprocess",
playback_only = false,
capture_stdout = true,
capture_stderr = true,
args = {
mpv_websocket_path,
"-m",
mpv_socket,
"-w",
"6677",
},
})
end
local function end_websocket()
mp.abort_async_command(initialised_websocket)
initialised_websocket = nil
end
local function toggle_websocket()
local paused = mp.get_property_bool("pause")
if initialised_websocket and paused then
end_websocket()
elseif not initialised_websocket and not paused then
start_websocket()
end
end
mp.register_script_message("togglewebsocket", toggle_websocket)
start_websocket()

File diff suppressed because it is too large Load Diff

View File

@@ -1,92 +0,0 @@
-- Rebuild the terminal status line as a lua script
-- Be aware that this will require more cpu power!
-- Also, this is based on a rather old version of the
-- builtin mpv status line.
-- Add a string to the status line
function atsl(s)
newStatus = newStatus .. s
end
function update_status_line()
-- Reset the status line
newStatus = ""
if mp.get_property_bool("pause") then
atsl("(Paused) ")
elseif mp.get_property_bool("paused-for-cache") then
atsl("(Buffering) ")
end
if mp.get_property("aid") ~= "no" then
atsl("A")
end
if mp.get_property("vid") ~= "no" then
atsl("V")
end
atsl(": ")
atsl(mp.get_property_osd("time-pos"))
atsl(" / ");
atsl(mp.get_property_osd("duration"));
atsl(" (")
atsl(mp.get_property_osd("percent-pos", -1))
atsl("%)")
local r = mp.get_property_number("speed", -1)
if r ~= 1 then
atsl(string.format(" x%4.2f", r))
end
r = mp.get_property_number("avsync", nil)
if r ~= nil then
atsl(string.format(" A-V: %f", r))
end
r = mp.get_property("total-avsync-change", 0)
if math.abs(r) > 0.05 then
atsl(string.format(" ct:%7.3f", r))
end
r = mp.get_property_number("decoder-drop-frame-count", -1)
if r > 0 then
atsl(" Late: ")
atsl(r)
end
r = mp.get_property_osd("video-bitrate")
if r ~= nil and r ~= "" then
atsl(" Vb: ")
atsl(r)
end
r = mp.get_property_osd("audio-bitrate")
if r ~= nil and r ~= "" then
atsl(" Ab: ")
atsl(r)
end
r = mp.get_property_number("cache", 0)
if r > 0 then
atsl(string.format(" Cache: %d%% ", r))
end
-- Set the new status line
mp.set_property("options/term-status-msg", newStatus)
end
timer = mp.add_periodic_timer(1, update_status_line)
function on_pause_change(name, value)
if value == false then
timer:resume()
else
timer:stop()
end
mp.add_timeout(0.1, update_status_line)
end
mp.observe_property("pause", "bool", on_pause_change)
mp.register_event("seek", update_status_line)

1
scripts/subs2srs Symbolic link
View File

@@ -0,0 +1 @@
../submodules/mpvacious

View File

@@ -1,921 +0,0 @@
-- thumbfast.lua
--
-- High-performance on-the-fly thumbnailer
--
-- Built for easy integration in third-party UIs.
local options = {
-- Socket path (leave empty for auto)
socket = "",
-- Thumbnail path (leave empty for auto)
thumbnail = "",
-- Maximum thumbnail size in pixels (scaled down to fit)
-- Values are scaled when hidpi is enabled
max_height = 200,
max_width = 200,
-- Apply tone-mapping, no to disable
tone_mapping = "auto",
-- Overlay id
overlay_id = 42,
-- Spawn thumbnailer on file load for faster initial thumbnails
spawn_first = false,
-- Close thumbnailer process after an inactivity period in seconds, 0 to disable
quit_after_inactivity = 0,
-- Enable on network playback
network = false,
-- Enable on audio playback
audio = false,
-- Enable hardware decoding
hwdec = false,
-- Windows only: use native Windows API to write to pipe (requires LuaJIT)
direct_io = false,
-- Custom path to the mpv executable
mpv_path = "mpv"
}
mp.utils = require "mp.utils"
mp.options = require "mp.options"
mp.options.read_options(options, "thumbfast")
local properties = {}
local pre_0_30_0 = mp.command_native_async == nil
local pre_0_33_0 = true
function subprocess(args, async, callback)
callback = callback or function() end
if not pre_0_30_0 then
if async then
return mp.command_native_async({name = "subprocess", playback_only = true, args = args}, callback)
else
return mp.command_native({name = "subprocess", playback_only = false, capture_stdout = true, args = args})
end
else
if async then
return mp.utils.subprocess_detached({args = args}, callback)
else
return mp.utils.subprocess({args = args})
end
end
end
local winapi = {}
if options.direct_io then
local ffi_loaded, ffi = pcall(require, "ffi")
if ffi_loaded then
winapi = {
ffi = ffi,
C = ffi.C,
bit = require("bit"),
socket_wc = "",
-- WinAPI constants
CP_UTF8 = 65001,
GENERIC_WRITE = 0x40000000,
OPEN_EXISTING = 3,
FILE_FLAG_WRITE_THROUGH = 0x80000000,
FILE_FLAG_NO_BUFFERING = 0x20000000,
PIPE_NOWAIT = ffi.new("unsigned long[1]", 0x00000001),
INVALID_HANDLE_VALUE = ffi.cast("void*", -1),
-- don't care about how many bytes WriteFile wrote, so allocate something to store the result once
_lpNumberOfBytesWritten = ffi.new("unsigned long[1]"),
}
-- cache flags used in run() to avoid bor() call
winapi._createfile_pipe_flags = winapi.bit.bor(winapi.FILE_FLAG_WRITE_THROUGH, winapi.FILE_FLAG_NO_BUFFERING)
ffi.cdef[[
void* __stdcall CreateFileW(const wchar_t *lpFileName, unsigned long dwDesiredAccess, unsigned long dwShareMode, void *lpSecurityAttributes, unsigned long dwCreationDisposition, unsigned long dwFlagsAndAttributes, void *hTemplateFile);
bool __stdcall WriteFile(void *hFile, const void *lpBuffer, unsigned long nNumberOfBytesToWrite, unsigned long *lpNumberOfBytesWritten, void *lpOverlapped);
bool __stdcall CloseHandle(void *hObject);
bool __stdcall SetNamedPipeHandleState(void *hNamedPipe, unsigned long *lpMode, unsigned long *lpMaxCollectionCount, unsigned long *lpCollectDataTimeout);
int __stdcall MultiByteToWideChar(unsigned int CodePage, unsigned long dwFlags, const char *lpMultiByteStr, int cbMultiByte, wchar_t *lpWideCharStr, int cchWideChar);
]]
winapi.MultiByteToWideChar = function(MultiByteStr)
if MultiByteStr then
local utf16_len = winapi.C.MultiByteToWideChar(winapi.CP_UTF8, 0, MultiByteStr, -1, nil, 0)
if utf16_len > 0 then
local utf16_str = winapi.ffi.new("wchar_t[?]", utf16_len)
if winapi.C.MultiByteToWideChar(winapi.CP_UTF8, 0, MultiByteStr, -1, utf16_str, utf16_len) > 0 then
return utf16_str
end
end
end
return ""
end
else
options.direct_io = false
end
end
local file = nil
local file_bytes = 0
local spawned = false
local disabled = false
local force_disabled = false
local spawn_waiting = false
local spawn_working = false
local script_written = false
local dirty = false
local x = nil
local y = nil
local last_x = x
local last_y = y
local last_seek_time = nil
local effective_w = options.max_width
local effective_h = options.max_height
local real_w = nil
local real_h = nil
local last_real_w = nil
local last_real_h = nil
local script_name = nil
local show_thumbnail = false
local filters_reset = {["lavfi-crop"]=true, ["crop"]=true}
local filters_runtime = {["hflip"]=true, ["vflip"]=true}
local filters_all = {["hflip"]=true, ["vflip"]=true, ["lavfi-crop"]=true, ["crop"]=true}
local tone_mappings = {["none"]=true, ["clip"]=true, ["linear"]=true, ["gamma"]=true, ["reinhard"]=true, ["hable"]=true, ["mobius"]=true}
local last_tone_mapping = nil
local last_vf_reset = ""
local last_vf_runtime = ""
local last_rotate = 0
local par = ""
local last_par = ""
local last_has_vid = 0
local has_vid = 0
local file_timer = nil
local file_check_period = 1/60
local allow_fast_seek = true
local client_script = [=[
#!/usr/bin/env bash
MPV_IPC_FD=0; MPV_IPC_PATH="%s"
trap "kill 0" EXIT
while [[ $# -ne 0 ]]; do case $1 in --mpv-ipc-fd=*) MPV_IPC_FD=${1/--mpv-ipc-fd=/} ;; esac; shift; done
if echo "print-text thumbfast" >&"$MPV_IPC_FD"; then echo -n > "$MPV_IPC_PATH"; tail -f "$MPV_IPC_PATH" >&"$MPV_IPC_FD" & while read -r -u "$MPV_IPC_FD" 2>/dev/null; do :; done; fi
]=]
local function get_os()
local raw_os_name = ""
if jit and jit.os and jit.arch then
raw_os_name = jit.os
else
if package.config:sub(1,1) == "\\" then
-- Windows
local env_OS = os.getenv("OS")
if env_OS then
raw_os_name = env_OS
end
else
raw_os_name = subprocess({"uname", "-s"}).stdout
end
end
raw_os_name = (raw_os_name):lower()
local os_patterns = {
["windows"] = "windows",
["linux"] = "linux",
["osx"] = "darwin",
["mac"] = "darwin",
["darwin"] = "darwin",
["^mingw"] = "windows",
["^cygwin"] = "windows",
["bsd$"] = "darwin",
["sunos"] = "darwin"
}
-- Default to linux
local str_os_name = "linux"
for pattern, name in pairs(os_patterns) do
if raw_os_name:match(pattern) then
str_os_name = name
break
end
end
return str_os_name
end
local os_name = mp.get_property("platform") or get_os()
local path_separator = os_name == "windows" and "\\" or "/"
if options.socket == "" then
if os_name == "windows" then
options.socket = "thumbfast"
else
options.socket = "/tmp/thumbfast"
end
end
if options.thumbnail == "" then
if os_name == "windows" then
options.thumbnail = os.getenv("TEMP").."\\thumbfast.out"
else
options.thumbnail = "/tmp/thumbfast.out"
end
end
local unique = mp.utils.getpid()
options.socket = options.socket .. unique
options.thumbnail = options.thumbnail .. unique
if options.direct_io then
if os_name == "windows" then
winapi.socket_wc = winapi.MultiByteToWideChar("\\\\.\\pipe\\" .. options.socket)
end
if winapi.socket_wc == "" then
options.direct_io = false
end
end
local mpv_path = options.mpv_path
if mpv_path == "mpv" and os_name == "darwin" and unique then
-- TODO: look into ~~osxbundle/
mpv_path = string.gsub(subprocess({"ps", "-o", "comm=", "-p", tostring(unique)}).stdout, "[\n\r]", "")
if mpv_path ~= "mpv" then
mpv_path = string.gsub(mpv_path, "/mpv%-bundle$", "/mpv")
local mpv_bin = mp.utils.file_info("/usr/local/mpv")
if mpv_bin and mpv_bin.is_file then
mpv_path = "/usr/local/mpv"
else
local mpv_app = mp.utils.file_info("/Applications/mpv.app/Contents/MacOS/mpv")
if mpv_app and mpv_app.is_file then
mp.msg.warn("symlink mpv to fix Dock icons: `sudo ln -s /Applications/mpv.app/Contents/MacOS/mpv /usr/local/mpv`")
else
mp.msg.warn("drag to your Applications folder and symlink mpv to fix Dock icons: `sudo ln -s /Applications/mpv.app/Contents/MacOS/mpv /usr/local/mpv`")
end
end
end
end
local function vo_tone_mapping()
local passes = mp.get_property_native("vo-passes")
if passes and passes["fresh"] then
for k, v in pairs(passes["fresh"]) do
for k2, v2 in pairs(v) do
if k2 == "desc" and v2 then
local tone_mapping = string.match(v2, "([0-9a-z.-]+) tone map")
if tone_mapping then
return tone_mapping
end
end
end
end
end
end
local function vf_string(filters, full)
local vf = ""
local vf_table = properties["vf"]
if vf_table and #vf_table > 0 then
for i = #vf_table, 1, -1 do
if filters[vf_table[i].name] then
local args = ""
for key, value in pairs(vf_table[i].params) do
if args ~= "" then
args = args .. ":"
end
args = args .. key .. "=" .. value
end
vf = vf .. vf_table[i].name .. "=" .. args .. ","
end
end
end
if (full and options.tone_mapping ~= "no") or options.tone_mapping == "auto" then
if properties["video-params"] and properties["video-params"]["primaries"] == "bt.2020" then
local tone_mapping = options.tone_mapping
if tone_mapping == "auto" then
tone_mapping = last_tone_mapping or properties["tone-mapping"]
if tone_mapping == "auto" and properties["current-vo"] == "gpu-next" then
tone_mapping = vo_tone_mapping()
end
end
if not tone_mappings[tone_mapping] then
tone_mapping = "hable"
end
last_tone_mapping = tone_mapping
vf = vf .. "zscale=transfer=linear,format=gbrpf32le,tonemap="..tone_mapping..",zscale=transfer=bt709,"
end
end
if full then
vf = vf.."scale=w="..effective_w..":h="..effective_h..par..",pad=w="..effective_w..":h="..effective_h..":x=-1:y=-1,format=bgra"
end
return vf
end
local function calc_dimensions()
local width = properties["video-out-params"] and properties["video-out-params"]["dw"]
local height = properties["video-out-params"] and properties["video-out-params"]["dh"]
if not width or not height then return end
local scale = properties["display-hidpi-scale"] or 1
if width / height > options.max_width / options.max_height then
effective_w = math.floor(options.max_width * scale + 0.5)
effective_h = math.floor(height / width * effective_w + 0.5)
else
effective_h = math.floor(options.max_height * scale + 0.5)
effective_w = math.floor(width / height * effective_h + 0.5)
end
local v_par = properties["video-out-params"] and properties["video-out-params"]["par"] or 1
if v_par == 1 then
par = ":force_original_aspect_ratio=decrease"
else
par = ""
end
end
local info_timer = nil
local function info(w, h)
local rotate = properties["video-params"] and properties["video-params"]["rotate"]
local image = properties["current-tracks"] and properties["current-tracks"]["video"] and properties["current-tracks"]["video"]["image"]
local albumart = image and properties["current-tracks"]["video"]["albumart"]
disabled = (w or 0) == 0 or (h or 0) == 0 or
has_vid == 0 or
(properties["demuxer-via-network"] and not options.network) or
(albumart and not options.audio) or
(image and not albumart) or
force_disabled
if info_timer then
info_timer:kill()
info_timer = nil
elseif has_vid == 0 or (rotate == nil and not disabled) then
info_timer = mp.add_timeout(0.05, function() info(w, h) end)
end
local json, err = mp.utils.format_json({width=w, height=h, disabled=disabled, available=true, socket=options.socket, thumbnail=options.thumbnail, overlay_id=options.overlay_id})
if pre_0_30_0 then
mp.command_native({"script-message", "thumbfast-info", json})
else
mp.command_native_async({"script-message", "thumbfast-info", json}, function() end)
end
end
local function remove_thumbnail_files()
if file then
file:close()
file = nil
file_bytes = 0
end
os.remove(options.thumbnail)
os.remove(options.thumbnail..".bgra")
end
local activity_timer
local function spawn(time)
if disabled then return end
local path = properties["path"]
if path == nil then return end
if options.quit_after_inactivity > 0 then
if show_thumbnail or activity_timer:is_enabled() then
activity_timer:kill()
end
activity_timer:resume()
end
local open_filename = properties["stream-open-filename"]
local ytdl = open_filename and properties["demuxer-via-network"] and path ~= open_filename
if ytdl then
path = open_filename
end
remove_thumbnail_files()
local vid = properties["vid"]
has_vid = vid or 0
local args = {
mpv_path, "--no-config", "--msg-level=all=no", "--idle", "--pause", "--keep-open=always", "--really-quiet", "--no-terminal",
"--load-scripts=no", "--osc=no", "--ytdl=no", "--load-stats-overlay=no", "--load-osd-console=no", "--load-auto-profiles=no",
"--edition="..(properties["edition"] or "auto"), "--vid="..(vid or "auto"), "--no-sub", "--no-audio",
"--start="..time, allow_fast_seek and "--hr-seek=no" or "--hr-seek=yes",
"--ytdl-format=worst", "--demuxer-readahead-secs=0", "--demuxer-max-bytes=128KiB",
"--vd-lavc-skiploopfilter=all", "--vd-lavc-software-fallback=1", "--vd-lavc-fast", "--vd-lavc-threads=2", "--hwdec="..(options.hwdec and "auto" or "no"),
"--vf="..vf_string(filters_all, true),
"--sws-scaler=fast-bilinear",
"--video-rotate="..last_rotate,
"--ovc=rawvideo", "--of=image2", "--ofopts=update=1", "--o="..options.thumbnail
}
if not pre_0_30_0 then
table.insert(args, "--sws-allow-zimg=no")
end
if os_name == "darwin" and properties["macos-app-activation-policy"] then
table.insert(args, "--macos-app-activation-policy=accessory")
end
if os_name == "windows" or pre_0_33_0 then
table.insert(args, "--input-ipc-server="..options.socket)
elseif not script_written then
local client_script_path = options.socket..".run"
local script = io.open(client_script_path, "w+")
if script == nil then
mp.msg.error("client script write failed")
return
else
script_written = true
script:write(string.format(client_script, options.socket))
script:close()
subprocess({"chmod", "+x", client_script_path}, true)
table.insert(args, "--scripts="..client_script_path)
end
else
local client_script_path = options.socket..".run"
table.insert(args, "--scripts="..client_script_path)
end
table.insert(args, "--")
table.insert(args, path)
spawned = true
spawn_waiting = true
subprocess(args, true,
function(success, result)
if spawn_waiting and (success == false or (result.status ~= 0 and result.status ~= -2)) then
spawned = false
spawn_waiting = false
options.tone_mapping = "no"
mp.msg.error("mpv subprocess create failed")
if not spawn_working then -- notify users of required configuration
if options.mpv_path == "mpv" then
if properties["current-vo"] == "libmpv" then
if options.mpv_path == mpv_path then -- attempt to locate ImPlay
mpv_path = "ImPlay"
spawn(time)
else -- ImPlay not in path
if os_name ~= "darwin" then
force_disabled = true
info(real_w or effective_w, real_h or effective_h)
end
mp.commandv("show-text", "thumbfast: ERROR! cannot create mpv subprocess", 5000)
mp.commandv("script-message-to", "implay", "show-message", "thumbfast initial setup", "Set mpv_path=PATH_TO_ImPlay in thumbfast config:\n" .. string.gsub(mp.command_native({"expand-path", "~~/script-opts/thumbfast.conf"}), "[/\\]", path_separator).."\nand restart ImPlay")
end
else
mp.commandv("show-text", "thumbfast: ERROR! cannot create mpv subprocess", 5000)
if os_name == "windows" then
mp.commandv("script-message-to", "mpvnet", "show-text", "thumbfast: ERROR! install standalone mpv, see README", 5000, 20)
mp.commandv("script-message", "mpv.net", "show-text", "thumbfast: ERROR! install standalone mpv, see README", 5000, 20)
end
end
else
mp.commandv("show-text", "thumbfast: ERROR! cannot create mpv subprocess", 5000)
-- found ImPlay but not defined in config
mp.commandv("script-message-to", "implay", "show-message", "thumbfast", "Set mpv_path=PATH_TO_ImPlay in thumbfast config:\n" .. string.gsub(mp.command_native({"expand-path", "~~/script-opts/thumbfast.conf"}), "[/\\]", path_separator).."\nand restart ImPlay")
end
end
elseif success == true and (result.status == 0 or result.status == -2) then
if not spawn_working and properties["current-vo"] == "libmpv" and options.mpv_path ~= mpv_path then
mp.commandv("script-message-to", "implay", "show-message", "thumbfast initial setup", "Set mpv_path=ImPlay in thumbfast config:\n" .. string.gsub(mp.command_native({"expand-path", "~~/script-opts/thumbfast.conf"}), "[/\\]", path_separator).."\nand restart ImPlay")
end
spawn_working = true
spawn_waiting = false
end
end
)
end
local function run(command)
if not spawned then return end
if options.direct_io then
local hPipe = winapi.C.CreateFileW(winapi.socket_wc, winapi.GENERIC_WRITE, 0, nil, winapi.OPEN_EXISTING, winapi._createfile_pipe_flags, nil)
if hPipe ~= winapi.INVALID_HANDLE_VALUE then
local buf = command .. "\n"
winapi.C.SetNamedPipeHandleState(hPipe, winapi.PIPE_NOWAIT, nil, nil)
winapi.C.WriteFile(hPipe, buf, #buf + 1, winapi._lpNumberOfBytesWritten, nil)
winapi.C.CloseHandle(hPipe)
end
return
end
local command_n = command.."\n"
if os_name == "windows" then
if file and file_bytes + #command_n >= 4096 then
file:close()
file = nil
file_bytes = 0
end
if not file then
file = io.open("\\\\.\\pipe\\"..options.socket, "r+b")
end
elseif pre_0_33_0 then
subprocess({"/usr/bin/env", "sh", "-c", "echo '" .. command .. "' | socat - " .. options.socket})
return
elseif not file then
file = io.open(options.socket, "r+")
end
if file then
file_bytes = file:seek("end")
file:write(command_n)
file:flush()
end
end
local function draw(w, h, script)
if not w or not show_thumbnail then return end
if x ~= nil then
if pre_0_30_0 then
mp.command_native({"overlay-add", options.overlay_id, x, y, options.thumbnail..".bgra", 0, "bgra", w, h, (4*w)})
else
mp.command_native_async({"overlay-add", options.overlay_id, x, y, options.thumbnail..".bgra", 0, "bgra", w, h, (4*w)}, function() end)
end
elseif script then
local json, err = mp.utils.format_json({width=w, height=h, x=x, y=y, socket=options.socket, thumbnail=options.thumbnail, overlay_id=options.overlay_id})
mp.commandv("script-message-to", script, "thumbfast-render", json)
end
end
local function real_res(req_w, req_h, filesize)
local count = filesize / 4
local diff = (req_w * req_h) - count
if (properties["video-params"] and properties["video-params"]["rotate"] or 0) % 180 == 90 then
req_w, req_h = req_h, req_w
end
if diff == 0 then
return req_w, req_h
else
local threshold = 5 -- throw out results that change too much
local long_side, short_side = req_w, req_h
if req_h > req_w then
long_side, short_side = req_h, req_w
end
for a = short_side, short_side - threshold, -1 do
if count % a == 0 then
local b = count / a
if long_side - b < threshold then
if req_h < req_w then return b, a else return a, b end
end
end
end
return nil
end
end
local function move_file(from, to)
if os_name == "windows" then
os.remove(to)
end
-- move the file because it can get overwritten while overlay-add is reading it, and crash the player
os.rename(from, to)
end
local function seek(fast)
if last_seek_time then
run("async seek " .. last_seek_time .. (fast and " absolute+keyframes" or " absolute+exact"))
end
end
local seek_period = 3/60
local seek_period_counter = 0
local seek_timer
seek_timer = mp.add_periodic_timer(seek_period, function()
if seek_period_counter == 0 then
seek(allow_fast_seek)
seek_period_counter = 1
else
if seek_period_counter == 2 then
if allow_fast_seek then
seek_timer:kill()
seek()
end
else seek_period_counter = seek_period_counter + 1 end
end
end)
seek_timer:kill()
local function request_seek()
if seek_timer:is_enabled() then
seek_period_counter = 0
else
seek_timer:resume()
seek(allow_fast_seek)
seek_period_counter = 1
end
end
local function check_new_thumb()
-- the slave might start writing to the file after checking existance and
-- validity but before actually moving the file, so move to a temporary
-- location before validity check to make sure everything stays consistant
-- and valid thumbnails don't get overwritten by invalid ones
local tmp = options.thumbnail..".tmp"
move_file(options.thumbnail, tmp)
local finfo = mp.utils.file_info(tmp)
if not finfo then return false end
spawn_waiting = false
local w, h = real_res(effective_w, effective_h, finfo.size)
if w then -- only accept valid thumbnails
move_file(tmp, options.thumbnail..".bgra")
real_w, real_h = w, h
if real_w and (real_w ~= last_real_w or real_h ~= last_real_h) then
last_real_w, last_real_h = real_w, real_h
info(real_w, real_h)
end
if not show_thumbnail then
file_timer:kill()
end
return true
end
return false
end
file_timer = mp.add_periodic_timer(file_check_period, function()
if check_new_thumb() then
draw(real_w, real_h, script_name)
end
end)
file_timer:kill()
local function clear()
file_timer:kill()
seek_timer:kill()
if options.quit_after_inactivity > 0 then
if show_thumbnail or activity_timer:is_enabled() then
activity_timer:kill()
end
activity_timer:resume()
end
last_seek_time = nil
show_thumbnail = false
last_x = nil
last_y = nil
if script_name then return end
if pre_0_30_0 then
mp.command_native({"overlay-remove", options.overlay_id})
else
mp.command_native_async({"overlay-remove", options.overlay_id}, function() end)
end
end
local function quit()
activity_timer:kill()
if show_thumbnail then
activity_timer:resume()
return
end
run("quit")
spawned = false
real_w, real_h = nil, nil
clear()
end
activity_timer = mp.add_timeout(options.quit_after_inactivity, quit)
activity_timer:kill()
local function thumb(time, r_x, r_y, script)
if disabled then return end
time = tonumber(time)
if time == nil then return end
if r_x == "" or r_y == "" then
x, y = nil, nil
else
x, y = math.floor(r_x + 0.5), math.floor(r_y + 0.5)
end
script_name = script
if last_x ~= x or last_y ~= y or not show_thumbnail then
show_thumbnail = true
last_x = x
last_y = y
draw(real_w, real_h, script)
end
if options.quit_after_inactivity > 0 then
if show_thumbnail or activity_timer:is_enabled() then
activity_timer:kill()
end
activity_timer:resume()
end
if time == last_seek_time then return end
last_seek_time = time
if not spawned then spawn(time) end
request_seek()
if not file_timer:is_enabled() then file_timer:resume() end
end
local function watch_changes()
if not dirty or not properties["video-out-params"] then return end
dirty = false
local old_w = effective_w
local old_h = effective_h
calc_dimensions()
local vf_reset = vf_string(filters_reset)
local rotate = properties["video-rotate"] or 0
local resized = old_w ~= effective_w or
old_h ~= effective_h or
last_vf_reset ~= vf_reset or
(last_rotate % 180) ~= (rotate % 180) or
par ~= last_par
if resized then
last_rotate = rotate
info(effective_w, effective_h)
elseif last_has_vid ~= has_vid and has_vid ~= 0 then
info(effective_w, effective_h)
end
if spawned then
if resized then
-- mpv doesn't allow us to change output size
local seek_time = last_seek_time
run("quit")
clear()
spawned = false
spawn(seek_time or mp.get_property_number("time-pos", 0))
file_timer:resume()
else
if rotate ~= last_rotate then
run("set video-rotate "..rotate)
end
local vf_runtime = vf_string(filters_runtime)
if vf_runtime ~= last_vf_runtime then
run("vf set "..vf_string(filters_all, true))
last_vf_runtime = vf_runtime
end
end
else
last_vf_runtime = vf_string(filters_runtime)
end
last_vf_reset = vf_reset
last_rotate = rotate
last_par = par
last_has_vid = has_vid
if not spawned and not disabled and options.spawn_first and resized then
spawn(mp.get_property_number("time-pos", 0))
file_timer:resume()
end
end
local function update_property(name, value)
properties[name] = value
end
local function update_property_dirty(name, value)
properties[name] = value
dirty = true
if name == "tone-mapping" then
last_tone_mapping = nil
end
end
local function update_tracklist(name, value)
-- current-tracks shim
for _, track in ipairs(value) do
if track.type == "video" and track.selected then
properties["current-tracks/video/image"] = track.image
properties["current-tracks/video/albumart"] = track.albumart
return
end
end
end
local function sync_changes(prop, val)
update_property(prop, val)
if val == nil then return end
if type(val) == "boolean" then
if prop == "vid" then
has_vid = 0
last_has_vid = 0
info(effective_w, effective_h)
clear()
return
end
val = val and "yes" or "no"
end
if prop == "vid" then
has_vid = 1
end
if not spawned then return end
run("set "..prop.." "..val)
dirty = true
end
local function file_load()
clear()
spawned = false
real_w, real_h = nil, nil
last_real_w, last_real_h = nil, nil
last_tone_mapping = nil
last_seek_time = nil
if info_timer then
info_timer:kill()
info_timer = nil
end
calc_dimensions()
info(effective_w, effective_h)
end
local function shutdown()
run("quit")
remove_thumbnail_files()
if os_name ~= "windows" then
os.remove(options.socket)
os.remove(options.socket..".run")
end
end
local function on_duration(prop, val)
allow_fast_seek = (val or 30) >= 30
end
mp.observe_property("current-tracks", "native", function(name, value)
if pre_0_33_0 then
mp.unobserve_property(update_tracklist)
pre_0_33_0 = false
end
update_property(name, value)
end)
mp.observe_property("track-list", "native", update_tracklist)
mp.observe_property("display-hidpi-scale", "native", update_property_dirty)
mp.observe_property("video-out-params", "native", update_property_dirty)
mp.observe_property("video-params", "native", update_property_dirty)
mp.observe_property("vf", "native", update_property_dirty)
mp.observe_property("tone-mapping", "native", update_property_dirty)
mp.observe_property("demuxer-via-network", "native", update_property)
mp.observe_property("stream-open-filename", "native", update_property)
mp.observe_property("macos-app-activation-policy", "native", update_property)
mp.observe_property("current-vo", "native", update_property)
mp.observe_property("video-rotate", "native", update_property)
mp.observe_property("path", "native", update_property)
mp.observe_property("vid", "native", sync_changes)
mp.observe_property("edition", "native", sync_changes)
mp.observe_property("duration", "native", on_duration)
mp.register_script_message("thumb", thumb)
mp.register_script_message("clear", clear)
mp.register_event("file-loaded", file_load)
mp.register_event("shutdown", shutdown)
mp.register_idle(watch_changes)

1
scripts/thumbfast.lua Symbolic link
View File

@@ -0,0 +1 @@
../submodules/thumbfast/thumbfast.lua

View File

@@ -1 +1 @@
../mpv-youtube-upnext/youtube-upnext.lua
../submodules/mpv-youtube-upnext/youtube-upnext.lua

View File

@@ -1 +1 @@
ytdl-preload/ytdl-preload.lua
../submodules/ytdl-preload/ytdl-preload.lua

1407
shaders/ArtCNN_C4F16.glsl Normal file

File diff suppressed because it is too large Load Diff

1407
shaders/ArtCNN_C4F16_DS.glsl Normal file

File diff suppressed because it is too large Load Diff

3927
shaders/ArtCNN_C4F32.glsl Normal file

File diff suppressed because it is too large Load Diff

3927
shaders/ArtCNN_C4F32_DS.glsl Normal file

File diff suppressed because it is too large Load Diff

754
stats.lua
View File

@@ -1,754 +0,0 @@
-- Display some stats.
--
-- Please consult the readme for information about usage and configuration:
-- https://github.com/Argon-/mpv-stats
--
-- Please note: not every property is always available and therefore not always
-- visible.
local mp = require 'mp'
local options = require 'mp.options'
local utils = require 'mp.utils'
-- Options
local o = {
-- Default key bindings
key_oneshot = "i",
key_toggle = "I",
key_page_1 = "1",
key_page_2 = "2",
key_page_3 = "3",
duration = 4,
redraw_delay = 1, -- acts as duration in the toggling case
ass_formatting = true,
persistent_overlay = false, -- whether the stats can be overwritten by other output
print_perfdata_passes = false, -- when true, print the full information about all passes
filter_params_max_length = 100, -- a filter list longer than this many characters will be shown one filter per line instead
debug = false,
-- Graph options and style
plot_perfdata = true,
plot_vsync_ratio = true,
plot_vsync_jitter = true,
skip_frames = 5,
global_max = true,
flush_graph_data = true, -- clear data buffers when toggling
plot_bg_border_color = "0000FF",
plot_bg_color = "262626",
plot_color = "FFFFFF",
-- Text style
font = "Source Sans Pro",
font_mono = "Source Sans Pro", -- monospaced digits are sufficient
font_size = 8,
font_color = "FFFFFF",
border_size = 0.8,
border_color = "262626",
shadow_x_offset = 0.0,
shadow_y_offset = 0.0,
shadow_color = "000000",
alpha = "11",
-- Custom header for ASS tags to style the text output.
-- Specifying this will ignore the text style values above and just
-- use this string instead.
custom_header = "",
-- Text formatting
-- With ASS
ass_nl = "\\N",
ass_indent = "\\h\\h\\h\\h\\h",
ass_prefix_sep = "\\h\\h",
ass_b1 = "{\\b1}",
ass_b0 = "{\\b0}",
ass_it1 = "{\\i1}",
ass_it0 = "{\\i0}",
-- Without ASS
no_ass_nl = "\n",
no_ass_indent = "\t",
no_ass_prefix_sep = " ",
no_ass_b1 = "\027[1m",
no_ass_b0 = "\027[0m",
no_ass_it1 = "\027[3m",
no_ass_it0 = "\027[0m",
}
options.read_options(o)
local format = string.format
local max = math.max
local min = math.min
-- Function used to record performance data
local recorder = nil
-- Timer used for redrawing (toggling) and clearing the screen (oneshot)
local display_timer = nil
-- Current page and <page key>:<page function> mappings
local curr_page = o.key_page_1
local pages = {}
-- Save these sequences locally as we'll need them a lot
local ass_start = mp.get_property_osd("osd-ass-cc/0")
local ass_stop = mp.get_property_osd("osd-ass-cc/1")
-- Ring buffers for the values used to construct a graph.
-- .pos denotes the current position, .len the buffer length
-- .max is the max value in the corresponding buffer
local vsratio_buf, vsjitter_buf
local function init_buffers()
vsratio_buf = {0, pos = 1, len = 50, max = 0}
vsjitter_buf = {0, pos = 1, len = 50, max = 0}
end
-- Save all properties known to this version of mpv
local property_list = {}
for p in string.gmatch(mp.get_property("property-list"), "([^,]+)") do property_list[p] = true end
-- Mapping of properties to their deprecated names
local property_aliases = {
["decoder-frame-drop-count"] = "drop-frame-count",
["frame-drop-count"] = "vo-drop-frame-count",
["container-fps"] = "fps",
}
-- Return deprecated name for the given property
local function compat(p)
while not property_list[p] and property_aliases[p] do
p = property_aliases[p]
end
return p
end
local function set_ASS(b)
if not o.use_ass or o.persistent_overlay then
return ""
end
return b and ass_start or ass_stop
end
local function no_ASS(t)
return set_ASS(false) .. t .. set_ASS(true)
end
local function b(t)
return o.b1 .. t .. o.b0
end
local function it(t)
return o.it1 .. t .. o.it0
end
local function text_style()
if not o.use_ass then
return ""
end
if o.custom_header and o.custom_header ~= "" then
return set_ASS(true) .. o.custom_header
else
return format("%s{\\r}{\\an7}{\\fs%d}{\\fn%s}{\\bord%f}{\\3c&H%s&}" ..
"{\\1c&H%s&}{\\alpha&H%s&}{\\xshad%f}{\\yshad%f}{\\4c&H%s&}",
set_ASS(true), o.font_size, o.font, o.border_size,
o.border_color, o.font_color, o.alpha, o.shadow_x_offset,
o.shadow_y_offset, o.shadow_color)
end
end
local function has_vo_window()
return mp.get_property("vo-configured") == "yes"
end
local function has_ansi()
local is_windows = type(package) == 'table'
and type(package.config) == 'string'
and package.config:sub(1, 1) == '\\'
if is_windows then
return os.getenv("ANSICON")
end
return true
end
-- Generate a graph from the given values.
-- Returns an ASS formatted vector drawing as string.
--
-- values: Array/table of numbers representing the data. Used like a ring buffer
-- it will get iterated backwards `len` times starting at position `i`.
-- i : Index of the latest data value in `values`.
-- len : The length/amount of numbers in `values`.
-- v_max : The maximum number in `values`. It is used to scale all data
-- values to a range of 0 to `v_max`.
-- v_avg : The average number in `values`. It is used to try and center graphs
-- if possible. May be left as nil
-- scale : A value that will be multiplied with all data values.
-- x_tics: Horizontal width multiplier for the steps
local function generate_graph(values, i, len, v_max, v_avg, scale, x_tics)
-- Check if at least one value exists
if not values[i] then
return ""
end
local x_max = (len - 1) * x_tics
local y_offset = o.border_size
local y_max = o.font_size * 0.66
local x = 0
-- try and center the graph if possible, but avoid going above `scale`
if v_avg then
scale = min(scale, v_max / (2 * v_avg))
end
local s = {format("m 0 0 n %f %f l ", x, y_max - (y_max * values[i] / v_max * scale))}
i = ((i - 2) % len) + 1
for p = 1, len - 1 do
if values[i] then
x = x - x_tics
s[#s+1] = format("%f %f ", x, y_max - (y_max * values[i] / v_max * scale))
end
i = ((i - 2) % len) + 1
end
s[#s+1] = format("%f %f %f %f", x, y_max, 0, y_max)
local bg_box = format("{\\bord0.5}{\\3c&H%s&}{\\1c&H%s&}m 0 %f l %f %f %f 0 0 0",
o.plot_bg_border_color, o.plot_bg_color, y_max, x_max, y_max, x_max)
return format("%s{\\r}{\\pbo%f}{\\shad0}{\\alpha&H00}{\\p1}%s{\\p0}{\\bord0}{\\1c&H%s}{\\p1}%s{\\p0}%s",
o.prefix_sep, y_offset, bg_box, o.plot_color, table.concat(s), text_style())
end
local function append(s, str, attr)
if not str then
return false
end
attr.prefix_sep = attr.prefix_sep or o.prefix_sep
attr.indent = attr.indent or o.indent
attr.nl = attr.nl or o.nl
attr.suffix = attr.suffix or ""
attr.prefix = attr.prefix or ""
attr.no_prefix_markup = attr.no_prefix_markup or false
attr.prefix = attr.no_prefix_markup and attr.prefix or b(attr.prefix)
s[#s+1] = format("%s%s%s%s%s%s", attr.nl, attr.indent,
attr.prefix, attr.prefix_sep, no_ASS(str), attr.suffix)
return true
end
-- Format and append a property.
-- A property whose value is either `nil` or empty (hereafter called "invalid")
-- is skipped and not appended.
-- Returns `false` in case nothing was appended, otherwise `true`.
--
-- s : Table containing strings.
-- prop : The property to query and format (based on its OSD representation).
-- attr : Optional table to overwrite certain (formatting) attributes for
-- this property.
-- exclude: Optional table containing keys which are considered invalid values
-- for this property. Specifying this will replace empty string as
-- default invalid value (nil is always invalid).
local function append_property(s, prop, attr, excluded)
excluded = excluded or {[""] = true}
local ret = mp.get_property_osd(prop)
if not ret or excluded[ret] then
if o.debug then
print("No value for property: " .. prop)
end
return false
end
return append(s, ret, attr)
end
local function append_perfdata(s, dedicated_page)
local vo_p = mp.get_property_native("vo-passes")
if not vo_p then
return
end
local ds = mp.get_property_bool("display-sync-active", false)
local target_fps = ds and mp.get_property_number("display-fps", 0)
or mp.get_property_number(compat("container-fps"), 0)
if target_fps > 0 then target_fps = 1 / target_fps * 1e9 end
-- Sums of all last/avg/peak values
local last_s, avg_s, peak_s = {}, {}, {}
for frame, data in pairs(vo_p) do
last_s[frame], avg_s[frame], peak_s[frame] = 0, 0, 0
for _, pass in ipairs(data) do
last_s[frame] = last_s[frame] + pass["last"]
avg_s[frame] = avg_s[frame] + pass["avg"]
peak_s[frame] = peak_s[frame] + pass["peak"]
end
end
-- Pretty print measured time
local function pp(i)
-- rescale to microseconds for a saner display
return format("%05d", i / 1000)
end
-- Format n/m with a font weight based on the ratio
local function p(n, m)
local i = 0
if m > 0 then
i = tonumber(n) / m
end
-- Calculate font weight. 100 is minimum, 400 is normal, 700 bold, 900 is max
local w = (700 * math.sqrt(i)) + 200
return format("{\\b%d}%02d%%{\\b0}", w, i * 100)
end
s[#s+1] = format("%s%s%s%s{\\fs%s}%s{\\fs%s}",
dedicated_page and "" or o.nl, dedicated_page and "" or o.indent,
b("Frame Timings:"), o.prefix_sep, o.font_size * 0.66,
"(last/average/peak μs)", o.font_size)
for frame, data in pairs(vo_p) do
local f = "%s%s%s{\\fn%s}%s / %s / %s %s%s{\\fn%s}%s%s%s"
if dedicated_page then
s[#s+1] = format("%s%s%s:", o.nl, o.indent,
b(frame:gsub("^%l", string.upper)))
for _, pass in ipairs(data) do
s[#s+1] = format(f, o.nl, o.indent, o.indent,
o.font_mono, pp(pass["last"]),
pp(pass["avg"]), pp(pass["peak"]),
o.prefix_sep .. o.prefix_sep, p(pass["last"], last_s[frame]),
o.font, o.prefix_sep, o.prefix_sep, pass["desc"])
if o.plot_perfdata and o.use_ass then
s[#s+1] = generate_graph(pass["samples"], pass["count"],
pass["count"], pass["peak"],
pass["avg"], 0.9, 0.25)
end
end
-- Print sum of timing values as "Total"
s[#s+1] = format(f, o.nl, o.indent, o.indent,
o.font_mono, pp(last_s[frame]),
pp(avg_s[frame]), pp(peak_s[frame]), "", "", o.font,
o.prefix_sep, o.prefix_sep, b("Total"))
else
-- for the simplified view, we just print the sum of each pass
s[#s+1] = format(f, o.nl, o.indent, o.indent, o.font_mono,
pp(last_s[frame]), pp(avg_s[frame]), pp(peak_s[frame]),
"", "", o.font, o.prefix_sep, o.prefix_sep,
frame:gsub("^%l", string.upper))
end
end
end
local function append_display_sync(s)
if not mp.get_property_bool("display-sync-active", false) then
return
end
local vspeed = append_property(s, "video-speed-correction", {prefix="DS:"})
if vspeed then
append_property(s, "audio-speed-correction",
{prefix="/", nl="", indent=" ", prefix_sep=" ", no_prefix_markup=true})
else
append_property(s, "audio-speed-correction",
{prefix="DS:" .. o.prefix_sep .. " - / ", prefix_sep=""})
end
append_property(s, "mistimed-frame-count", {prefix="Mistimed:", nl=""})
append_property(s, "vo-delayed-frame-count", {prefix="Delayed:", nl=""})
-- As we need to plot some graphs we print jitter and ratio on their own lines
if not display_timer.oneshot and (o.plot_vsync_ratio or o.plot_vsync_jitter) and o.use_ass then
local ratio_graph = ""
local jitter_graph = ""
if o.plot_vsync_ratio then
ratio_graph = generate_graph(vsratio_buf, vsratio_buf.pos, vsratio_buf.len, vsratio_buf.max, nil, 0.8, 1)
end
if o.plot_vsync_jitter then
jitter_graph = generate_graph(vsjitter_buf, vsjitter_buf.pos, vsjitter_buf.len, vsjitter_buf.max, nil, 0.8, 1)
end
append_property(s, "vsync-ratio", {prefix="VSync Ratio:", suffix=o.prefix_sep .. ratio_graph})
append_property(s, "vsync-jitter", {prefix="VSync Jitter:", suffix=o.prefix_sep .. jitter_graph})
else
-- Since no graph is needed we can print ratio/jitter on the same line and save some space
local vratio = append_property(s, "vsync-ratio", {prefix="VSync Ratio:"})
append_property(s, "vsync-jitter", {prefix="VSync Jitter:", nl="" or o.nl})
end
end
local function append_filters(s, prop, prefix)
local length = 0
local filters = {}
for _,f in ipairs(mp.get_property_native(prop, {})) do
local n = f.name
if f.enabled ~= nil and not f.enabled then
n = n .. " (disabled)"
end
local p = {}
for key,value in pairs(f.params) do
p[#p+1] = key .. "=" .. value
end
if #p > 0 then
p = " [" .. table.concat(p, " ") .. "]"
else
p = ""
end
length = length + n:len() + p:len()
filters[#filters+1] = no_ASS(n) .. it(no_ASS(p))
end
if #filters > 0 then
local ret
if length < o.filter_params_max_length then
ret = table.concat(filters, ", ")
else
local sep = o.nl .. o.indent .. o.indent
ret = sep .. table.concat(filters, sep)
end
s[#s+1] = o.nl .. o.indent .. b(prefix) .. o.prefix_sep .. ret
end
end
local function add_header(s)
s[#s+1] = text_style()
end
local function add_file(s)
append(s, "", {prefix="File:", nl="", indent=""})
append_property(s, "filename", {prefix_sep="", nl="", indent=""})
if not (mp.get_property_osd("filename") == mp.get_property_osd("media-title")) then
append_property(s, "media-title", {prefix="Title:"})
end
local ch_index = mp.get_property_number("chapter")
if ch_index and ch_index >= 0 then
append_property(s, "chapter-list/" .. tostring(ch_index) .. "/title", {prefix="Chapter:"})
append_property(s, "chapter-list/count",
{prefix="(" .. tostring(ch_index + 1) .. "/", suffix=")", nl="",
indent=" ", prefix_sep=" ", no_prefix_markup=true})
end
local demuxer_cache = mp.get_property_native("demuxer-cache-state", {})
if demuxer_cache["fw-bytes"] then
demuxer_cache = demuxer_cache["fw-bytes"] -- returns bytes
else
demuxer_cache = 0
end
local demuxer_secs = mp.get_property_number("demuxer-cache-duration", 0)
local stream_cache = mp.get_property_number("cache-used", 0) * 1024 -- returns KiB
if stream_cache + demuxer_cache + demuxer_secs > 0 then
append(s, utils.format_bytes_humanized(stream_cache + demuxer_cache), {prefix="Total Cache:"})
append(s, utils.format_bytes_humanized(demuxer_cache), {prefix="(Demuxer:",
suffix=",", nl="", no_prefix_markup=true, indent=o.prefix_sep})
append(s, format("%.1f", demuxer_secs), {suffix=" sec)", nl="", indent="",
no_prefix_markup=true})
local speed = mp.get_property_number("cache-speed", 0)
if speed > 0 then
append(s, utils.format_bytes_humanized(speed) .. "/s", {prefix="Speed:", nl="",
indent=o.prefix_sep, no_prefix_markup=true})
end
end
append_property(s, "file-size", {prefix="Size:"})
end
local function add_video(s)
local r = mp.get_property_native("video-params")
-- in case of e.g. lavi-complex there can be no input video, only output
if not r then
r = mp.get_property_native("video-out-params")
end
if not r then
return
end
append(s, "", {prefix=o.nl .. o.nl .. "Video:", nl="", indent=""})
if append_property(s, "video-codec", {prefix_sep="", nl="", indent=""}) then
append_property(s, "hwdec-current", {prefix="(hwdec:", nl="", indent=" ",
no_prefix_markup=true, suffix=")"}, {no=true, [""]=true})
end
append_property(s, "avsync", {prefix="A-V:"})
if append_property(s, compat("decoder-frame-drop-count"),
{prefix="Dropped Frames:", suffix=" (decoder)"}) then
append_property(s, compat("frame-drop-count"), {suffix=" (output)", nl="", indent=""})
end
if append_property(s, "display-fps", {prefix="Display FPS:", suffix=" (specified)"}) then
append_property(s, "estimated-display-fps",
{suffix=" (estimated)", nl="", indent=""})
else
append_property(s, "estimated-display-fps",
{prefix="Display FPS:", suffix=" (estimated)"})
end
if append_property(s, compat("container-fps"), {prefix="FPS:", suffix=" (specified)"}) then
append_property(s, "estimated-vf-fps",
{suffix=" (estimated)", nl="", indent=""})
else
append_property(s, "estimated-vf-fps",
{prefix="FPS:", suffix=" (estimated)"})
end
append_display_sync(s)
append_perfdata(s, o.print_perfdata_passes)
if append(s, r["w"], {prefix="Native Resolution:"}) then
append(s, r["h"], {prefix="x", nl="", indent=" ", prefix_sep=" ", no_prefix_markup=true})
end
append_property(s, "window-scale", {prefix="Window Scale:"})
append(s, format("%.2f", r["aspect"]), {prefix="Aspect Ratio:"})
append(s, r["pixelformat"], {prefix="Pixel Format:"})
-- Group these together to save vertical space
local prim = append(s, r["primaries"], {prefix="Primaries:"})
local cmat = append(s, r["colormatrix"], {prefix="Colormatrix:", nl=prim and "" or o.nl})
append(s, r["colorlevels"], {prefix="Levels:", nl=cmat and "" or o.nl})
-- Append HDR metadata conditionally (only when present and interesting)
local hdrpeak = r["sig-peak"] or 0
local hdrinfo = ""
if hdrpeak > 1 then
hdrinfo = " (HDR peak: " .. format("%.2f", hdrpeak) .. ")"
end
append(s, r["gamma"], {prefix="Gamma:", suffix=hdrinfo})
append_property(s, "packet-video-bitrate", {prefix="Bitrate:", suffix=" kbps"})
append_filters(s, "vf", "Filters:")
end
local function add_audio(s)
local r = mp.get_property_native("audio-params")
-- in case of e.g. lavi-complex there can be no input audio, only output
if not r then
r = mp.get_property_native("audio-out-params")
end
if not r then
return
end
append(s, "", {prefix=o.nl .. o.nl .. "Audio:", nl="", indent=""})
append_property(s, "audio-codec", {prefix_sep="", nl="", indent=""})
append(s, r["format"], {prefix="Format:"})
append(s, r["samplerate"], {prefix="Sample Rate:", suffix=" Hz"})
append(s, r["channel-count"], {prefix="Channels:"})
append_property(s, "packet-audio-bitrate", {prefix="Bitrate:", suffix=" kbps"})
append_filters(s, "af", "Filters:")
end
-- Determine whether ASS formatting shall/can be used and set formatting sequences
local function eval_ass_formatting()
o.use_ass = o.ass_formatting and has_vo_window()
if o.use_ass then
o.nl = o.ass_nl
o.indent = o.ass_indent
o.prefix_sep = o.ass_prefix_sep
o.b1 = o.ass_b1
o.b0 = o.ass_b0
o.it1 = o.ass_it1
o.it0 = o.ass_it0
else
o.nl = o.no_ass_nl
o.indent = o.no_ass_indent
o.prefix_sep = o.no_ass_prefix_sep
if not has_ansi() then
o.b1 = ""
o.b0 = ""
o.it1 = ""
o.it0 = ""
else
o.b1 = o.no_ass_b1
o.b0 = o.no_ass_b0
o.it1 = o.no_ass_it1
o.it0 = o.no_ass_it0
end
end
end
-- Returns an ASS string with "normal" stats
local function default_stats()
local stats = {}
eval_ass_formatting()
add_header(stats)
add_file(stats)
add_video(stats)
add_audio(stats)
return table.concat(stats)
end
-- Returns an ASS string with extended VO stats
local function vo_stats()
local stats = {}
eval_ass_formatting()
add_header(stats)
append_perfdata(stats, true)
return table.concat(stats)
end
-- Returns an ASS string with stats about filters/profiles/shaders
local function filter_stats()
return "coming soon"
end
-- Current page and <page key>:<page function> mapping
curr_page = o.key_page_1
pages = {
[o.key_page_1] = { f = default_stats, desc = "Default" },
[o.key_page_2] = { f = vo_stats, desc = "Extended Frame Timings" },
--[o.key_page_3] = { f = filter_stats, desc = "Dummy" },
}
-- Returns a function to record vsratio/jitter with the specified `skip` value
local function record_data(skip)
init_buffers()
skip = max(skip, 0)
local i = skip
return function()
if i < skip then
i = i + 1
return
else
i = 0
end
if o.plot_vsync_jitter then
local r = mp.get_property_number("vsync-jitter", nil)
if r then
vsjitter_buf.pos = (vsjitter_buf.pos % vsjitter_buf.len) + 1
vsjitter_buf[vsjitter_buf.pos] = r
vsjitter_buf.max = max(vsjitter_buf.max, r)
end
end
if o.plot_vsync_ratio then
local r = mp.get_property_number("vsync-ratio", nil)
if r then
vsratio_buf.pos = (vsratio_buf.pos % vsratio_buf.len) + 1
vsratio_buf[vsratio_buf.pos] = r
vsratio_buf.max = max(vsratio_buf.max, r)
end
end
end
end
-- Call the function for `page` and print it to OSD
local function print_page(page)
if o.persistent_overlay then
mp.set_osd_ass(0, 0, pages[page].f())
else
mp.osd_message(pages[page].f(), display_timer.oneshot and o.duration or o.redraw_delay + 1)
end
end
local function clear_screen()
if o.persistent_overlay then mp.set_osd_ass(0, 0, "") else mp.osd_message("", 0) end
end
-- Add keybindings for every page
local function add_page_bindings()
local function a(k)
return function()
curr_page = k
print_page(k)
if display_timer.oneshot then display_timer:kill() ; display_timer:resume() end
end
end
for k, _ in pairs(pages) do
mp.add_forced_key_binding(k, k, a(k), {repeatable=true})
end
end
-- Remove keybindings for every page
local function remove_page_bindings()
for k, _ in pairs(pages) do
mp.remove_key_binding(k)
end
end
local function process_key_binding(oneshot)
-- Stats are already being displayed
if display_timer:is_enabled() then
-- Previous and current keys were oneshot -> restart timer
if display_timer.oneshot and oneshot then
display_timer:kill()
print_page(curr_page)
display_timer:resume()
-- Previous and current keys were toggling -> end toggling
elseif not display_timer.oneshot and not oneshot then
display_timer:kill()
clear_screen()
remove_page_bindings()
if recorder then
mp.unregister_event(recorder)
recorder = nil
end
end
-- No stats are being displayed yet
else
if not oneshot and (o.plot_vsync_jitter or o.plot_vsync_ratio) then
recorder = record_data(o.skip_frames)
mp.register_event("tick", recorder)
end
display_timer:kill()
display_timer.oneshot = oneshot
display_timer.timeout = oneshot and o.duration or o.redraw_delay
add_page_bindings()
print_page(curr_page)
display_timer:resume()
end
end
-- Create the timer used for redrawing (toggling) or clearing the screen (oneshot)
-- The duration here is not important and always set in process_key_binding()
display_timer = mp.add_periodic_timer(o.duration,
function()
if display_timer.oneshot then
display_timer:kill() ; clear_screen() ; remove_page_bindings()
else
print_page(curr_page)
end
end)
display_timer:kill()
-- Single invocation key binding
mp.add_key_binding(o.key_oneshot, "display-stats", function() process_key_binding(true) end,
{repeatable=true})
-- Toggling key binding
mp.add_key_binding(o.key_toggle, "display-stats-toggle", function() process_key_binding(false) end,
{repeatable=false})
-- Single invocation bindings without key, can be used in input.conf to create
-- bindings for a specific page: "e script-binding stats/display-page-2"
for k, _ in pairs(pages) do
mp.add_key_binding(nil, "display-page-" .. k, function() process_key_binding(true) end,
{repeatable=true})
end
-- Reprint stats immediately when VO was reconfigured, only when toggled
mp.register_event("video-reconfig",
function()
if display_timer:is_enabled() then
print_page(curr_page)
end
end)

1
submodules/ModernZ Submodule

Submodule submodules/ModernZ added at cd23007c69

1
submodules/animecards Submodule

Submodule submodules/animecards added at ced1d30630

1
submodules/mpvacious Submodule

Submodule submodules/mpvacious added at 01c6adc825

1
submodules/thumbfast Submodule

Submodule submodules/thumbfast added at 9deb0733c4