Esempio n. 1
0
def restart_file():
    """
    restart a File
    :return: ""
    """

    file_id = request.form["file_id"]

    file = File.query.filter_by(id=file_id).first()
    if not file:
        abort(404)

    if ProcessRepository.is_running(file.id):
        ProcessRepository.cancel_process(file.id)
    else:
        # clear progress, cancel_process() also does this
        file.clear()

    # set status of file to "queued"
    file.status = StatusMap.queued.value

    db.session.commit()

    # check if it's necessary to start new processes
    ProcessRepository.check_and_start_processes()

    return ""
Esempio n. 2
0
    def test_file_done():
        with patch("os.rename") as m_rename:
            with patch("os.remove") as m_remove:
                # add fake_file to database in order to test renaming
                filename = "ThisIsAmazing.11.12.10.PyEncode.Is.The.Best.SEPARATOR.1080p.MP4-ABC.mp4"
                path = "/this/path/is/fake"
                fake_file = File(id=1, filename=path + os.sep + filename)
                fake_file.output_filename = filename + ".pyencode"
                db.session.add(fake_file)
                db.session.commit()

                # set options we want to test
                config["encoding"]["delete_old_file"] = "True"
                config["encoding"]["rename_enabled"] = "True"
                config["encoding"][
                    "rename_search"] = r"(?P<head>.+)(?P<resolution>1080|720|2160)(?:p|P)\.(?P<tail>.+)\.(?P<extension>\w{3})"
                config["encoding"]["rename_replace"] = r"\g<head>720p.\g<tail>-selfmade.mkv"
                expected_filename = "ThisIsAmazing.11.12.10.PyEncode.Is.The.Best.SEPARATOR.720p.MP4-ABC-selfmade.mkv"

                ProcessRepository.processes[fake_file.id] = None
                ProcessRepository.file_done(fake_file)
                m_remove.assert_called_once_with(fake_file.filename)
                m_rename.assert_called_once_with(path + os.sep + fake_file.output_filename,
                                                 path + os.sep + expected_filename)

        return
Esempio n. 3
0
    def test_file_done():
        with patch("os.rename") as m_rename:
            with patch("os.remove") as m_remove:
                # add fake_file to database in order to test renaming
                filename = "ThisIsAmazing.11.12.10.PyEncode.Is.The.Best.SEPARATOR.1080p.MP4-ABC.mp4"
                path = "/this/path/is/fake"
                fake_file = File(id=1, filename=path + os.sep + filename)
                fake_file.output_filename = filename + ".pyencode"
                db.session.add(fake_file)
                db.session.commit()

                # set options we want to test
                config["encoding"]["delete_old_file"] = "True"
                config["encoding"]["rename_enabled"] = "True"
                config["encoding"][
                    "rename_search"] = r"(?P<head>.+)(?P<resolution>1080|720|2160)(?:p|P)\.(?P<tail>.+)\.(?P<extension>\w{3})"
                config["encoding"][
                    "rename_replace"] = r"\g<head>720p.\g<tail>-selfmade.mkv"
                expected_filename = "ThisIsAmazing.11.12.10.PyEncode.Is.The.Best.SEPARATOR.720p.MP4-ABC-selfmade.mkv"

                ProcessRepository.processes[fake_file.id] = None
                ProcessRepository.file_done(fake_file)
                m_remove.assert_called_once_with(fake_file.filename)
                m_rename.assert_called_once_with(
                    path + os.sep + fake_file.output_filename,
                    path + os.sep + expected_filename)

        return
Esempio n. 4
0
def restart_package():
    """
    restart a Package
    :return: ""
    """

    package_id = request.form["package_id"]

    package = Package.query.filter_by(id=package_id).first()
    if not package:
        abort(404)

    # cancel all currently running processes that belong to this package
    for file in package.files:
        if ProcessRepository.is_running(file.id):
            ProcessRepository.cancel_process(file.id)
        else:
            # clear progress, cancel_process() also does this
            file.clear()

        # set status of each file to "queued"
        file.status = StatusMap.queued.value

    db.session.commit()

    # check if it's necessary to start new processes
    ProcessRepository.check_and_start_processes()

    return ""
