vosk_ros_model_downloader.py
Go to the documentation of this file.
1 #!/usr/bin/env python3
2 # -*- coding: utf-8 -*-
3 
4 import tkinter as tk
5 from tkinter.filedialog import askdirectory
6 from tkinter import ttk
7 import tkinter.filedialog as filedialog
8 
9 import os
10 import rospy
11 import rospkg
12 
13 import zipfile
14 
15 import urllib3
16 import requests
17 from bs4 import BeautifulSoup
18 from threading import Thread
19 
21  def __init__(self):
22  rospack = rospkg.RosPack()
23  rospack.list()
24  self.package_path = rospack.get_path('ros_vosk')
25  model_path = '/models/'
26  self.model_dir = self.package_path + model_path
27 
28  model_folder = os.path.join(self.package_path, 'models')
29  if not os.path.isdir(model_folder):
30  os.mkdir(model_folder)
31 
32  self.execution_method = None
33 
34  self.url = None
35 
36  self.gui_x = 650
37  self.gui_y = 450
38  self.gui_font = "Raleway"
39 
40  self.gui_master = tk.Tk()
41  self.gui_master.title('VOSK model downloader')
42  self.gui_master.geometry('{}x{}'.format(self.gui_x, self.gui_y))
43 
44  self.model_to_download = None
45  self.languages, self.model_names = self.load_models()
46 
47  style = ttk.Style()
48  style.map('TCombobox', fieldbackground=[('readonly','white')])
49  style.map('TCombobox', selectbackground=[('readonly', 'white')])
50  style.map('TCombobox', selectforeground=[('readonly', 'black')])
51 
52  self.gui_master.grid_rowconfigure(4, weight=1)
53  self.gui_master.grid_columnconfigure(0, weight=1)
54 
55  self.model_frame = tk.Frame(self.gui_master, padx=10, pady=10)
56  self.model_frame.grid(row=0, sticky="news")
57 
58  self.directory_frame = tk.Frame(self.gui_master, padx=10, pady=10)
59  self.directory_frame.grid(row=1, sticky="news")
60 
61  self.control_frame = tk.Frame(self.gui_master)
62  self.control_frame.grid(row=2, sticky="news")
63 
64  self.model_frame.grid_rowconfigure(4, weight=1)
65  self.model_frame.grid_columnconfigure(1, weight=1)
66 
67  self.lbl_welcome = tk.Label(self.model_frame, text = 'The VOSK model downloader for ROS!', font= self.gui_font)
68  self.lbl_welcome.grid(row=0, columnspan=2, sticky="news", pady=10)
69 
70  self.lbl_language = tk.Label(self.model_frame, text = 'Select Language:', font= self.gui_font)
71  self.lbl_language.grid(row=1, column=0, sticky="w")
72 
73  self.lbl_model = tk.Label(self.model_frame, text = 'Select Model:', font= self.gui_font)
74  self.lbl_model.grid(row=1, column=1, sticky="w")
75 
76  self.combo_languages = ttk.Combobox(self.model_frame, value=(self.languages), state="readonly", font= self.gui_font)
77  self.combo_languages.bind('<<ComboboxSelected>>', self.on_combo_language_select)
78  self.combo_languages.grid(row=2, column=0, sticky="news", pady=2)
79  self.combo_languages.current(0)
80 
81  model_name = self.get_model(self.combo_languages.get())
82  self.combo_models = ttk.Combobox(self.model_frame, values=model_name, state="readonly", font= self.gui_font)
83  self.combo_models.bind('<<ComboboxSelected>>', self.on_combo_model_select)
84  self.combo_models.grid(row=2, column=1, sticky="news", pady=2)
85  self.combo_models.current(0)
86  self.model_to_download = self.combo_models.get()
87 
88  self.lbl_info = tk.Label(self.model_frame, text = 'Some info about the selected model.. ', font= self.gui_font)
89  self.lbl_info.grid(row=3, columnspan=2, sticky="w", pady=10)
90 
91  size, error, notes, license = self.get_model_info(self.combo_models.get(),self.combo_languages.get())
92  model_info = "Name: %s\nSize: %s\nWord error rate/Speed: %s\nNotes: %s\nLicense: %s\n" % (self.model_to_download, size, error, notes, license)
93  self.model_info_message = tk.Message(self.model_frame, width=(self.gui_x-5), text= model_info, background='white', font=self.gui_font)
94  self.model_info_message.grid(row=4, columnspan=2, sticky="news", pady=2)
95 
96  self.directory_frame.grid_rowconfigure(3, weight=1)
97  self.directory_frame.grid_columnconfigure(1, weight=1)
98 
99  self.lbl_download = tk.Label(self.directory_frame, text= "Download model in directory: ", font= self.gui_font, anchor=tk.W)
100  self.lbl_download.grid(row=0, column=0, sticky="w", pady=10)
101 
102  self.lbl_directory = tk.Label(self.directory_frame, text= self.model_dir, font= self.gui_font, anchor=tk.W)
103  self.lbl_directory.grid(row=1, column=0, sticky="news")
104 
105  self.btn_browse = tk.Button(self.directory_frame, text = "Browse", width=10, command=lambda:self.btn_click_browse_folder(), font = self.gui_font)
106  self.btn_browse.grid(row=1, column=1, sticky="news", pady=10)
107 
108  self.btn_download = tk.Button(self.directory_frame, text = "Download!", width=10, command=lambda:self.btn_click_download(self.model_to_download), font = self.gui_font)
109  self.btn_download.grid(row=2, column=1, sticky="news",pady=10)
110 
111  self.progressbar = ttk.Progressbar(self.directory_frame, length=400)
112  self.progressbar.grid(row=2, column=0, sticky="news", pady=10)
113 
115  value = self.listbox_languages.get(tk.ANCHOR)
116 
117  def get_listbox_model(self):
118  value = self.listbox_model.get(tk.ANCHOR)
119 
121  path = filedialog.askdirectory()
122  if len(path) != 0:
123  self.model_dir = path
124  self.lbl_directory.config(text= self.model_dir)
125 
126  def get_model(self, language):
127  models = []
128  for model in self.model_names:
129  if model["Language"] == language:
130  models.append(model['Model'])
131  return(models)
132 
133  def load_models(self):
134  http = urllib3.PoolManager()
135 
136  self.url = "https://alphacephei.com/vosk/models"
137 
138  self.r = http.request('GET', self.url)
139  soup = BeautifulSoup(self.r.data, 'html.parser')
140 
141  head_list = []
142  item_list = []
143  model_list = []
144  language_list = []
145  language = None
146 
147  for table in soup.find_all('table'):
148  for head in table.find_all('thead'):
149  for column in head.find_all('th'):
150  head_list.append(column.text)
151  for table_body in table.find_all('tbody'):
152  for row in table_body.find_all('tr'):
153  row_list = []
154  for column in row.find_all('td'):
155  row_list.append(column.text)
156  item_list.append(row_list)
157  break
158 
159  for item in item_list:
160  if len(item) == 5:
161  if item[0] != "\xa0" and item[1] == "\xa0" and (item[2] == "\xa0" or item[2] == "Older Models") and item[3] == "\xa0":
162  language = item[0]
163  if language_list.count(language) == 0:
164  language_list.append(language)
165  else:
166  model_dict = {"Language": language, head_list[0]: item[0], head_list[1]: item[1], head_list[2]: item[2], head_list[3]: item[3], head_list[4]: item[4]}
167  model_list.append(model_dict)
168  return language_list, model_list
169 
170  def get_model_info(self, selected_model, language):
171  size = None
172  error = None
173  notes = None
174  license = None
175  for model in self.model_names:
176  if model["Language"] == language:
177  if model["Model"] == selected_model:
178  size = model["Size"]
179  error = model["Word error rate/Speed"]
180  notes = model["Notes"]
181  license = model["License"]
182  break
183  return size, error, notes, license
184 
185  def btn_click_download(self, model_to_download):
186  downloadThread= Thread(target=lambda:self.download(model_to_download))
187  downloadThread.start()
188  self.btn_download["state"] = "disabled"
189  self.btn_browse["state"] = "disabled"
190 
191  def download(self, model_to_download):
192  model_url, filename = self.get_model_link(model_to_download)
193 
194  if model_url!=None:
195  req=requests.get(model_url,stream=True)
196 
197  if "Content-Length" in req.headers:
198  total_size=req.headers['Content-Length']
199  else:
200  total_size=None
201  with open(self.model_dir+filename,"wb") as fileobj:
202  for chunk in req.iter_content(chunk_size=1024):
203  if chunk:
204  fileobj.write(chunk)
205  current_size=os.path.getsize(self.model_dir+filename)
206  #lbl_size.config(text=str(getStandardSize(current_size)))
207 
208  if total_size!=None:
209  percentage = round((int(current_size)/int(total_size))*100)
210  #lbl_percentage.config(text=str(percentg)+" %")
211  self.progressbar['value']=percentage
212  else:
213  percentage = "Infinite"
214  self.progressbar.config(mode="indeterminate")
215  self.progressbar.start()
216  #labelPercentage.config(text=str(percentage)+" %")
217 
218  if total_size!=None:
219  current_size=os.path.getsize(self.model_dir+filename)
220  #lbl_size.config(text=str(getStandardSize(current_size)))
221  #lbl_percentage.config(text=str(percentage) + " %")
222  percentage=round((int(current_size)/int(total_size))*100)
223  self.progressbar['value']=percentage
224  self.btn_download["state"] = "normal"
225  self.btn_browse["state"] = "normal"
226 
227  self.unzip(self.model_dir, filename)
228 
229  if self.execution_method == "inner":
230  self.gui_master.destroy()
231  #quit
232  else:
233  current_size=os.path.getsize(self.model_dir+filename)
234  #lbl_size.config(text=str(getStandardSize(current_size)))
235  #lbl_percentage.config(text="100 %")
236  self.progressbar['value'] = 100
237  self.btn_download["state"] = "normal"
238  self.btn_browse["state"] = "normal"
239 
240  def on_combo_language_select(self, event):
241  self.combo_models.set("")
242  model = self.get_model(self.combo_languages.get())
243  self.combo_models.config(values = model)
244  self.combo_models.current(0)
245 
246  self.model_to_download = self.combo_models.get()
247  selected_language = self.combo_languages.get()
248  size, error, notes, license = self.get_model_info(self.model_to_download, selected_language)
249  info = "Name: %s\nSize: %s\nWord error rate/Speed: %s\nNotes: %s\nLicense: %s\n" % (self.model_to_download, size, error, notes, license)
250  self.model_info_message.config(text=info)
251 
252  def get_model_link(self, model_to_download):
253  soup = BeautifulSoup(self.r.data, "lxml")
254 
255  for link in soup.findAll('a'):
256  model_link = link.get('href')
257  if model_link.startswith(self.url):
258  if model_to_download+".zip" in model_link:
259  file_name = model_link.split(self.url+'/', 1)
260  file_name = file_name[1]
261  return model_link, file_name
262 
263  def on_combo_model_select(self, event):
264  self.model_to_download = self.combo_models.get()
265  selected_language = self.combo_languages.get()
266  size, error, notes, license = self.get_model_info(self.model_to_download, selected_language)
267  info = "Name: %s\nSize: %s\nWord error rate/Speed: %s\nNotes: %s\nLicense: %s\n" % (self.model_to_download, size, error, notes, license)
268  self.model_info_message.config(text=info)
269 
270  def unzip(self, directory, filename):
271  with zipfile.ZipFile(directory+filename, 'r') as zip_ref:
272  zip_ref.extractall(directory)
273  os.remove(directory+filename)
274 
276  self.execution_method = "standalone"
277  self.gui_master.mainloop()
278 
279  def execute(self):
280  self.execution_method = "inner"
281  self.gui_master.mainloop()
282 
283 if __name__ == '__main__':
284  downloader = model_downloader()
285  downloader.execute_standalone()
vosk_ros_model_downloader.model_downloader.btn_download
btn_download
Definition: vosk_ros_model_downloader.py:108
vosk_ros_model_downloader.model_downloader.lbl_info
lbl_info
Definition: vosk_ros_model_downloader.py:88
vosk_ros_model_downloader.model_downloader.model_to_download
model_to_download
Definition: vosk_ros_model_downloader.py:44
vosk_ros_model_downloader.model_downloader.__init__
def __init__(self)
Definition: vosk_ros_model_downloader.py:21
vosk_ros_model_downloader.model_downloader.combo_models
combo_models
Definition: vosk_ros_model_downloader.py:82
vosk_ros_model_downloader.model_downloader.model_info_message
model_info_message
Definition: vosk_ros_model_downloader.py:93
vosk_ros_model_downloader.model_downloader.get_model
def get_model(self, language)
Definition: vosk_ros_model_downloader.py:126
vosk_ros_model_downloader.model_downloader.load_models
def load_models(self)
Definition: vosk_ros_model_downloader.py:133
vosk_ros_model_downloader.model_downloader.get_listbox_model
def get_listbox_model(self)
Definition: vosk_ros_model_downloader.py:117
vosk_ros_model_downloader.model_downloader.lbl_model
lbl_model
Definition: vosk_ros_model_downloader.py:73
vosk_ros_model_downloader.model_downloader.btn_click_download
def btn_click_download(self, model_to_download)
Definition: vosk_ros_model_downloader.py:185
vosk_ros_model_downloader.model_downloader.model_names
model_names
Definition: vosk_ros_model_downloader.py:45
vosk_ros_model_downloader.model_downloader.get_listbox_language
def get_listbox_language(self)
Definition: vosk_ros_model_downloader.py:114
vosk_ros_model_downloader.model_downloader.gui_y
gui_y
Definition: vosk_ros_model_downloader.py:37
vosk_ros_model_downloader.model_downloader.package_path
package_path
Definition: vosk_ros_model_downloader.py:24
vosk_ros_model_downloader.model_downloader.gui_master
gui_master
Definition: vosk_ros_model_downloader.py:40
vosk_ros_model_downloader.model_downloader.execution_method
execution_method
Definition: vosk_ros_model_downloader.py:32
vosk_ros_model_downloader.model_downloader.model_frame
model_frame
Definition: vosk_ros_model_downloader.py:55
vosk_ros_model_downloader.model_downloader.get_model_link
def get_model_link(self, model_to_download)
Definition: vosk_ros_model_downloader.py:252
vosk_ros_model_downloader.model_downloader.btn_click_browse_folder
def btn_click_browse_folder(self)
Definition: vosk_ros_model_downloader.py:120
vosk_ros_model_downloader.model_downloader.lbl_directory
lbl_directory
Definition: vosk_ros_model_downloader.py:102
vosk_ros_model_downloader.model_downloader.gui_font
gui_font
Definition: vosk_ros_model_downloader.py:38
vosk_ros_model_downloader.model_downloader.r
r
Definition: vosk_ros_model_downloader.py:138
vosk_ros_model_downloader.model_downloader.unzip
def unzip(self, directory, filename)
Definition: vosk_ros_model_downloader.py:270
vosk_ros_model_downloader.model_downloader.on_combo_language_select
def on_combo_language_select(self, event)
Definition: vosk_ros_model_downloader.py:240
vosk_ros_model_downloader.model_downloader.lbl_language
lbl_language
Definition: vosk_ros_model_downloader.py:70
vosk_ros_model_downloader.model_downloader.model_dir
model_dir
Definition: vosk_ros_model_downloader.py:26
vosk_ros_model_downloader.model_downloader.lbl_download
lbl_download
Definition: vosk_ros_model_downloader.py:99
vosk_ros_model_downloader.model_downloader.directory_frame
directory_frame
Definition: vosk_ros_model_downloader.py:58
vosk_ros_model_downloader.model_downloader.control_frame
control_frame
Definition: vosk_ros_model_downloader.py:61
vosk_ros_model_downloader.model_downloader.execute_standalone
def execute_standalone(self)
Definition: vosk_ros_model_downloader.py:275
vosk_ros_model_downloader.model_downloader.btn_browse
btn_browse
Definition: vosk_ros_model_downloader.py:105
vosk_ros_model_downloader.model_downloader
Definition: vosk_ros_model_downloader.py:20
vosk_ros_model_downloader.model_downloader.gui_x
gui_x
Definition: vosk_ros_model_downloader.py:36
vosk_ros_model_downloader.model_downloader.get_model_info
def get_model_info(self, selected_model, language)
Definition: vosk_ros_model_downloader.py:170
vosk_ros_model_downloader.model_downloader.combo_languages
combo_languages
Definition: vosk_ros_model_downloader.py:76
vosk_ros_model_downloader.model_downloader.execute
def execute(self)
Definition: vosk_ros_model_downloader.py:279
vosk_ros_model_downloader.model_downloader.url
url
Definition: vosk_ros_model_downloader.py:34
vosk_ros_model_downloader.model_downloader.on_combo_model_select
def on_combo_model_select(self, event)
Definition: vosk_ros_model_downloader.py:263
vosk_ros_model_downloader.model_downloader.progressbar
progressbar
Definition: vosk_ros_model_downloader.py:111
vosk_ros_model_downloader.model_downloader.download
def download(self, model_to_download)
Definition: vosk_ros_model_downloader.py:191
vosk_ros_model_downloader.model_downloader.lbl_welcome
lbl_welcome
Definition: vosk_ros_model_downloader.py:67


vosk
Author(s): Angelo Antikatzidis. , Alpha Cephei Inc.
autogenerated on Fri May 5 2023 02:23:58