Flask Opencv Recode mini 视频剪辑
Flask Opencv Recode mini Video clips
在使用 open cv 和 python.
录制我的网络摄像头时,我很难生成一个迷你视频剪辑(每个都是 10 秒的视频剪辑)
基本上我想将网络摄像头视频剪切成 10 秒时长的片段并存储在一个文件夹中。
当我做这个视频剪辑剪切但当我检查第一个视频剪辑有 100% 的完整视频。
第二个有大约 75% 的完整视频,第三个有大约 50% 等等。
那么我该如何解决这个问题。
我将把我的孔代码放在下面。希望你能帮助解决这个问题
camera = cv2.VideoCapture(0)
global rec, img, out
rec = 0
def gen_frames():
global img
while True:
success, img = camera.read()
def record(out):
global rec, img
while(rec != False):
time.sleep(0.05)
out.write(img)
@app.route('/requests',methods=['POST','GET'])
def tasks():
if request.form.get('rec') == 'Start/Stop Recording':
global rec, img, out
rec= not rec
############### This Part work when manualy recode on and off ###############
# if rec:
# print("start")
# global out
# now=datetime.datetime.now()
# fourcc = cv2.VideoWriter_fourcc(*'XVID')
# p = os.path.sep.join(['clips', "vid_{}.avi".format(str(now).replace(":",''))])
# out = cv2.VideoWriter(p, fourcc, 25.0, size)
# thread = Thread(target = record, args=[out,])
# thread.start()
# if(rec==False):
# print("stop")
# out.release()
class TimerClass(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
self.event = threading.Event()
def run(self):
while (rec != False) and not self.event.is_set():
now=datetime.datetime.now()
fourcc = cv2.VideoWriter_fourcc(*'XVID')
p = os.path.sep.join(['clips', "vid_{}.avi".format(str(now).replace(":",''))])
out = cv2.VideoWriter(p, fourcc, 25.0, size)
thread = Thread(target = record, args=[out,])
thread.start()
self.event.wait(10)
def stop(self):
self.event.set()
tmr = TimerClass()
if(rec):
print("start")
tmr.start()
if(rec==False):
print("stop")
tmr.stop()
elif request.method=='GET':
return render_template('index.html')
return render_template('index.html')
if __name__ == '__main__':
app.run(host='0.0.0.0', threaded=True)
至于我的问题是,在 TimerClass
的循环中,你每 10 秒创建一个新线程,但你永远不会停止前一个线程,它仍然记录帧。我会直接在 TimerClass
中写入帧,而不是使用另一个线程。
OR 线程 record()
应该检查时间并在 10 秒后停止。
我使用 timedelta
来计算何时停止录制一个文件并创建下一个文件。我在 TimerClass
中做,但你可以在 record()
中做类似的事情
VideoWriter(..., 25.0)
不会写成 25fps
但它只是视频播放器显示此视频的速度信息。要获得 10 秒的视频,您需要睡眠 0.04
因为 1s / 25fps = 0.04
否则您将不得不写入 250 帧(10s * 25fps = 250fps)。
因为代码也需要一些时间来工作,所以我必须使用 0.03
而不是 0.04
来获得 10 秒的视频。
完整的工作代码。
我使用 render_template_string
而不是 render_template
将所有内容都放在一个文件中 - 每个人都可以简单地复制和测试它。
from flask import Flask, Response, request, render_template, render_template_string
import cv2
import os
import datetime, time
import threading
# global varaibles
capture = False
rec = False
out = None
img = None
app = Flask(__name__)
app.config['SEND_FILE_MAX_AGE_DEFAULT'] = 300
camera = cv2.VideoCapture(0)
frame_width = int(camera.get(3))
frame_height = int(camera.get(4))
size = (frame_width, frame_height)
os.makedirs('./shots', exist_ok=True)
os.makedirs('./clips', exist_ok=True)
def gen_frames():
global capture
global img
print('[DEBUG] gen_frames: start')
while True:
success, img = camera.read()
if not success:
break
if capture:
capture = False
now = datetime.datetime.now()
filename = "shot_{}.png".format(str(now).replace(":",''))
path = os.path.sep.join(['shots', filename])
print('[DEBUG] capture:', path)
cv2.imwrite(path, img)
frame = cv2.imencode('.jpg', img)[1].tobytes()
yield (b'--frame\r\n'
b'Content-Type: image/jpeg\r\n\r\n' + frame + b'\r\n')
@app.route('/video_feed')
def video_feed():
return Response(gen_frames(), mimetype='multipart/x-mixed-replace; boundary=frame')
@app.route('/')
def index():
#return render_template('index.html')
return render_template_string('''
Go to <a href="/requests">FORM</a>
''')
# define class only once
class TimerClass(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
self.event = threading.Event()
def run(self):
seconds_10 = datetime.timedelta(seconds=10)
while rec and not self.event.is_set():
now = datetime.datetime.now()
filename = "vid_{}.avi".format(str(now).replace(":", ''))
path = os.path.sep.join(['clips', filename])
fourcc = cv2.VideoWriter_fourcc(*'XVID')
out = cv2.VideoWriter(path, fourcc, 25.0, size)
end = now + seconds_10
print('[DEBUG] end:', end)
while now < end and rec and not self.event.is_set():
if img is not None: # `img` can be `numpy.array` so it can't check `if img:`
out.write(img)
time.sleep(0.03) # 1s / 25fps = 0.04 # it needs some time for code.
now = datetime.datetime.now()
out.release()
def stop(self):
self.event.set()
@app.route('/requests', methods=['POST', 'GET'])
def tasks():
global capture
global rec
print('[DEBUG] click:', request.form.get('click'))
print('[DEBUG] rec :', request.form.get('rec'))
if request.method == 'POST':
if request.form.get('click') == 'Capture':
capture = True
if request.form.get('rec') == 'Start/Stop Recording':
rec = not rec
tmr = TimerClass()
if rec:
print("start")
tmr.start()
else:
print("stop")
tmr.stop()
#return render_template_string('index.html')
return render_template_string('''
<img src="/video_feed"><br/>
<form method="POST">
<button type="submit" name="click" value="Capture">Capture</button>
<button type="submit" name="rec" value="Start/Stop Recording">Start/Stop Recording</button>
</form>
''')
if __name__ == '__main__':
thread_cam = threading.Thread(target=gen_frames)
thread_cam.start()
app.run(host='0.0.0.0', threaded=True)
编辑:
同线程record()
def record(seconds):
now = datetime.datetime.now()
filename = "vid_{}.avi".format(str(now).replace(":", ''))
path = os.path.sep.join(['clips', filename])
fourcc = cv2.VideoWriter_fourcc(*'XVID')
out = cv2.VideoWriter(path, fourcc, 25.0, size)
end = now + datetime.timedelta(seconds=seconds)
print('[DEBUG] end:', end)
while now < end and rec:
if img is not None: # `img` can be `numpy.array` so it can't check `if img:`
out.write(img)
time.sleep(0.03) # 1s / 25fps = 0.04 # it needs some time for code.
now = datetime.datetime.now()
out.release()
# define class only once
class TimerClass(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
self.event = threading.Event()
def run(self):
length = 10
while rec and not self.event.is_set():
t = threading.Thread(target=record, args=(length,))
t.start()
self.event.wait(length)
def stop(self):
self.event.set()
在使用 open cv 和 python.
录制我的网络摄像头时,我很难生成一个迷你视频剪辑(每个都是 10 秒的视频剪辑)基本上我想将网络摄像头视频剪切成 10 秒时长的片段并存储在一个文件夹中。 当我做这个视频剪辑剪切但当我检查第一个视频剪辑有 100% 的完整视频。 第二个有大约 75% 的完整视频,第三个有大约 50% 等等。
那么我该如何解决这个问题。 我将把我的孔代码放在下面。希望你能帮助解决这个问题
camera = cv2.VideoCapture(0)
global rec, img, out
rec = 0
def gen_frames():
global img
while True:
success, img = camera.read()
def record(out):
global rec, img
while(rec != False):
time.sleep(0.05)
out.write(img)
@app.route('/requests',methods=['POST','GET'])
def tasks():
if request.form.get('rec') == 'Start/Stop Recording':
global rec, img, out
rec= not rec
############### This Part work when manualy recode on and off ###############
# if rec:
# print("start")
# global out
# now=datetime.datetime.now()
# fourcc = cv2.VideoWriter_fourcc(*'XVID')
# p = os.path.sep.join(['clips', "vid_{}.avi".format(str(now).replace(":",''))])
# out = cv2.VideoWriter(p, fourcc, 25.0, size)
# thread = Thread(target = record, args=[out,])
# thread.start()
# if(rec==False):
# print("stop")
# out.release()
class TimerClass(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
self.event = threading.Event()
def run(self):
while (rec != False) and not self.event.is_set():
now=datetime.datetime.now()
fourcc = cv2.VideoWriter_fourcc(*'XVID')
p = os.path.sep.join(['clips', "vid_{}.avi".format(str(now).replace(":",''))])
out = cv2.VideoWriter(p, fourcc, 25.0, size)
thread = Thread(target = record, args=[out,])
thread.start()
self.event.wait(10)
def stop(self):
self.event.set()
tmr = TimerClass()
if(rec):
print("start")
tmr.start()
if(rec==False):
print("stop")
tmr.stop()
elif request.method=='GET':
return render_template('index.html')
return render_template('index.html')
if __name__ == '__main__':
app.run(host='0.0.0.0', threaded=True)
至于我的问题是,在 TimerClass
的循环中,你每 10 秒创建一个新线程,但你永远不会停止前一个线程,它仍然记录帧。我会直接在 TimerClass
中写入帧,而不是使用另一个线程。
OR 线程 record()
应该检查时间并在 10 秒后停止。
我使用 timedelta
来计算何时停止录制一个文件并创建下一个文件。我在 TimerClass
中做,但你可以在 record()
VideoWriter(..., 25.0)
不会写成 25fps
但它只是视频播放器显示此视频的速度信息。要获得 10 秒的视频,您需要睡眠 0.04
因为 1s / 25fps = 0.04
否则您将不得不写入 250 帧(10s * 25fps = 250fps)。
因为代码也需要一些时间来工作,所以我必须使用 0.03
而不是 0.04
来获得 10 秒的视频。
完整的工作代码。
我使用 render_template_string
而不是 render_template
将所有内容都放在一个文件中 - 每个人都可以简单地复制和测试它。
from flask import Flask, Response, request, render_template, render_template_string
import cv2
import os
import datetime, time
import threading
# global varaibles
capture = False
rec = False
out = None
img = None
app = Flask(__name__)
app.config['SEND_FILE_MAX_AGE_DEFAULT'] = 300
camera = cv2.VideoCapture(0)
frame_width = int(camera.get(3))
frame_height = int(camera.get(4))
size = (frame_width, frame_height)
os.makedirs('./shots', exist_ok=True)
os.makedirs('./clips', exist_ok=True)
def gen_frames():
global capture
global img
print('[DEBUG] gen_frames: start')
while True:
success, img = camera.read()
if not success:
break
if capture:
capture = False
now = datetime.datetime.now()
filename = "shot_{}.png".format(str(now).replace(":",''))
path = os.path.sep.join(['shots', filename])
print('[DEBUG] capture:', path)
cv2.imwrite(path, img)
frame = cv2.imencode('.jpg', img)[1].tobytes()
yield (b'--frame\r\n'
b'Content-Type: image/jpeg\r\n\r\n' + frame + b'\r\n')
@app.route('/video_feed')
def video_feed():
return Response(gen_frames(), mimetype='multipart/x-mixed-replace; boundary=frame')
@app.route('/')
def index():
#return render_template('index.html')
return render_template_string('''
Go to <a href="/requests">FORM</a>
''')
# define class only once
class TimerClass(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
self.event = threading.Event()
def run(self):
seconds_10 = datetime.timedelta(seconds=10)
while rec and not self.event.is_set():
now = datetime.datetime.now()
filename = "vid_{}.avi".format(str(now).replace(":", ''))
path = os.path.sep.join(['clips', filename])
fourcc = cv2.VideoWriter_fourcc(*'XVID')
out = cv2.VideoWriter(path, fourcc, 25.0, size)
end = now + seconds_10
print('[DEBUG] end:', end)
while now < end and rec and not self.event.is_set():
if img is not None: # `img` can be `numpy.array` so it can't check `if img:`
out.write(img)
time.sleep(0.03) # 1s / 25fps = 0.04 # it needs some time for code.
now = datetime.datetime.now()
out.release()
def stop(self):
self.event.set()
@app.route('/requests', methods=['POST', 'GET'])
def tasks():
global capture
global rec
print('[DEBUG] click:', request.form.get('click'))
print('[DEBUG] rec :', request.form.get('rec'))
if request.method == 'POST':
if request.form.get('click') == 'Capture':
capture = True
if request.form.get('rec') == 'Start/Stop Recording':
rec = not rec
tmr = TimerClass()
if rec:
print("start")
tmr.start()
else:
print("stop")
tmr.stop()
#return render_template_string('index.html')
return render_template_string('''
<img src="/video_feed"><br/>
<form method="POST">
<button type="submit" name="click" value="Capture">Capture</button>
<button type="submit" name="rec" value="Start/Stop Recording">Start/Stop Recording</button>
</form>
''')
if __name__ == '__main__':
thread_cam = threading.Thread(target=gen_frames)
thread_cam.start()
app.run(host='0.0.0.0', threaded=True)
编辑:
同线程record()
def record(seconds):
now = datetime.datetime.now()
filename = "vid_{}.avi".format(str(now).replace(":", ''))
path = os.path.sep.join(['clips', filename])
fourcc = cv2.VideoWriter_fourcc(*'XVID')
out = cv2.VideoWriter(path, fourcc, 25.0, size)
end = now + datetime.timedelta(seconds=seconds)
print('[DEBUG] end:', end)
while now < end and rec:
if img is not None: # `img` can be `numpy.array` so it can't check `if img:`
out.write(img)
time.sleep(0.03) # 1s / 25fps = 0.04 # it needs some time for code.
now = datetime.datetime.now()
out.release()
# define class only once
class TimerClass(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
self.event = threading.Event()
def run(self):
length = 10
while rec and not self.event.is_set():
t = threading.Thread(target=record, args=(length,))
t.start()
self.event.wait(length)
def stop(self):
self.event.set()