예제 #1
0
    def setUpClass(TestQueryClass):
        """ Init unit test data """
        # Create Qt application
        TestQueryClass.app = OpenShotApp(sys.argv, mode="unittest")
        TestQueryClass.clip_ids = []
        TestQueryClass.file_ids = []
        TestQueryClass.transition_ids = []

        # Import additional classes that need the app defined first
        from classes.query import Clip, File, Transition

        # Insert some clips into the project data
        for num in range(5):
            # Create clip
            c = openshot.Clip(os.path.join(info.IMAGES_PATH, "AboutLogo.png"))

            # Parse JSON
            clip_data = json.loads(c.Json())

            # Insert into project data
            query_clip = Clip()
            query_clip.data = clip_data
            query_clip.save()

            # Keep track of the ids
            TestQueryClass.clip_ids.append(query_clip.id)

        # Insert some files into the project data
        for num in range(5):
            # Create file
            r = openshot.DummyReader(openshot.Fraction(24, 1), 640, 480, 44100, 2, 30.0)

            # Parse JSON
            file_data = json.loads(r.Json())

            # Insert into project data
            query_file = File()
            query_file.data = file_data
            query_file.data["path"] = os.path.join(info.IMAGES_PATH, "AboutLogo.png")
            query_file.data["media_type"] = "image"
            query_file.save()

            # Keep track of the ids
            TestQueryClass.file_ids.append(query_file.id)

        # Insert some transitions into the project data
        for num in range(5):
            # Create mask object
            transition_object = openshot.Mask()
            transitions_data = json.loads(transition_object.Json())

            # Insert into project data
            query_transition = Transition()
            query_transition.data = transitions_data
            query_transition.save()

            # Keep track of the ids
            TestQueryClass.transition_ids.append(query_transition.id)
