def process_text(access_token, user_id, sticker_number, sticker_type, title,
                 urls, output_message_id):

    bot = telegram.Bot(token=access_token)

    sticker_name = get_sticker_name_from_sticker_number(
        bot, sticker_type, sticker_number)

    has_uploaded_first_sticker = False

    backup_count = 0
    new_sticker_name = sticker_name[:]
    is_valid_sticker_number = False
    while not is_valid_sticker_number:

        print(new_sticker_name)

        # check if there has been a sticker set
        sticker_set = get_sticker_set(bot, new_sticker_name)

        # three conditions:
        # 1. no sticker set -> upload stickers
        # 2. exist sticker set, and sticker set finished uploading -> return finished sticker set
        # 3. exist sticker set, but sticker set didn't finish uploading -> delete old sticker set and upload stickers
        if sticker_set != None:
            # condition 2
            if len(sticker_set.stickers) == len(urls):
                bot.edit_message_text(
                    chat_id=user_id,
                    message_id=output_message_id,
                    text=(f"總算找到了\n"
                          f"This one?!\n\n"
                          f"Line sticker number:{sticker_number}"))

                bot.send_sticker(
                    chat_id=user_id,
                    sticker=sticker_set.stickers[0].file_id,
                    reply_markup=InlineKeyboardMarkup([[
                        InlineKeyboardButton(
                            text=title,
                            url=f"https://t.me/addstickers/{new_sticker_name}")
                    ]]))
                return
            # condition 3
            else:
                delete_sticker_set(bot, sticker_set)

        # upload
        upload_static_text = (
            f"{title}\n"
            f"發現{len(urls)}張貼圖,轉換需要一段時間,完成時會再通知\n\n"
            f"Found {len(urls)} stickers. You will be notified when finishing converting\n"
        )

        # first image for creating a sticker set
        if not has_uploaded_first_sticker:
            sticker_file = get_sticker_from_url(sticker_type, urls[0])

            if sticker_type != "animated":
                sticker_file.save(f"{sticker_number}.png")
                sticker0 = bot.upload_sticker_file(user_id=user_id,
                                                   png_sticker=open(
                                                       f"{sticker_number}.png",
                                                       'rb')).file_id
            else:
                ffmpeg_write_video(sticker_file,
                                   filename=f"{sticker_number}.webm",
                                   fps=30,
                                   codec="libvpx-vp9",
                                   bitrate=None,
                                   preset="medium",
                                   with_mask=True,
                                   write_logfile=False,
                                   audiofile=None,
                                   threads=None,
                                   ffmpeg_params=[],
                                   pixel_format=None)
                sticker0 = f"{sticker_number}.webm"

            has_uploaded_first_sticker = True

        # create a sticker set
        is_potential_valid_sticker_name = False

        while not is_potential_valid_sticker_name:

            try:
                if sticker_type != "animated":
                    bot.create_new_sticker_set(
                        user_id=user_id,
                        name=new_sticker_name,
                        title=f"{title} @RekcitsEnilbot",
                        png_sticker=sticker0,
                        emojis=get_random_emoji())
                else:
                    bot.create_new_sticker_set(
                        user_id=user_id,
                        name=new_sticker_name,
                        title=f"{title} @RekcitsEnilbot",
                        webm_sticker=open(sticker0, 'rb'),
                        emojis=get_random_emoji())
                is_potential_valid_sticker_name = True
                is_valid_sticker_number = True

                upload_text = f"{upload_static_text}{'*' * 1}{'_' * (len(urls) - 1)}{1}/{len(urls)}"
                bot.edit_message_text(chat_id=user_id,
                                      message_id=output_message_id,
                                      text=upload_text)

            except BadRequest as e:

                if str(e) == "Shortname_occupy_failed" or str(
                        e) == "Sticker set name is already occupied":
                    # A special error that I don't know what cause it.
                    # Telegram say that this is an internal error.....
                    new_sticker_name = f"backup_{backup_count}_{sticker_name}"
                    backup_count = backup_count + 1
                    is_potential_valid_sticker_name = True
                else:
                    print("??????")
                    print(
                        'Error on line {}'.format(
                            sys.exc_info()[-1].tb_lineno),
                        type(e).__name__, e)
                    print(e)
                    return

    sticker_name = new_sticker_name[:]

    # the left images to be uploaded
    for idx, url in enumerate(urls[1:]):
        sticker_file = get_sticker_from_url(sticker_type, url)

        if sticker_type != "animated":
            sticker_file.save(f"{sticker_number}.png")
        else:
            ffmpeg_write_video(sticker_file,
                               filename=f"{sticker_number}.webm",
                               fps=30,
                               codec="libvpx-vp9",
                               bitrate=None,
                               preset="medium",
                               with_mask=True,
                               write_logfile=False,
                               audiofile=None,
                               threads=None,
                               ffmpeg_params=[],
                               pixel_format=None)

        if sticker_type != "animated":
            try:
                sticker = bot.upload_sticker_file(user_id=user_id,
                                                  png_sticker=open(
                                                      f"{sticker_number}.png",
                                                      'rb')).file_id
            except Exception as e:
                w, h = sticker_image.size
                print('Error on line {}'.format(sys.exc_info()[-1].tb_lineno),
                      type(e).__name__, e)
                print(w, h)
                print(url)
                print(e)
                return

            bot.add_sticker_to_set(user_id=user_id,
                                   name=sticker_name,
                                   png_sticker=sticker,
                                   emojis=get_random_emoji())
        else:
            bot.add_sticker_to_set(user_id=user_id,
                                   name=sticker_name,
                                   webm_sticker=open(f"{sticker_number}.webm",
                                                     'rb'),
                                   emojis=get_random_emoji())

        upload_text = f"{upload_static_text}{'*' * (idx + 2)}{'_' * (len(urls) - (idx + 2))}{idx + 2}/{len(urls)}"
        bot.edit_message_text(chat_id=user_id,
                              message_id=output_message_id,
                              text=upload_text)

    # delete temporary file
    if sticker_type != "animated":
        os.remove(f"{sticker_number}.png")
    else:
        os.remove(f"{sticker_number}.webm")
        os.remove(f"temp.png")
        os.remove(f"temp.gif")

    # finish uploading
    bot.send_message(chat_id=user_id,
                     text=(f"噠啦~☆\n\n"
                           f"Finished!\n\n"
                           f"Line sticker number:{sticker_number}\n"
                           f"https://t.me/addstickers/{sticker_name}"))

    # send the first sticker of sticker set
    sticker_set = get_sticker_set(bot, sticker_name)
    bot.send_sticker(chat_id=user_id,
                     sticker=sticker_set.stickers[0].file_id,
                     reply_markup=InlineKeyboardMarkup([[
                         InlineKeyboardButton(
                             text=title,
                             url=f"https://t.me/addstickers/{sticker_name}")
                     ]]))

    return
