media player with video without sound
This commit is contained in:
parent
9be9a9bfac
commit
091a2279cb
@ -24,13 +24,13 @@ def create_api():
|
|||||||
|
|
||||||
from .controllers.user import user
|
from .controllers.user import user
|
||||||
from .controllers.playlist import playlist
|
from .controllers.playlist import playlist
|
||||||
from .controllers.file import file
|
from .controllers.file import files
|
||||||
from .controllers.auth import auth
|
from .controllers.auth import auth
|
||||||
from .controllers.roles import roles_bp
|
from .controllers.roles import roles_bp
|
||||||
|
|
||||||
app.register_blueprint(user, url_prefix='/api')
|
app.register_blueprint(user, url_prefix='/api')
|
||||||
app.register_blueprint(playlist, url_prefix='/api')
|
app.register_blueprint(playlist, url_prefix='/api')
|
||||||
app.register_blueprint(file, url_prefix='/api/file')
|
app.register_blueprint(files, url_prefix='/api')
|
||||||
app.register_blueprint(auth, url_prefix='/api/auth')
|
app.register_blueprint(auth, url_prefix='/api/auth')
|
||||||
app.register_blueprint(roles_bp, url_prefix='/api')
|
app.register_blueprint(roles_bp, url_prefix='/api')
|
||||||
|
|
||||||
|
@ -105,7 +105,7 @@ class PlaylistAbl:
|
|||||||
@staticmethod
|
@staticmethod
|
||||||
def remove_file(playlist_id, data):
|
def remove_file(playlist_id, data):
|
||||||
query = db.session.query(PlaylistFile) \
|
query = db.session.query(PlaylistFile) \
|
||||||
.filter(PlaylistFile.id == data['id']) \
|
.filter(PlaylistFile.file_id == data['file_id']) \
|
||||||
.first()
|
.first()
|
||||||
db.session.delete(query)
|
db.session.delete(query)
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
|
@ -2,15 +2,14 @@ from flask import Blueprint, request, jsonify, send_file
|
|||||||
from ..models import File
|
from ..models import File
|
||||||
from .. import db
|
from .. import db
|
||||||
|
|
||||||
file = Blueprint('file', __name__)
|
files = Blueprint('files', __name__)
|
||||||
FILE_DIR = './data/'
|
FILE_DIR = './data/'
|
||||||
|
|
||||||
@file.route('/', methods=['POST'])
|
@files.route('/files', methods=['POST'])
|
||||||
def upload():
|
def upload():
|
||||||
files = request.files.getlist('file')
|
|
||||||
print(files)
|
|
||||||
res = []
|
res = []
|
||||||
for file in files:
|
for file_key in request.files:
|
||||||
|
file = request.files[file_key]
|
||||||
exists = db.session.query(File).filter(File.name == file.filename).first()
|
exists = db.session.query(File).filter(File.name == file.filename).first()
|
||||||
if not exists:
|
if not exists:
|
||||||
file.save(FILE_DIR + file.filename)
|
file.save(FILE_DIR + file.filename)
|
||||||
@ -22,7 +21,7 @@ def upload():
|
|||||||
db.session.commit()
|
db.session.commit()
|
||||||
return jsonify(res)
|
return jsonify(res)
|
||||||
|
|
||||||
@file.route('/', methods=['GET'])
|
@files.route('/files', methods=['GET'])
|
||||||
def list():
|
def list():
|
||||||
files = db.session.query(File).all()
|
files = db.session.query(File).all()
|
||||||
res = []
|
res = []
|
||||||
@ -30,12 +29,12 @@ def list():
|
|||||||
res.append(file.as_dict())
|
res.append(file.as_dict())
|
||||||
return jsonify(res)
|
return jsonify(res)
|
||||||
|
|
||||||
@file.route('/<int:file_id>', methods=['GET'])
|
@files.route('/files/<int:file_id>', methods=['GET'])
|
||||||
def load(file_id):
|
def load(file_id):
|
||||||
file = db.session.query(File).filter(File.id == file_id).first()
|
file = db.session.query(File).filter(File.id == file_id).first()
|
||||||
return send_file(('../../data/' + file.name), mimetype=file.type)
|
return send_file(('../../data/' + file.name), mimetype=file.type)
|
||||||
|
|
||||||
@file.route('/<int:file_id>', methods=['DELETE'])
|
@files.route('/files/<int:file_id>', methods=['DELETE'])
|
||||||
def delete(file_id):
|
def delete(file_id):
|
||||||
rows = db.session.query(File).filter(File.id == file_id).all()
|
rows = db.session.query(File).filter(File.id == file_id).all()
|
||||||
for row in rows:
|
for row in rows:
|
||||||
|
@ -1,35 +1,145 @@
|
|||||||
import tkinter as tk
|
import tkinter as tk
|
||||||
from PIL import ImageTk, Image
|
import cv2
|
||||||
|
from PIL import Image, ImageTk, Image
|
||||||
|
from tkvideo import tkvideo
|
||||||
import time
|
import time
|
||||||
|
import imageio
|
||||||
|
|
||||||
class SlideShow:
|
class SlideShow:
|
||||||
def __init__(self, root, files):
|
def __init__(self, root, files):
|
||||||
|
print(files)
|
||||||
self.root = root
|
self.root = root
|
||||||
self.files = files
|
self.files = files
|
||||||
self.idx = 0
|
self.idx = -1
|
||||||
|
|
||||||
self.image_label = tk.Label(root)
|
self.canvas = tk.Canvas(root, bg='black')
|
||||||
self.image_label.pack()
|
self.canvas.pack()
|
||||||
self.image_label.pack(fill=tk.BOTH, expand=True)
|
self.canvas.pack(fill=tk.BOTH, expand=True)
|
||||||
|
self.canvas.pack_propagate(False)
|
||||||
|
|
||||||
self.root.after(100, self.next_file)
|
self.root.after(100, self.next_file)
|
||||||
|
|
||||||
def next_file(self):
|
def next_file(self):
|
||||||
|
media = None
|
||||||
|
while media is None or not media.supported:
|
||||||
|
self.idx = (self.idx + 1) % len(self.files)
|
||||||
file = self.files[self.idx]
|
file = self.files[self.idx]
|
||||||
path = './data/' + file['name']
|
media = MediaFactory(self, file)
|
||||||
image = Image.open(path)
|
|
||||||
|
|
||||||
|
print(media.time)
|
||||||
|
print(self.idx)
|
||||||
|
|
||||||
|
self.root.after(media.time, self.next_file)
|
||||||
|
|
||||||
|
def resize_full_screen(self, image):
|
||||||
# Get root window width and height
|
# Get root window width and height
|
||||||
screen_width = self.root.winfo_width()
|
screen_width = self.root.winfo_width()
|
||||||
screen_height = self.root.winfo_height()
|
screen_height = self.root.winfo_height()
|
||||||
|
|
||||||
# Resize the image to fit the screen
|
# Resize the image to fit the screen
|
||||||
image = image.resize((screen_width, screen_height), Image.ANTIALIAS)
|
return image.resize((screen_width, screen_height), Image.BICUBIC)
|
||||||
|
|
||||||
photo = ImageTk.PhotoImage(image)
|
def show_image(self, image):
|
||||||
self.image_label.config(image=photo)
|
self.image = image
|
||||||
self.image_label.image = photo
|
self.canvas.create_image(0, 0, image=self.image, anchor=tk.NW)
|
||||||
|
|
||||||
self.idx = (self.idx + 1) % len(self.files)
|
class MediaFactory:
|
||||||
self.root.after(file['seconds'] * 1000, self.next_file)
|
def __init__(self, parent, file):
|
||||||
|
self.parent = parent
|
||||||
|
self.file = file
|
||||||
|
print(self.file)
|
||||||
|
self.supported = True
|
||||||
|
match file['type']:
|
||||||
|
case "image/gif":
|
||||||
|
self.gif_player()
|
||||||
|
case "image/jpeg" | "image/jpg":
|
||||||
|
self.image_player()
|
||||||
|
case "video/mp4":
|
||||||
|
self.video_player()
|
||||||
|
case _:
|
||||||
|
print(file['type'], " not supported")
|
||||||
|
self.supported = False
|
||||||
|
|
||||||
|
def image_player(self):
|
||||||
|
print("image player")
|
||||||
|
path = './data/' + self.file['name']
|
||||||
|
image = Image.open(path)
|
||||||
|
|
||||||
|
image = self.parent.resize_full_screen(image)
|
||||||
|
photo = ImageTk.PhotoImage(image=image)
|
||||||
|
self.parent.show_image(photo)
|
||||||
|
self.time = self.file['seconds'] * 1000
|
||||||
|
|
||||||
|
def video_player(self):
|
||||||
|
video_player = VideoPlayer(self.parent, self.file)
|
||||||
|
self.time = video_player.time
|
||||||
|
|
||||||
|
def gif_player(self):
|
||||||
|
gif_player = GIFPlayer(self.parent, self.file)
|
||||||
|
self.time = gif_player.time
|
||||||
|
|
||||||
|
class VideoPlayer:
|
||||||
|
def __init__(self, parent, file):
|
||||||
|
self.file = file
|
||||||
|
self.parent = parent
|
||||||
|
self.path = './data/' + self.file['name']
|
||||||
|
|
||||||
|
self.cap = cv2.VideoCapture(self.path)
|
||||||
|
|
||||||
|
self.total_frames = int(self.cap.get(cv2.CAP_PROP_FRAME_COUNT))
|
||||||
|
self.fps = int(self.cap.get(cv2.CAP_PROP_FPS))
|
||||||
|
print(self.total_frames, self.fps)
|
||||||
|
self.time = int(self.total_frames * ((int(1000/self.fps)+1)))
|
||||||
|
self.time = 30 * 1000
|
||||||
|
print(int(1000/self.fps))
|
||||||
|
self.is_playing = True
|
||||||
|
self.i = 0
|
||||||
|
self.update()
|
||||||
|
|
||||||
|
def update(self):
|
||||||
|
if self.is_playing:
|
||||||
|
self.i = self.i + 1
|
||||||
|
#print(self.i)
|
||||||
|
ret, frame = self.cap.read()
|
||||||
|
if ret:
|
||||||
|
image = Image.fromarray(cv2.cvtColor(frame, cv2.COLOR_BGR2RGB))
|
||||||
|
image = self.parent.resize_full_screen(image)
|
||||||
|
photo = ImageTk.PhotoImage(image=image)
|
||||||
|
self.parent.show_image(photo)
|
||||||
|
else:
|
||||||
|
self.is_playing = False
|
||||||
|
self.cap.release()
|
||||||
|
self.parent.root.after(int(1000/self.fps), self.update)
|
||||||
|
|
||||||
|
class GIFPlayer():
|
||||||
|
def __init__(self, parent, file):
|
||||||
|
self.parent = parent
|
||||||
|
self.file = file
|
||||||
|
self.path = './data/' + self.file['name']
|
||||||
|
self.current_frame = 0
|
||||||
|
self.time = 0
|
||||||
|
self.play_gif()
|
||||||
|
|
||||||
|
|
||||||
|
def load_gif_frames(self):
|
||||||
|
gif = Image.open(self.path)
|
||||||
|
frames = []
|
||||||
|
try:
|
||||||
|
while True:
|
||||||
|
frames.append(ImageTk.PhotoImage(gif.copy()))
|
||||||
|
gif.seek(len(frames)) # Move to the next frame
|
||||||
|
except EOFError:
|
||||||
|
pass # Reached the end of the GIF
|
||||||
|
|
||||||
|
return frames
|
||||||
|
|
||||||
|
def play_gif(self):
|
||||||
|
try:
|
||||||
|
frame = ImageTk.PhotoImage(file=self.path, format="gif -index %i" %(self.current_frame))
|
||||||
|
self.parent.label.config(image=frame)
|
||||||
|
self.parent.label.image = frame
|
||||||
|
|
||||||
|
self.current_frame = self.current_frame + 1
|
||||||
|
self.after((100), self.play_gif)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
Loading…
Reference in New Issue
Block a user