VLC updates, and some infra bugs fix
This commit is contained in:
@@ -1,6 +1,9 @@
|
||||
import logging
|
||||
import os
|
||||
from typing import Dict
|
||||
|
||||
logger = logging.getLogger("desktopenv.getters.vlc")
|
||||
|
||||
|
||||
def get_vlc_playing_info(env, config: Dict[str, str]):
|
||||
"""
|
||||
@@ -13,7 +16,33 @@ def get_vlc_playing_info(env, config: Dict[str, str]):
|
||||
password = 'password'
|
||||
|
||||
content = env.controller.get_vlc_status(host, port, password)
|
||||
print("content: ", content)
|
||||
with open(_path, "wb") as f:
|
||||
f.write(content)
|
||||
|
||||
return _path
|
||||
|
||||
|
||||
def get_vlc_config(env, config: Dict[str, str]):
|
||||
"""
|
||||
Reads the VLC configuration file to check setting.
|
||||
"""
|
||||
_path = os.path.join(env.cache_dir, config["dest"])
|
||||
|
||||
os_type = env.controller.execute_python_command("import platform; print(platform.system())")['output'].strip()
|
||||
|
||||
# fixme: depends on how we config and install the vlc in virtual machine, need to be aligned and double-checked
|
||||
if os_type == "Linux":
|
||||
config_path = \
|
||||
env.controller.execute_python_command("import os; print(os.path.expanduser('~/snap/vlc/common/vlcrc'))")[
|
||||
'output'].strip()
|
||||
elif os_type == "Darwin":
|
||||
config_path = env.controller.execute_python_command(
|
||||
"import os; print(os.path.expanduser('~/Library/Preferences/org.videolan.vlc/vlcrc'))")['output'].strip()
|
||||
elif os_type == "Windows":
|
||||
config_path = env.controller.execute_python_command(
|
||||
"import os; print(os.path.expanduser('~\\AppData\\Roaming\\vlc\\vlcrc'))")['output'].strip()
|
||||
|
||||
content = env.controller.get_file(config_path)
|
||||
with open(_path, "wb") as f:
|
||||
f.write(content)
|
||||
|
||||
|
||||
@@ -130,6 +130,12 @@ To enable and use the HTTP interface in VLC Media Player for remote control and
|
||||
- You will be prompted for a password. Enter the password you set in the Lua HTTP settings.
|
||||
- Once logged in, you will have access to VLC's HTTP interface for remote control.
|
||||
|
||||
#### Packages
|
||||
```bash
|
||||
|
||||
pip install opencv-python-headless Pillow imagehash
|
||||
```
|
||||
|
||||
#### Troubleshooting
|
||||
|
||||
- If you cannot access the HTTP interface, check if your firewall or security software is blocking the connection.
|
||||
|
||||
@@ -1,64 +1,142 @@
|
||||
import os
|
||||
import platform
|
||||
from xml.etree import ElementTree
|
||||
import pygetwindow as gw
|
||||
import pyautogui
|
||||
from typing import Dict
|
||||
|
||||
import logging
|
||||
import os
|
||||
import subprocess
|
||||
from typing import Dict
|
||||
from xml.etree import ElementTree
|
||||
|
||||
import acoustid
|
||||
import cv2
|
||||
import imagehash
|
||||
import pyautogui
|
||||
import pygetwindow as gw # todo: change to the library that supports Linux
|
||||
from PIL import Image
|
||||
|
||||
logger = logging.getLogger("desktopenv.metrics.vlc")
|
||||
|
||||
def get_vlc_config(setting_name):
|
||||
"""
|
||||
Reads the VLC configuration file to check for a specific setting.
|
||||
|
||||
# Example usage
|
||||
setting_name = 'recordings_folder='
|
||||
setting = read_vlc_config(setting_name)
|
||||
"""
|
||||
# Common paths for VLC config file on different operating systems
|
||||
paths = {
|
||||
'Windows': os.path.expanduser('~\\AppData\\Roaming\\vlc\\vlcrc'),
|
||||
'Darwin': os.path.expanduser('~/Library/Preferences/org.videolan.vlc/vlcrc'),
|
||||
'Linux': os.path.expanduser('~/.config/vlc/vlcrc')
|
||||
}
|
||||
|
||||
os_type = platform.system()
|
||||
config_path = paths.get(os_type)
|
||||
|
||||
if not config_path or not os.path.exists(config_path):
|
||||
logger.warning("VLC config file not found for this operating system.")
|
||||
return None
|
||||
|
||||
try:
|
||||
with open(config_path, 'r', encoding="utf-8") as file:
|
||||
for line in file:
|
||||
if line.startswith(setting_name):
|
||||
return line.strip()
|
||||
except IOError as e:
|
||||
logger.error(f"Error reading config file: {e}")
|
||||
|
||||
return None
|
||||
|
||||
|
||||
def is_vlc_playing(actual: str, rule: Dict[str, str]) -> float:
|
||||
def is_vlc_playing(actual_status_path: str, rule: Dict[str, str]) -> float:
|
||||
"""
|
||||
Checks if VLC is currently playing a file.
|
||||
"""
|
||||
with open(actual, 'rb') as file:
|
||||
with open(actual_status_path, 'rb') as file:
|
||||
actual_status = file.read().decode('utf-8')
|
||||
|
||||
tree = ElementTree.fromstring(actual_status)
|
||||
status = tree.find('state').text
|
||||
if status == 'playing':
|
||||
file_info = tree.find('information/category[@name="meta"]/info[@name="filename"]').text
|
||||
print("file_info: ", file_info)
|
||||
if file_info:
|
||||
return 1 if file_info.endswith(rule['expected']) else 0
|
||||
if rule['type'] == 'file_name':
|
||||
file_info = tree.find('information/category[@name="meta"]/info[@name="filename"]').text
|
||||
if file_info:
|
||||
return 1 if file_info.endswith(rule['file_name']) else 0
|
||||
elif rule['type'] == 'url':
|
||||
file_info = tree.find('information/category[@name="meta"]/info[@name="url"]').text
|
||||
if file_info:
|
||||
return 1 if file_info.endswith(rule['url']) else 0
|
||||
else:
|
||||
logger.error(f"Unknown type: {rule['type']}")
|
||||
return 0
|
||||
else:
|
||||
return 0
|
||||
|
||||
|
||||
def is_vlc_recordings_folder(actual_config_path: str, rule: Dict[str, str]) -> float:
|
||||
"""
|
||||
Checks if VLC's recording folder is set to the expected value.
|
||||
"""
|
||||
with open(actual_config_path, 'rb') as file:
|
||||
config_file = file.read().decode('utf-8')
|
||||
|
||||
expected_recording_file_path = rule['recording_file_path']
|
||||
|
||||
try:
|
||||
for line in config_file:
|
||||
# Skip comments and empty lines
|
||||
if line.startswith('#') or not line.strip():
|
||||
continue
|
||||
# Check if the line contains the recording path setting
|
||||
if 'recorded_files_path' in line:
|
||||
# Extract the value of the recording path and remove surrounding whitespace
|
||||
current_path = line.split('=')[-1].strip()
|
||||
# Compare with the Desktop path
|
||||
if current_path == expected_recording_file_path:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
# The configuration key was not found in the file
|
||||
return False
|
||||
except FileNotFoundError:
|
||||
logger.error("VLC configuration file not found.")
|
||||
return False
|
||||
except Exception as e:
|
||||
logger.error(f"An error occurred: {e}")
|
||||
return False
|
||||
|
||||
|
||||
def are_audio_files_similar(mp3_file_path, mp4_file_path):
|
||||
# Extract audio fingerprint from MP3 file
|
||||
mp3_fingerprint, mp3_duration = acoustid.fingerprint_file(mp3_file_path)
|
||||
|
||||
# Extract the audio stream from the MP4 file
|
||||
mp4_audio_path = os.path.splitext(mp4_file_path)[0] + '_extracted.mp3'
|
||||
try:
|
||||
subprocess.run(["ffmpeg", "-i", mp4_file_path, "-vn", "-ar", "44100", "-ac", "2", "-ab", "192k", "-f", "mp3",
|
||||
mp4_audio_path], check=True)
|
||||
except subprocess.CalledProcessError as e:
|
||||
print(f"An error occurred during audio extraction from MP4: {e}")
|
||||
return False
|
||||
|
||||
# Extract audio fingerprint from the extracted audio
|
||||
mp4_fingerprint, mp4_duration = acoustid.fingerprint_file(mp4_audio_path)
|
||||
|
||||
# Clean up temporary extracted audio file
|
||||
os.remove(mp4_audio_path)
|
||||
|
||||
# Compare fingerprints (rudimentary comparison)
|
||||
if mp3_duration >= mp4_duration and mp3_fingerprint == mp4_fingerprint:
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
|
||||
def compare_videos(video_path1, video_path2, max_frames_to_check=100, threshold=5):
|
||||
# Open both video files
|
||||
cap1 = cv2.VideoCapture(video_path1)
|
||||
cap2 = cv2.VideoCapture(video_path2)
|
||||
|
||||
frames_checked = 0
|
||||
mismatch_count = 0
|
||||
|
||||
while frames_checked < max_frames_to_check:
|
||||
# Read frames from both videos
|
||||
ret1, frame1 = cap1.read()
|
||||
ret2, frame2 = cap2.read()
|
||||
|
||||
# If a video ends, then check if both ended to confirm they are of the same length
|
||||
if not ret1 or not ret2:
|
||||
return ret1 == ret2
|
||||
|
||||
# Convert frames to PIL Images
|
||||
frame1 = Image.fromarray(cv2.cvtColor(frame1, cv2.COLOR_BGR2RGB))
|
||||
frame2 = Image.fromarray(cv2.cvtColor(frame2, cv2.COLOR_BGR2RGB))
|
||||
|
||||
# Compute the perceptual hash for each frame
|
||||
hash1 = imagehash.phash(frame1)
|
||||
hash2 = imagehash.phash(frame2)
|
||||
|
||||
# Increment the frames checked
|
||||
frames_checked += 1
|
||||
|
||||
# Compute the difference in the hashes
|
||||
if hash1 - hash2 > threshold:
|
||||
mismatch_count += 1
|
||||
# If there's a significant difference, the frames are not the same
|
||||
if mismatch_count > threshold:
|
||||
return False
|
||||
|
||||
# If we reach here, the content appears to be the same
|
||||
return True
|
||||
|
||||
|
||||
def is_vlc_fullscreen():
|
||||
"""
|
||||
Checks if the VLC window is in full-screen mode.
|
||||
|
||||
Reference in New Issue
Block a user