如何使用JavaScript/ReactJS在FastAPI中上传视频列表并使用OpenCV处理它们?

vdzxcuhz  于 2023-02-05  发布在  Java
关注(0)|答案(1)|浏览(180)

我正在尝试从上传单个视频切换到上传和处理多个视频;然而,我的代码似乎只保存/读取了第一个视频,我似乎找不出原因,因为当我打印上传的文件列表时,它确实包括了所有被忽略的后续视频。

前端:ReactJS x1c 0d1x
后端:快速API

这是后端的代码:

@app.post("/upload")
def upload_video(fileList: Optional[List[UploadFile]] = File(None)):

    videofiles = []

    for file in fileList:
        print("Uploading:", file.filename)
        print(".................................")

        extension = file.filename.split(".")[-1] in ("mp4", "avi")
        if not extension:
            return "Video must be in mp4 or avi format!"
    try:
        try:
            contents = file.file.read()
            with temp as f:
                print("what's happening: ")
                f.write(contents)
                videofiles.append(cv2.VideoCapture(temp.name))

                print('list of videos uploaded :')
                for vidcap in videofiles:
                    print("video:", vidcap)

                    # Check if camera opened successfully
                    if (vidcap.isOpened() == False):
                        print("Error opening video file")

                    # get height, width and frame count of the video
                    width, height = (
                        int(vidcap.get(cv2.CAP_PROP_FRAME_WIDTH)),
                        int(vidcap.get(cv2.CAP_PROP_FRAME_HEIGHT))
                    )

                    print(f"width: {width}")
                    print(f"height: {height}")

                    # count the number of frames
                    frames = vidcap.get(cv2.CAP_PROP_FRAME_COUNT)
                    fps = vidcap.get(cv2.CAP_PROP_FPS)

                    # calculate duration of the video
                    seconds = round(frames / fps)
                    video_time = datetime.timedelta(seconds=seconds)
                    print(f"duration in seconds: {seconds}")
                    print(f"video time: {video_time}")

        except Exception:
            return {"message": "There was an error uploading the file"}
        finally:
            file.file.close()
    except Exception:
        return {"message": "There was an error processing the file"}
    finally:
        os.remove(temp.name)

    count = 0;
    for vid in videofiles:
        count += 1
    print("number of video capture objects uploaded:", count)

return {"uploadStatus": "Complete", "filenames": [f.filename for f in fileList]}

这是我最后从这个代码中得到的:

我有一种感觉,这与视频捕获有关,但我以为当我从使用单个视频捕获遍历视频列表切换到为每个上传的视频创建视频捕获列表时,这个问题已经解决了。但正如您从屏幕截图中看到的,视频捕获列表只有第一个视频的一个对象。
知道是什么引起的吗

编辑:我使用这个question来上传单个视频,并基于相同的逻辑来迭代视频列表,但这也不起作用。

piv4azn7

piv4azn71#

下面是一个示例,介绍如何使用Fetch API在前端和FastAPI在后端上传视频列表,以及使用OpenCV处理文件。这个示例基于this answerthis answer

工作示例

    • 应用程序. py**
from fastapi import FastAPI, File, UploadFile, Request
from tempfile import NamedTemporaryFile
from typing import List, Optional
from fastapi.templating import Jinja2Templates
import cv2
import os

app = FastAPI()
templates = Jinja2Templates(directory='templates')

def process_video(filename):
    print('Processing ' + filename)
    cap = cv2.VideoCapture(filename)
    while cap.isOpened():
        ret, frame = cap.read()
        if not ret:
            break
        gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
        cv2.imshow('frame', gray)
        if cv2.waitKey(1) == ord('q'):
            break
    cap.release()
    cv2.destroyAllWindows()

@app.post('/submit')
def upload(files: Optional[List[UploadFile]] = File(None)):
    for file in files:
        temp = NamedTemporaryFile(delete=False)
        try:
            try:
                contents = file.file.read()
                with temp as f:
                    f.write(contents);
            except Exception:
                return {'message': 'There was an error uploading the file'}
            finally:
                file.file.close()
            
            process_video(temp.name)
        except Exception:
            return {'message': 'There was an error processing the file'}
        finally:
            #temp.close()  # the `with` statement above takes care of closing the file
            os.remove(temp.name)
        
    return {'Files Uploaded': [f.filename for f in files]}
    

@app.get('/')
def index(request: Request):
    return templates.TemplateResponse('index.html', {'request': request})

模板/索引. html

<!DOCTYPE html>
<html>
   <body>
      <input type="file" id="fileInput" name="file" multiple><br>
      <input type="button" value="Upload video files" onclick="submit()">
      <script>
         function submit() {
             var fileInput = document.getElementById('fileInput');
             if (fileInput.files[0]) {
                var formData = new FormData();
                for (const file of fileInput.files)
                    formData.append('files', file);
                    
                 fetch('/submit', {
                       method: 'POST',
                       body: formData,
                     })
                     .then(res => res.text())
                     .then(data => {
                       console.log(data);
                     })
                     .catch(error => {
                       console.error(error);
                     });
             }
         }
      </script>
   </body>
</html>

相关问题