Example #1
0
def handle_playlist_update(src_path: str):
    rtmp_playlist_path = os.path.abspath(src_path)
    basedir: str = os.path.dirname(rtmp_playlist_path)
    try:
        stream_obj: Stream = Stream.objects.get(pk=os.path.basename(basedir))
    except ValueError as err:
        capture_exception(err)
        logging.error("Stream id is not valid UUID")
        return
    tracker_urls = [
        tracker.url
        for tracker in Tracker.objects.filter(is_active=True).all()
    ]
    with open(rtmp_playlist_path) as f:
        chunk_filenames = re.findall(CHUNK_FILENAME_PATTERN, f.read(),
                                     re.MULTILINE)
        print(chunk_filenames)
        if not chunk_filenames:
            return
        chunk_filename = chunk_filenames[-1]
        start_time = time.time()
        chunk_number: int = int(chunk_filename.rstrip(".ts"))
        if not Chunk.objects.filter(stream=stream_obj,
                                    number=chunk_number).exists():
            try:
                with transaction.atomic():
                    if stream_obj.viewers and stream_obj.viewers < config.TARGET_SEED_USERS:
                        cloud_url_prob = stream_obj.viewers / config.TARGET_SEED_USERS
                    else:
                        cloud_url_prob = Decimal(
                            config.USE_CLOUD_PROB /
                            100) if config.USE_CLOUD_PROB else 0
                    chunk_path = os.path.join(basedir, chunk_filename)
                    secret_filename = f"{chunk_number}_{random_string()}.ts"
                    new_chunk: Chunk = \
                        Chunk.objects.create(stream=stream_obj, number=chunk_number, filename=secret_filename, prob=cloud_url_prob)
                    t = Torrent(path=chunk_path,
                                trackers=tracker_urls,
                                webseeds=[
                                    new_chunk.file_url,
                                ],
                                piece_size=2**20)
                    t.generate()
                    new_chunk.magnet_link = t.magnet()
                    with io.BytesIO() as torrent_file:
                        t.write_stream(torrent_file)
                        gs_client.upload_file(
                            torrent_file,
                            gs_torrent_path(stream_obj.id, new_chunk.number))
                    with VideoFileClip(chunk_path) as chunk_clip:
                        new_chunk.duration = Decimal(chunk_clip.duration)
                        if new_chunk.number % UPDATE_THUMBNAIL_EVERY == 0:
                            thumbnail_path = f"/tmp/thumbnails/{stream_obj.id}.jpg"
                            time_mark = chunk_clip.duration * 0.05
                            chunk_clip.save_frame(thumbnail_path, t=time_mark)
                            gs_client.upload_file(
                                thumbnail_path,
                                gs_thumbnail_path(stream_obj.id))
                    gs_client.upload_file(chunk_path,
                                          gs_chunk_path(
                                              stream_obj.id,
                                              new_chunk.filename),
                                          content_type="video/MP2T")
                    new_chunk.is_public = True
                    new_chunk.save()
                    stream_obj.update_playlist()
                    logging.info(
                        f"new chunk: {str(stream_obj.id)[0:5]}/{chunk_number} in {round(time.time() - start_time, 2)}s"
                    )
            except Exception as err:
                capture_exception(err)
                logging.error(err)
Example #2
0
 def make_public(self):
     gs_client.make_public(gs_chunk_path(self.stream_id, self.filename))
     self.is_public = True
     self.save()
Example #3
0
 def file_url(self) -> str:
     return os.path.join(gs_client.root_path,
                         gs_chunk_path(self.stream_id, self.filename))
Example #4
0
 def make_private(self):
     gs_client.make_private(gs_chunk_path(self.stream_id, self.filename))
     self.is_public = False
     self.save()
Example #5
0
 def delete(self, *args, **kwargs):
     gs_client.delete_file(gs_chunk_path(self.stream_id, self.filename))
     super().delete(*args, **kwargs)