Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

The function get_time() fails to provide an acurrate time #269

Open
alcor717 opened this issue Dec 27, 2023 · 1 comment
Open

The function get_time() fails to provide an acurrate time #269

alcor717 opened this issue Dec 27, 2023 · 1 comment

Comments

@alcor717
Copy link

Hello, I am trying to write a tiny video editor. It basically allows you to set start and end marks and press enter to cut clips. The problem is that the end marks (and it's odd because it doesn't happen with the start marks) are set a few tenths of a second before the desired moment. It's strange because I would understand a delay due to human reaction time, but instead, there is an advance. Here is the relevant code:
from moviepy.video.io.VideoFileClip import VideoFileClip
import vlc
import wx
import sys

def ms_to_hms(ms):
"""Convert milliseconds to h:mm:ss.xxx"""
seconds, ms = divmod(ms, 1000)
minutes, seconds = divmod(seconds, 60)
hours, minutes = divmod(minutes, 60)
return f"{hours}:{minutes:02d}:{seconds:02d}.{ms:03d}"

class VideoFrame(wx.Frame):
TIME_UNITS = [10, 100, 1000, 5000, 60000, 300000] # Centiseconds, Deciseconds, Seconds, 5 Seconds, Minutes, 5 Minutes

def __init__(self, parent, title, video_path):
    super().__init__(parent, title=title, size=(800, 600))
    self.video_path = video_path
    self.time_unit_index = 4  # Minutes by default
    self.init_ui()
    self.Show(True)

def init_ui(self):
    self.panel = wx.Panel(self)
    self.Instance = vlc.Instance()
    self.player = self.Instance.media_list_player_new()
    Media = self.Instance.media_new(self.video_path)
    media_list = self.Instance.media_list_new([Media])
    self.player.set_media_list(media_list)
    self.player.get_media_player().set_hwnd(self.panel.GetHandle())
    self.start_mark = None
    self.end_mark = None
    self.panel.Bind(wx.EVT_CHAR_HOOK, self.on_key_press)

def on_key_press(self, event):
    keycode = event.GetKeyCode()
    control_down = event.ControlDown()
    shift_down = event.ShiftDown()

    if keycode == wx.WXK_SPACE:
        self.toggle_play_pause()
    elif keycode == wx.WXK_RETURN:
        self.cut_clip()
    elif keycode == ord('S'):
        if shift_down:
            self.clear_start_mark()
        else:
            self.set_start_mark()
    elif keycode == ord('E'):
        if shift_down:
            self.clear_end_mark()
        else:
            self.set_end_mark()
    elif keycode in [wx.WXK_RIGHT, wx.WXK_LEFT]:
        offset = self.TIME_UNITS[self.time_unit_index] * (1 if keycode == wx.WXK_RIGHT else -1)
        if shift_down:
            self.adjust_mark("start", offset)
        elif control_down:
            self.adjust_mark("end", offset)

def toggle_play_pause(self):
    if self.player.is_playing():
        self.player.pause()
    else:
        self.player.play()

def set_start_mark(self):
    self.start_mark = self.player.get_media_player().get_time()
    print(f"Start mark set at: {ms_to_hms(self.start_mark)}")

def clear_start_mark(self):
    self.start_mark = None
    print("Start mark cleared")

def set_end_mark(self):
    self.end_mark = self.player.get_media_player().get_time()
    print(f"End mark set at: {ms_to_hms(self.end_mark)}")

def clear_end_mark(self):
    self.end_mark = None
    print("End mark cleared")

def adjust_mark(self, mark_type, offset):
    new_mark = None
    if mark_type == "start" and self.start_mark is not None:
        new_mark = max(0, min(self.start_mark + offset, self.player.get_media_player().get_length()))
        self.start_mark = new_mark
    elif mark_type == "end" and self.end_mark is not None:
        new_mark = max(0, min(self.end_mark + offset, self.player.get_media_player().get_length()))
        self.end_mark = new_mark

    if new_mark is not None:
        print(f"{mark_type.capitalize()} mark adjusted to: {ms_to_hms(new_mark)}")

def cut_clip(self):
    if self.start_mark is not None and self.end_mark is not None:
        clip = VideoFileClip(self.video_path).subclip(self.start_mark/1000, self.end_mark/1000)
        output_path = "cut_clip.mp4"
        clip.write_videofile(output_path)
        print(f"Clip cut: Start - {ms_to_hms(self.start_mark)}, End - {ms_to_hms(self.end_mark)}")

def main(video_path):
app = wx.App(False)
frame = VideoFrame(None, "Video Player", video_path)
app.MainLoop()

if name == "main":
video_path = sys.argv[1]
main(video_path)

@mrJean1
Copy link
Collaborator

mrJean1 commented Dec 27, 2023

The results from methods player.get_time, player.get_position, player.get_length and media.get_duration are not reliable until the video has been playing for several seconds. Examples like cocoavlc.py are affected by that same issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants