def test_producer_timestamp_live(stream, total): source = AVSource.create(url(stream)) assert type(source) is kinesis.KVSource assert source.stream == stream session = source.open(start=time(), decoding=False, fps=30, threshold=10) #session = source.open(start=time(), decoding=False, fps=15, timestamp='SERVER') assert session is not None assert 'video' in session assert 'audio' not in session logging.info(session) for i in range(total): m, media, frame = source.read(session) assert m == 'video' assert media == session[m] if hasattr(frame, 'shape'): assert media['height'] == frame.shape[0] assert media['width'] == frame.shape[1] assert 3 == frame.shape[2] logging.info( f"[{i}] {tuple(frame.shape)} duration={media['duration']:.3f}s, time={media['time']:.3f}s, now={time():.3f}s" ) else: logging.info( f"[{i}] duration={media['duration']:.3f}s, time={media['time']:.3f}s, now={time():.3f}s" ) source.close(session) assert not session
def test_multi_sessions(credentials, FPS): ip = credentials['ip'] port = credentials['port'] user = credentials['username'] passwd = credentials['passwd'] source = AVSource.create(url(ip, port), user=user, passwd=passwd) sessions = source.open('fisheye', 'Original', decoding=True, with_audio=False) logging.info(f"{[session['cam']['area'] for session in sessions]}") assert len(sessions) == 3 areas = set() for session in sessions: area = session['cam']['area'] if 'video' in session: video = session['video'] if video['fps'] is None: video['fps'] = area in FPS and FPS[area] or 15 frame = source.read(session) areas.add(area) source.close(session) assert frame is not None, f"Failed to read frame from '{session['cam']['area']}'" assert not session assert len( areas ) == 3, f"Three distinc areas are expected but only got {len(areas)}: {areas}"
def test_youtube_live(url): source = AVSource.create(url) assert type(source) is youtube.YTSource assert source.url == url session = source.open(mode='LIVE', decoding=False) assert session is not None assert 'video' in session logging.info(session) for i in range(100): m, meta, frame = source.read(session, media='video') assert meta == session['video'] assert frame is not None pts = float(frame.pts * frame.time_base) duration = float(frame.duration * frame.time_base) logging.info( f"frame[{meta['count']}] fpts={pts:.3f}s, fduration={duration:.3f}s, duration={meta['duration']:.3f}s, time={meta['time']:.3f}s, now={time():.3f}s" ) #assert media['height'] == frame.shape[0] #assert media['width'] == frame.shape[1] #assert 3 == frame.shape[2] if 'audio' in session: for i in range(5): m, meta, frame = source.read(session, media='audio') media = session['audio'] logging.info(f"[{i}] {media}") assert frame is not None assert media == meta assert media['sample_rate'] == 48000 assert media['channels'] == 2 # assert 1024 == frame.shape[1] source.close(session) assert not session
def avsrc_dump(src, count=60, last=None, **kwargs): from ml.streaming import AVSource print() print(f'========== AVSource: {src} ============') src = AVSource.create(src) session = src.open(decoding=False, **kwargs) pkts = [(src.read(session)[-1], session['video']['keyframe'], session['video']['duration']) for _ in range(count)][last:] print('key:', [key for _, key, _ in pkts]) print('corrupt:', [pkt.is_corrupt for pkt, _, _ in pkts]) print('pkt.dts:', [pkt.dts for pkt, _, _ in pkts]) print('pkt.pts:', [pkt.pts for pkt, _, _ in pkts]) print('pkt.duration:', [pkt.duration for pkt, _, _ in pkts]) print('frm.duration:', [duration for _, _, duration in pkts]) print('pkt.size:', [pkt.size for pkt, _, _ in pkts]) src.close(session) return pkts
def __init__(self, ip=None, port=None, user='******', passwd='admin', accessKey=None, secretKey=None): # AWS/KVS credentials given or from ENV super(NUUOProducerTest, self).__init__(accessKey, secretKey) # NUUO credentials given or from ENV NUUO_IP = ip or os.getenv('NUUO_IP', None) NUUO_PORT = port or os.getenv('NUUO_PORT', None) NUUO_USER = user or os.getenv('NUUO_USER', None) NUUO_PASSWD = passwd or os.getenv('NUUO_PASSWD', None) self.nuuo = AVSource.create(f"nuuo://{NUUO_IP}:{NUUO_PORT}", user=NUUO_USER, passwd=NUUO_PASSWD)
def test_single_session(ip, port, user, passwd, areas, FPS): area = areas[1] fps = FPS[area] decoding = not True source = AVSource.create(url(ip, port), user=user, passwd=passwd) sessions = source.open(area, 'Original', fps=fps, decoding=decoding, exact=True, with_audio=True) assert len(sessions) == 1 session = sessions[0] video = session['video'] logging.info(f"Session: \n{session}") total = 300 X = sys.x_available() for i in range(total): res = source.read(session, media=None) if res is None: logging.warning(f"Skipped invalid frame") continue m, media, frame = res if decoding: duration = float( media['duration'] * media['timbe_base'] ) if m == 'video' else frame.size / 2 / media['sample_rate'] logging.info( f"{m}[{media['count']}]: {frame.shape} of {frame.dtype} with duraton {duration:.3f}s at {media['time']:.3f}s, now={time():.3f}s" ) else: duration = float( media['duration'] * media['time_base'] ) if m == 'video' else frame.size / media['sample_rate'] logging.info( f"{m}[{media['count']}]: {media['keyframe'] and 'key ' or ''}({frame.size} bytes) with duration {duration:.3f}s at {media['time']:.3f}s, now={time():.3f}s" ) logging.info(f"{m}/{video['format']} stream FPS={video['fps_rt']:.2f}") source.close(session) assert not session
def test_youtube_live_av(url): source = AVSource.create(url) assert type(source) is youtube.YTSource assert source.url == url hls = youtube.yt_hls_url(url) options = dict( rtsp_transport='http', # required for VPN rtsp_flags='prefer_tcp', stimeout='2000000') # in case of network down logging.info(f"av.open({hls}, {options})") s = av.open(hls, options=options, timeout=5.0 * 2) v = s.demux(video=0) for i in range(100): f = next(v) pts = float(f.pts * f.time_base) duration = float(f.duration * f.time_base) logging.info( f"frame[{i}] time={pts:.3f}s, duration={duration:.3f}s, now={time():.3f}s" )
def test_video_h264_time(video_mp4): src = AVSource.create(video_mp4) frames = src.open() packets = src.open(decoding=False) names = ('frames', 'packets') sessions = (frames, packets) stats = {'frames': [], 'packets': []} for name, session in zip(names, sessions): start = session['start'] video = session['video'] elapse = 0 time_all = [] duration_all = [] elapse_all = [] for i in range(5): elapse += video.get('duration') or 0 res = src.read(session, media='video') if res is None: break time = video['time'] duration = video['duration'] time_all.append(time) duration_all.append(duration) elapse_all.append(elapse) assert duration > 0 if i == 0: assert time == start assert elapse == 0 else: import math assert math.isclose( time - start, elapse, rel_tol=1e-5), f"{time - start} != {elapse}" print() print('duration:', duration_all) print('elapse:', elapse_all) print('time:', time_all) print(f"start={start}")
def test_single_session(credentials, areas, FPS): ip = credentials['ip'] port = credentials['port'] user = credentials['username'] passwd = credentials['passwd'] area = areas[2] fps = FPS[area] decoding = True source = AVSource.create(url(ip, port), user=user, passwd=passwd) sessions = source.open(area, 'Original', fps=fps, decoding=decoding, exact=True, with_audio=True) assert len(sessions) == 1 session = sessions[0] video = session['video'] logging.info(f"Session: \n{session}") total = 30 X = sys.x_available() for i in range(total): res = source.read(session, media=None) assert res is not None m, media, frame = res if decoding: # NUUO H.264 contains no pts info logging.info( f"{m}[{media['count']}]: {frame.shape} of {frame.dtype} at {media['time']:.3f}s" ) else: logging.info( f"{m}[{media['count']}]: {media['keyframe'] and 'key ' or ''}({frame.size} bytes) at {media['time']:.3f}s" ) logging.info(f"{m}/{media['format']} stream FPS={video['fps_rt']:.2f}") source.close(session) assert not session
def test_multi_sessions(ip, port, user, passwd, areas, FPS): source = AVSource.create(url(ip, port), user=user, passwd=passwd) sessions = source.open('Ent', 'Original', decoding=True, with_audio=False) logging.info( f"sessions for {[session['cam']['area'] for session in sessions]}") assert len(sessions) == 2 areas = set() for session in sessions: area = session['cam']['area'] if 'video' in session: video = session['video'] if video['fps'] is None: video['fps'] = area in FPS and FPS[area] or 30 frame = source.read(session) areas.add(session['cam']['area']) source.close(session) assert frame is not None, f"Failed to read frame from '{session['cam']['area']}'" assert not session assert len( areas ) == 2, f"Two distinc areas are expected but only got {len(areas)}: {areas}"
def test_webcam(src=0): source = AVSource.create(0) assert type(source) is AVSource assert source.src == src # open(self, start=None, end=None, expires=5 * 60, mode='LIVE', offset=4.75): session = source.open(fps=15, resolution='720p', decoding=True) assert session is not None assert 'video' in session assert 'audio' not in session logging.info(session) total = 5 X = sys.x_available() while True: res = source.read(session, media='video') assert res m, media, frame = res count = media['count'] if m == 'video': logging.info( f"[{count}] Decoded video frame{frame.shape}@{media['fps']:.2f}FPS" ) elif m == 'audio': logging.info( f"[{count}] Decoded audio frame{frame.shape}@{media['fps']:.2f}FPS" ) else: assert False, f"Unknown media {m}" if X: cv.imshow(frame, title='LIVE') cv.waitKey(1) if count == total: break