Skip to content

Commit e67caf1

Browse files
committed
give more info to callback function
1 parent 5748265 commit e67caf1

File tree

2 files changed

+28
-18
lines changed

2 files changed

+28
-18
lines changed

video_to_sqlite/callback.py

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,28 +3,32 @@
33
from video_to_sqlite import cli
44

55

6-
def process(frame):
6+
def process(frame, metadata):
77
"""
88
An example of using a callback to add custom columns to a video-to-sqlite db.
99
Add the highest, lowest, and mean value of the frame to the row.
1010
1111
:param frame: a numpy ndarray of the video frame
12+
:param metadata: a dict containing metadata for the frame
1213
:return: a dict, where keys will be column names and values the cell contents in the db
1314
"""
14-
maximum = frame.max()
15-
minimum = frame.min()
16-
mean = frame.mean()
15+
if metadata['pict_type'] == 'I': # a keyframe
16+
maximum = int(frame.max())
17+
minimum = int(frame.min())
18+
mean = int(frame.mean())
1719

18-
return {
19-
'max': maximum,
20-
'min': minimum,
21-
'mean': mean,
22-
}
20+
return {
21+
'max': maximum,
22+
'min': minimum,
23+
'mean': mean,
24+
}
25+
else:
26+
return {} # ignore non-keyframes
2327

2428

2529
if __name__ == '__main__':
2630
"""
2731
Usage: python callback.py <db file> <video file>
2832
Call `cli.main()` with the database file, video file, prefix, and callback function
2933
"""
30-
cli.main(sys.argv[1], sys.argv[2], callback=process)
34+
cli.main(sys.argv[1], sys.argv[2], prefix='', callback=process)

video_to_sqlite/cli.py

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import os
2+
13
import click
24
import imageio.v3 as iio
35
import re
@@ -46,12 +48,12 @@ def main(db_path, video_filename, prefix, callback=None):
4648
4749
By default, the `frames` table contains metadata about each frame.
4850
To include additional columns, supply a function in the `callback`
49-
agrument.
51+
argument.
5052
5153
`callback` is an optional argument for running additional
5254
processing on each frame of the video.
53-
If supplied, the function should accept a numpy ndarray of the frame as
54-
the single argument, and return a dict.
55+
If supplied, the function should accept a numpy ndarray of the frame,
56+
and a dict containing metadata for the given frame, and return a dict.
5557
Keys in the returned dict will become columns in the database, and values
5658
will be that column's value for the frame.
5759
@@ -96,12 +98,13 @@ def parse_video(video_filename, callback=None):
9698
if frame['pkt_dts'] == 'N/A':
9799
continue # last frame doesn't get displayed or something?
98100

99-
frame['filename'] = video_filename
101+
frame['filename'] = os.path.basename(video_filename)
100102
processed_frames.append(frame)
101103

102104
if callback:
103-
for frame, frame_metadata in zip(iio.imiter(video_filename), processed_frames):
104-
frame_metadata.update(callback(frame))
105+
for i, (frame, frame_metadata) in enumerate(zip(iio.imiter(video_filename), processed_frames)):
106+
frame_metadata['frame_no'] = i
107+
frame_metadata.update(callback(frame, frame_metadata))
105108

106109
return metadata, processed_frames
107110

@@ -121,14 +124,17 @@ def save_to_db(db, video_filename, metadata, frames, prefix):
121124
data,
122125
pk='filename',
123126
replace=True,
127+
alter=True,
124128
)
125129

126130
frame_tracker = TypeTracker()
127131
db[f'{prefix}frames'].insert_all(
128-
frame_tracker.wrap([dict(frame, **{'frame_no': i}) for i, frame in enumerate(frames)]),
132+
frame_tracker.wrap(frames),
129133
pk=('frame_no', 'filename'),
130134
foreign_keys=[
131135
('filename', f'{prefix}videos', 'filename'),
132136
],
133-
replace=True)
137+
replace=True,
138+
alter=True,
139+
)
134140
db[f'{prefix}frames'].transform(types=frame_tracker.types)

0 commit comments

Comments
 (0)