簡體   English   中英

為什么我的代碼無法保存從網絡攝像頭捕獲的幀的視頻文件,但我可以將幀保存為圖像文件就好了?

[英]Why my code fails to save video files of frames capture from a webcam but I can save the frames as image files just fine?

我正在嘗試開發 Python 腳本,它可以從網絡攝像頭捕獲和記錄幀,還可以從麥克風記錄音頻幾秒鍾,並重復直到預定時間停止。 來自網絡攝像頭的幀可以保存為 jpg 文件就好了。 音頻也可以毫無問題地保存為 wav 文件。 但視頻文件無法打開並報錯“此文件無法播放。這可能是因為文件類型不受支持、文件擴展名不正確或文件已損壞。” 我使用 OpenCV 獲取幀並記錄視頻和圖像文件。 我已經在我的電腦(Windows 10)上安裝了 ffmpeg,運行我的代碼時沒有出現異常錯誤。

下面是我制作的腳本。 該程序設置為運行 runningDur = 12 秒。 每個視頻文件 (.mp4) 應每 5 秒保存一次,持續時間為 5 秒 (videoSaveIntv)。 每 4 秒 (frameSaveIntv) 將一幀保存為圖像文件 (.jpg)。 音頻文件將每 5 秒 (audioSaveIntv) 保存一次,持續時間為 4 秒 (audirorecdur)。

import numpy as np
import cv2 as cv
from datetime import time, datetime, timedelta
import sounddevice as sd
from scipy.io.wavfile import write as audioWrite
from threading import Thread
import traceback


cap = cv.VideoCapture(0) # use this line for testing with local camera (webcam, etc.)

# Define the codec and create VideoWriter object
fourcc = cv.VideoWriter_fourcc(*'mp4v')
fps = 20.0
#frameSize = (640, 480)
frameSize = (cv.CAP_PROP_FRAME_WIDTH, cv.CAP_PROP_FRAME_HEIGHT)
# Define parameters for audio recording
audirorecdur = 4
fs= 44100
sd.default.samplerate = fs
sd.default.channels = 1
# flag to trigger video recording
flag1 = True
# flag to trigger frame capture
flag2 = True 
# flag to trigger audio recording
flag3 = True
# startTime1 is to help controlling when we will save a frame as an image file
startTime1 = datetime.now()
# startTime2 is to help controlling how long this script will run
startTime2 = startTime1
# startTime3 is to help controling how long each video file will be saved
startTime3 = startTime1
# startTime4 is to help controling how long each audio file will be saved
startTime4 = startTime1
# create video file object...... maybe not necessary for project purpose
#out1 = cv.VideoWriter("D:/pyvidrec/rec_%03d.mp4", fourcc, fps, frameSize)
# determine how long should we run this program in seconds, 86400 s = 1 day
runningDur = 12
# determine time length of each saved video file in seconds
videoSaveIntv = 5
# determine interval of frame save in seconds
frameSaveIntv = 4
# determine time interval of audio recording start time in seconds
audioSaveIntv = 5

def saveAudioFile():
    sd.wait()
    audioWrite(audiofilename, fs, audiorecording)  # Save as WAV file 