Esempio n. 5
0
def delete_package():
    """
    delete a Package
    :return: ""
    """

    package_id = request.form["package_id"]

    package = Package.query.filter_by(id=package_id).first()
    if not package:
        abort(404)

    # cancel all currently running processes that belong to this package
    for file in package.files:
        if ProcessRepository.is_running(file.id):
            ProcessRepository.cancel_process(file.id)

        # mark this file to be deleted (even though SQLAlchemy handles this already)
        db.session.delete(file)

    db.session.delete(package)
    db.session.commit()

    # check if it's necessary to start new processes
    ProcessRepository.check_and_start_processes()

    return ""
Esempio n. 6
0
def restart_package():
    """
    restart a Package
    :return: ""
    """

    package_id = request.form["package_id"]

    package = Package.query.filter_by(id=package_id).first()
    if not package:
        abort(404)

    # cancel all currently running processes that belong to this package
    for file in package.files:
        if ProcessRepository.is_running(file.id):
            ProcessRepository.cancel_process(file.id)
        else:
            # clear progress, cancel_process() also does this
            file.clear()

        # set status of each file to "queued"
        file.status = StatusMap.queued.value

    db.session.commit()

    # check if it's necessary to start new processes
    ProcessRepository.check_and_start_processes()

    return ""
Esempio n. 7
0
def delete_package():
    """
    delete a Package
    :return: ""
    """

    package_id = request.form["package_id"]

    package = Package.query.filter_by(id=package_id).first()
    if not package:
        abort(404)

    # cancel all currently running processes that belong to this package
    for file in package.files:
        if ProcessRepository.is_running(file.id):
            ProcessRepository.cancel_process(file.id)

        # mark this file to be deleted (even though SQLAlchemy handles this already)
        db.session.delete(file)

    db.session.delete(package)
    db.session.commit()

    # check if it's necessary to start new processes
    ProcessRepository.check_and_start_processes()

    return ""
Esempio n. 8
0
def restart_file():
    """
    restart a File
    :return: ""
    """

    file_id = request.form["file_id"]

    file = File.query.filter_by(id=file_id).first()
    if not file:
        abort(404)

    if ProcessRepository.is_running(file.id):
        ProcessRepository.cancel_process(file.id)
    else:
        # clear progress, cancel_process() also does this
        file.clear()

    # set status of file to "queued"
    file.status = StatusMap.queued.value

    db.session.commit()

    # check if it's necessary to start new processes
    ProcessRepository.check_and_start_processes()

    return ""
Esempio n. 9
0
def toggle_encoding_active():
    """
    toggle the current encoding active status (from either True to False and vice-versa)
    :return: ""
    """

    ProcessRepository.set_encoding_active(not ProcessRepository.encoding_active)
    return ""
Esempio n. 10
0
def cancel_processes():
    """
    cancel all currently running Processes and check for new processes
    :return: ""
    """

    ProcessRepository.cancel_all_processes()

    # after cancelling check if it's necessary to start new processes
    ProcessRepository.check_and_start_processes()
    return ""
Esempio n. 11
0
    def run(self):
        """
        run the encoding
        """
        # probe file first
        frame_count = self.ffmpeg_probe_frame_count()

        if frame_count == -1:
            app.logger.debug("Probing of " + self.file.filename +
                             " failed - aborting...")
            ProcessRepository.file_failed(self.file)
            return

        # app.logger.debug("Probing of " + file.filename + " successful.. frame count: " + str(frame_count))
        split_path = os.path.split(self.file.filename)
        path = split_path[0]
        original_filename = split_path[1]
        filename_noext = os.path.split(
            os.path.splitext(original_filename)[0])[1]
        # form output filename and store it in self.file for later use
        self.file.output_filename = filename_noext + ".pyencode"

        cmd = ["ffmpeg"]
        cmd.extend(["-i", self.file.filename])
        # add parameters from config
        cmd.extend(shlex.split(config.get("encoding", "parameters")))
        cmd.extend(["-y", path + os.sep + self.file.output_filename])

        app.logger.debug("Starting encoding of " + self.file.filename +
                         " with %s" % " ".join(cmd))

        for info in self.run_ffmpeg(cmd, frame_count):
            if info["return_code"] != -1:
                app.logger.debug(
                    "Error occured while running ffmpeg. Last lines of output: "
                )
                app.logger.debug("\n".join(info["last_lines"]))
                ProcessRepository.file_failed(self.file)
                return

            # store information in database
            # convert kB to bytes
            info["ffmpeg_size"] *= 1024

            # we don't need the return_code anymore (and don't want to store it)
            info.pop("return_code")

            # update file in DB
            File.query.filter_by(id=self.file.id).update(info)
            db.session.commit()

            # update self.file
            for k in info:
                setattr(self.file, k, info[k])

            # tell ProcessRepository there's some progress going on
            ProcessRepository.file_progress(self.file)

        if self.active:
            ProcessRepository.file_done(self.file)
Esempio n. 12
0
    def test_check_and_start_processes(self, mock_probe, mock_run):
        def mocked_run_ffmpeg(cmd, frame_count):
            yield {
                "return_code": -1,
                "ffmpeg_eta": 1,
                "ffmpeg_progress": 0,
                "ffmpeg_bitrate": 0,
                "ffmpeg_time": 0,
                "ffmpeg_size": 0,
                "ffmpeg_fps": 0
            }

        # mock run_ffmpeg()
        mock_run.side_effect = mocked_run_ffmpeg

        # add Package
        package = Package(queue=True)
        db.session.add(package)
        # add File
        file = File(status=StatusMap.queued.value,
                    filename="dummy.mkv",
                    size=100 * 1024)
        db.session.add(file)
        package.files.append(file)

        db.session.commit()

        # set parallel processes to 1
        config["general"]["parallel_processes"] = "1"

        # start processing
        with patch("os.rename"):
            with patch("os.remove"):
                ProcessRepository.set_encoding_active(True)

        self.assertTrue(mock_run.called)
        self.assertTrue(mock_run.call_count == 1)

        received = self.socketio_client.get_received()
        # there should have gotten one file_started and file_done event triggered
        self.assertEqual(
            len([x for x in received if x["name"] == "file_started"]), 1)
        self.assertEqual(
            len([x for x in received if x["name"] == "file_done"]), 1)

        # the status should be "finished" now
        # self.assertEqual(File.query.filter_by(id=file.id).first().status, StatusMap.finished.value)
        # print(File.query.filter_by(id=file.id).first().status)
        return
Esempio n. 13
0
    def test_set_encoding_active(self):
        # encoding_active should be False when creating app
        self.assertFalse(ProcessRepository.encoding_active)

        ProcessRepository.set_encoding_active(True)

        # ... and should be True now
        self.assertTrue(ProcessRepository.encoding_active)

        # test we received active_changed with the correct data
        received = self.socketio_client.get_received()
        self.assertEqual(len(received), 1)
        self.assertEqual(received[0]["name"], "active_changed")
        self.assertEqual(received[0]["args"], [{"active": True}])

        return
Esempio n. 14
0
    def test_set_encoding_active(self):
        # encoding_active should be False when creating app
        self.assertFalse(ProcessRepository.encoding_active)

        ProcessRepository.set_encoding_active(True)

        # ... and should be True now
        self.assertTrue(ProcessRepository.encoding_active)

        # test we received active_changed with the correct data
        received = self.socketio_client.get_received()
        self.assertEqual(len(received), 1)
        self.assertEqual(received[0]["name"], "active_changed")
        self.assertEqual(received[0]["args"], [{"active": True}])

        return
Esempio n. 15
0
    def run(self):
        """
        run the encoding
        """
        # probe file first
        frame_count = self.ffmpeg_probe_frame_count()

        if frame_count == -1:
            app.logger.debug("Probing of " + self.file.filename + " failed - aborting...")
            ProcessRepository.file_failed(self.file)
            return

        # app.logger.debug("Probing of " + file.filename + " successful.. frame count: " + str(frame_count))
        split_path = os.path.split(self.file.filename)
        path = split_path[0]
        original_filename = split_path[1]
        filename_noext = os.path.split(os.path.splitext(original_filename)[0])[1]
        # form output filename and store it in self.file for later use
        self.file.output_filename = filename_noext + ".pyencode"

        cmd = ["ffmpeg"]
        cmd.extend(["-i", self.file.filename])
        # add parameters from config
        cmd.extend(shlex.split(config.get("encoding", "parameters")))
        cmd.extend(["-y", path + os.sep + self.file.output_filename])

        app.logger.debug("Starting encoding of " + self.file.filename + " with %s" % " ".join(cmd))

        for info in self.run_ffmpeg(cmd, frame_count):
            if info["return_code"] != -1:
                app.logger.debug("Error occured while running ffmpeg. Last lines of output: ")
                app.logger.debug("\n".join(info["last_lines"]))
                ProcessRepository.file_failed(self.file)
                return

            # store information in database
            # convert kB to bytes
            info["ffmpeg_size"] *= 1024

            # we don't need the return_code anymore (and don't want to store it)
            info.pop("return_code")

            # update file in DB
            File.query.filter_by(id=self.file.id).update(info)
            db.session.commit()

            # update self.file
            for k in info:
                setattr(self.file, k, info[k])

            # tell ProcessRepository there's some progress going on
            ProcessRepository.file_progress(self.file)

        if self.active:
            ProcessRepository.file_done(self.file)
Esempio n. 16
0
def add_package():
    """
    add a new Package
    :return: "1"
    """

    i = 0
    paths = json.loads(request.form["paths"])
    for path in paths:
        paths[i] = html.unescape(path)
        path = paths[i]
        if not os.path.isfile(path):
            print(path + " does not exist..")
            return "not_existing"

        i += 1

    last_package = Package.query.filter_by(queue=True).order_by(Package.position.desc()).limit(1).first()
    if not last_package:
        position = 0
    else:
        position = last_package.position + 1

    package = Package(user=current_user, title=request.form["title"], queue=(request.form["queue"] == "1"),
                      position=position)
    db.session.add(package)

    file_pos = 0
    for path in paths:
        file = File(filename=path, size=os.path.getsize(path), status=StatusMap.queued.value, position=file_pos)
        package.files.append(file)
        file_pos += 1

    db.session.commit()

    # after adding, see if we have to start processes
    ProcessRepository.check_and_start_processes()
    return "1"
Esempio n. 17
0
def delete_file():
    """
    delete a File
    :return: ""
    """

    file_id = request.form["file_id"]
    file = File.query.filter_by(id=file_id).first()

    if not file:
        abort(404)

    # cancel the currently running processes that
    if ProcessRepository.is_running(file.id):
        ProcessRepository.cancel_process(file.id)

    db.session.delete(file)
    db.session.commit()

    # check if it's necessary to start new processes
    ProcessRepository.check_and_start_processes()

    return ""
Esempio n. 18
0
def delete_file():
    """
    delete a File
    :return: ""
    """

    file_id = request.form["file_id"]
    file = File.query.filter_by(id=file_id).first()

    if not file:
        abort(404)

    # cancel the currently running processes that
    if ProcessRepository.is_running(file.id):
        ProcessRepository.cancel_process(file.id)

    db.session.delete(file)
    db.session.commit()

    # check if it's necessary to start new processes
    ProcessRepository.check_and_start_processes()

    return ""
Esempio n. 19
0
    def test_check_and_start_processes(self, mock_probe, mock_run):
        def mocked_run_ffmpeg(cmd, frame_count):
            yield {"return_code": -1, "ffmpeg_eta": 1, "ffmpeg_progress": 0, "ffmpeg_bitrate": 0, "ffmpeg_time": 0, "ffmpeg_size": 0, "ffmpeg_fps": 0}

        # mock run_ffmpeg()
        mock_run.side_effect = mocked_run_ffmpeg

        # add Package
        package = Package(queue=True)
        db.session.add(package)
        # add File
        file = File(status=StatusMap.queued.value, filename="dummy.mkv", size=100 * 1024)
        db.session.add(file)
        package.files.append(file)

        db.session.commit()

        # set parallel processes to 1
        config["general"]["parallel_processes"] = "1"

        # start processing
        with patch("os.rename"):
            with patch("os.remove"):
                ProcessRepository.set_encoding_active(True)

        self.assertTrue(mock_run.called)
        self.assertTrue(mock_run.call_count == 1)

        received = self.socketio_client.get_received()
        # there should have gotten one file_started and file_done event triggered
        self.assertEqual(len([x for x in received if x["name"] == "file_started"]), 1)
        self.assertEqual(len([x for x in received if x["name"] == "file_done"]), 1)

        # the status should be "finished" now
        # self.assertEqual(File.query.filter_by(id=file.id).first().status, StatusMap.finished.value)
        # print(File.query.filter_by(id=file.id).first().status)
        return
Esempio n. 20
0
def fail_on_exit():
    """
    on exit cancel all processes
    """
    ProcessRepository.cancel_all_processes()
Esempio n. 21
0
    def setUp(self):
        super().setUp()

        self.socketio_client = socketio.test_client(app)
        ProcessRepository.set_encoding_active(False)
        self.socketio_client.queue.clear()
Esempio n. 22
0
    def setUp(self):
        super().setUp()

        self.socketio_client = socketio.test_client(app)
        ProcessRepository.set_encoding_active(False)
        self.socketio_client.queue.clear()
Esempio n. 23
0
def fail_on_exit():
    """
    on exit cancel all processes
    """
    ProcessRepository.cancel_all_processes()