This repository has been archived on 2024-10-24. You can view files and clone it, but cannot push or open issues or pull requests.
NG_2023_Video/main.py

169 lines
5.8 KiB
Python
Raw Normal View History

2023-06-06 15:18:12 +00:00
from mail import send_email
from flask import Flask, abort, render_template, redirect, request, url_for
from PIL import Image
from proglog import ProgressBarLogger
import os
import uuid
import moviepy.editor as moviepy
app = Flask(__name__)
ALLOWED_UPLOAD_EXTENSIONS = {'mp4', 'webm', 'mkv', 'avi', 'ogv'}
2023-06-15 18:04:28 +00:00
ALLOWED_CONVERT_EXTENSIONS = {'mp4', 'webm',
'mkv', 'avi', 'ogv', 'ogg', 'mp3', 'flac'}
2023-06-06 15:18:12 +00:00
AUDIO_EXTENSIONS = {'ogg', 'mp3', 'flac'}
2023-06-15 18:04:28 +00:00
ALLOWED_WATERMARK_EXTENSIONS = {
'bmp', 'png', 'jpg', 'jpeg', 'tiff', 'tga', 'svg'}
2023-06-06 15:18:12 +00:00
percentages = {}
2023-06-15 18:04:28 +00:00
2023-06-06 15:18:12 +00:00
class BarLogger(ProgressBarLogger):
global percentages
id = None
def bars_callback(self, bar, attr, value, old_value=None):
percentages[self.id] = (value / self.bars[bar]['total']) * 100
def __init__(self, id):
super(self.__class__, self).__init__()
self.id = id
2023-06-15 18:04:28 +00:00
2023-06-06 15:18:12 +00:00
def is_integer(n):
try:
return float(n).is_integer()
except ValueError:
return False
2023-06-15 18:04:28 +00:00
2023-06-06 15:18:12 +00:00
def getExtension(filename, isWatermark=False):
if not '.' in filename:
return False
extension = filename.rsplit('.', 1)[1].lower()
if extension in ALLOWED_UPLOAD_EXTENSIONS and not isWatermark:
return extension
elif extension in ALLOWED_WATERMARK_EXTENSIONS and isWatermark:
return extension
else:
return False
2023-06-15 18:04:28 +00:00
2023-06-06 15:18:12 +00:00
@app.route('/', methods=['GET', 'POST'])
def index():
if request.method == 'POST' and 'video' in request.files:
file = request.files['video']
2023-06-16 19:19:01 +00:00
if file.filename:
2023-06-06 15:18:12 +00:00
extension = getExtension(file.filename)
2023-06-16 19:19:01 +00:00
if extension:
2023-06-06 15:18:12 +00:00
filename = str(uuid.uuid4()) + '.' + extension
file.save(os.path.join('videos', filename))
return redirect(url_for('video', id=filename))
2023-06-16 19:19:01 +00:00
else:
return render_template('index.html', error='Non-allowed file extension.')
2023-06-06 15:18:12 +00:00
return render_template('index.html')
2023-06-15 18:04:28 +00:00
2023-06-06 15:18:12 +00:00
@app.route('/video', methods=['GET', 'POST'])
def video():
error = ''
changed = False
audio = None
id = request.args.get('id')
2023-06-15 18:04:28 +00:00
if id == None:
abort(400)
2023-06-06 15:18:12 +00:00
path = os.path.join('videos', id)
2023-06-16 19:19:01 +00:00
if os.path.isfile(path):
2023-06-06 15:18:12 +00:00
clip = moviepy.VideoFileClip(path)
if request.method == 'POST':
start = request.form.get('start')
end = request.form.get('end')
extension = request.form.get('extension')
email = request.form.get('email')
if not email:
abort(400)
if start and end:
if is_integer(start) and is_integer(end) and int(start) < int(end):
if int(start) < 0 or int(end) > clip.duration:
error += 'Selected subclip out of bounds.<br>'
else:
clip = clip.subclip(start, end)
changed = True
2023-06-16 19:19:01 +00:00
else:
error += 'Invalid start or end times.<br>'
2023-06-06 15:18:12 +00:00
if extension:
if extension in ALLOWED_CONVERT_EXTENSIONS:
if extension in AUDIO_EXTENSIONS:
audio = clip.audio
newId = id.rsplit('.', 1)[0] + '.' + extension
if id == newId:
error += 'A different extension than the currently used one is needed.<br>'
else:
changed = True
else:
error += 'Requested recode extension not allowed.<br>'
if 'watermark' in request.files:
file = request.files['watermark']
2023-06-16 19:19:01 +00:00
if file.filename:
2023-06-06 15:18:12 +00:00
if audio:
error += 'Audio cannot be watermarked.<br>'
else:
watermarkExtension = getExtension(file.filename, True)
if watermarkExtension:
2023-06-15 18:04:28 +00:00
watermarkPath = os.path.join(
'videos', id + '-watermark' + '.' + watermarkExtension)
2023-06-06 15:18:12 +00:00
file.save(watermarkPath)
formatter = {'PNG': 'RGBA', 'JPEG': 'RGB'}
img = Image.open(watermarkPath)
2023-06-15 18:04:28 +00:00
rgbimg = Image.new(formatter.get(
img.format, 'RGB'), img.size)
2023-06-06 15:18:12 +00:00
rgbimg.paste(img)
rgbimg.save(watermarkPath, format=img.format)
watermark = (moviepy.ImageClip(watermarkPath)
2023-06-15 18:04:28 +00:00
.set_duration(clip.duration)
.set_pos(('right', 'bottom')))
2023-06-06 15:18:12 +00:00
2023-06-15 18:04:28 +00:00
clip = moviepy.CompositeVideoClip(
[clip, watermark])
2023-06-06 15:18:12 +00:00
os.remove(watermarkPath)
changed = True
else:
error += 'Non-allowed watermark extension.<br>'
if changed:
logger = BarLogger(id)
if 'newId' in locals():
os.remove(path)
id = newId
path = os.path.join('videos', id)
if audio:
audio.write_audiofile(path, logger=logger)
else:
clip.write_videofile(path, logger=logger)
send_email(email, path)
os.remove(path)
return render_template('success.html', error=error)
2023-06-15 18:04:28 +00:00
return render_template('video.html', length=int(clip.duration), error=error)
2023-06-06 15:18:12 +00:00
else:
abort(404)
2023-06-15 18:04:28 +00:00
2023-06-06 15:18:12 +00:00
@app.route('/progress', methods=['GET'])
def progress():
id = request.args.get('id')
percentage = percentages.get(id)
if percentage:
return str(percentage)
else:
abort(404)
2023-06-15 18:04:28 +00:00
2023-06-06 15:18:12 +00:00
if __name__ == '__main__':
if not os.path.isdir('videos'):
os.mkdir('videos')
app.run()