#opencv #google-cloud-functions #google-cloud-storage
# #opencv #google-cloud-функции #google-облачное хранилище
Вопрос:
Отправная точка:
В папке (/1_original_videos) в корзине с именем myBucket в облачном хранилище Google есть видео с именем MyVideo.mp4.
myBucket
-->/1_original_video
-->myVideo.mp4
Цель:
Цель состоит в том, чтобы взять это видео, разделить его на фрагменты в облачной функции myCloudFunction и сохранить фрагменты во вложенной папке с именем chunks в myBucket. Часть разделения на куски не является проблемой. Проблема заключается в чтении видео.
Mycloudфункция должна запускаться с помощью HTTP-триггера.
_______________
myVideo.mp4 ---->|myCloudFunction|----> chunk0.mp4, chunk1.mp4, chunk2.mp4, ... , chunkN-1.mp4
‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾
^
|
|
|
HTTP trigger
Если бы видео было на моем локальном компьютере, для его чтения было бы достаточно следующего:
import cv2
cap = cv2.VideoCapture("/some/path/in/my/local/computer/myVideo.mp4")
Попытки:
Путь с аутентифицированным URL:
import cv2
cap = cv2.VideoCapture("https://storage.cloud.google.com/myBucket/1_original_videos/myVideo.mp4")
При тестировании этого подхода это результирующее сообщение (см. Полный код ниже):
"File Cannot be Opened"
Полный код:
import cv2
def video2chunks(request):
# Request:
REQUEST_JSON = request.get_json()
#If the HTTP contains a key called "start" (e.g. "{"start":"whatever"}"):
if REQUEST_JSON and 'start' in REQUEST_JSON:
try:
# Create VideoCapture object:
cap = cv2.VideoCapture("https://storage.cloud.google.com/myBucket/1_original_videos/myVideo.mp4")
# If no VideoCapture object is created:
if not cap.isOpened():
message = "File Cannot be Opened"
# If a Videocapture object is created, compute some of the video parameters:
else:
fps = int(cap.get(cv2.CAP_PROP_FPS))
size = (int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)),int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)))
fourcc = int(cv2.VideoWriter_fourcc('X','V','I','D')) # XVID codecs
message = "Video downloaded successfully. Some params are: "
message = "FPS= " str(fps) " | size= " str(size)
except Exception as e:
message = str(e)
else:
message = "You did not provide a key called start "
return message
Я пытался найти примеры или лучший способ сделать это в облачной функции, но пока безуспешно. Любые альтернативы также будут высоко оценены.
Комментарии:
1. выясните, как получить этот файл «локально». если вы заставляете OpenCV извлекать файл из http URL, OpenCV нуждается в gstreamer или ffmpeg. извлеките файл, сохраните его локально.
Ответ №1:
Я не знаю, поддерживает ли библиотека cv2 каким-либо образом чтение непосредственно из облачного хранилища. Тем не менее, как указывает Кристоф, вы можете загрузить файл, обработать его и загрузить результаты. Код будет по существу таким же, как и при локальном запуске.
Следует отметить, что облачные функции предлагают временный каталог, который я выбрал для хранения изображения. Однако важно знать, что любой файл, хранящийся там, фактически занимает часть вашей оперативной памяти, поэтому размер выделенной функциональной памяти должен быть соответствующим. Также вы можете заметить, что временные файлы удаляются перед выходом из функции, это просто лучшая практика в облачных функциях.
import cv2
import os
from google.cloud import storage
def myfunc(request):
# Substitute the variables below for whatever suits your needs
# BUCKET_ID :: The bucket ID
# INPUT_IMAGE_GCS :: Path to GCS object
# OUTPUT_IMAGE_PATH :: Path to save the resulting image/video
# Read video and save to /tmp directory
bucket = storage.Client().bucket(BUCKET_ID)
blob = bucket.blob(INPUT_IMAGE_GCS)
blob.download_to_filename('/tmp/video.mp4')
# Video processing stuff
vidcap = cv2.VideoCapture('/tmp/video.mp4')
success, image = vidcap.read()
cv2.imwrite("/tmp/frame.jpg", image)
# Save results to GCS
img_blob = bucket.blob('potato/frame.jpg')
img_blob.upload_from_filename(OUTPUT_IMAGE_PATH)
# Delete tmp resources to free memory
os.remove('/tmp/video.mp4')
os.remove('/tmp/frame.jpg')
return '', 200