@@ -129,8 +129,8 @@ func ProbeVideo(ctx context.Context, ffprobeBinary string, inputFilePath string)
129
129
"-v" , "error" , // Hide debug information
130
130
131
131
// video
132
- " -skip_frame" , " nokey" ,
133
- "-show_entries" , "frame=pkt_pts_time" , // List all I frames
132
+ // we could use -skip_frame nokey, but it's extremely slow because it decodes the whole video
133
+ "-show_entries" , "packet=pts_time,flags" ,
134
134
"-show_entries" , "format=duration" ,
135
135
"-show_entries" , "stream=duration,width,height" ,
136
136
"-select_streams" , "v" , // Video stream only, we're not interested in audio
@@ -154,9 +154,10 @@ func ProbeVideo(ctx context.Context, ffprobeBinary string, inputFilePath string)
154
154
}
155
155
156
156
out := struct {
157
- Frames []struct {
158
- PktPtsTime string `json:"pkt_pts_time"`
159
- } `json:"frames"`
157
+ Packets []struct {
158
+ PtsTime string `json:"pts_time"`
159
+ Flags string `json:"flags"`
160
+ } `json:"packets"`
160
161
Streams []struct {
161
162
Width int `json:"width"`
162
163
Height int `json:"height"`
@@ -191,17 +192,23 @@ func ProbeVideo(ctx context.Context, ffprobeBinary string, inputFilePath string)
191
192
Duration : duration ,
192
193
}
193
194
194
- for _ , frame := range out .Frames {
195
- if frame .PktPtsTime == "" {
195
+ for _ , packet := range out .Packets {
196
+ // Skip packets without PtsTime.
197
+ if packet .PtsTime == "" || packet .PtsTime == "N/A" {
196
198
continue
197
199
}
198
200
199
- pktPtsTime , err := strconv .ParseFloat (frame .PktPtsTime , 64 )
201
+ // We're only interested in key frames.
202
+ if len (packet .Flags ) > 0 && packet .Flags [0 ] != 'K' {
203
+ continue
204
+ }
205
+
206
+ ptsTime , err := strconv .ParseFloat (packet .PtsTime , 64 )
200
207
if err != nil {
201
208
return nil , err
202
209
}
203
210
204
- data .PktPtsTime = append (data .PktPtsTime , pktPtsTime )
211
+ data .PktPtsTime = append (data .PktPtsTime , ptsTime )
205
212
}
206
213
207
214
return & data , nil
0 commit comments