OpenShot Video Editor  2.0.0
waveform.py
Go to the documentation of this file.
1 ##
2 #
3 # @file
4 # @brief This file has code to generate audio waveform data structures
5 # @author Jonathan Thomas <jonathan@openshot.org>
6 #
7 # @section LICENSE
8 #
9 # Copyright (c) 2008-2016 OpenShot Studios, LLC
10 # (http://www.openshotstudios.com). This file is part of
11 # OpenShot Video Editor (http://www.openshot.org), an open-source project
12 # dedicated to delivering high quality video editing and animation solutions
13 # to the world.
14 #
15 # OpenShot Video Editor is free software: you can redistribute it and/or modify
16 # it under the terms of the GNU General Public License as published by
17 # the Free Software Foundation, either version 3 of the License, or
18 # (at your option) any later version.
19 #
20 # OpenShot Video Editor is distributed in the hope that it will be useful,
21 # but WITHOUT ANY WARRANTY; without even the implied warranty of
22 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 # GNU General Public License for more details.
24 #
25 # You should have received a copy of the GNU General Public License
26 # along with OpenShot Library. If not, see <http://www.gnu.org/licenses/>.
27 #
28 
29 import platform
30 import threading
31 from copy import deepcopy
32 from classes import info
33 from classes.app import get_app
34 from classes.logger import log
35 from classes import settings
36 import openshot
37 
38 
39 # Get settings
41 
42 
43 ##
44 # Get a Clip object form libopenshot, and grab audio data
45 def get_audio_data(clip_id, file_path, channel_filter, volume_keyframe):
46  clip = openshot.Clip(file_path)
47  clip.Open()
48 
49  # Disable video stream (for speed improvement)
50  clip.Reader().info.has_video = False
51 
52  log.info("Clip loaded, start thread")
53  t = threading.Thread(target=get_waveform_thread, args=[clip, clip_id, file_path, channel_filter, volume_keyframe])
54  t.start()
55 
56 ##
57 # Get the audio data from a clip in a separate thread
58 def get_waveform_thread(clip, clip_id, file_path, channel_filter=-1, volume_keyframe=None):
59  audio_data = []
60  sample_rate = clip.Reader().info.sample_rate
61 
62  # How many samples per second do we need (to approximate the waveform)
63  samples_per_second = 20
64  sample_divisor = round(sample_rate / samples_per_second)
65  log.info("Getting waveform for sample rate: %s" % sample_rate)
66 
67  sample = 0
68  for frame_number in range(1, clip.Reader().info.video_length):
69  # Get frame object
70  frame = clip.Reader().GetFrame(frame_number)
71 
72  # Get volume for this frame
73  volume = 1.0
74  if volume_keyframe:
75  volume = volume_keyframe.GetValue(frame_number)
76 
77  # Loop through samples in frame (hopping through it to get X # of data points per second)
78  while True:
79  # Determine amount of range
80  magnitude_range = sample_divisor
81  if sample + magnitude_range > frame.GetAudioSamplesCount():
82  magnitude_range = frame.GetAudioSamplesCount() - sample
83 
84  # Get audio data for this channel
85  if sample < frame.GetAudioSamplesCount():
86  audio_data.append(frame.GetAudioSample(channel_filter, sample, magnitude_range) * volume)
87  else:
88  # Adjust starting sample for next frame
89  sample = max(0, sample - frame.GetAudioSamplesCount())
90  break # We are done with this frame
91 
92  # Jump to next sample needed
93  sample += sample_divisor
94 
95  # Close reader
96  clip.Close()
97 
98  # Emit signal when done
99  log.info("get_waveform_thread completed")
100  get_app().window.WaveformReady.emit(clip_id, audio_data)
def get_app()
Returns the current QApplication instance of OpenShot.
Definition: app.py:54
def get_waveform_thread(clip, clip_id, file_path, channel_filter=-1, volume_keyframe=None)
Get the audio data from a clip in a separate thread.
Definition: waveform.py:58
def get_audio_data(clip_id, file_path, channel_filter, volume_keyframe)
Get a Clip object form libopenshot, and grab audio data.
Definition: waveform.py:45
def get_settings()
Get the current QApplication&#39;s settings instance.
Definition: settings.py:43