예제 #2
0
    def accept(self):
        """ Ok button clicked """
        log.info('accept')

        # Get settings from form
        start_position = self.txtStartTime.value()
        track_num = self.cmbTrack.currentData()
        fade_value = self.cmbFade.currentData()
        fade_length = self.txtFadeLength.value()
        transition_path = self.cmbTransition.currentData()
        transition_length = self.txtTransitionLength.value()
        image_length = self.txtImageLength.value()
        zoom_value = self.cmbZoom.currentData()

        # Init position
        position = start_position

        random_transition = False
        if transition_path == "random":
            random_transition = True

        # Get frames per second
        fps = get_app().project.get(["fps"])
        fps_float = float(fps["num"]) / float(fps["den"])

        # Loop through each file (in the current order)
        for file in self.treeFiles.timeline_model.files:
            # Create a clip
            clip = Clip()
            clip.data = {}

            if (file.data["media_type"] == "video"
                    or file.data["media_type"] == "image"):
                # Determine thumb path
                thumb_path = os.path.join(info.THUMBNAIL_PATH,
                                          "%s.png" % file.data["id"])
            else:
                # Audio file
                thumb_path = os.path.join(info.PATH, "images",
                                          "AudioThumbnail.png")

            # Get file name
            path, filename = os.path.split(file.data["path"])

            # Convert path to the correct relative path (based on this folder)
            file_path = file.absolute_path()

            # Create clip object for this file
            c = openshot.Clip(file_path)

            # Append missing attributes to Clip JSON
            new_clip = json.loads(c.Json())
            new_clip["position"] = position
            new_clip["layer"] = track_num
            new_clip["file_id"] = file.id
            new_clip["title"] = filename
            new_clip["image"] = thumb_path

            # Skip any clips that are missing a 'reader' attribute
            # TODO: Determine why this even happens, as it shouldn't be possible
            if not new_clip.get("reader"):
                continue  # Skip to next file

            # Overwrite frame rate (incase the user changed it in the File Properties)
            file_properties_fps = float(file.data["fps"]["num"]) / float(
                file.data["fps"]["den"])
            file_fps = float(new_clip["reader"]["fps"]["num"]) / float(
                new_clip["reader"]["fps"]["den"])
            fps_diff = file_fps / file_properties_fps
            new_clip["reader"]["fps"]["num"] = file.data["fps"]["num"]
            new_clip["reader"]["fps"]["den"] = file.data["fps"]["den"]
            # Scale duration / length / and end properties
            new_clip["reader"]["duration"] *= fps_diff
            new_clip["end"] *= fps_diff
            new_clip["duration"] *= fps_diff

            # Check for optional start and end attributes
            start_time = 0
            end_time = new_clip["reader"]["duration"]

            if 'start' in file.data.keys():
                start_time = file.data['start']
                new_clip["start"] = start_time
            if 'end' in file.data.keys():
                end_time = file.data['end']
                new_clip["end"] = end_time

            # Adjust clip duration, start, and end
            new_clip["duration"] = new_clip["reader"]["duration"]
            if file.data["media_type"] == "image":
                end_time = image_length
                new_clip["end"] = end_time

            # Adjust Fade of Clips (if no transition is chosen)
            if not transition_path:
                if fade_value != None:
                    # Overlap this clip with the previous one (if any)
                    position = max(start_position,
                                   new_clip["position"] - fade_length)
                    new_clip["position"] = position

                if fade_value == 'Fade In' or fade_value == 'Fade In & Out':
                    start = openshot.Point(
                        round(start_time * fps_float) + 1, 0.0,
                        openshot.BEZIER)
                    start_object = json.loads(start.Json())
                    end = openshot.Point(
                        min(
                            round((start_time + fade_length) * fps_float) + 1,
                            round(end_time * fps_float) + 1), 1.0,
                        openshot.BEZIER)
                    end_object = json.loads(end.Json())
                    new_clip['alpha']["Points"].append(start_object)
                    new_clip['alpha']["Points"].append(end_object)

                if fade_value == 'Fade Out' or fade_value == 'Fade In & Out':
                    start = openshot.Point(
                        max(
                            round((end_time * fps_float) + 1) -
                            (round(fade_length * fps_float) + 1),
                            round(start_time * fps_float) + 1), 1.0,
                        openshot.BEZIER)
                    start_object = json.loads(start.Json())
                    end = openshot.Point(
                        round(end_time * fps_float) + 1, 0.0, openshot.BEZIER)
                    end_object = json.loads(end.Json())
                    new_clip['alpha']["Points"].append(start_object)
                    new_clip['alpha']["Points"].append(end_object)

            # Adjust zoom amount
            if zoom_value != None:
                # Location animation
                if zoom_value == "Random":
                    animate_start_x = uniform(-0.5, 0.5)
                    animate_end_x = uniform(-0.15, 0.15)
                    animate_start_y = uniform(-0.5, 0.5)
                    animate_end_y = uniform(-0.15, 0.15)

                    # Scale animation
                    start_scale = uniform(0.5, 1.5)
                    end_scale = uniform(0.85, 1.15)

                elif zoom_value == "Zoom In":
                    animate_start_x = 0.0
                    animate_end_x = 0.0
                    animate_start_y = 0.0
                    animate_end_y = 0.0

                    # Scale animation
                    start_scale = 1.0
                    end_scale = 1.25

                elif zoom_value == "Zoom Out":
                    animate_start_x = 0.0
                    animate_end_x = 0.0
                    animate_start_y = 0.0
                    animate_end_y = 0.0

                    # Scale animation
                    start_scale = 1.25
                    end_scale = 1.0

                # Add keyframes
                start = openshot.Point(
                    round(start_time * fps_float) + 1, start_scale,
                    openshot.BEZIER)
                start_object = json.loads(start.Json())
                end = openshot.Point(
                    round(end_time * fps_float) + 1, end_scale,
                    openshot.BEZIER)
                end_object = json.loads(end.Json())
                new_clip["gravity"] = openshot.GRAVITY_CENTER
                new_clip["scale_x"]["Points"].append(start_object)
                new_clip["scale_x"]["Points"].append(end_object)
                new_clip["scale_y"]["Points"].append(start_object)
                new_clip["scale_y"]["Points"].append(end_object)

                # Add keyframes
                start_x = openshot.Point(
                    round(start_time * fps_float) + 1, animate_start_x,
                    openshot.BEZIER)
                start_x_object = json.loads(start_x.Json())
                end_x = openshot.Point(
                    round(end_time * fps_float) + 1, animate_end_x,
                    openshot.BEZIER)
                end_x_object = json.loads(end_x.Json())
                start_y = openshot.Point(
                    round(start_time * fps_float) + 1, animate_start_y,
                    openshot.BEZIER)
                start_y_object = json.loads(start_y.Json())
                end_y = openshot.Point(
                    round(end_time * fps_float) + 1, animate_end_y,
                    openshot.BEZIER)
                end_y_object = json.loads(end_y.Json())
                new_clip["gravity"] = openshot.GRAVITY_CENTER
                new_clip["location_x"]["Points"].append(start_x_object)
                new_clip["location_x"]["Points"].append(end_x_object)
                new_clip["location_y"]["Points"].append(start_y_object)
                new_clip["location_y"]["Points"].append(end_y_object)

            if transition_path:
                # Add transition for this clip (if any)
                # Open up QtImageReader for transition Image
                if random_transition:
                    random_index = randint(0, len(self.transitions))
                    transition_path = self.transitions[random_index]

                # Get reader for transition
                transition_reader = openshot.QtImageReader(transition_path)

                brightness = openshot.Keyframe()
                brightness.AddPoint(1, 1.0, openshot.BEZIER)
                brightness.AddPoint(
                    round(
                        min(transition_length, end_time - start_time) *
                        fps_float) + 1, -1.0, openshot.BEZIER)
                contrast = openshot.Keyframe(3.0)

                # Create transition dictionary
                transitions_data = {
                    "layer": track_num,
                    "title": "Transition",
                    "type": "Mask",
                    "start": 0,
                    "end": min(transition_length, end_time - start_time),
                    "brightness": json.loads(brightness.Json()),
                    "contrast": json.loads(contrast.Json()),
                    "reader": json.loads(transition_reader.Json()),
                    "replace_image": False
                }

                # Overlap this clip with the previous one (if any)
                position = max(start_position, position - transition_length)
                transitions_data["position"] = position
                new_clip["position"] = position

                # Create transition
                tran = Transition()
                tran.data = transitions_data
                tran.save()

            # Save Clip
            clip.data = new_clip
            clip.save()

            # Increment position by length of clip
            position += (end_time - start_time)

        # Accept dialog
        super(AddToTimeline, self).accept()
예제 #3
0
    def read_legacy_project_file(self, file_path):
        """Attempt to read a legacy version 1.x openshot project file"""
        import sys, pickle
        from classes.query import File, Track, Clip, Transition
        from classes.app import get_app
        import openshot

        try:
            import json
        except ImportError:
            import simplejson as json

        # Get translation method
        _ = get_app()._tr

        # Append version info
        v = openshot.GetVersion()
        project_data = {}
        project_data["version"] = {
            "openshot-qt": info.VERSION,
            "libopenshot": v.ToString()
        }

        # Get FPS from project
        from classes.app import get_app
        fps = get_app().project.get(["fps"])
        fps_float = float(fps["num"]) / float(fps["den"])

        # Import legacy openshot classes (from version 1.X)
        from classes.legacy.openshot import classes as legacy_classes
        from classes.legacy.openshot.classes import project as legacy_project
        from classes.legacy.openshot.classes import sequences as legacy_sequences
        from classes.legacy.openshot.classes import track as legacy_track
        from classes.legacy.openshot.classes import clip as legacy_clip
        from classes.legacy.openshot.classes import keyframe as legacy_keyframe
        from classes.legacy.openshot.classes import files as legacy_files
        from classes.legacy.openshot.classes import transition as legacy_transition
        from classes.legacy.openshot.classes import effect as legacy_effect
        from classes.legacy.openshot.classes import marker as legacy_marker
        sys.modules['openshot.classes'] = legacy_classes
        sys.modules['classes.project'] = legacy_project
        sys.modules['classes.sequences'] = legacy_sequences
        sys.modules['classes.track'] = legacy_track
        sys.modules['classes.clip'] = legacy_clip
        sys.modules['classes.keyframe'] = legacy_keyframe
        sys.modules['classes.files'] = legacy_files
        sys.modules['classes.transition'] = legacy_transition
        sys.modules['classes.effect'] = legacy_effect
        sys.modules['classes.marker'] = legacy_marker

        # Keep track of files that failed to load
        failed_files = []

        with open(file_path.encode('UTF-8'), 'rb') as f:
            try:
                # Unpickle legacy openshot project file
                v1_data = pickle.load(f, fix_imports=True, encoding="UTF-8")
                file_lookup = {}

                # Loop through files
                for item in v1_data.project_folder.items:
                    # Is this item a File (i.e. ignore folders)
                    if isinstance(item, legacy_files.OpenShotFile):
                        # Create file
                        try:
                            clip = openshot.Clip(item.name)
                            reader = clip.Reader()
                            file_data = json.loads(reader.Json())

                            # Determine media type
                            if file_data["has_video"] and not self.is_image(
                                    file_data):
                                file_data["media_type"] = "video"
                            elif file_data["has_video"] and self.is_image(
                                    file_data):
                                file_data["media_type"] = "image"
                            elif file_data["has_audio"] and not file_data[
                                    "has_video"]:
                                file_data["media_type"] = "audio"

                            # Save new file to the project data
                            file = File()
                            file.data = file_data
                            file.save()

                            # Keep track of new ids and old ids
                            file_lookup[item.unique_id] = file

                        except:
                            # Handle exception quietly
                            msg = (
                                "%s is not a valid video, audio, or image file."
                                % item.name)
                            log.error(msg)
                            failed_files.append(item.name)

                # Delete all tracks
                track_list = copy.deepcopy(Track.filter())
                for track in track_list:
                    track.delete()

                # Create new tracks
                track_counter = 0
                for legacy_t in reversed(v1_data.sequences[0].tracks):
                    t = Track()
                    t.data = {
                        "number": track_counter,
                        "y": 0,
                        "label": legacy_t.name
                    }
                    t.save()

                    track_counter += 1

                # Loop through clips
                track_counter = 0
                for sequence in v1_data.sequences:
                    for track in reversed(sequence.tracks):
                        for clip in track.clips:
                            # Get associated file for this clip
                            if clip.file_object.unique_id in file_lookup.keys(
                            ):
                                file = file_lookup[clip.file_object.unique_id]
                            else:
                                # Skip missing file
                                log.info(
                                    "Skipping importing missing file: %s" %
                                    clip.file_object.unique_id)
                                continue

                            # Create clip
                            if (file.data["media_type"] == "video"
                                    or file.data["media_type"] == "image"):
                                # Determine thumb path
                                thumb_path = os.path.join(
                                    info.THUMBNAIL_PATH,
                                    "%s.png" % file.data["id"])
                            else:
                                # Audio file
                                thumb_path = os.path.join(
                                    info.PATH, "images", "AudioThumbnail.png")

                            # Get file name
                            path, filename = os.path.split(file.data["path"])

                            # Convert path to the correct relative path (based on this folder)
                            file_path = file.absolute_path()

                            # Create clip object for this file
                            c = openshot.Clip(file_path)

                            # Append missing attributes to Clip JSON
                            new_clip = json.loads(c.Json())
                            new_clip["file_id"] = file.id
                            new_clip["title"] = filename
                            new_clip["image"] = thumb_path

                            # Check for optional start and end attributes
                            new_clip["start"] = clip.start_time
                            new_clip["end"] = clip.end_time
                            new_clip["position"] = clip.position_on_track
                            new_clip["layer"] = track_counter

                            # Clear alpha (if needed)
                            if clip.video_fade_in or clip.video_fade_out:
                                new_clip["alpha"]["Points"] = []

                            # Video Fade IN
                            if clip.video_fade_in:
                                # Add keyframes
                                start = openshot.Point(
                                    round(clip.start_time * fps_float) + 1,
                                    0.0, openshot.BEZIER)
                                start_object = json.loads(start.Json())
                                end = openshot.Point(
                                    round((clip.start_time +
                                           clip.video_fade_in_amount) *
                                          fps_float) + 1, 1.0, openshot.BEZIER)
                                end_object = json.loads(end.Json())
                                new_clip["alpha"]["Points"].append(
                                    start_object)
                                new_clip["alpha"]["Points"].append(end_object)

                            # Video Fade OUT
                            if clip.video_fade_out:
                                # Add keyframes
                                start = openshot.Point(
                                    round((clip.end_time -
                                           clip.video_fade_out_amount) *
                                          fps_float) + 1, 1.0, openshot.BEZIER)
                                start_object = json.loads(start.Json())
                                end = openshot.Point(
                                    round(clip.end_time * fps_float) + 1, 0.0,
                                    openshot.BEZIER)
                                end_object = json.loads(end.Json())
                                new_clip["alpha"]["Points"].append(
                                    start_object)
                                new_clip["alpha"]["Points"].append(end_object)

                            # Clear Audio (if needed)
                            if clip.audio_fade_in or clip.audio_fade_out:
                                new_clip["volume"]["Points"] = []
                            else:
                                p = openshot.Point(1, clip.volume / 100.0,
                                                   openshot.BEZIER)
                                p_object = json.loads(p.Json())
                                new_clip["volume"] = {"Points": [p_object]}

                            # Audio Fade IN
                            if clip.audio_fade_in:
                                # Add keyframes
                                start = openshot.Point(
                                    round(clip.start_time * fps_float) + 1,
                                    0.0, openshot.BEZIER)
                                start_object = json.loads(start.Json())
                                end = openshot.Point(
                                    round((clip.start_time +
                                           clip.video_fade_in_amount) *
                                          fps_float) + 1, clip.volume / 100.0,
                                    openshot.BEZIER)
                                end_object = json.loads(end.Json())
                                new_clip["volume"]["Points"].append(
                                    start_object)
                                new_clip["volume"]["Points"].append(end_object)

                            # Audio Fade OUT
                            if clip.audio_fade_out:
                                # Add keyframes
                                start = openshot.Point(
                                    round((clip.end_time -
                                           clip.video_fade_out_amount) *
                                          fps_float) + 1, clip.volume / 100.0,
                                    openshot.BEZIER)
                                start_object = json.loads(start.Json())
                                end = openshot.Point(
                                    round(clip.end_time * fps_float) + 1, 0.0,
                                    openshot.BEZIER)
                                end_object = json.loads(end.Json())
                                new_clip["volume"]["Points"].append(
                                    start_object)
                                new_clip["volume"]["Points"].append(end_object)

                            # Save clip
                            clip_object = Clip()
                            clip_object.data = new_clip
                            clip_object.save()

                        # Loop through transitions
                        for trans in track.transitions:
                            # Fix default transition
                            if not trans.resource or not os.path.exists(
                                    trans.resource):
                                trans.resource = os.path.join(
                                    info.PATH, "transitions", "common",
                                    "fade.svg")

                            # Open up QtImageReader for transition Image
                            transition_reader = openshot.QtImageReader(
                                trans.resource)

                            trans_begin_value = 1.0
                            trans_end_value = -1.0
                            if trans.reverse:
                                trans_begin_value = -1.0
                                trans_end_value = 1.0

                            brightness = openshot.Keyframe()
                            brightness.AddPoint(1, trans_begin_value,
                                                openshot.BEZIER)
                            brightness.AddPoint(
                                round(trans.length * fps_float) + 1,
                                trans_end_value, openshot.BEZIER)
                            contrast = openshot.Keyframe(trans.softness * 10.0)

                            # Create transition dictionary
                            transitions_data = {
                                "id": get_app().project.generate_id(),
                                "layer": track_counter,
                                "title": "Transition",
                                "type": "Mask",
                                "position": trans.position_on_track,
                                "start": 0,
                                "end": trans.length,
                                "brightness": json.loads(brightness.Json()),
                                "contrast": json.loads(contrast.Json()),
                                "reader": json.loads(transition_reader.Json()),
                                "replace_image": False
                            }

                            # Save transition
                            t = Transition()
                            t.data = transitions_data
                            t.save()

                        # Increment track counter
                        track_counter += 1

            except Exception as ex:
                # Error parsing legacy contents
                msg = _("Failed to load project file %(path)s: %(error)s" % {
                    "path": file_path,
                    "error": ex
                })
                log.error(msg)
                raise Exception(msg)

        # Show warning if some files failed to load
        if failed_files:
            # Throw exception
            raise Exception(
                _("Failed to load the following files:\n%s" %
                  ", ".join(failed_files)))

        # Return mostly empty project_data dict (with just the current version #)
        log.info("Successfully loaded legacy project file: %s" % file_path)
        return project_data
예제 #4
0
    def setUpClass(cls):
        """ Init unit test data """
        # Create Qt application
        cls.app = QGuiApplication.instance()
        cls.clip_ids = []
        cls.file_ids = []
        cls.transition_ids = []

        clips = []

        # Insert some clips into the project data
        for num in range(5):
            # Create clip
            c = openshot.Clip(os.path.join(info.IMAGES_PATH, "AboutLogo.png"))
            c.Position(num * 10.0)
            c.End(5.0)

            # Parse JSON
            clip_data = json.loads(c.Json())

            # Insert into project data
            query_clip = Clip()
            query_clip.data = clip_data
            query_clip.save()

            # Keep track of the ids
            cls.clip_ids.append(query_clip.id)
            clips.append(query_clip)

        # Insert some files into the project data
        for num in range(5):
            # Create file
            r = openshot.DummyReader(openshot.Fraction(24, 1), 640, 480, 44100,
                                     2, 30.0)

            # Parse JSON
            file_data = json.loads(r.Json())

            # Insert into project data
            query_file = File()
            query_file.data = file_data
            query_file.data["path"] = os.path.join(info.IMAGES_PATH,
                                                   "AboutLogo.png")
            query_file.data["media_type"] = "image"
            query_file.save()

            # Keep track of the ids
            cls.file_ids.append(query_file.id)

        # Insert some transitions into the project data
        for c in clips:
            # Create mask object
            t = openshot.Mask()
            # Place over the last second of current clip
            pos = c.data.get("position", 0.0)
            start = c.data.get("start", 0.0)
            end = c.data.get("end", 0.0)
            t.Position((pos - start + end) - 1.0)
            t.End(1.0)

            # Insert into project data
            transitions_data = json.loads(t.Json())
            query_transition = Transition()
            query_transition.data = transitions_data
            query_transition.save()

            # Keep track of the ids
            cls.transition_ids.append(query_transition.id)

        # Don't keep the full query objects around
        del clips