# start the main loop
try:
    while cap.isOpened():
        # get a frame from camera, ret will return True if a frame is received
        ret, frame = cap.read()
        # get current time
        checkTime = datetime.now()
        
        # if no frame received, stop this program
        if not ret:
            print("Can't receive frame (stream end?). Exiting ...")
            break

        # if the video save interval has passed, make flag1 = True
        if (checkTime - startTime3).total_seconds() >= videoSaveIntv:
            flag1 = True
        # if flag1 is True, create new video file
        if flag1 == True:
            out1 = cv.VideoWriter("D:/pyvidrec/%02d%02d%02d_%02d%02d.mp4" % (checkTime.year-2000, checkTime.month, checkTime.day, checkTime.hour, checkTime.minute), fourcc, fps, frameSize)
            # reset startTime3 as checkTime
            startTime3 = checkTime
            flag1 = False
        # write the frame into the video file
        out1.write(frame)

        # if the frame save interval has passed since last time check, make the flag2 = True
        if (checkTime - startTime1).total_seconds() >= frameSaveIntv:
            flag2 = True
        # if flag2 is True, save current frame in an image file
        if flag2 == True:
            cv.imwrite("D:/pyvidrec/%02d%02d%02d_%02d%02d%02d.jpg" % (checkTime.year-2000, checkTime.month, checkTime.day, checkTime.hour, checkTime.minute, checkTime.second),frame)
            # reset startTime1 as checkTime
            startTime1 = checkTime
            # turn flag to False
            flag2 = False

        # if the audio save interval has passed since last time check, make the flag3 = True
        if (checkTime - startTime4).total_seconds() >= audioSaveIntv:
            flag3 = True
            try:
                sd.stop()
                audioWrite(audiofilename, fs, audiorecording)
            except:
                traceback.print_exc()
            
        # if flag3 is True, start getting audio recording
        if flag3 == True:
            audiorecording = sd.rec(int(audirorecdur * fs))
            audiofilename = "D:/pyvidrec/%02d%02d%02d_%02d%02d%02d.wav" % (checkTime.year-2000, checkTime.month, checkTime.day, checkTime.hour, checkTime.minute, checkTime.second)
            #saveAudioFileThread = Thread(target = saveAudioFile)
            #saveAudioFileThread.run()
            # reset startTime4 as checkTime
            startTime4 = checkTime
            # turn flag to False
            flag3 = False
        # if cv.waitKey(1) == ord('q'):
        #     break
    
        # if program has run for certain time, stop it
        if (checkTime - startTime2).total_seconds() >= runningDur:
            break

    # Release everything if job is finished
    cap.release()
    out1.release()

except KeyboardInterrupt:
    print("KeyboardInterrupt Exception is caught. Exiting program...")
    cap.release()
    out1.release()

except:
    traceback.print_exc()
    cap.release()
    out1.release()

該腳本給出了 output 個 2 個 mp4 文件、3 個 jpg 文件和 2 個 wav 文件。 只有 mp4 文件無法打開。 請幫我。

導致無法播放視頻文件的問題很少:

  • 表達式frameSize = (cv.CAP_PROP_FRAME_WIDTH, cv.CAP_PROP_FRAME_HEIGHT)結果frameSize = (3, 4)
    正確的語法是從cap獲取大小:

     frame_width = int(cap.get(cv.CAP_PROP_FRAME_WIDTH)) frame_height = int(cap.get(cv.CAP_PROP_FRAME_HEIGHT)) frameSize = (frame_width, frame_height)
  • 我們必須在打開一個新的 MP4 視頻文件之前執行out1.release()
    在執行out1 = cv.VideoWriter之前,執行out1.release() ,除了第一次。
    我們可以在循環上方將out1初始化為None ,如果out1不是None則執行out1.release()

     if out1 is not None: out1.release() # Close the video file, before opening a new one out1 = cv.VideoWriter("D:/pyvidrec...

沒有音頻的代碼示例:

import numpy as np
import cv2 as cv
from datetime import time, datetime, timedelta
#import sounddevice as sd
#from scipy.io.wavfile import write as audioWrite
#from threading import Thread
import traceback


cap = cv.VideoCapture(0) # use this line for testing with local camera (webcam, etc.)

# Define the codec and create VideoWriter object
fourcc = cv.VideoWriter_fourcc(*'mp4v')
fps = 20.0
#frameSize = (640, 480)
#frameSize = (cv.CAP_PROP_FRAME_WIDTH, cv.CAP_PROP_FRAME_HEIGHT)
frame_width = int(cap.get(cv.CAP_PROP_FRAME_WIDTH))
frame_height = int(cap.get(cv.CAP_PROP_FRAME_HEIGHT))
frameSize = (frame_width, frame_height)

