经过反复试验,我有了一个可行的解决方案。虽然这可能并不适合所有人,但它可能会帮助一些人,所以这里是:
我首先创建了一个从视频中提取帧的脚本,该脚本必须存在于所有工作节点上:
#!/home/hadoop/anaconda2/bin/python
import os
import sys
import subprocess as sp
import numpy as np
import cv2
import copy
# RDD.pipe sends via stdin
i = 0
try:
i = input()
except:
sys.exit()
file_name = 'v.mp4'
FFMPEG_BIN = "ffmpeg" # on Linux ans Mac OS
command = [ FFMPEG_BIN,
'-i', '/home/hadoop/' + file_name,
'-f', 'image2pipe',
'-vf', 'select=gte(n\, %d)' % i,
'-vframes', '1',
'-pix_fmt', 'rgb24',
'-loglevel', 'panic',
'-vcodec', 'png', '-']
pipe = sp.Popen(command, stdout=sp.PIPE, bufsize=10**8)
data = pipe.stdout.read()
pipe.stdout.close()
import base64
print(base64.b64encode(data))
然后,在 pyspark 脚本中,我创建一个带有脚本参数的 RDD:
params = [str(i) for i in range(1, 1001)]
rdd1 = sc.parallelize(params, numSlices=1000)
pipeRDD = rdd1.pipe('/home/hadoop/src/extract_frame.sh')
resizedRDD = pipeRDD.map(resizeMapper)
test = resizedRDD.collect()
测试现在有前 1000 帧。 resize mapper 调整每一帧的大小,这里是:
def resizeMapper(x):
import base64
import cv2
a = base64.b64decode(x)
im = cv2.imdecode(np.fromstring(a, dtype=np.uint8), 1)
im = cv2.resize(im, (200, 200))
return im
我希望这对那里的人有所帮助。