Ejemplo n.º 2
0
    def write_videofile(
        self,
        filename,
        fps=None,
        codec=None,
        bitrate=None,
        audio=True,
        audio_fps=44100,
        preset="medium",
        audio_nbytes=4,
        audio_codec=None,
        audio_bitrate=None,
        audio_bufsize=2000,
        temp_audiofile=None,
        temp_audiofile_path="",
        remove_temp=True,
        write_logfile=False,
        threads=None,
        ffmpeg_params=None,
        logger="bar",
        pixel_format=None,
    ):
        """Write the clip to a videofile.

        Parameters
        ----------

        filename
          Name of the video file to write in, as a string or a path-like object.
          The extension must correspond to the "codec" used (see below),
          or simply be '.avi' (which will work with any codec).

        fps
          Number of frames per second in the resulting video file. If None is
          provided, and the clip has an fps attribute, this fps will be used.

        codec
          Codec to use for image encoding. Can be any codec supported
          by ffmpeg. If the filename is has extension '.mp4', '.ogv', '.webm',
          the codec will be set accordingly, but you can still set it if you
          don't like the default. For other extensions, the output filename
          must be set accordingly.

          Some examples of codecs are:

          - ``'libx264'`` (default codec for file extension ``.mp4``)
            makes well-compressed videos (quality tunable using 'bitrate').
          - ``'mpeg4'`` (other codec for extension ``.mp4``) can be an alternative
            to ``'libx264'``, and produces higher quality videos by default.
          - ``'rawvideo'`` (use file extension ``.avi``) will produce
            a video of perfect quality, of possibly very huge size.
          - ``png`` (use file extension ``.avi``) will produce a video
            of perfect quality, of smaller size than with ``rawvideo``.
          - ``'libvorbis'`` (use file extension ``.ogv``) is a nice video
            format, which is completely free/ open source. However not
            everyone has the codecs installed by default on their machine.
          - ``'libvpx'`` (use file extension ``.webm``) is tiny a video
            format well indicated for web videos (with HTML5). Open source.

        audio
          Either ``True``, ``False``, or a file name.
          If ``True`` and the clip has an audio clip attached, this
          audio clip will be incorporated as a soundtrack in the movie.
          If ``audio`` is the name of an audio file, this audio file
          will be incorporated as a soundtrack in the movie.

        audio_fps
          frame rate to use when generating the sound.

        temp_audiofile
          the name of the temporary audiofile, as a string or path-like object,
          to be created and then used to write the complete video, if any.

        temp_audiofile_path
          the location that the temporary audiofile is placed, as a
          string or path-like object. Defaults to the current working directory.

        audio_codec
          Which audio codec should be used. Examples are 'libmp3lame'
          for '.mp3', 'libvorbis' for 'ogg', 'libfdk_aac':'m4a',
          'pcm_s16le' for 16-bit wav and 'pcm_s32le' for 32-bit wav.
          Default is 'libmp3lame', unless the video extension is 'ogv'
          or 'webm', at which case the default is 'libvorbis'.

        audio_bitrate
          Audio bitrate, given as a string like '50k', '500k', '3000k'.
          Will determine the size/quality of audio in the output file.
          Note that it mainly an indicative goal, the bitrate won't
          necessarily be the this in the final file.

        preset
          Sets the time that FFMPEG will spend optimizing the compression.
          Choices are: ultrafast, superfast, veryfast, faster, fast, medium,
          slow, slower, veryslow, placebo. Note that this does not impact
          the quality of the video, only the size of the video file. So
          choose ultrafast when you are in a hurry and file size does not
          matter.

        threads
          Number of threads to use for ffmpeg. Can speed up the writing of
          the video on multicore computers.

        ffmpeg_params
          Any additional ffmpeg parameters you would like to pass, as a list
          of terms, like ['-option1', 'value1', '-option2', 'value2'].

        write_logfile
          If true, will write log files for the audio and the video.
          These will be files ending with '.log' with the name of the
          output file in them.

        logger
          Either ``"bar"`` for progress bar or ``None`` or any Proglog logger.

        pixel_format
          Pixel format for the output video file.

        Examples
        --------

        >>> from moviepy import VideoFileClip
        >>> clip = VideoFileClip("myvideo.mp4").subclip(100,120)
        >>> clip.write_videofile("my_new_video.mp4")
        >>> clip.close()

        """
        name, ext = os.path.splitext(os.path.basename(filename))
        ext = ext[1:].lower()
        logger = proglog.default_bar_logger(logger)

        if codec is None:

            try:
                codec = extensions_dict[ext]["codec"][0]
            except KeyError:
                raise ValueError("MoviePy couldn't find the codec associated "
                                 "with the filename. Provide the 'codec' "
                                 "parameter in write_videofile.")

        if audio_codec is None:
            if ext in ["ogv", "webm"]:
                audio_codec = "libvorbis"
            else:
                audio_codec = "libmp3lame"
        elif audio_codec == "raw16":
            audio_codec = "pcm_s16le"
        elif audio_codec == "raw32":
            audio_codec = "pcm_s32le"

        audiofile = audio if isinstance(audio, str) else None
        make_audio = ((audiofile is None) and (audio is True)
                      and (self.audio is not None))

        if make_audio and temp_audiofile:
            # The audio will be the clip's audio
            audiofile = temp_audiofile
        elif make_audio:
            audio_ext = find_extension(audio_codec)
            audiofile = os.path.join(
                temp_audiofile_path,
                name + Clip._TEMP_FILES_PREFIX + "wvf_snd.%s" % audio_ext,
            )

        # enough cpu for multiprocessing ? USELESS RIGHT NOW, WILL COME AGAIN
        # enough_cpu = (multiprocessing.cpu_count() > 1)
        logger(message="Moviepy - Building video %s." % filename)
        if make_audio:
            self.audio.write_audiofile(
                audiofile,
                audio_fps,
                audio_nbytes,
                audio_bufsize,
                audio_codec,
                bitrate=audio_bitrate,
                write_logfile=write_logfile,
                logger=logger,
            )

        ffmpeg_write_video(
            self,
            filename,
            fps,
            codec,
            bitrate=bitrate,
            preset=preset,
            write_logfile=write_logfile,
            audiofile=audiofile,
            threads=threads,
            ffmpeg_params=ffmpeg_params,
            logger=logger,
            pixel_format=pixel_format,
        )

        if remove_temp and make_audio:
            if os.path.exists(audiofile):
                os.remove(audiofile)
        logger(message="Moviepy - video ready %s" % filename)