# Define parameters for audio recording
#audirorecdur = 4
#fs= 44100
#sd.default.samplerate = fs
#sd.default.channels = 1
# flag to trigger video recording
flag1 = True
# flag to trigger frame capture
flag2 = True 
# flag to trigger audio recording
flag3 = True
# startTime1 is to help controlling when we will save a frame as an image file
startTime1 = datetime.now()
# startTime2 is to help controlling how long this script will run
startTime2 = startTime1
# startTime3 is to help controling how long each video file will be saved
startTime3 = startTime1
# startTime4 is to help controling how long each audio file will be saved
startTime4 = startTime1
# create video file object...... maybe not necessary for project purpose
#out1 = cv.VideoWriter("D:/pyvidrec/rec_%03d.mp4", fourcc, fps, frameSize)
# determine how long should we run this program in seconds, 86400 s = 1 day
runningDur = 12
# determine time length of each saved video file in seconds
videoSaveIntv = 5
# determine interval of frame save in seconds
frameSaveIntv = 4
# determine time interval of audio recording start time in seconds
audioSaveIntv = 5

#def saveAudioFile():
#    sd.wait()
#    audioWrite(audiofilename, fs, audiorecording)  # Save as WAV file 

out1 = None

# start the main loop
try:
    while cap.isOpened():
        # get a frame from camera, ret will return True if a frame is received
        ret, frame = cap.read()
        # get current time
        checkTime = datetime.now()
        
        # if no frame received, stop this program
        if not ret:
            print("Can't receive frame (stream end?). Exiting ...")
            break

        # if the video save interval has passed, make flag1 = True
        if (checkTime - startTime3).total_seconds() >= videoSaveIntv:
            flag1 = True
        # if flag1 is True, create new video file
        if flag1 == True:
            if out1 is not None:
                out1.release()  # Close the video file, before opening a new one
            out1 = cv.VideoWriter("D:/pyvidrec/%02d%02d%02d_%02d%02d.mp4" % (checkTime.year-2000, checkTime.month, checkTime.day, checkTime.hour, checkTime.minute), fourcc, fps, frameSize)
            # reset startTime3 as checkTime
            startTime3 = checkTime
            flag1 = False

        # write the frame into the video file
        if out1 is not None:
            out1.write(frame)

        # if the frame save interval has passed since last time check, make the flag2 = True
        if (checkTime - startTime1).total_seconds() >= frameSaveIntv:
            flag2 = True
        # if flag2 is True, save current frame in an image file
        if flag2 == True:
            cv.imwrite("D:/pyvidrec/%02d%02d%02d_%02d%02d%02d.jpg" % (checkTime.year-2000, checkTime.month, checkTime.day, checkTime.hour, checkTime.minute, checkTime.second),frame)
            # reset startTime1 as checkTime
            startTime1 = checkTime
            # turn flag to False
            flag2 = False

        # if the audio save interval has passed since last time check, make the flag3 = True
        #if (checkTime - startTime4).total_seconds() >= audioSaveIntv:
        #    flag3 = True
        #    try:
        #        sd.stop()
        #        audioWrite(audiofilename, fs, audiorecording)
        #    except:
        #        traceback.print_exc()
            
        # if flag3 is True, start getting audio recording
        #if flag3 == True:
        #    audiorecording = sd.rec(int(audirorecdur * fs))
        #    audiofilename = "D:/pyvidrec/%02d%02d%02d_%02d%02d%02d.wav" % (checkTime.year-2000, checkTime.month, checkTime.day, checkTime.hour, checkTime.minute, checkTime.second)
        #    #saveAudioFileThread = Thread(target = saveAudioFile)
        #    #saveAudioFileThread.run()
        #    # reset startTime4 as checkTime
        #    startTime4 = checkTime
        #    # turn flag to False
        #    flag3 = False
        ## if cv.waitKey(1) == ord('q'):
        #     break
    
        # if program has run for certain time, stop it
        if (checkTime - startTime2).total_seconds() >= runningDur:
            break

    # Release everything if job is finished
    cap.release()
    out1.release()

except KeyboardInterrupt:
    print("KeyboardInterrupt Exception is caught. Exiting program...")
    cap.release()
    out1.release()

except:
    traceback.print_exc()
    cap.release()
    out1.release()

筆記:
下次您發布問題時,請發布一個最小的可重現代碼示例 - 創建一個干凈的代碼示例,排除所有與問題無關的部分(例如:音頻與視頻問題無關)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM