It is currently November 29th, 2020, 7:20 pm

Rain Video

Post your work-in-progress and completed skins to share and discuss.
User avatar
eclectic-tech
Rainmeter Sage
Posts: 4192
Joined: April 12th, 2012, 9:40 pm
Location: Cedar Point, Ohio, USA

Rain Video

Post by eclectic-tech »

RAINMETER VIDEO PLAYER
rainvideo5-0.jpg
rainvideo5-3.jpg
rainvideo5-2.jpg
rainvideo5-1.jpg
rainvideo5-4.jpg
A video player based on FFmpeg's FFplay.exe as discussed in this thread by Yincognito.

Should play most downloaded video file formats. Tested: .mp4, .mp3, .avi, .flv, .webm, .mrec
Also has the ability to display image files.

FFPlay includes controls of Video, Sound, and Waveforms
Hover the button for actions
In order to have button controls that do not require clicking the FFPlay window first to give it focus, I use an add-on to send key codes without changing focus away from the FFPlay window. I use IsFullScreen plugin by JSMorley to prevent sending keys if FFPlay.exe is not the focused window (buttons will be greyed out).

The buttons send these key codes to the active window (FFPlay) to achieve the desired action:
ACTION | 'KEY'
Quit Video | 'q' or 'ESC'
Toggle Play/Pause | 'p' or 'Spacebar'
Frame Step | 's'
Back 10 sec | 'Left-Arrow'
Ahead 10 sec | 'Right-Arrow'
Select Stream | 'w'
Vol Up | '0' or 'Asterisk'
Vol Dn | '9' or '/'
Toggle Mute | 'm'

Context menu select sizes:
Default Video Size (usually 480 on YouTube)
320X180 Size
480X270 Size
640X360 Size
960X540 Size

PLUGINS USED
FileChoose plugin by Setsukka (included after V 1.2020.09.18)
IsFullScreen plugin by JSMorley included in the RMSKIN package
SysColorr plugin by Brian Ferguson

NOTES ON USE
Context menu video size can be set when no video is playing.
Control styles 'Text' or 'Buttons' can be selected from the context menu
When a video is playing Control Actions will appear. Hovering the first label will toggle them so only the toggle and video show. The controls can be moved anywhere on the screen
Video window can be position and resized while playing, but will revert to the skin location after quitting video play
If you change the main skin's screen position, Middle-click the skin (or use the context menu) to refresh position of the video window
DO NOT UNLOAD THE SKIN WHILE A VIDEO IS PLAYING; always quit the video first!
(Otherwise, FFPlay will stop responding and must be killed by Windows)

SUMMARY
A plugin for Rainmeter would be better, but until then I hope this helps. :welcome:

OPTIONS
Option 1) Download RMSKIN (27 meg includes ffplay.exe, SendKey.exe, FileChoose.dll, IsFullScreen.dll, SysColor.dll): My MediaFire Link

Option 2) Download full FFmpeg (127 meg): Latest FFmpeg GIT build for Windows and follow steps in Option 3.

Option 3) If you already have FFmpeg on your system, you can create a new skin from the code below. Place FFPlay.exe in ''@Resources\FFmpeg' in that new skin folder. Download and install FileChoose.dll, IsFullScreen, and SysColor. Find SendKey program (I forgot where I got it)




V 1.2020.09.27a
'RainVideo\RainVideo.ini'

Code: Select all

[Variables]
File=C:\Users\John\Videos\Music\George Michael - Freedom! ’90 (Official Video).mp4
Width=640
Height=34
Default=1
Size=0
Repeat=0
XPosition=(#CurrentConfigX#+128)
; ControlType: 'Text' or 'Buttons'
ControlType=Buttons

[Metadata]
Name=RainVideo
Author=Eclectic Tech
Information=Play videos. Selectable frame size when no video is playing. Controls: quit, pause, step frame, repeat, fullscreen, volume up/down, mute when video has focus (left-click video first).
License=CC3-BY-SA-NC
Version=1.2020.09.27a

[Rainmeter]
Update=1000
DynamicWindowSize=1
AccurateText=1

MiddleMouseUpAction=[!Refresh]
RightMouseUpAction=[!SkinCustomMenu]

ContextTitle=[\x25cb] Default Size
ContextAction=[!WriteKeyValue Variables Size 0][!WriteKeyValue Variables Default 1][!WriteKeyValue Variables Width 640][!WriteKeyValue Variables Height 34][!Refresh]
ContextTitle2=[\x25cb] 320X180 Size
ContextAction2=[!WriteKeyValue Variables Size 1][!WriteKeyValue Variables Default 0][!WriteKeyValue Variables Width 320][!WriteKeyValue Variables Height 180][!Refresh]
ContextTitle3=[\x25cb] 480X270 Size
ContextAction3=[!WriteKeyValue Variables Size 2][!WriteKeyValue Variables Default 0][!WriteKeyValue Variables Width 480][!WriteKeyValue Variables Height 270][!Refresh]
ContextTitle4=[\x25cb] 640X360 Size
ContextAction4=[!WriteKeyValue Variables Size 3][!WriteKeyValue Variables Default 0][!WriteKeyValue Variables Width 640][!WriteKeyValue Variables Height 360][!Refresh]
ContextTitle5=[\x25cb] 960X540 Size
ContextAction5=[!WriteKeyValue Variables Size 4][!WriteKeyValue Variables Default 0][!WriteKeyValue Variables Width 960][!WriteKeyValue Variables Height 540][!Refresh]
ContextTitle6=---
ContextAction6=[]
ContextTitle7=[\x25cb] Repeat
ContextAction7=[!WriteKeyValue Variables Repeat (1-#Repeat#)][!Refresh]
ContextTitle8=---
ContextAction8=[]
ContextTitle9=[\x25cb] Text Controls
ContextAction9=[!WriteKeyValue Variables ControlType Text][!Refresh]
ContextTitle10=[\x25cb] Button Controls
ContextAction10=[!WriteKeyValue Variables ControlType Buttons][!Refresh]
ContextTitle11=---
ContextAction11=[]
ContextTitle12=Refresh Position
ContextAction12=[!Refresh]
ContextTitle13=---
ContextAction13=[]
ContextTitle14=More Actions >>>
ContextAction14=[!SkinMenu]

;---Measures---
[mAccent]
Measure=Plugin
Plugin=SysColor
ColorType=DWM_COLOR

[MeasureContextSize]
Measure=Calc
Formula=#Size#
IfCondition=(#CurrentSection#=0)
IfTrueAction=[!SetOption Rainmeter ContextTitle "[\x25c9] Default Size"]
IfFalseAction=[!SetOption Rainmeter ContextTitle "[\x25cb] Default Size"]
IfCondition2=(#CurrentSection#=1)
IfTrueAction2=[!SetOption Rainmeter ContextTitle2 "[\x25c9] 320X180 Size"]
IfFalseAction2=[!SetOption Rainmeter ContextTitle2 "[\x25cb] 320X180 Size"]
IfCondition3=(#CurrentSection#=2)
IfTrueAction3=[!SetOption Rainmeter ContextTitle3 "[\x25c9] 480X270 Size"]
IfFalseAction3=[!SetOption Rainmeter ContextTitle3 "[\x25cb] 480X270 Size"]
IfCondition4=(#CurrentSection#=3)
IfTrueAction4=[!SetOption Rainmeter ContextTitle4 "[\x25c9] 640X360 Size"]
IfFalseAction4=[!SetOption Rainmeter ContextTitle4 "[\x25cb] 640X360 Size"]
IfCondition5=(#CurrentSection#=4)
IfTrueAction5=[!SetOption Rainmeter ContextTitle5 "[\x25c9] 960X540 Size"]
IfFalseAction5=[!SetOption Rainmeter ContextTitle5 "[\x25cb] 960X540 Size"]
UpdateDivider=-1

[MeasureContextRepeat]
Measure=Calc
Formula=#Repeat#
IfCondition=(#CurrentSection#=0)
IfTrueAction=[!SetOption Rainmeter ContextTitle7 "[\x25c9] Repeat"][!SetOption MeterRepeat Text "Repeat: On"]
IfFalseAction=[!SetOption Rainmeter ContextTitle7 "[\x25cb] Repeat"][!SetOption MeterRepeat Text "Repeat: Off"]
UpdateDivider=-1

[MeasureContextControlType]
Measure=String
String=#ControlType#
IfMatch=(?i)text
IfMatchAction=[!SetOption Rainmeter ContextTitle9 "[\x25c9] Text Controls"][!SetOption Rainmeter ContextTitle10 "[\x25cb] Button Controls"]
IfNotMatchAction=[!SetOption Rainmeter ContextTitle9 "[\x25cb] Text Controls"][!SetOption Rainmeter ContextTitle10 "[\x25c9] Button Controls"]
UpdateDivider=-1

[MeasureFocus]
Measure=Plugin
Plugin=IsFullScreen
IfMatch=ffplay.exe
IfMatchAction=[!SetVariable ButtonAlpha 255]
IfNotMatchAction=[!SetVariable ButtonAlpha 128]

[MeasureVideoSize]
Measure=String
String="-x #Width# -y #Height#"
UpdateDivider=-1
IfCondition=(#Default#=1)
IfTrueAction=[!SetVariable Width "640"][!SetVariable Height 34][!SetVariable XPosition (#CurrentConfigX#+128)][!UpdateMeter *][!Redraw]
IfFalseAction=[!SetVariable Width "#Width#"][!SetVariable Height #Height#][!SetVariable XPosition (#CurrentConfigX#+128)][!UpdateMeter *][!Redraw]
DynamicVariables=1

[MeasurePlaying]
Measure=Process
ProcessName=ffplay.exe
IfCondition=(MeasurePlaying=1)
IfTrueAction=[!DisableMouseAction Rainmeter "MiddleMouseUpAction|RightMouseUpAction"]
IfFalseAction=[!EnableMouseAction Rainmeter "MiddleMouseUpAction|RightMouseUpAction"]

[MeasureChoose]
Measure=Plugin
Plugin=FileChoose
GetTarget=1
CopyLink=1
LinkCache=%USERPROFILE%/Videos/
ReturnValue=WholePath
Command1=[!SetVariable File """$Path$"""][!WriteKeyValue Variables File """$Path$"""][!Update]
DynamicVariables=1

; Make the Title Pretty
[MeasureTitle]
Measure=String
String=#File#
RegExpSubstitute=1
Substitute="^.*\\(.*)\..*$":"\1"
DynamicVariables=1

; Play in pre-defined size window 
[MeasurePlay0]
Measure=Plugin
Plugin=RunCommand
Parameter=ffplay "#File#" -left #XPosition# -top #CurrentConfigY# [MeasureVideoSize] -window_title "[MeasureTitle]" -hide_banner -loop #Repeat# -autoexit
OutputType=ANSI
State=Hide
StartInFolder=#@#ffmpeg
DynamicVariables=1
FinishAction=[!DeActivateConfig "#RootConfig#\Controls"]

; Play in default size window
[MeasurePlay1]
Measure=Plugin
Plugin=RunCommand
Parameter=ffplay "#File#" -left #XPosition# -top #CurrentConfigY# -window_title "[MeasureTitle]" -hide_banner -loop #Repeat# -autoexit
OutputType=ANSI
State=Hide
StartInFolder=#@#ffmpeg
DynamicVariables=1
FinishAction=[!DeActivateConfig "#RootConfig#\Controls"]

;---Styles---

[StyleText]
FontWeight=500
FontSize=11
FontColor=255,255,255,255
SolidColor=[mAccent]
Padding=5,5,5,5
AntiAlias=1

;---Meters---

[MeterUpperLeftCorner]
Meter=Shape
X=0
Y=0
Shape=Rectangle 1,1,(#Width#-2),(#Height#-2) | StrokeWidth (2*([MeasurePlaying]<0?)) | Stroke Color [mAccent] | Fill Color 0,0,0,1
DynamicVariables=1
Hidden=([MeasurePlaying]=1)?

[MeterPlay]
Meter=String
MeterStyle=StyleText
X=(#Width#-70)
Y=4
W=120
StringAlign=Center
Text=Play
LeftMouseUpAction=[!CommandMeasure MeasurePlay#Default# "Run"][!ActivateConfig "#RootConfig#\Controls" "#ControlType#.ini"]
Hidden=([MeasurePlaying]=1)?
DynamicVariables=1

[MeterChooseFile]
Meter=String
MeterStyle=StyleText
X=70
Y=4
W=120
StringAlign=Center
Text=File
LeftMouseUpAction=[!CommandMeasure MeasureChoose "ChooseFile 1"]
Hidden=([MeasurePlaying]=1)?
DynamicVariables=1

[MeterRepeat]
Meter=String
MeterStyle=StyleText
X=(#Width#*0.5)
Y=4
W=120
StringAlign=Center
Text=Repeat: #Repeat#
Hidden=([MeasurePlaying]=1)?
LeftMouseUpAction=[!WriteKeyValue Variables Repeat (1-#Repeat#)][!Refresh]
DynamicVariables=1

[MeterCurrent]
Meter=String
MeterStyle=StyleText
X=(#Width#*0.5)
Y=36
StringAlign=Center
ClipString=2
ClipStringW=(#Width#*0.5)
Text=[MeasureTitle]
Hidden=([MeasurePlaying]=1)?
DynamicVariables=1

Button Style: 'RainVideo\Controls\Text.ini'

Code: Select all

; ========= Metadata ==========
[Metadata]
Name=RainVideoControlsText
Author=Eclectic Tech deviantArt.com/eclectictech
Information=
; BY=attribution / SA=share-alike / ND=no-derivatives / NC=non-commercial
License=CC BY-SA-NC 3.0
Version=1.2020.09.27a

; ========= Variables ==========
[Variables]
ButtonWidth=120
ButtonAlpha=255
; Exchange the X & Y values below for vertical or horizontal buttons
HSpacing=r
VSpacing=4R

; ========= Skin Settings ==========
[Rainmeter]
Update=1000
AccurateText=1
DynamicWindowSize=1
Group=#RootConfig#
DefaultAlwaysOnTop=1
OnRefreshAction=[!ZPos +2][!HideMeterGroup Buttons]

ContextTitle=Horizontal Buttons
ContextAction=[!SetVariable HSpacing "4R"][!SetVariable VSpacing "r"][!UpdateMeter *][!Redraw][!WriteKeyValue Variables HSpacing "4R"][!WriteKeyValue Variables VSpacing "r"]
ContextTitle2=Vertical Buttons
ContextAction2=[!SetVariable HSpacing "r"][!SetVariable VSpacing "4R"][!UpdateMeter *][!Redraw][!WriteKeyValue Variables HSpacing "r"][!WriteKeyValue Variables VSpacing "4R"]

; ========= Measures ==========
[mAccent]
Measure=Plugin
Plugin=SysColor
ColorType=DWM_COLOR

[MeasureFocus]
Measure=Plugin
Plugin=IsFullScreen
IfMatch=ffplay.exe
IfMatchAction=[!SetVariable ButtonAlpha 255]
IfNotMatchAction=[!SetVariable ButtonAlpha 128]

[MeasurePlaying]
Measure=Process
ProcessName=ffplay.exe

[MeasureQuit]
Measure=String
String=[MeasureFocus]
IfMatch=ffplay.exe
IfMatchAction=["#@#SendKey\SendKey.exe "q""][!DeActivateConfig]
IfNotMatchAction=[]
IfMatchMode=1
UpdateDivider=-1
DynamicVariables=1

[MeasurePlayPause]
Measure=String
String=[MeasureFocus]
IfMatch=ffplay.exe
IfMatchAction=["#@#SendKey\SendKey.exe "{Space}""]
IfNotMatchAction=[]
IfMatchMode=1
UpdateDivider=-1
DynamicVariables=1

[MeasureStepFrame]
Measure=String
String=[MeasureFocus]
IfMatch=ffplay.exe
IfMatchAction=["#@#SendKey\SendKey.exe "s""]
IfNotMatchAction=[]
IfMatchMode=1
UpdateDivider=-1
DynamicVariables=1

[MeasureBack10]
Measure=String
String=[MeasureFocus]
IfMatch=ffplay.exe
IfMatchAction=["#@#SendKey\SendKey.exe "{Left}""]
IfNotMatchAction=[]
IfMatchMode=1
UpdateDivider=-1
DynamicVariables=1

[MeasureAhead10]
Measure=String
String=[MeasureFocus]
IfMatch=ffplay.exe
IfMatchAction=["#@#SendKey\SendKey.exe "{Right}""]
IfNotMatchAction=[]
IfMatchMode=1
UpdateDivider=-1
DynamicVariables=1

[MeasureWave]
Measure=String
String=[MeasureFocus]
IfMatch=ffplay.exe
IfMatchAction=["#@#SendKey\SendKey.exe "w""]
IfNotMatchAction=[]
IfMatchMode=1
UpdateDivider=-1
DynamicVariables=1

[MeasureVolUp]
Measure=String
String=[MeasureFocus]
IfMatch=ffplay.exe
IfMatchAction=["#@#SendKey\SendKey.exe "0""]
IfNotMatchAction=[]
IfMatchMode=1
UpdateDivider=-1
DynamicVariables=1

[MeasureVolDn]
Measure=String
String=[MeasureFocus]
IfMatch=ffplay.exe
IfMatchAction=["#@#SendKey\SendKey.exe "9""]
IfNotMatchAction=[]
IfMatchMode=1
UpdateDivider=-1
DynamicVariables=1

[MeasureMute]
Measure=String
String=[MeasureFocus]
IfMatch=ffplay.exe
IfMatchAction=["#@#SendKey\SendKey.exe "m""]
IfNotMatchAction=[]
IfMatchMode=1
UpdateDivider=-1
DynamicVariables=1

; ========= Meter Styles ==========

[StyleText]
FontWeight=500
FontSize=11
FontColor=255,255,255,255
SolidColor=[mAccent]
Padding=5,5,5,5
AntiAlias=1

[StyleButton]
FontWeight=500
FontSize=11
FontColor=255,255,255,#ButtonAlpha#
SolidColor=[mAccent]
Padding=5,5,5,5
AntiAlias=1
W=#ButtonWidth#
X=#HSpacing#
Y=#VSpacing#

; ========= Meters ==========

; Control Buttons
[HoverButtonControl]
Meter=Shape 
X=0
Y=0
Shape=Rectangle 0,0,(#ButtonWidth#+8),26 | StrokeWidth 0 | Fill Color 0,0,0,1
MouseOverAction=[!ToggleMeterGroup Buttons][!UpdateMeter *][!Redraw]
DynamicVariables=1

[HoverButton]
Meter=String 
MeterStyle=StyleText
X=60
Y=r
W=#ButtonWidth#
StringAlign=Center 
StringStyle=Italic
Text=Toggle Controls
;Hidden=([MeasurePlaying]=-1)?
DynamicVariables=1

[PauseButton]
Group=Buttons
Meter=String
MeterStyle=StyleButton
StringAlign=Center
Text=Pause/Play
MouseOverAction=[!UpdateMeasure MeasurePlayPause]
Hidden=([MeasurePlaying]=-1)?
DynamicVariables=1

[StepFrameButton]
Group=Buttons
Meter=String
MeterStyle=StyleButton
StringAlign=Center
Text=Frame Step
MouseOverAction=[!UpdateMeasure MeasureStepFrame]
Hidden=([MeasurePlaying]=-1)?
DynamicVariables=1

[Back10Button]
Group=Buttons
Meter=String
MeterStyle=StyleButton
StringAlign=Center
Text=Back 10 Sec
MouseOverAction=[!UpdateMeasure MeasureBack10]
Hidden=([MeasurePlaying]=-1)?
DynamicVariables=1

[Ahead10Button]
Group=Buttons
Meter=String
MeterStyle=StyleButton
StringAlign=Center
Text=Ahead 10 Sec
MouseOverAction=[!UpdateMeasure MeasureAhead10]
Hidden=([MeasurePlaying]=-1)?
DynamicVariables=1

[WaveButton]
Group=Buttons
Meter=String
MeterStyle=StyleButton
StringAlign=Center
Text=Next Stream
MouseOverAction=[!UpdateMeasure MeasureWave]
Hidden=([MeasurePlaying]=-1)?
DynamicVariables=1

[VolumeUpButton]
Group=Buttons
Meter=String
MeterStyle=StyleButton
StringAlign=Center
Text=Scroll Volume
MouseScrollUpAction=[!UpdateMeasure MeasureVolUp]
MouseScrollDownAction=[!UpdateMeasure MeasureVolDn]
Hidden=([MeasurePlaying]=-1)?
DynamicVariables=1

[MuteButton]
Group=Buttons
Meter=String
MeterStyle=StyleButton
StringAlign=Center
Text=Toggle Mute
MouseOverAction=[!UpdateMeasure MeasureMute]
Hidden=([MeasurePlaying]=-1)?
DynamicVariables=1

[QuitButton]
Group=Buttons
Meter=String 
MeterStyle=StyleButton
StringAlign=Center
Text=Quit
MouseOverAction=[!UpdateMeasure MeasureQuit]
Hidden=([MeasurePlaying]=-1)?
DynamicVariables=1

Button style: 'RainVideo\Controls\Buttons.ini'

Code: Select all

; ========= Metadata ==========
[Metadata]
Name=RainVideoControlsButtons
Author=Eclectic Tech deviantArt.com/eclectictech
Information=
; BY=attribution / SA=share-alike / ND=no-derivatives / NC=non-commercial
License=CC BY-SA-NC 3.0
Version=1.2020.09.27a

; ========= Variables ==========
[Variables]
ButtonWidth=24
ButtonColor=[mAccent]
; Exchange the X & Y values below for vertical or horizontal buttons
HSpacing=r
VSpacing=4R

; ========= Skin Settings ==========
[Rainmeter]
Update=1000
AccurateText=1
DynamicWindowSize=1
Group=#RootConfig#
DefaultAlwaysOnTop=1
OnRefreshAction=[!ZPos +2][!HideMeterGroup Buttons]

ContextTitle=Horizontal Buttons
ContextAction=[!SetVariable HSpacing "4R"][!SetVariable VSpacing "r"][!UpdateMeter *][!Redraw][!WriteKeyValue Variables HSpacing "4R"][!WriteKeyValue Variables VSpacing "r"]
ContextTitle2=Vertical Buttons
ContextAction2=[!SetVariable HSpacing "r"][!SetVariable VSpacing "4R"][!UpdateMeter *][!Redraw][!WriteKeyValue Variables HSpacing "r"][!WriteKeyValue Variables VSpacing "4R"]

; ========= Measures ==========
[mAccent]
Measure=Plugin
Plugin=SysColor
ColorType=DWM_COLOR

[MeasureFocus]
Measure=Plugin
Plugin=IsFullScreen
IfMatch=ffplay.exe
IfMatchAction=[!SetVariable ButtonAlpha 255]
IfNotMatchAction=[!SetVariable ButtonAlpha 128]

[MeasurePlaying]
Measure=Process
ProcessName=ffplay.exe

[MeasureQuit]
Measure=String
String=[MeasureFocus]
IfMatch=ffplay.exe
IfMatchAction=["#@#SendKey\SendKey.exe "q""][!DeActivateConfig]
IfNotMatchAction=[]
IfMatchMode=1
UpdateDivider=-1
DynamicVariables=1

[MeasurePlayPause]
Measure=String
String=[MeasureFocus]
IfMatch=ffplay.exe
IfMatchAction=["#@#SendKey\SendKey.exe "{Space}""]
IfNotMatchAction=[]
IfMatchMode=1
UpdateDivider=-1
DynamicVariables=1

[MeasureStepFrame]
Measure=String
String=[MeasureFocus]
IfMatch=ffplay.exe
IfMatchAction=["#@#SendKey\SendKey.exe "s""]
IfNotMatchAction=[]
IfMatchMode=1
UpdateDivider=-1
DynamicVariables=1

[MeasureBack10]
Measure=String
String=[MeasureFocus]
IfMatch=ffplay.exe
IfMatchAction=["#@#SendKey\SendKey.exe "{Left}""]
IfNotMatchAction=[]
IfMatchMode=1
UpdateDivider=-1
DynamicVariables=1

[MeasureAhead10]
Measure=String
String=[MeasureFocus]
IfMatch=ffplay.exe
IfMatchAction=["#@#SendKey\SendKey.exe "{Right}""]
IfNotMatchAction=[]
IfMatchMode=1
UpdateDivider=-1
DynamicVariables=1

[MeasureWave]
Measure=String
String=[MeasureFocus]
IfMatch=ffplay.exe
IfMatchAction=["#@#SendKey\SendKey.exe "w""]
IfNotMatchAction=[]
IfMatchMode=1
UpdateDivider=-1
DynamicVariables=1

[MeasureVolUp]
Measure=String
String=[MeasureFocus]
IfMatch=ffplay.exe
IfMatchAction=["#@#SendKey\SendKey.exe "0""]
IfNotMatchAction=[]
IfMatchMode=1
UpdateDivider=-1
DynamicVariables=1

[MeasureVolDn]
Measure=String
String=[MeasureFocus]
IfMatch=ffplay.exe
IfMatchAction=["#@#SendKey\SendKey.exe "9""]
IfNotMatchAction=[]
IfMatchMode=1
UpdateDivider=-1
DynamicVariables=1

[MeasureMute]
Measure=String
String=[MeasureFocus]
IfMatch=ffplay.exe
IfMatchAction=["#@#SendKey\SendKey.exe "m""]
IfNotMatchAction=[]
IfMatchMode=1
UpdateDivider=-1
DynamicVariables=1

; ========= Meter Styles ==========

[StyleText]
FontWeight=700
FontSize=11
FontColor=[mAccent]
SolidColor=0,0,0,255
Padding=5,5,5,5
AntiAlias=1

[StyleButton]
ImageAlpha=#ButtonAlpha#
SolidColor=0,0,0,1
Padding=5,5,5,5
AntiAlias=1
W=#ButtonWidth#
H=#ButtonWidth#
X=#HSpacing#
Y=#VSpacing#
MouseLeaveAction=[!SetOption #CurrentSection# ImageTint "255,255,255"][!UpdateMeter #CurrentSection#][!Redraw]

; ========= Meters ==========

; Control Buttons
[HoverButtonControl]
Meter=Shape 
X=0
Y=0
Shape=Rectangle 0,0,#ButtonWidth#,#ButtonWidth# | StrokeWidth 0 | Fill Color 0,0,0,1
MouseOverAction=[!ToggleMeterGroup Buttons][!UpdateMeter *][!Redraw]
DynamicVariables=1

[HoverButton]
Meter=Image 
MeterStyle=StyleButton
ImageName=#@#Images\arrow-down-w
X=r
Y=r
ImageAlpha=255
MouseOverAction=[!SetOption #CurrentSection# ImageTint "[mAccent]"][!UpdateMeter #CurrentSection#][!Redraw]
DynamicVariables=1

[PauseButton]
Group=Buttons
Meter=Image 
MeterStyle=StyleButton
ImageName=#@#Images\play-w
MouseOverAction=[!SetOption #CurrentSection# ImageTint "[mAccent]"][!UpdateMeter #CurrentSection#][!Redraw][!UpdateMeasure MeasurePlayPause]
Hidden=([MeasurePlaying]=-1)?
DynamicVariables=1

[StepFrameButton]
Group=Buttons
Meter=Image 
MeterStyle=StyleButton
ImageName=#@#Images\pause-w
MouseOverAction=[!SetOption #CurrentSection# ImageTint "[mAccent]"][!UpdateMeter #CurrentSection#][!Redraw][!UpdateMeasure MeasureStepFrame]
Hidden=([MeasurePlaying]=-1)?
DynamicVariables=1

[Back10Button]
Group=Buttons
Meter=Image 
MeterStyle=StyleButton
ImageName=#@#Images\previous-w
MouseOverAction=[!SetOption #CurrentSection# ImageTint "[mAccent]"][!UpdateMeter #CurrentSection#][!Redraw][!UpdateMeasure MeasureBack10]
Hidden=([MeasurePlaying]=-1)?
DynamicVariables=1

[Ahead10Button]
Group=Buttons
Meter=Image 
MeterStyle=StyleButton
ImageName=#@#Images\next-w
MouseOverAction=[!SetOption #CurrentSection# ImageTint "[mAccent]"][!UpdateMeter #CurrentSection#][!Redraw][!UpdateMeasure MeasureAhead10]
Hidden=([MeasurePlaying]=-1)?
DynamicVariables=1

[QuitButton]
Group=Buttons
Meter=Image 
MeterStyle=StyleButton
ImageName=#@#Images\stop-w
MouseOverAction=[!SetOption #CurrentSection# ImageTint "[mAccent]"][!UpdateMeter #CurrentSection#][!Redraw][!UpdateMeasure MeasureQuit]
Hidden=([MeasurePlaying]=-1)?
DynamicVariables=1

[WaveButton]
Group=Buttons
Meter=Image 
MeterStyle=StyleButton
ImageName=#@#Images\arrow-up-w
MouseOverAction=[!SetOption #CurrentSection# ImageTint "[mAccent]"][!UpdateMeter #CurrentSection#][!Redraw][!UpdateMeasure MeasureWave]
Hidden=([MeasurePlaying]=-1)?
DynamicVariables=1

[VolumeUpDnButton]
Group=Buttons
Meter=Image 
MeterStyle=StyleButton
ImageName=#@#Images\audio-high-w
MouseOverAction=[!SetOption #CurrentSection# ImageTint "[mAccent]"][!UpdateMeter #CurrentSection#][!Redraw]
MouseScrollUpAction=[!UpdateMeasure MeasureVolUp]
MouseScrollDownAction=[!UpdateMeasure MeasureVolDn]
Hidden=([MeasurePlaying]=-1)?
DynamicVariables=1

[MuteButton]
Group=Buttons
Meter=Image 
MeterStyle=StyleButton
ImageName=#@#Images\audio-mute-w
MouseOverAction=[!SetOption #CurrentSection# ImageTint "[&mAccent]"][!UpdateMeter #CurrentSection#][!Redraw][!UpdateMeasure MeasureMute]
Hidden=([MeasurePlaying]=-1)?
DynamicVariables=1

HISTORY
V 1.2020.09.27a :: Added Accent color for use in skins | Added "Button' images controls | Control are separate skins, TopMost, & Horz/Vert aligned

V 1.2020.09.27 :: Added IsFullScreen to only send codes when FFPlay has focus | Buttons separated for easier access | Buttons inactive indication

V 1.2020.09.25 :: Added hover action buttons (per balala's suggestion) | Added 'Repeat Toggle' button | Video window placement while playing

V 1.2020.09.21 :: Added 'Repeat' | Interactive Context Menu

V 1.2020.09.19 :: Corrected ContextAction5 parameters; change "#File#" to "#*File*#" etc. (escaped variables)

V 1.2020.09.18 :: Includes FileChoose.dll

V 1.2020.09.17 :: Initial release (missing FileChoose.dll; downloadable from link above)
You do not have the required permissions to view the files attached to this post.
User avatar
Yincognito
Posts: 2933
Joined: February 27th, 2015, 2:38 pm
Location: Terra Yincognita

Re: Rain Video

Post by Yincognito »

eclectic-tech wrote: September 18th, 2020, 2:52 amA video player based on FFmpeg's FFplay.exe as discussed in this thread by Yincognito.
Excellent idea, eclectic-tech - and I'm glad balala mentioned your thread to me in my chats with him on the matter. I've been actually working on a similar but still different approach on this for a couple of days now, but due to the fact that, given my (sometimes not so productive) perfectionism my approach is centered around full integration with Rainmeter and my relaxed nature doesn't make this a must have right now issue, I believe that your implementation might very well be easier and simpler to implement.

I'm using ffmpeg.exe to largely achieve a similar thing, though at increased cost in terms of CPU and HDD usage. Since my main focus was to make this seamlessly integrate with Rainmeter - for example, "playing the video" in an actual skin as "opposed" to playing in a 3rd party window - I had to use ffmpeg.exe and extract the frames in order to be playable using a Bitmap meter (I have single image and image sequence attempts as well, but so far only the Bitmap attempt, i.e. the "image mosaic" one, is correctly functioning).

This is my attempt (it's not fully functional like yours, because I have to do more things from inside the Rainmeter code compared to your approach where ffplay.exe handles 99% of the job, but as I said, I believe your idea is better) - bear in mind that this doesn't cover the audio part yet, is for now tailored for a 30 FPS video, where the Span variable is total video time, From is the point in second where the loading begins (incremented by Time as the video progresses), Time is the amount of seconds to "load" from the video in one of the output "buffer" images, Tile basically equals Time x FPS (e.g. for 30 FPS and a Time of 3 seconds, Tile would have to be 90), W and H are the dimensions of the video window, and so on:

Code: Select all

[Variables]
Update=33
Clip=input.mp4
Span=47
From=0
Time=1
Step=1
Tile=30
W=640
H=360
Extracted=0
RBuffer=0
WBuffer=1
SW=2
Buttons=2
Padding=10
ShadowOffset=5
ShadowBlur=7
GlowColor=0,255,0,255

[Rainmeter]
Update=#Update#
DynamicWindowSize=1
AccurateText=1

---Measures---

[Extract]
Measure=Plugin
Plugin=RunCommand
Parameter=ffmpeg -ss #From# -t #Time# -i #Clip# -vf scale=#W#:#H#,tile=#Tile#x1 output#WBuffer#.bmp -y -hide_banner -loglevel fatal -nostats
StartInFolder=#@#
State=Hide
OutputType=ANSI
FinishAction=[!SetVariable Extracted 1][!EnableMeasure Frame]
DynamicVariables=1

[Frame]
Disabled=1
Measure=Loop
StartValue=0
EndValue=#Tile#
Increment=#Step#
LoopCount=1
IfCondition=(Frame=[Frame:MinValue])
IfTrueAction=[!SetVariable Extracted 0][!SetVariable From (#From#+#Time#)][!SetVariable RBuffer #WBuffer#][!SetVariable WBuffer #RBuffer#][!UpdateMeasure Extract][!CommandMeasure Extract "Run"]
IfCondition2=(Frame=[Frame:MaxValue]) && (#Extracted#=1)
IfTrueAction2=[!CommandMeasure Frame "Reset"][!UpdateMeasure Frame]
IfConditionMode=1
DynamicVariables=1

---Styles---

[TextStyle]
X=#Padding#R
Y=0r
H=([Stop:W]*2.5)
FontFace=Tahoma
FontSize=20
FontColor=255,255,255,255
StringEffect=Shadow
FontEffectColor=0,0,0,255
AntiAlias=1
MouseOverAction=[!SetOption #CURRENTSECTION# MeterStyle "TextStyle | OverStyle"][!UpdateMeter #CURRENTSECTION#][!Redraw]
MouseLeaveAction=[!SetOption #CURRENTSECTION# MeterStyle "TextStyle | LeaveStyle"][!UpdateMeter #CURRENTSECTION#][!Redraw]

[OverStyle]
InlineSetting=Shadow | (-#ShadowOffset#) | (-#ShadowOffset#) | (#ShadowBlur#) | #GlowColor#
InlineSetting2=Shadow | (-#ShadowOffset#) | (#ShadowOffset#) | (#ShadowBlur#) | #GlowColor#
InlineSetting3=Shadow | (#ShadowOffset#) | (-#ShadowOffset#) | (#ShadowBlur#) | #GlowColor#
InlineSetting4=Shadow | (#ShadowOffset#) | (#ShadowOffset#) | (#ShadowBlur#) | #GlowColor#

[LeaveStyle]

---Meters---

[Border]
Meter=Shape
Shape=Rectangle (#SW#/2),(#SW#/2),(#W#+#SW#),(#H#+#SW#) | Fill Color 0,0,0,64 | StrokeWidth #SW# | Stroke Color 255,255,255,255
UpdateDivider=-1

[Video]
Meter=Bitmap
X=#SW#r
Y=#SW#r
BitmapImage="#@#output#RBuffer#.bmp"
BitmapFrames=#Tile#
MeasureName=Frame
DynamicVariables=1

[Stop]
Meter=String
MeterStyle=TextStyle | LeaveStyle
X=(#W#/2-([Stop:W]*#Buttons#+#Padding#*(#Buttons#-1))/2)r
Y=(#SW#*2+#H#)r
Text="◼"
LeftMouseUpAction=[!SetVariable From 0][!SetVariable Extracted 0][!CommandMeasure Extract "Kill"][!DisableMeasure Frame][!UpdateMeasure Frame]
UpdateDivider=-1
DynamicVariables=1

[Play]
Meter=String
MeterStyle=TextStyle | LeaveStyle
Text="⯈"
LeftMouseUpAction=[!CommandMeasure Extract "Run"]
UpdateDivider=-1
DynamicVariables=1
Preview.jpg
Also, notice that the Stop button is just a rudimentary and not yet perfect way of stopping play; the 2 images used to buffer the video (one for read and one for write, alternating over and over once the read image has been played) will have to be manually be deleted for now on ending the play, as even though the code for it is trivial, my focus has been to make this as functional a possible. The files (both the FFmpeg executables and the adjustable "input.mp4" video need to be placed in the @Resources folder of the skin).

I would like to "hear" your opinion about it and also invite others to contribute to this if they want, if not with code at least with ideas - if they're interested, of course.

By the way, you probably know this already, but in your approach (and mine as well, but didn't get that far yet, LOL), you can make this yield a huge amount of information through ffprobe.exe, basically replicating what a Rainmeter Video measure would yield to the user, i.e. get the video size, FPS, formats, and really a TON of other info about the played video. Generally you'd do this just before actually playing the video, so you can both show the info to the user and potentially use that information to "tweak" the skin settings accordingly (simple example: setting the size to the actual video dimensions, where possible). Also, ffmpeg.exe can be used to process the video in any thinkable or unthinkable way, if needed (simple example: capture frame, capture part of the video, convert, grab the audio, etc).
eclectic-tech wrote: September 18th, 2020, 2:52 amA plugin for Rainmeter would be better, but until then I hope this helps.
Yes, actually FFmpeg DLLs can relatively easily be integrated in a plugin distribution, and basically use them as the base on which the plugin is built. I've looked into this a bit, and although from what others say it doesn't seem to be really difficult, given my poor knowledge of C++ I had to stick to getting information about it... :oops: This is possible not only through exposed functions and procedures in the FFmpeg DLLs (which can be compiled according to the needs), but I think also by using ffmpeg.exe to output to a single image at the actual FPS of the video (using the -re parameter) and directing that contents to the memory instead of a file in C++. Unfortunately, while the image sequence, i.e. image001.bmp, image002.bmp, ... imageNNN.bmp, can be made to work just as the Bitmap meter approach, the single file output doesn't seem to be successful for the simple (yet a bit stupid) reason that Windows apparently has some isssues when reading from a file that is currently written. :confused:
You do not have the required permissions to view the files attached to this post.
User avatar
balala
Rainmeter Sage
Posts: 11827
Joined: October 11th, 2010, 6:27 pm
Location: Gheorgheni, Romania

Re: Rain Video

Post by balala »

I just downloaded and installed the RainVideo package and want to share my first impressions.
From the begining I have to say that I just gave it a first try, but didn't study deeply eclectic-tech's entire description, so there maybe could be something I missed, sorry if I did. I definitely will study it on weekend, when will have much more time (I feel it requires more time to study it).
So, what I definitely did find interesting:
  • The possibility to make back / forth steps with the arrow keys. Truly a simple, but much more useful feature.
  • The waveforms possibility (with w key). Less usefull (for me at least), but definitely interesting.
A disadvanatage from my point of view: would be nice to be possible to drag the started video (if it is possible), to can move it on screen. I didn't find such a possibility.

So congratulations to eclectic-tech and to Yincognito as well for this relly great tool, which has a great potential. :thumbup: :thumbup: :thumbup:
User avatar
eclectic-tech
Rainmeter Sage
Posts: 4192
Joined: April 12th, 2012, 9:40 pm
Location: Cedar Point, Ohio, USA

Re: Rain Video

Post by eclectic-tech »

Yincognito wrote: September 18th, 2020, 3:06 pm Excellent idea, eclectic-tech - and I'm glad balala mentioned your thread to me in my chats with him on the matter. I've been actually working on a similar but still different approach on this for a couple of days now, but due to the fact that, given my (sometimes not so productive) perfectionism my approach is centered around full integration with Rainmeter and my relaxed nature doesn't make this a must have right now issue, I believe that your implementation might very well be easier and simpler to implement.

I'm using ffmpeg.exe to largely achieve a similar thing, though at increased cost in terms of CPU and HDD usage. Since my main focus was to make this seamlessly integrate with Rainmeter - for example, "playing the video" in an actual skin as "opposed" to playing in a 3rd party window - I had to use ffmpeg.exe and extract the frames in order to be playable using a Bitmap meter (I have single image and image sequence attempts as well, but so far only the Bitmap attempt, i.e. the "image mosaic" one, is correctly functioning).
...
I would like to "hear" your opinion about it and also invite others to contribute to this if they want, if not with code at least with ideas - if they're interested, of course.
...
Thanks, this is simply an alternate implementation of your suggestion regarding FFmpeg.

Yes, I have witnessed your desire for perfection and hope you succeed. I too am not well versed in C++ programming language, and am too set in my ways to have the patience to learn more.

I think that your attempt to integrate using a Bitmap meter is a very resourceful idea. I am able to see what you have accomplished so far in extracting frame images, but feel it is going to present a lot of issues when dealing with longer video clips and then having to integrate and sync the audio. That is a "rabbit hole' I do not want to go down.

The only way I feel this can be taken much further would be to integrate FFmpeg dlls capabilities into a Rainmeter plugin (something I have no capability or desire to do).

I look forward to seeing any further development of your Bitmap approach and will be glad offer suggestions.
User avatar
Yincognito
Posts: 2933
Joined: February 27th, 2015, 2:38 pm
Location: Terra Yincognita

Re: Rain Video

Post by Yincognito »

eclectic-tech wrote: September 18th, 2020, 7:38 pm Thanks, this is simply an alternate implementation of your suggestion regarding FFmpeg.
A perfectly valid and functional one, for sure. :great: I chose to do it the way I did as I wanted the video "embedded" in the skin itself (thus, being able to be moved along with the skin and such). Obviously such an approach presents a couple of challenges, and you correctly identified them in your post.
eclectic-tech wrote: September 18th, 2020, 7:38 pm Yes, I have witnessed your desire for perfection and hope you succeed. I too am not well versed in C++ programming language, and am too set in my ways to have the patience to learn more.

I think that your attempt to integrate using a Bitmap meter is a very resourceful idea. I am able to see what you have accomplished so far in extracting frame images, but feel it is going to present a lot of issues when dealing with longer video clips and then having to integrate and sync the audio. That is a "rabbit hole' I do not want to go down.

The only way I feel this can be taken much further would be to integrate FFmpeg dlls capabilities into a Rainmeter plugin (something I have no capability or desire to do).

I look forward to seeing any further development of your Bitmap approach and will be glad offer suggestions.
Agreed on most parts.

The length of the video is not a problem at all, as only 1 second (adjustable, of course) and a number equal to the video's FPS (so, a max of 60 FPS is supported) is loaded into the 2 images used as sources for the Bitmap meter in the original code. Even if you set it to load more than 1 second in the 2 buffer images (and set Tile accordingly with the FPS x Time formula), it will still work, no matter how long is the video.

I don't think the audio part is going to be a problem, but yes, the synchronization might very well be, although the FFmpeg executables have the tools needed to adjust that (and a LOT more). The reason for it still being a potential problem has actually more to do with the fact that Rainmeter can't really reproduce a precise time based FPS. In other words, ffmpeg.exe might be able to do it, but Rainmeter would have some slight inconsistencies from time to time. Although, if I think about it, I might be wrong and things might work just fine, considering I only need to extract 1 second of video and 1 second of audio on every "iteration", so to speak.

Yes, a plugin would do this better, and that's mainly because it will be able to do things in the very fast RAM memory instead of on the disk, like I'm doing it now (just because all image meters require a file on disk). I appreciate and thank you for your offer to help and I reciprocate. I know a thing or two about those FFmpeg commands, and both mine and your skins can benefit a lot from those extensive FFmpeg executables' capabilities.
User avatar
Yincognito
Posts: 2933
Joined: February 27th, 2015, 2:38 pm
Location: Terra Yincognita

Re: Rain Video

Post by Yincognito »

balala wrote: September 18th, 2020, 7:32 pmA disadvanatage from my point of view: would be nice to be possible to drag the started video (if it is possible), to can move it on screen. I didn't find such a possibility.
Eclectic-tech uses ffplay.exe to play the video, which has the VERY significant benefit of not having to do half the job of playing in Rainmeter code, but it's still a 3rd party program, which means its window will be more or less independent of the position and / or size of the calling Rainmeter skin. The ffplay.exe window position CAN be adjusted, of course, but I'm not sure it can be done in realtime AND retain all the benefits from the program at the same time (like the current position in the video, for example, which would be more or less "lost" on a new execution of the program).

That's a possibility available in my variant though ... along with the drawbacks from it, LOL (i.e. having to deal with an accurate frame rate, the playing process, the audio or the synchronization in native Rainmeter code).
User avatar
balala
Rainmeter Sage
Posts: 11827
Joined: October 11th, 2010, 6:27 pm
Location: Gheorgheni, Romania

Re: Rain Video

Post by balala »

Yincognito wrote: September 18th, 2020, 8:29 pm which means its window will be more or less independent of the position and / or size of the calling Rainmeter skin.
No, it's not independent at all. The playing window has the same position as the skin (their upper left corners coincid). If you move the skin while the video is playing, it doesn't follow the skin, but if you stop the video, move the skin and restart the video, it is loaded into the new position, where the skin is in that moment.
User avatar
Yincognito
Posts: 2933
Joined: February 27th, 2015, 2:38 pm
Location: Terra Yincognita

Re: Rain Video

Post by Yincognito »

balala wrote: September 18th, 2020, 8:47 pm No, it's not independent at all. The playing window has the same position as the skin (their upper left corners coincid). If you move the skin while the video is playing, it doesn't follow the skin, but if you stop the video, move the skin and restart the video, it is loaded into the new position, where the skin is in that moment.
Well, I guess we understand differently being dependent and independent of a Rainmeter skin window then. :D I know there is the code in place that will update the ffplay.exe window to the new position of the skin, but that window is still technically independent of any Rainmeter skin window. That means without the adjustment code the 2 windows don't have any connection between them whatsoever. I might be to strict on the definition here, but in my view being dependent in this case would mean that one window has at least a partial "automatic" movement according to the other window (while the main process, i.e. playing, is active). :???:

EDIT: That being said, I will look to add some more features to eclectic-tech's variant tomorrow. Hopefully I'll succeed.
User avatar
eclectic-tech
Rainmeter Sage
Posts: 4192
Joined: April 12th, 2012, 9:40 pm
Location: Cedar Point, Ohio, USA

Re: Rain Video

Post by eclectic-tech »

balala wrote: September 18th, 2020, 8:47 pm No, it's not independent at all. The playing window has the same position as the skin (their upper left corners coincid). If you move the skin while the video is playing, it doesn't follow the skin, but if you stop the video, move the skin and restart the video, it is loaded into the new position, where the skin is in that moment.
Yes, the FFPlay window is positioned at #CurrentConfigX#/#CurrentConfigY#.
I use the Process plugin to disable Draggable and RightMouseUpAction while the FFPlay process is active. This was designed to prevent moving the skin window or changing any custom skin actions while the third party window is active; I am trying to minimize any changes to the skin while a video is active because they really have no relationship once the video start.

The action you described is how I intended the skin to be used:
1) Select your desired resolution from the custom skin action
2) Position the skin where you want it
NOTE: the black outline is your guide in positioning for all resolutions except 'Default Video Size'
When using 'Default Video Size', the video will start at the skin 0,0 but may be off screen if you set the skin too far down the screen or too far right
3) The only simple mouse action available while a video is playing is 'LeftMouseUpAction' to toggle the 'Help Info'; all other mouse and key actions are used to control FFPlay
NOTE: It is possible to override my disabled actions, but I wanted to limit skin actions since video controls also use the mouse and keyboard, and as you noticed, it is possible to move the skin but the third party video will not be affected until the video is replayed.

This is a 'work-in-progress' and changes and suggestions are welcomed.
User avatar
balala
Rainmeter Sage
Posts: 11827
Joined: October 11th, 2010, 6:27 pm
Location: Gheorgheni, Romania

Re: Rain Video

Post by balala »

eclectic-tech wrote: September 19th, 2020, 1:53 am I use the Process plugin to disable Draggable and RightMouseUpAction while the FFPlay process is active. This was designed to prevent moving the skin window or changing any custom skin actions while the third party window is active; I am trying to minimize any changes to the skin while a video is active because they really have no relationship once the video start.
Just note that you've used the Process as a measure in your code, not as a plugin. So, it's not the Process plugin, but the Process measure (sorry, hope you don't mind I wrote this). Process has became an internal measure on August 24, with Rainmeter r3403.
eclectic-tech wrote: September 19th, 2020, 1:53 am 1) Select your desired resolution from the custom skin action
Not sure, how?
eclectic-tech wrote: September 19th, 2020, 1:53 am NOTE: the black outline is your guide in positioning for all resolutions except 'Default Video Size'
When using 'Default Video Size', the video will start at the skin 0,0 but may be off screen if you set the skin too far down the screen or too far right
How do you set and use the "Default Video Size"? This seems to be a default setting, but can you change the resolution and play the video with a different resolution than the default one, but not on full screen?