Ejemplo n.º 3
0
def test_ffmpeg_write_video(
    util,
    codec,
    is_valid_codec,
    ext,
    write_logfile,
    with_mask,
    bitrate,
    threads,
):
    filename = os.path.join(util.TMP_DIR, f"moviepy_ffmpeg_write_video{ext}")
    if os.path.isfile(filename):
        try:
            os.remove(filename)
        except PermissionError:
            pass

    logfile_name = filename + ".log"
    if os.path.isfile(logfile_name):
        os.remove(logfile_name)

    clip = BitmapClip([["R"], ["G"], ["B"]], fps=10).with_duration(0.3)
    if with_mask:
        clip = clip.with_mask(
            BitmapClip([["W"], ["O"], ["O"]], fps=10,
                       is_mask=True).with_duration(0.3))

    kwargs = dict(
        logger=None,
        write_logfile=write_logfile,
        with_mask=with_mask,
    )
    if codec is not None:
        kwargs["codec"] = codec
    if bitrate is not None:
        kwargs["bitrate"] = bitrate
    if threads is not None:
        kwargs["threads"] = threads

    ffmpeg_write_video(clip, filename, 10, **kwargs)

    if is_valid_codec:
        assert os.path.isfile(filename)

        final_clip = VideoFileClip(filename)

        r, g, b = final_clip.get_frame(0)[0][0]
        assert r == 254
        assert g == 0
        assert b == 0

        r, g, b = final_clip.get_frame(0.1)[0][0]
        assert r == (0 if not with_mask else 1)
        assert g == (255 if not with_mask else 1)
        assert b == 1

        r, g, b = final_clip.get_frame(0.2)[0][0]
        assert r == 0
        assert g == 0
        assert b == (255 if not with_mask else 0)

    if write_logfile:
        assert os.path.isfile(logfile_name)