1
+ from fractions import Fraction
2
+
1
3
import av
2
4
3
5
from .output import Output
@@ -50,15 +52,26 @@ def stop(self):
50
52
except Exception :
51
53
pass
52
54
self ._container = None
55
+ self ._streams = {}
53
56
54
57
def outputframe (self , frame , keyframe = True , timestamp = None , packet = None , audio = False ):
55
58
"""Output an encoded frame using PyAv."""
56
59
if self .recording and self ._container :
57
- orig_stream = packet .stream
58
- if orig_stream not in self ._streams :
59
- raise RuntimeError ("Stream not found in PyavOutput" )
60
- # Here we replace in encoder's stream by the corresponding one for our output container.
61
- packet .stream = self ._streams [orig_stream ]
60
+ orig_stream = None
61
+ # We must make a packet that looks like it came from our own container's version of the stream.
62
+ if not packet :
63
+ # No packet present. It must have come from a video encoder that isn't using libav, so make one up.
64
+ packet = av .Packet (frame )
65
+ packet .dts = timestamp
66
+ packet .pts = timestamp
67
+ packet .time_base = Fraction (1 , 1000000 )
68
+ packet .stream = self ._streams ["video" ]
69
+ else :
70
+ # We can perform a switcheroo on the packet's stream, swapping the encoder's version for ours!
71
+ orig_stream = packet .stream
72
+ if orig_stream not in self ._streams :
73
+ raise RuntimeError ("Stream not found in PyavOutput" )
74
+ packet .stream = self ._streams [orig_stream ]
62
75
63
76
try :
64
77
self ._container .mux (packet )
@@ -74,4 +87,5 @@ def outputframe(self, frame, keyframe=True, timestamp=None, packet=None, audio=F
74
87
# Put the original stream back, just in case the encoder has multiple outputs and will pass
75
88
# it to each one.
76
89
packet .stream = orig_stream
90
+
77
91
self .outputtimestamp (timestamp )
0 commit comments