forked from 0x2620/pandora
followup to ba5e4af355
- create keyframe index as part of creating stream
This commit is contained in:
parent
ba5e4af355
commit
8584632555
3 changed files with 40 additions and 41 deletions
|
@ -5,10 +5,39 @@ from bisect import bisect_left
|
|||
|
||||
import ox
|
||||
|
||||
def make_keyframe_index(video):
|
||||
cmd = [
|
||||
'ffprobe',
|
||||
'-v', 'error',
|
||||
'-show_packets', '-select_streams', 'v',
|
||||
'-show_entries', 'packet=pts_time,flags',
|
||||
'-of', 'csv',
|
||||
'-i', video
|
||||
]
|
||||
p = subprocess.Popen(cmd, stdout=subprocess.PIPE)
|
||||
stdout, stderr = p.communicate()
|
||||
result = stdout.decode().strip()
|
||||
keyframe_times = []
|
||||
timecode = 0
|
||||
for line in result.split('\n'):
|
||||
if line.split(',')[1] != 'N/A':
|
||||
timecode = line.split(',')[1]
|
||||
if ',K' in line:
|
||||
keyframe_times.append(float(timecode))
|
||||
|
||||
last_keyframe = ox.avinfo(video)['duration']
|
||||
if keyframe_times[-1] != last_keyframe:
|
||||
keyframe_times.append(last_keyframe)
|
||||
|
||||
keyframes_cache = video + '.keyframes'
|
||||
with open(keyframes_cache, 'w') as fd:
|
||||
json.dump(keyframe_times, fd, indent=0)
|
||||
return keyframe_times
|
||||
|
||||
|
||||
class Chop(object):
|
||||
keyframes = []
|
||||
subtitles = None
|
||||
info = {}
|
||||
ffmpeg = [
|
||||
'ffmpeg',
|
||||
'-nostats', '-loglevel', 'error',
|
||||
|
@ -77,12 +106,6 @@ class Chop(object):
|
|||
for segment in segments:
|
||||
os.unlink(segment)
|
||||
|
||||
def get_info(self):
|
||||
if self.info:
|
||||
return self.info
|
||||
self.info = ox.avinfo(self.video)
|
||||
return self.info
|
||||
|
||||
def get_keyframes(self):
|
||||
video = self.video
|
||||
if self.keyframes:
|
||||
|
@ -93,35 +116,8 @@ class Chop(object):
|
|||
with open(keyframes_cache, 'r') as fd:
|
||||
self.keyframes = json.load(fd)
|
||||
return self.keyframes
|
||||
|
||||
cmd = [
|
||||
'ffprobe',
|
||||
'-v', 'error',
|
||||
'-show_packets', '-select_streams', 'v',
|
||||
'-show_entries', 'packet=pts_time,flags',
|
||||
'-of', 'csv',
|
||||
'-i', video
|
||||
]
|
||||
p = subprocess.Popen(cmd, stdout=subprocess.PIPE)
|
||||
stdout, stderr = p.communicate()
|
||||
result = stdout.decode().strip()
|
||||
keyframe_times = []
|
||||
timecode = 0
|
||||
for line in result.split('\n'):
|
||||
if line.split(',')[1] != 'N/A':
|
||||
timecode = line.split(',')[1]
|
||||
if ',K' in line:
|
||||
keyframe_times.append(float(timecode))
|
||||
|
||||
last_keyframe = self.get_info()['duration']
|
||||
if keyframe_times[-1] != last_keyframe:
|
||||
keyframe_times.append(last_keyframe)
|
||||
|
||||
self.keyframes = keyframe_times
|
||||
if not os.path.exists(keyframes_cache):
|
||||
with open(keyframes_cache, 'w') as fd:
|
||||
json.dump(keyframe_times, fd)
|
||||
return keyframe_times
|
||||
self.keyframes = make_keyframe_index(video)
|
||||
return self.keyframes
|
||||
|
||||
def get_gop_sections(self, start: float, end: float) -> dict:
|
||||
keyframes = self.get_keyframes()
|
||||
|
@ -141,17 +137,17 @@ class Chop(object):
|
|||
}
|
||||
|
||||
def encode(self, source, target, start, duration):
|
||||
info = self.get_info()
|
||||
if self.info['audio']:
|
||||
info = ox.avinfo(self.video)
|
||||
if info['audio']:
|
||||
acodec = [
|
||||
'-c:a',
|
||||
self.info['audio'][0]['codec']
|
||||
info['audio'][0]['codec']
|
||||
]
|
||||
else:
|
||||
acodec = []
|
||||
vcodec = [
|
||||
'-c:v',
|
||||
self.info['video'][0]['codec']
|
||||
info['video'][0]['codec']
|
||||
]
|
||||
|
||||
cmd = self.ffmpeg + [
|
||||
|
|
|
@ -21,6 +21,8 @@ from ox.utils import json
|
|||
from django.conf import settings
|
||||
from PIL import Image
|
||||
|
||||
from .chop import Chop, make_keyframe_index
|
||||
|
||||
img_extension = 'jpg'
|
||||
|
||||
MAX_DISTANCE = math.sqrt(3 * pow(255, 2))
|
||||
|
@ -347,6 +349,7 @@ def stream(video, target, profile, info, audio_track=0, flags={}):
|
|||
shutil.move(enc_target, target)
|
||||
for f in glob('%s.log*' % target):
|
||||
os.unlink(f)
|
||||
make_keyframe_index(target)
|
||||
return True, None
|
||||
|
||||
|
||||
|
@ -614,7 +617,6 @@ def chop(video, start, end, subtitles=None):
|
|||
else:
|
||||
subtitles_f = None
|
||||
if ext == '.mp4':
|
||||
from .chop import Chop
|
||||
Chop(video, choped_video, start, end, subtitles_f)
|
||||
if subtitles_f:
|
||||
os.unlink(subtitles_f)
|
||||
|
|
|
@ -370,6 +370,7 @@ class File(models.Model):
|
|||
self.info.update(stream.info)
|
||||
self.parse_info()
|
||||
self.save()
|
||||
extract.make_keyframe_index(stream.media.path)
|
||||
return True, stream.media.size
|
||||
return save_chunk(stream, stream.media, chunk, offset, name, done_cb)
|
||||
return False, 0
|
||||
|
|
Loading…
Reference in a new issue