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

Improved TkVideoPlayer #27

Open
wants to merge 35 commits into
base: master
Choose a base branch
from
Open

Conversation

Akascape
Copy link

@Akascape Akascape commented Apr 2, 2023

Use this version if you want any of the following feature:

  • Added accurate frame seeking
  • Added audio (beta stage)
  • Added more info parameters
  • Minor error issues fixed
  • Improved documentation
  • Fixed one memory leak issue

Documentation.md Outdated
| keep_aspect | keep_aspect(bool) | keeps aspect ratio when resizing
| metadata | - | returns meta information of the video if available in the form of dictionary
| set_resampling_method| method(int) | By default the resampling method while resizing is NEAREST, changing this can affect how its resampled when image is resized, refer PIL documentation to read more (note: this can also affect the framerate of the video)|
| **\_\_init\_\_** | <li>scaled(bool)</li> <li>consistant_frame_rate(bool)</li> <li>keep_aspect(bool)=False</li> | <li>The _scaled_ parameter scales the video to the label size.</li> <li>The _consistant_frame_rate_ parameter adds an appropriate time delay to keep the framerate consistant.</li> <li>_keep_aspect_ keeps aspect ratio when resizing. (note: It will not increase the size) </li> |
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Improved the documentation

Readme.md Outdated

This example source code can be found [here](https://github.com/PaulleDemon/tkVideoPlayer/blob/master/examples/sample_player.py)
### Sample video players made using tkVideoPlayer:
<img src="https://user-images.githubusercontent.com/89206401/229363046-36ebcffd-36d2-4c7f-98ce-4aa6b402e9e0.png" width=550> <img src="https://github.com/PaulleDemon/tkVideoPlayer/blob/master/videoplayer_screenshot.png?raw=True" width=550>
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added a new example program

@@ -0,0 +1,89 @@
"""
Author: Akascape
This is an advanced example of tkvideoplayer with frame-seeking
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A new example program

@@ -6,8 +6,7 @@
from PIL import ImageTk, Image, ImageOps
from typing import Tuple, Dict

logging.getLogger('libav').setLevel(logging.ERROR) # removes warning: deprecated pixel format used

logging.getLogger('libav').setLevel(logging.CRITICAL) # removes warning: deprecated pixel format used
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Show only critical errors.

"framesize": (0, 0) # tuple containing frame height and width of the video

"framesize": (0, 0), # tuple containing frame height and width of the video
"frames": 0, # total frames of the video
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added 3 more video info: name, total frames, codec


def _display_frame(self, event):
""" displays the frame on the label """
self.event_generate("<<FrameChanged>>")
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added a new frame changed event

self._seek_sec = 0


if self._seek_pause:
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

new parameter pause can be used to pause the video after seeking

self.play()
self.after(50, self.pause)

if self._seek_frame: # seek to a specific frame
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

New seek frame method for seeking any particular frame

@@ -199,9 +244,11 @@ def load(self, path: str):
""" loads the file from the given path """
self.stop()
self.path = path

self._load_thread = None
self._container = None
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we should reload the container so that it works even after any pyav crash.

self._load_thread = threading.Thread(target=self._load, args=(self.path, ), daemon=True)
self._load_thread.start()

def is_paused(self):
""" returns if the video is paused """
return self._paused

def is_stopped(self):
""" returns if the video is stopped """
return self._stop
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

stop event can be useful while looping or opening a new video

self._seek_sec = sec
self._any_frame = any_frame
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

any_frame can be useful while seeking some corrupted videos

self._frame = frame
self._seek_pause = pause
self._delay = delay if int(delay)<1 else 1.0
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add a slight delay while seeking a frame, so that cpu usage can be minimized.

@Akascape Akascape marked this pull request as ready for review April 2, 2023 15:53
@Akascape Akascape marked this pull request as draft April 2, 2023 15:54
@Akascape Akascape marked this pull request as ready for review April 2, 2023 15:56
@vguttmann
Copy link

Have you also taken care of audio? As far as I'm aware, the base library doesn't play audio as of yet.

@Akascape
Copy link
Author

@vguttmann The problem is with syncing audio video together without any delay. Issue already raised here : #2

But I guess we can add it, maybe in future I will try...

@Akascape
Copy link
Author

Akascape commented Mar 3, 2024

@vguttmann I tried adding audio, but it doesn't sync properly with all video. https://github.com/Akascape/tkVideoPlayer

@PaulleDemon
Copy link
Owner

@Akascape have you tried using multiple threads? like a separate thread for Audio. Check this StackOverflow answer I wrote a while back. Also, is this branch up-to-date with the current release? I am pretty busy these days so I may not be able to contribute. If you make it work let me know, I'll look into it and merge.

@Akascape
Copy link
Author

Akascape commented Mar 4, 2024

@PaulleDemon I am not using a different thread, I used container.decode(video=0, audio=0) method which yields both video and audio frames simultaneously.
And it works perfectly with a video where the frames are ordered according to PTS (presentation time). While most of the videos with different codecs are not ordered like this and causes stuttering issue when played simultaneously.

I have asked the question here: https://stackoverflow.com/questions/78095616/syncing-audio-video-in-pyav-decoding

But someone said that it is not necessary for a file to have the frames in presentation order. We must sync them separately.

I also tried adding another thread for container.decode(audio=0) but again there is a sync issue as the video frames are not always shown in their respective pts. We have just used the sleep delay method which doesn't work for multiple framerates.

The audio frame decoding is realtime but video frame is not. Maybe we should find a way to display the video frames according to their pts to avoid sync delays.

So for now, it works well with some video files. I am still working on this.

@Akascape
Copy link
Author

Akascape commented Mar 5, 2024

@PaulleDemon Fixed the audio issue, I used the buffering method which just store (10-30) frames per loop and show them according to audio pts, which is also realtime. but don't know if there will be any issue with files having variable frame rate
Whenever you get time, test the implementation: https://github.com/Akascape/tkVideoPlayer/blob/master/tkVideoPlayer/tkvideoplayer.py

@PaulleDemon
Copy link
Owner

@Akascape Good to know you figured it out. I would still require some more people to test it out. Can you create a new pull request titled "added sound" or something so people can come test it out?

Also, I see one commit stating fixed memory leak, what memory leak is that about? Is it upgrading to pyav 11 or something?

@Akascape
Copy link
Author

Akascape commented Mar 5, 2024

@PaulleDemon I found that there is a memory leak if the stream is not closed before loading a new file. It's simple, just add stream.close() to fix it.

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

Successfully merging this pull request may close these issues.

3 participants