From 24707a62d9d501f2d72e40fbcb04aa22ad6678d8 Mon Sep 17 00:00:00 2001 From: Kazto Kitabatake Date: Wed, 12 Jul 2023 14:34:26 +0900 Subject: [PATCH 01/13] =?UTF-8?q?yt-dlp=E4=BB=AE=E5=AE=9F=E8=A3=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app.py | 2 ++ menuItemsDic.py | 2 ++ recorder.py | 17 ++++++++++++----- requirements.txt | 1 + sources/ydl.py | 43 +++++++++++++++++++++++++++++++++++++++++++ views/main.py | 13 +++++++++++++ 6 files changed, 73 insertions(+), 5 deletions(-) create mode 100644 sources/ydl.py diff --git a/app.py b/app.py index d23ed1f..4d79079 100644 --- a/app.py +++ b/app.py @@ -71,6 +71,8 @@ def initialize(self): # 「ツイキャスの監視を有効化」の設定値を確認 if self.config.getboolean("twitcasting", "enable", True) and self.tc.initialize(): self.tc.start() + from sources import ydl + self.ydl = ydl.YDL() self.hMainView.Show() if self.config.getboolean("general", "autoHide", False): self.hMainView.events.hide() diff --git a/menuItemsDic.py b/menuItemsDic.py index 14d1ffa..d7919c5 100644 --- a/menuItemsDic.py +++ b/menuItemsDic.py @@ -29,6 +29,8 @@ def getValueString(ref_id): "TC_SET_TOKEN": _("アクセストークンを設定(&T)"), "TC_MANAGE_USER": _("通知対象ユーザの管理(&M)") + "...", "TC_FILETYPES": _("録画形式の設定"), + "YDL_SUB": _("その他のサービス(&yt-dlp)"), + "YDL_DOWNLOAD": _("&URLを指定してダウンロード"), "OP_SETTINGS": _("設定(&S)") + "...", "OP_SHORTCUT": _("キーボードショートカットの設定(&K)") + "...", "OP_HOTKEY": _("グローバルホットキーの設定(&H)") + "...", diff --git a/recorder.py b/recorder.py index c73043e..1c0f8bb 100644 --- a/recorder.py +++ b/recorder.py @@ -18,7 +18,7 @@ class Recorder(threading.Thread): - def __init__(self, source, stream, userName, time, movie="", *, header={}, userAgent="Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko", skipExisting=False): + def __init__(self, source, stream, userName, time, movie="", *, header={}, userAgent="Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko", skipExisting=False, ext=None): """コンストラクタ :param source: SourceBaseクラスを継承したオブジェクト。 @@ -53,6 +53,10 @@ def __init__(self, source, stream, userName, time, movie="", *, header={}, userA self.processHeader(header) self.userAgent = userAgent self.skipExisting = skipExisting + if ext is None: + self.ext = self.source.getFiletype() + else: + self.ext = ext super().__init__(daemon=True) self.log.info("stream URL: %s" % self.stream) @@ -76,7 +80,7 @@ def getOutputFile(self): if self.addMovieId: fname += "(%s)" % self.movie lst.append(fname) - ext = self.source.getFiletype() + ext = self.ext path = "%s.%s" % ("\\".join(lst), ext) path = self.extractVariable(path) os.makedirs(os.path.dirname(path), exist_ok=True) @@ -144,15 +148,18 @@ def getCommand(self): "-headers", '"%s"' % self.header, ] + if self.userAgent: + cmd += [ + "-user-agent", + '"%s"' % self.userAgent, + ] cmd += [ - "-user-agent", - '"%s"' % self.userAgent, "-i", '"%s"' % self.stream, "-max_muxing_queue_size", "1024", ] - if not self.needEncode(self.source.getFiletype()): + if not self.needEncode(self.ext): cmd += [ "-c", "copy", diff --git a/requirements.txt b/requirements.txt index 0774e59..72adff9 100644 --- a/requirements.txt +++ b/requirements.txt @@ -12,3 +12,4 @@ https://github.com/actlaboratory/named-pipe/archive/v1.0.4.zip https://github.com/actlaboratory/diff_archiver/archive/v1.0.1.zip beautifulsoup4 lxml +yt-dlp==2023.7.6 diff --git a/sources/ydl.py b/sources/ydl.py new file mode 100644 index 0000000..e4be6ee --- /dev/null +++ b/sources/ydl.py @@ -0,0 +1,43 @@ +# yt-dlp module for ULTRA + +import datetime +import json +import logging + +import yt_dlp + +import constants +import recorder +from sources.base import SourceBase + + +class YDL(SourceBase): + name = "ydl" + friendlyName = _("その他のサービス(yt-dlp)") + index = 1 + filetypes = { + "b": _("動画"), + "a": _("音声のみ"), + } + defaultFiletype = "b" + + def __init__(self): + super().__init__() + self.log = logging.getLogger("%s.%s" % (constants.LOG_PREFIX, "sources.ydl")) + + def download(self, url): + # yt-dlpのオプション + options = { + # 詳しいログを出す + "verbose": True, + # とりあえず動画に固定 + "format": "b", + # ログ出力 + "logger": self.log, + } + with yt_dlp.YoutubeDL(options) as ydl: + info = ydl.extract_info(url, False) + with open("info.json", "w", encoding="utf-8") as f: + json.dump(info, f, ensure_ascii=False, indent=1) + r = recorder.Recorder(self, info["url"], "%(user)s(%(extractor)s)" % {"user": info["channel"], "extractor": info["extractor"]}, datetime.datetime.strptime(info["upload_date"], "%Y%m%d"), info["id"], header=info["http_headers"], userAgent="", ext=info["ext"]) + r.start() diff --git a/views/main.py b/views/main.py index 3beabd1..d58e826 100644 --- a/views/main.py +++ b/views/main.py @@ -106,6 +106,7 @@ def Apply(self,target): self.hServicesMenu.Bind(wx.EVT_MENU_OPEN, self.event.OnMenuOpen) self.hTwitcastingMenu=wx.Menu() self.hTwitcastingFiletypesMenu = wx.Menu() + self.hYDLMenu=wx.Menu() self.hOptionMenu = wx.Menu() self.hHelpMenu=wx.Menu() @@ -117,6 +118,7 @@ def Apply(self,target): # サービスメニューの中身 self.RegisterMenuCommand(self.hServicesMenu, "TC_SUB", subMenu=self.hTwitcastingMenu) + self.RegisterMenuCommand(self.hServicesMenu, "YDL_SUB", subMenu=self.hYDLMenu) # ツイキャスメニューの中身 self.RegisterCheckMenuCommand(self.hTwitcastingMenu, "TC_ENABLE") self.RegisterCheckMenuCommand(self.hTwitcastingMenu, "TC_SAVE_COMMENTS") @@ -133,6 +135,10 @@ def Apply(self,target): "TC_MANAGE_USER", ]) self.RegisterMenuCommand(self.hTwitcastingMenu, "TC_FILETYPES", subMenu=self.hTwitcastingFiletypesMenu) + # yt-dlpメニューの中身 + self.RegisterMenuCommand(self.hYDLMenu, [ + "YDL_DOWNLOAD", + ]) # オプションメニュー self.RegisterMenuCommand(self.hOptionMenu, [ @@ -267,6 +273,13 @@ def OnMenuSelect(self,event): globalVars.app.tc.users = d.GetValue() globalVars.app.tc.saveUserList() + # yt-dlp:URLを指定してダウンロード + if selected == menuItemsStore.getRef("YDL_DOWNLOAD"): + d = SimpleInputDialog.Dialog(_("URLを入力"), _("URLの指定")) + d.Initialize() + if d.Show() == wx.ID_CANCEL: return + globalVars.app.ydl.download(d.GetData()) + # 設定 if selected == menuItemsStore.getRef("OP_SETTINGS"): d = settingsDialog.Dialog() From 595a0f863e9b7aee4aee1d4d276e07a1774deda0 Mon Sep 17 00:00:00 2001 From: Kazto Kitabatake Date: Wed, 12 Jul 2023 21:30:20 +0900 Subject: [PATCH 02/13] fix pillow version --- requirements.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/requirements.txt b/requirements.txt index 72adff9..9ef4d3b 100644 --- a/requirements.txt +++ b/requirements.txt @@ -13,3 +13,4 @@ https://github.com/actlaboratory/diff_archiver/archive/v1.0.1.zip beautifulsoup4 lxml yt-dlp==2023.7.6 +pillow==9 From 85634f11bade952839e017c420e1c5cf7e196847 Mon Sep 17 00:00:00 2001 From: Kazto Kitabatake Date: Thu, 13 Jul 2023 18:39:10 +0900 Subject: [PATCH 03/13] =?UTF-8?q?=E3=82=A8=E3=83=A9=E3=83=BC=E5=87=A6?= =?UTF-8?q?=E7=90=86=E3=82=92=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sources/ydl.py | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/sources/ydl.py b/sources/ydl.py index e4be6ee..8aabcd4 100644 --- a/sources/ydl.py +++ b/sources/ydl.py @@ -3,11 +3,13 @@ import datetime import json import logging +import traceback import yt_dlp import constants import recorder +import simpleDialog from sources.base import SourceBase @@ -34,10 +36,21 @@ def download(self, url): "format": "b", # ログ出力 "logger": self.log, + # プレイリストの各アイテムをダウンロードしないようにする + "extract_flat": "in_playlist", } - with yt_dlp.YoutubeDL(options) as ydl: - info = ydl.extract_info(url, False) - with open("info.json", "w", encoding="utf-8") as f: - json.dump(info, f, ensure_ascii=False, indent=1) + try: + with yt_dlp.YoutubeDL(options) as ydl: + info = ydl.extract_info(url, False) + except Exception as e: + self.log.error(traceback.format_exc()) + simpleDialog.errorDialog(_("動画情報の取得に失敗しました。\n詳細:%s") % e) + return + # ビデオ以外は現状サポートしていない + _type = info.get("_type", "video") + if _type != "video": + self.log.error("unsupported: %s" % _type) + simpleDialog.errorDialog(_("%sのダウンロードは現在サポートされていません。") % _type) + return r = recorder.Recorder(self, info["url"], "%(user)s(%(extractor)s)" % {"user": info["channel"], "extractor": info["extractor"]}, datetime.datetime.strptime(info["upload_date"], "%Y%m%d"), info["id"], header=info["http_headers"], userAgent="", ext=info["ext"]) r.start() From b21d5ea0f96accaf224f7d817ee6b7d868c8fccd Mon Sep 17 00:00:00 2001 From: Kazto Kitabatake Date: Fri, 14 Jul 2023 10:36:14 +0900 Subject: [PATCH 04/13] =?UTF-8?q?=E5=8B=95=E7=94=BB=E5=BD=A2=E5=BC=8F?= =?UTF-8?q?=E3=81=AE=E9=81=B8=E6=8A=9E=E3=81=AB=E5=AF=BE=E5=BF=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- menuItemsDic.py | 1 + sources/ydl.py | 6 +++--- views/main.py | 4 ++++ 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/menuItemsDic.py b/menuItemsDic.py index d7919c5..6f4998d 100644 --- a/menuItemsDic.py +++ b/menuItemsDic.py @@ -31,6 +31,7 @@ def getValueString(ref_id): "TC_FILETYPES": _("録画形式の設定"), "YDL_SUB": _("その他のサービス(&yt-dlp)"), "YDL_DOWNLOAD": _("&URLを指定してダウンロード"), + "YDL_FILETYPES": _("録画形式の設定"), "OP_SETTINGS": _("設定(&S)") + "...", "OP_SHORTCUT": _("キーボードショートカットの設定(&K)") + "...", "OP_HOTKEY": _("グローバルホットキーの設定(&H)") + "...", diff --git a/sources/ydl.py b/sources/ydl.py index 8aabcd4..bc74090 100644 --- a/sources/ydl.py +++ b/sources/ydl.py @@ -19,7 +19,7 @@ class YDL(SourceBase): index = 1 filetypes = { "b": _("動画"), - "a": _("音声のみ"), + "ba": _("音声のみ"), } defaultFiletype = "b" @@ -32,8 +32,8 @@ def download(self, url): options = { # 詳しいログを出す "verbose": True, - # とりあえず動画に固定 - "format": "b", + # ダウンロードするファイル形式 + "format": self.getFiletype(), # ログ出力 "logger": self.log, # プレイリストの各アイテムをダウンロードしないようにする diff --git a/views/main.py b/views/main.py index d58e826..9748534 100644 --- a/views/main.py +++ b/views/main.py @@ -107,6 +107,7 @@ def Apply(self,target): self.hTwitcastingMenu=wx.Menu() self.hTwitcastingFiletypesMenu = wx.Menu() self.hYDLMenu=wx.Menu() + self.hYDLFiletypesMenu = wx.Menu() self.hOptionMenu = wx.Menu() self.hHelpMenu=wx.Menu() @@ -139,6 +140,7 @@ def Apply(self,target): self.RegisterMenuCommand(self.hYDLMenu, [ "YDL_DOWNLOAD", ]) + self.RegisterMenuCommand(self.hYDLMenu, "YDL_FILETYPES", subMenu=self.hYDLFiletypesMenu) # オプションメニュー self.RegisterMenuCommand(self.hOptionMenu, [ @@ -168,6 +170,8 @@ def OnMenuOpen(self, event): menu = event.GetMenu() if menu == self.parent.menu.hTwitcastingFiletypesMenu: globalVars.app.tc.getFiletypesMenu(menu) + if menu == self.parent.menu.hYDLFiletypesMenu: + globalVars.app.ydl.getFiletypesMenu(menu) def OnMenuSelect(self,event): """メニュー項目が選択されたときのイベントハンドら。""" From f37bef56dee5d0af79ef736ed0843836e3eb1e33 Mon Sep 17 00:00:00 2001 From: Kazto Kitabatake Date: Fri, 14 Jul 2023 13:51:07 +0900 Subject: [PATCH 05/13] =?UTF-8?q?ydl=E3=81=AF=E5=BF=85=E3=81=9A=E5=8B=95?= =?UTF-8?q?=E7=94=BBID=E3=82=92=E4=BB=98=E4=B8=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- recorder.py | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/recorder.py b/recorder.py index 1c0f8bb..ffbd5c1 100644 --- a/recorder.py +++ b/recorder.py @@ -38,12 +38,12 @@ def __init__(self, source, stream, userName, time, movie="", *, header={}, userA :param skipExisting: 保存先ファイルが存在する場合、録画処理を中断するかどうか :type skipExisting: bool """ - self.addMovieId = False + # 配信開始日時がとれなかったことを示すフラグ + self.timeIsNone = time is None if type(time) == int: time = datetime.datetime.fromtimestamp(time) elif time is None: time = datetime.datetime.now() - self.addMovieId = True self.stream = stream self.userName = userName self.time = time @@ -77,7 +77,7 @@ def getOutputFile(self): if globalVars.app.config.getboolean("record", "createSubDir", True): lst.append(self.replaceUnusableChar(globalVars.app.config["record"]["subDirName"])) fname = self.replaceUnusableChar(globalVars.app.config["record"]["fileName"]) - if self.addMovieId: + if self.addMovieId(): fname += "(%s)" % self.movie lst.append(fname) ext = self.ext @@ -236,9 +236,21 @@ def isRecordedByAnotherThread(self): def needEncode(self, ext): from sources.twitcasting import Twitcasting + # ツイキャスは必ずMP4 if isinstance(self.source, Twitcasting) and ext == "mp4": return False return True + + def addMovieId(self): + # 配信開始日時がとれなかった + if self.timeIsNone: + return True + # ydl + from sources.ydl import YDL + if isinstance(self.source, YDL): + return True + # 通常は不要 + return False def getRecordingUsers(self=None): """現在録画中のユーザ名のリストを返す From 0bb291d62dc0d3eb4fb05621d73c4153e8345d06 Mon Sep 17 00:00:00 2001 From: Kazto Kitabatake Date: Sat, 15 Jul 2023 12:00:26 +0900 Subject: [PATCH 06/13] use `uploader` instead of `channel` --- sources/ydl.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sources/ydl.py b/sources/ydl.py index bc74090..6bfda4e 100644 --- a/sources/ydl.py +++ b/sources/ydl.py @@ -52,5 +52,5 @@ def download(self, url): self.log.error("unsupported: %s" % _type) simpleDialog.errorDialog(_("%sのダウンロードは現在サポートされていません。") % _type) return - r = recorder.Recorder(self, info["url"], "%(user)s(%(extractor)s)" % {"user": info["channel"], "extractor": info["extractor"]}, datetime.datetime.strptime(info["upload_date"], "%Y%m%d"), info["id"], header=info["http_headers"], userAgent="", ext=info["ext"]) + r = recorder.Recorder(self, info["url"], "%(user)s(%(extractor)s)" % {"user": info["uploader"], "extractor": info["extractor"]}, datetime.datetime.strptime(info["upload_date"], "%Y%m%d"), info["id"], header=info["http_headers"], userAgent="", ext=info["ext"]) r.start() From 84b5e45cebbd8c313ec4815f8f0f26cf0f305dad Mon Sep 17 00:00:00 2001 From: Kazto Kitabatake Date: Sat, 15 Jul 2023 12:13:04 +0900 Subject: [PATCH 07/13] add debug functionality --- sources/ydl.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/sources/ydl.py b/sources/ydl.py index 6bfda4e..6a45e95 100644 --- a/sources/ydl.py +++ b/sources/ydl.py @@ -12,6 +12,10 @@ import simpleDialog from sources.base import SourceBase +# debug +# 0: 何もしない、1:info_jsonを保存 +DEBUG = 0 + class YDL(SourceBase): name = "ydl" @@ -46,6 +50,10 @@ def download(self, url): self.log.error(traceback.format_exc()) simpleDialog.errorDialog(_("動画情報の取得に失敗しました。\n詳細:%s") % e) return + # debug + if DEBUG: + with open("info_%s.json" % info["id"], "w", encoding="utf-8") as f: + json.dump(info, f, ensure_ascii=False, indent="\t") # ビデオ以外は現状サポートしていない _type = info.get("_type", "video") if _type != "video": From a105e939b7317dcfd336f0a29e9cff5ecf44642d Mon Sep 17 00:00:00 2001 From: Kazto Kitabatake Date: Mon, 17 Jul 2023 10:32:30 +0900 Subject: [PATCH 08/13] update documentation --- public/history.txt | 3 +++ public/readme.txt | 16 ++++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/public/history.txt b/public/history.txt index c8a4d8d..fa2a06a 100644 --- a/public/history.txt +++ b/public/history.txt @@ -1,5 +1,8 @@ Universal Live Tracking and Recording App(ULTRA) 更新履歴 +2023/07/17 Version 1.7.0 +1. 「yt-dlp」との連携機能を追加し、YouTubeなどの動画をダウンロードできるようになりました。現状、最新の動画を定期的に取得することはできませんが、再生ページのURLを入力することで、お好きな動画をダウンロードしていただけます。 + 2023/04/29 Version 1.6.0 1. Twitterスペースとの連携機能を廃止しました。Twitter APIの変更により、この機能の継続的な運用が難しくなりました。これまでご愛顧いただき、ありがとうございました。 2. ツイキャス連携機能において、[Twitterでフォローしているユーザを一括追加]を廃止しました。 diff --git a/public/readme.txt b/public/readme.txt index 8fd8a4e..8090860 100644 --- a/public/readme.txt +++ b/public/readme.txt @@ -22,6 +22,8 @@ ULTRAはWindowsの標準的なコントロールのみを使用しており、 現時点では、以下のサービスに対応しています。 今後の更新で、更に対応サービスを追加する予定です。 ・ツイキャス(https://twitcasting.tv/) +・YouTubeなど、「yt-dlp」(https://github.com/yt-dlp/yt-dlp)がサポートしているサービスからの動画のダウンロード +※yt-dlpとの連携機能は、基本的にYouTube動画のダウンロードのために使用することを想定しています。他のサービスの動画もダウンロードを試みますが、すべてのサービスの動画を確実にダウンロードできることを保障するものではありません。 第2章 セットアップ 2.1 インストール @@ -118,6 +120,20 @@ ULTRAをコンピュータから削除する場合は、「ULTRA」フォルダ 6. [過去ライブのダウンロード]と[ログイン状態で録画]では、同じログイン情報を共有しています。そのため、一方でパスワードを入力してログインに成功すると、もう一方の機能を使用する際にパスワードを入力する必要はありません。また、セッション情報は、ULTRAをインストールしたフォルダ内の「data」フォルダにある「twitcasting」サブフォルダ内に、「session.dat」というファイル名で保存されます。このファイルを外部に流出させないよう、十分ご注意ください。 7. ULTRA Version 1.5.2の更新に伴い、[ログイン状態で録画]および[過去ライブのダウンロード]機能でTwitterアカウントにログインする際、ツイキャスのサイトで設定された「ログインパスワード」を使用するようになりました。この機能の使用前に、ツイキャスのサイトでログインパスワードを設定し、それをULTRAに入力する必要があります。なお、旧バージョンで過去にログインしたことがあり、そのセッションが利用可能な場合、手動でセッションを削除したり、何らかの理由でセッションが無効になったりしない限り、特別な操作は不要です。 +4.2 「yt-dlp」対応サービスからの動画ダウンロード機能 +4.2.1 yt-dlpとの連携機能の概要 +本ソフトと一緒にインストールされる「yt-dlp」と連携し、動画をダウンロードする機能です。 +基本的に、YouTube動画のダウンロード機能として使用することを想定しています。 +動画をダウンロードするには、メニューバーの[サービス]→[その他のサービス(yt-dlp)]→[URLを指定してダウンロード]を選択し、再生ページのURLを入力します。 +なお、動画の形式は[動画]と[音声のみ]を選択できますが、具体的なファイル形式(mp4、mp3など)は、対象の動画の種類によって変化します。 +また、保存先フォルダ・ファイル名に関して、ユーザ名の末尾に対象サービス名(例:youtube)を、ファイル名の末尾に動画のIDを、それぞれ追加します。 + +4.2.2 制限事項 +本機能の利用に関して、現状、以下の制限があります。 +・プレイリストやチャンネルなど、複数の動画を含むURLを指定してダウンロードすることができません。必ず、動画のURLを入力してください。 +・動画のダウンロードに当たっては、「yt-dlpで取得した情報を元にffmpegを呼び出す」という方法をとっています。そのため、yt-dlpの対応サービスの内、ダウンロード時に特殊な処理が必要なサービスでは、本ソフトでの動画のダウンロードに失敗する可能性があります。現時点で、「ニコニコ動画」の動画をダウンロードできない事象を確認しています。 +・本ソフトを用いてYouTubeの動画をダウンロードした際、「録画エラー」として何らかのエラーメッセージが表示されることがあります。しかし、ダウンロードに失敗しているのか、成功しているのかは、保存されたファイルを確認しなければ判断できません。そこで、同じ動画を複数回ダウンロードしてしまうことのないよう、録画エラーが発生した場合でも、エラー内容を表示するのみで、直ちに録画処理を終了します(再度録画を開始することはありません)。 + 第5章 メニューリファレンス ここでは、ULTRAの各メニュー項目について解説します。 また、メニューを選択することによって表示される設定画面の内容についても記載しています。 From 32af9e9f46971f81213cd7a65e7811322d4ac437 Mon Sep 17 00:00:00 2001 From: Kazto Kitabatake Date: Mon, 17 Jul 2023 10:50:19 +0900 Subject: [PATCH 09/13] update translation --- locale/en-us/LC_MESSAGES/messages.mo | Bin 28276 -> 28904 bytes locale/en-us/LC_MESSAGES/messages.po | 132 +++++++++++++++++---------- locale/ja-jp/LC_MESSAGES/messages.po | 118 +++++++++++++++--------- locale/messages.po | 118 +++++++++++++++--------- 4 files changed, 236 insertions(+), 132 deletions(-) diff --git a/locale/en-us/LC_MESSAGES/messages.mo b/locale/en-us/LC_MESSAGES/messages.mo index 203e282ae0b916b6235689ad7e6bbdb6f43d3327..d24d21fba5b625b3edd18b16a1ecd335e8f7b91a 100644 GIT binary patch delta 6224 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 delta 5741 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 Y9R@7+EiN5=t7>sbc3h>x?o&4X2Ju6zzyJUM diff --git a/locale/en-us/LC_MESSAGES/messages.po b/locale/en-us/LC_MESSAGES/messages.po index f53f138..208af77 100644 --- a/locale/en-us/LC_MESSAGES/messages.po +++ b/locale/en-us/LC_MESSAGES/messages.po @@ -5,19 +5,19 @@ # msgid "" msgstr "" -"Project-Id-Version: TCV\n" +"Project-Id-Version: ULTRA\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-04-29 23:05+0900\n" -"PO-Revision-Date: 2023-04-29 23:07+0900\n" +"POT-Creation-Date: 2023-07-17 10:32+0900\n" +"PO-Revision-Date: 2023-07-17 10:49+0900\n" "Last-Translator: \n" "Language-Team: \n" "Language: en_US\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Generator: Poedit 3.2.2\n" +"X-Generator: Poedit 3.3.2\n" -#: app.py:66 menuItemsDic.py:31 +#: app.py:66 menuItemsDic.py:31 menuItemsDic.py:34 msgid "録画形式の設定" msgstr "Recording format settings" @@ -149,26 +149,34 @@ msgid "通知対象ユーザの管理(&M)" msgstr "&Manage Notified Users" #: menuItemsDic.py:32 +msgid "その他のサービス(&yt-dlp)" +msgstr "Other Services(&yt-dlp)" + +#: menuItemsDic.py:33 +msgid "&URLを指定してダウンロード" +msgstr "Download by &URL" + +#: menuItemsDic.py:35 msgid "設定(&S)" msgstr "&Settings" -#: menuItemsDic.py:33 +#: menuItemsDic.py:36 msgid "キーボードショートカットの設定(&K)" msgstr "Shortcut &Key Configuration" -#: menuItemsDic.py:34 +#: menuItemsDic.py:37 msgid "グローバルホットキーの設定(&H)" msgstr "Global &Hot Key Configuration" -#: menuItemsDic.py:35 +#: menuItemsDic.py:38 msgid "Windows起動時の自動起動を有効化(&W)" msgstr "Enable automatic startup on &Windows startup" -#: menuItemsDic.py:36 +#: menuItemsDic.py:39 msgid "最新バージョンを確認(&U)" msgstr "Check For &Updates" -#: menuItemsDic.py:37 +#: menuItemsDic.py:40 msgid "バージョン情報(&V)" msgstr "&Version Info" @@ -177,12 +185,12 @@ msgstr "&Version Info" msgid "配信開始:%s、サービス:%s" msgstr "Broadcasting Started: %s, service: %s" -#: recorder.py:169 recorder.py:171 recorder.py:182 recorder.py:194 -#: recorder.py:198 recorder.py:200 +#: recorder.py:176 recorder.py:178 recorder.py:189 recorder.py:201 +#: recorder.py:205 recorder.py:207 msgid "録画エラー" msgstr "Recording error" -#: recorder.py:169 +#: recorder.py:176 msgid "" "録画の開始に失敗しました。録画の保存先が適切に設定されていることを確認してく" "ださい。定期的に再試行する場合は[はい]、処理を中断する場合は[いいえ]を選択し" @@ -194,41 +202,41 @@ msgstr "" "interrupt the process. You may be able to start recording correctly by " "selecting Yes and changing where the recording is saved." -#: recorder.py:171 recorder.py:182 +#: recorder.py:178 recorder.py:189 #, python-format msgid "%sのライブの録画処理を中断しました。" msgstr "Recording process for %s's broadcasting has been canseled." -#: recorder.py:185 +#: recorder.py:192 msgid "録画開始" msgstr "Start recording" -#: recorder.py:185 recorder.py:212 sources\twitcasting.py:830 +#: recorder.py:192 recorder.py:219 sources\twitcasting.py:830 #: sources\twitcasting.py:842 #, python-format msgid "ユーザ:%(user)s、ムービーID:%(movie)s" msgstr "User: %(user)s, Movie ID:%(movie)s" -#: recorder.py:186 +#: recorder.py:193 msgid "録画中" msgstr "Recording" -#: recorder.py:194 recorder.py:198 +#: recorder.py:201 recorder.py:205 #, python-format msgid "%sのライブを録画中にエラーが発生しました。" msgstr "An error has occured while recording %s's live." -#: recorder.py:194 recorder.py:198 recorder.py:200 +#: recorder.py:201 recorder.py:205 recorder.py:207 #, python-format msgid "詳細:%s" msgstr "Details: %s" -#: recorder.py:200 +#: recorder.py:207 #, python-format msgid "%sのライブを録画中にエラーが発生したため、再度録画を開始します。" msgstr "An error has occured while recording %s's live. retrying..." -#: recorder.py:212 +#: recorder.py:219 msgid "録画終了" msgstr "End of recording" @@ -286,7 +294,7 @@ msgstr "" "Download has successfully finished.\n" "Update will be started when closing the application." -#: sources\twitcasting.py:42 sources\twitcasting.py:1107 views\main.py:369 +#: sources\twitcasting.py:42 sources\twitcasting.py:1107 views\main.py:386 msgid "ツイキャス" msgstr "TwitCasting" @@ -693,6 +701,32 @@ msgid "認証が必要です。ブラウザで操作を完了してください msgstr "" "Authorization is required. Open the browser, and finish the authentication." +#: sources\ydl.py:22 +msgid "その他のサービス(yt-dlp)" +msgstr "Other Services(yt-dlp)" + +#: sources\ydl.py:25 +msgid "動画" +msgstr "video" + +#: sources\ydl.py:26 +msgid "音声のみ" +msgstr "Audio only" + +#: sources\ydl.py:51 +#, python-format +msgid "" +"動画情報の取得に失敗しました。\n" +"詳細:%s" +msgstr "" +"Failed to get video information.\n" +"Details: %s" + +#: sources\ydl.py:61 +#, python-format +msgid "%sのダウンロードは現在サポートされていません。" +msgstr "Downloading %s is not currently supported." + #: views\auth.py:23 msgid "ブラウザでの操作を待っています..." msgstr "waiting for browser..." @@ -746,7 +780,7 @@ msgstr "shortcut" msgid "識別子" msgstr "identifier" -#: views\globalKeyConfig.py:31 views\main.py:278 +#: views\globalKeyConfig.py:31 views\main.py:295 msgid "ショートカットキーの設定" msgstr "Shortcut Key Configuration" @@ -755,7 +789,7 @@ msgstr "Shortcut Key Configuration" #: views\globalKeyConfig.py:120 views\globalKeyConfig.py:128 #: views\globalKeyConfig.py:138 views\globalKeyConfig.py:143 #: views\keyConfig.py:57 views\KeyValueSettingDialogBase.py:333 -#: views\main.py:375 views\main.py:394 +#: views\main.py:392 views\main.py:411 msgid "なし" msgstr "None" @@ -945,23 +979,23 @@ msgstr "" "and key names.\n" "\n" -#: views\main.py:152 +#: views\main.py:160 msgid "ファイル(&F)" msgstr "&File" -#: views\main.py:153 +#: views\main.py:161 msgid "サービス(&S)" msgstr "&Services" -#: views\main.py:154 +#: views\main.py:162 msgid "オプション(&O)" msgstr "&Options" -#: views\main.py:155 +#: views\main.py:163 msgid "ヘルプ(&H)" msgstr "&Help" -#: views\main.py:198 views\main.py:204 views\main.py:399 +#: views\main.py:208 views\main.py:214 views\main.py:416 #: views\settingsDialog.py:167 msgid "" "設定の保存に失敗しました。下記のファイルへのアクセスが可能であることを確認し" @@ -969,54 +1003,58 @@ msgid "" msgstr "" "Failed to save settings. Make sure you can access to the following files:" -#: views\main.py:216 +#: views\main.py:226 views\main.py:282 msgid "URLを入力" msgstr "Enter URL" -#: views\main.py:216 +#: views\main.py:226 msgid "再生ページのURL" msgstr "Playback page URL" -#: views\main.py:223 views\main.py:230 +#: views\main.py:233 views\main.py:240 msgid "ユーザ名を入力" msgstr "Enter user name" -#: views\main.py:223 views\main.py:230 views\tcManageUser.py:20 +#: views\main.py:233 views\main.py:240 views\tcManageUser.py:20 #: views\tcManageUser.py:99 msgid "ユーザ名" msgstr "user name" -#: views\main.py:246 +#: views\main.py:256 msgid "すでに削除されています。" msgstr "It has already been deleted." -#: views\main.py:248 +#: views\main.py:258 msgid "アクセストークンの削除" msgstr "Delete access token" -#: views\main.py:248 +#: views\main.py:258 msgid "" "ツイキャス連携機能を無効化し、アクセストークンを削除します。よろしいですか?" msgstr "" "Disable TwitCasting functions and remove the access token. Are you sure?" -#: views\main.py:255 views\main.py:344 views\main.py:350 +#: views\main.py:265 views\main.py:361 views\main.py:367 msgid "完了" msgstr "Finish" -#: views\main.py:255 +#: views\main.py:265 msgid "アクセストークンを削除しました。" msgstr "Removed the access token." -#: views\main.py:286 +#: views\main.py:282 +msgid "URLの指定" +msgstr "set URL" + +#: views\main.py:303 msgid "グローバルホットキーの設定" msgstr "Global Hot Keys Settings" -#: views\main.py:325 views\main.py:341 +#: views\main.py:342 views\main.py:358 msgid "確認" msgstr "confirmation" -#: views\main.py:325 +#: views\main.py:342 msgid "" "録画処理を実行中です。このまま終了すると、録画は中断されます。終了してもよろ" "しいですか?" @@ -1024,17 +1062,17 @@ msgstr "" "Recording process is running. If you exit, the recording will be " "interrupted. Are you sure?" -#: views\main.py:341 +#: views\main.py:358 msgid "Windows起動時の自動起動はすでに設定されています。設定を解除しますか?" msgstr "" "Automatic startup at Windows startup is already set. Do you want to un-set " "it?" -#: views\main.py:344 +#: views\main.py:361 msgid "Windows起動時の自動起動を無効化しました。" msgstr "Disabled automatic startup at Windows startup." -#: views\main.py:350 +#: views\main.py:367 msgid "Windows起動時の自動起動を設定しました。" msgstr "Set automatic startup at Windows startup." @@ -1379,9 +1417,6 @@ msgstr "close" #~ msgid "Twitterとの通信に失敗しました。詳細:%s" #~ msgstr "Communication with Twitter failed. Details: %s" -#~ msgid "ユーザ情報の取得に失敗しました。詳細:%s" -#~ msgstr "Failed to retrieve user information. Details: %s" - #~ msgid "認証情報の保存に失敗しました。" #~ msgstr "Failed to save credentials." @@ -1410,9 +1445,6 @@ msgstr "close" #~ msgid "入力されたURLが正しくありません。" #~ msgstr "The URL entered is incorrect." -#~ msgid "このスペースはまだ開始されていません。" -#~ msgstr "This space has not yet started." - #~ msgid "非公開アカウント" #~ msgstr "Private account" diff --git a/locale/ja-jp/LC_MESSAGES/messages.po b/locale/ja-jp/LC_MESSAGES/messages.po index 9dcbba5..abef4b3 100644 --- a/locale/ja-jp/LC_MESSAGES/messages.po +++ b/locale/ja-jp/LC_MESSAGES/messages.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: ULTRA\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-04-29 23:05+0900\n" +"POT-Creation-Date: 2023-07-17 10:32+0900\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -17,7 +17,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -#: app.py:66 menuItemsDic.py:31 +#: app.py:66 menuItemsDic.py:31 menuItemsDic.py:34 msgid "録画形式の設定" msgstr "" @@ -143,26 +143,34 @@ msgid "通知対象ユーザの管理(&M)" msgstr "" #: menuItemsDic.py:32 -msgid "設定(&S)" +msgid "その他のサービス(&yt-dlp)" msgstr "" #: menuItemsDic.py:33 +msgid "&URLを指定してダウンロード" +msgstr "" + +#: menuItemsDic.py:35 +msgid "設定(&S)" +msgstr "" + +#: menuItemsDic.py:36 msgid "キーボードショートカットの設定(&K)" msgstr "" -#: menuItemsDic.py:34 +#: menuItemsDic.py:37 msgid "グローバルホットキーの設定(&H)" msgstr "" -#: menuItemsDic.py:35 +#: menuItemsDic.py:38 msgid "Windows起動時の自動起動を有効化(&W)" msgstr "" -#: menuItemsDic.py:36 +#: menuItemsDic.py:39 msgid "最新バージョンを確認(&U)" msgstr "" -#: menuItemsDic.py:37 +#: menuItemsDic.py:40 msgid "バージョン情報(&V)" msgstr "" @@ -171,12 +179,12 @@ msgstr "" msgid "配信開始:%s、サービス:%s" msgstr "" -#: recorder.py:169 recorder.py:171 recorder.py:182 recorder.py:194 -#: recorder.py:198 recorder.py:200 +#: recorder.py:176 recorder.py:178 recorder.py:189 recorder.py:201 +#: recorder.py:205 recorder.py:207 msgid "録画エラー" msgstr "" -#: recorder.py:169 +#: recorder.py:176 msgid "" "録画の開始に失敗しました。録画の保存先が適切に設定されていることを確認してく" "ださい。定期的に再試行する場合は[はい]、処理を中断する場合は[いいえ]を選択し" @@ -184,41 +192,41 @@ msgid "" "きる場合があります。" msgstr "" -#: recorder.py:171 recorder.py:182 +#: recorder.py:178 recorder.py:189 #, python-format msgid "%sのライブの録画処理を中断しました。" msgstr "" -#: recorder.py:185 +#: recorder.py:192 msgid "録画開始" msgstr "" -#: recorder.py:185 recorder.py:212 sources\twitcasting.py:830 +#: recorder.py:192 recorder.py:219 sources\twitcasting.py:830 #: sources\twitcasting.py:842 #, python-format msgid "ユーザ:%(user)s、ムービーID:%(movie)s" msgstr "" -#: recorder.py:186 +#: recorder.py:193 msgid "録画中" msgstr "" -#: recorder.py:194 recorder.py:198 +#: recorder.py:201 recorder.py:205 #, python-format msgid "%sのライブを録画中にエラーが発生しました。" msgstr "" -#: recorder.py:194 recorder.py:198 recorder.py:200 +#: recorder.py:201 recorder.py:205 recorder.py:207 #, python-format msgid "詳細:%s" msgstr "" -#: recorder.py:200 +#: recorder.py:207 #, python-format msgid "%sのライブを録画中にエラーが発生したため、再度録画を開始します。" msgstr "" -#: recorder.py:212 +#: recorder.py:219 msgid "録画終了" msgstr "" @@ -272,7 +280,7 @@ msgid "" "ソフトウェア終了時に、自動でアップデートされます。" msgstr "" -#: sources\twitcasting.py:42 sources\twitcasting.py:1107 views\main.py:369 +#: sources\twitcasting.py:42 sources\twitcasting.py:1107 views\main.py:386 msgid "ツイキャス" msgstr "" @@ -638,6 +646,30 @@ msgstr "" msgid "認証が必要です。ブラウザで操作を完了してください。" msgstr "" +#: sources\ydl.py:22 +msgid "その他のサービス(yt-dlp)" +msgstr "" + +#: sources\ydl.py:25 +msgid "動画" +msgstr "" + +#: sources\ydl.py:26 +msgid "音声のみ" +msgstr "" + +#: sources\ydl.py:51 +#, python-format +msgid "" +"動画情報の取得に失敗しました。\n" +"詳細:%s" +msgstr "" + +#: sources\ydl.py:61 +#, python-format +msgid "%sのダウンロードは現在サポートされていません。" +msgstr "" + #: views\auth.py:23 msgid "ブラウザでの操作を待っています..." msgstr "" @@ -689,7 +721,7 @@ msgstr "" msgid "識別子" msgstr "" -#: views\globalKeyConfig.py:31 views\main.py:278 +#: views\globalKeyConfig.py:31 views\main.py:295 msgid "ショートカットキーの設定" msgstr "" @@ -698,7 +730,7 @@ msgstr "" #: views\globalKeyConfig.py:120 views\globalKeyConfig.py:128 #: views\globalKeyConfig.py:138 views\globalKeyConfig.py:143 #: views\keyConfig.py:57 views\KeyValueSettingDialogBase.py:333 -#: views\main.py:375 views\main.py:394 +#: views\main.py:392 views\main.py:411 msgid "なし" msgstr "" @@ -877,90 +909,94 @@ msgid "" "\n" msgstr "" -#: views\main.py:152 +#: views\main.py:160 msgid "ファイル(&F)" msgstr "" -#: views\main.py:153 +#: views\main.py:161 msgid "サービス(&S)" msgstr "" -#: views\main.py:154 +#: views\main.py:162 msgid "オプション(&O)" msgstr "" -#: views\main.py:155 +#: views\main.py:163 msgid "ヘルプ(&H)" msgstr "" -#: views\main.py:198 views\main.py:204 views\main.py:399 +#: views\main.py:208 views\main.py:214 views\main.py:416 #: views\settingsDialog.py:167 msgid "" "設定の保存に失敗しました。下記のファイルへのアクセスが可能であることを確認し" "てください。" msgstr "" -#: views\main.py:216 +#: views\main.py:226 views\main.py:282 msgid "URLを入力" msgstr "" -#: views\main.py:216 +#: views\main.py:226 msgid "再生ページのURL" msgstr "" -#: views\main.py:223 views\main.py:230 +#: views\main.py:233 views\main.py:240 msgid "ユーザ名を入力" msgstr "" -#: views\main.py:223 views\main.py:230 views\tcManageUser.py:20 +#: views\main.py:233 views\main.py:240 views\tcManageUser.py:20 #: views\tcManageUser.py:99 msgid "ユーザ名" msgstr "" -#: views\main.py:246 +#: views\main.py:256 msgid "すでに削除されています。" msgstr "" -#: views\main.py:248 +#: views\main.py:258 msgid "アクセストークンの削除" msgstr "" -#: views\main.py:248 +#: views\main.py:258 msgid "" "ツイキャス連携機能を無効化し、アクセストークンを削除します。よろしいですか?" msgstr "" -#: views\main.py:255 views\main.py:344 views\main.py:350 +#: views\main.py:265 views\main.py:361 views\main.py:367 msgid "完了" msgstr "" -#: views\main.py:255 +#: views\main.py:265 msgid "アクセストークンを削除しました。" msgstr "" -#: views\main.py:286 +#: views\main.py:282 +msgid "URLの指定" +msgstr "" + +#: views\main.py:303 msgid "グローバルホットキーの設定" msgstr "" -#: views\main.py:325 views\main.py:341 +#: views\main.py:342 views\main.py:358 msgid "確認" msgstr "" -#: views\main.py:325 +#: views\main.py:342 msgid "" "録画処理を実行中です。このまま終了すると、録画は中断されます。終了してもよろ" "しいですか?" msgstr "" -#: views\main.py:341 +#: views\main.py:358 msgid "Windows起動時の自動起動はすでに設定されています。設定を解除しますか?" msgstr "" -#: views\main.py:344 +#: views\main.py:361 msgid "Windows起動時の自動起動を無効化しました。" msgstr "" -#: views\main.py:350 +#: views\main.py:367 msgid "Windows起動時の自動起動を設定しました。" msgstr "" diff --git a/locale/messages.po b/locale/messages.po index 9dcbba5..abef4b3 100644 --- a/locale/messages.po +++ b/locale/messages.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: ULTRA\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-04-29 23:05+0900\n" +"POT-Creation-Date: 2023-07-17 10:32+0900\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -17,7 +17,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -#: app.py:66 menuItemsDic.py:31 +#: app.py:66 menuItemsDic.py:31 menuItemsDic.py:34 msgid "録画形式の設定" msgstr "" @@ -143,26 +143,34 @@ msgid "通知対象ユーザの管理(&M)" msgstr "" #: menuItemsDic.py:32 -msgid "設定(&S)" +msgid "その他のサービス(&yt-dlp)" msgstr "" #: menuItemsDic.py:33 +msgid "&URLを指定してダウンロード" +msgstr "" + +#: menuItemsDic.py:35 +msgid "設定(&S)" +msgstr "" + +#: menuItemsDic.py:36 msgid "キーボードショートカットの設定(&K)" msgstr "" -#: menuItemsDic.py:34 +#: menuItemsDic.py:37 msgid "グローバルホットキーの設定(&H)" msgstr "" -#: menuItemsDic.py:35 +#: menuItemsDic.py:38 msgid "Windows起動時の自動起動を有効化(&W)" msgstr "" -#: menuItemsDic.py:36 +#: menuItemsDic.py:39 msgid "最新バージョンを確認(&U)" msgstr "" -#: menuItemsDic.py:37 +#: menuItemsDic.py:40 msgid "バージョン情報(&V)" msgstr "" @@ -171,12 +179,12 @@ msgstr "" msgid "配信開始:%s、サービス:%s" msgstr "" -#: recorder.py:169 recorder.py:171 recorder.py:182 recorder.py:194 -#: recorder.py:198 recorder.py:200 +#: recorder.py:176 recorder.py:178 recorder.py:189 recorder.py:201 +#: recorder.py:205 recorder.py:207 msgid "録画エラー" msgstr "" -#: recorder.py:169 +#: recorder.py:176 msgid "" "録画の開始に失敗しました。録画の保存先が適切に設定されていることを確認してく" "ださい。定期的に再試行する場合は[はい]、処理を中断する場合は[いいえ]を選択し" @@ -184,41 +192,41 @@ msgid "" "きる場合があります。" msgstr "" -#: recorder.py:171 recorder.py:182 +#: recorder.py:178 recorder.py:189 #, python-format msgid "%sのライブの録画処理を中断しました。" msgstr "" -#: recorder.py:185 +#: recorder.py:192 msgid "録画開始" msgstr "" -#: recorder.py:185 recorder.py:212 sources\twitcasting.py:830 +#: recorder.py:192 recorder.py:219 sources\twitcasting.py:830 #: sources\twitcasting.py:842 #, python-format msgid "ユーザ:%(user)s、ムービーID:%(movie)s" msgstr "" -#: recorder.py:186 +#: recorder.py:193 msgid "録画中" msgstr "" -#: recorder.py:194 recorder.py:198 +#: recorder.py:201 recorder.py:205 #, python-format msgid "%sのライブを録画中にエラーが発生しました。" msgstr "" -#: recorder.py:194 recorder.py:198 recorder.py:200 +#: recorder.py:201 recorder.py:205 recorder.py:207 #, python-format msgid "詳細:%s" msgstr "" -#: recorder.py:200 +#: recorder.py:207 #, python-format msgid "%sのライブを録画中にエラーが発生したため、再度録画を開始します。" msgstr "" -#: recorder.py:212 +#: recorder.py:219 msgid "録画終了" msgstr "" @@ -272,7 +280,7 @@ msgid "" "ソフトウェア終了時に、自動でアップデートされます。" msgstr "" -#: sources\twitcasting.py:42 sources\twitcasting.py:1107 views\main.py:369 +#: sources\twitcasting.py:42 sources\twitcasting.py:1107 views\main.py:386 msgid "ツイキャス" msgstr "" @@ -638,6 +646,30 @@ msgstr "" msgid "認証が必要です。ブラウザで操作を完了してください。" msgstr "" +#: sources\ydl.py:22 +msgid "その他のサービス(yt-dlp)" +msgstr "" + +#: sources\ydl.py:25 +msgid "動画" +msgstr "" + +#: sources\ydl.py:26 +msgid "音声のみ" +msgstr "" + +#: sources\ydl.py:51 +#, python-format +msgid "" +"動画情報の取得に失敗しました。\n" +"詳細:%s" +msgstr "" + +#: sources\ydl.py:61 +#, python-format +msgid "%sのダウンロードは現在サポートされていません。" +msgstr "" + #: views\auth.py:23 msgid "ブラウザでの操作を待っています..." msgstr "" @@ -689,7 +721,7 @@ msgstr "" msgid "識別子" msgstr "" -#: views\globalKeyConfig.py:31 views\main.py:278 +#: views\globalKeyConfig.py:31 views\main.py:295 msgid "ショートカットキーの設定" msgstr "" @@ -698,7 +730,7 @@ msgstr "" #: views\globalKeyConfig.py:120 views\globalKeyConfig.py:128 #: views\globalKeyConfig.py:138 views\globalKeyConfig.py:143 #: views\keyConfig.py:57 views\KeyValueSettingDialogBase.py:333 -#: views\main.py:375 views\main.py:394 +#: views\main.py:392 views\main.py:411 msgid "なし" msgstr "" @@ -877,90 +909,94 @@ msgid "" "\n" msgstr "" -#: views\main.py:152 +#: views\main.py:160 msgid "ファイル(&F)" msgstr "" -#: views\main.py:153 +#: views\main.py:161 msgid "サービス(&S)" msgstr "" -#: views\main.py:154 +#: views\main.py:162 msgid "オプション(&O)" msgstr "" -#: views\main.py:155 +#: views\main.py:163 msgid "ヘルプ(&H)" msgstr "" -#: views\main.py:198 views\main.py:204 views\main.py:399 +#: views\main.py:208 views\main.py:214 views\main.py:416 #: views\settingsDialog.py:167 msgid "" "設定の保存に失敗しました。下記のファイルへのアクセスが可能であることを確認し" "てください。" msgstr "" -#: views\main.py:216 +#: views\main.py:226 views\main.py:282 msgid "URLを入力" msgstr "" -#: views\main.py:216 +#: views\main.py:226 msgid "再生ページのURL" msgstr "" -#: views\main.py:223 views\main.py:230 +#: views\main.py:233 views\main.py:240 msgid "ユーザ名を入力" msgstr "" -#: views\main.py:223 views\main.py:230 views\tcManageUser.py:20 +#: views\main.py:233 views\main.py:240 views\tcManageUser.py:20 #: views\tcManageUser.py:99 msgid "ユーザ名" msgstr "" -#: views\main.py:246 +#: views\main.py:256 msgid "すでに削除されています。" msgstr "" -#: views\main.py:248 +#: views\main.py:258 msgid "アクセストークンの削除" msgstr "" -#: views\main.py:248 +#: views\main.py:258 msgid "" "ツイキャス連携機能を無効化し、アクセストークンを削除します。よろしいですか?" msgstr "" -#: views\main.py:255 views\main.py:344 views\main.py:350 +#: views\main.py:265 views\main.py:361 views\main.py:367 msgid "完了" msgstr "" -#: views\main.py:255 +#: views\main.py:265 msgid "アクセストークンを削除しました。" msgstr "" -#: views\main.py:286 +#: views\main.py:282 +msgid "URLの指定" +msgstr "" + +#: views\main.py:303 msgid "グローバルホットキーの設定" msgstr "" -#: views\main.py:325 views\main.py:341 +#: views\main.py:342 views\main.py:358 msgid "確認" msgstr "" -#: views\main.py:325 +#: views\main.py:342 msgid "" "録画処理を実行中です。このまま終了すると、録画は中断されます。終了してもよろ" "しいですか?" msgstr "" -#: views\main.py:341 +#: views\main.py:358 msgid "Windows起動時の自動起動はすでに設定されています。設定を解除しますか?" msgstr "" -#: views\main.py:344 +#: views\main.py:361 msgid "Windows起動時の自動起動を無効化しました。" msgstr "" -#: views\main.py:350 +#: views\main.py:367 msgid "Windows起動時の自動起動を設定しました。" msgstr "" From f7981f451f823362d1d8826f2f07f8e45b4b4079 Mon Sep 17 00:00:00 2001 From: Kazto Kitabatake Date: Mon, 17 Jul 2023 10:52:24 +0900 Subject: [PATCH 10/13] bump to 1.7.0 --- constants.py | 4 ++-- public/readme.txt | 4 ++-- version.json | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/constants.py b/constants.py index 6ae91d5..5e24e86 100644 --- a/constants.py +++ b/constants.py @@ -9,8 +9,8 @@ APP_FULL_NAME = "Universal Live Tracking and Recording App"#アプリケーションの完全な名前 APP_NAME="ULTRA"#アプリケーションの名前 APP_ICON = "ultra.ico" -APP_VERSION="1.6.0" -APP_LAST_RELEASE_DATE="2023-04-29" +APP_VERSION="1.7.0" +APP_LAST_RELEASE_DATE="2023-07-17" APP_COPYRIGHT_YEAR="2021-2023" APP_LICENSE="Apache License 2.0" APP_DEVELOPERS="Kazto Kitabatake, ACT Laboratory" diff --git a/public/readme.txt b/public/readme.txt index 8090860..910e620 100644 --- a/public/readme.txt +++ b/public/readme.txt @@ -1,7 +1,7 @@ Universal Live Tracking and Recording App -ULTRA- - バージョン:  ver.1.6.0 - リリース:   2023-04-29 + バージョン:  ver.1.7.0 + リリース:   2023-07-17 開発・配布元: ACT Laboratory (https://actlab.org/) 主要開発者:  北畠一翔   ソフト種別:  オープンソースソフトウェア (GitHubリポジトリ:https://github.com/actlaboratory/ULTRA/) diff --git a/version.json b/version.json index 01e61b1..4a58391 100644 --- a/version.json +++ b/version.json @@ -1 +1 @@ -{"version": "1.6.0", "release_date": "2023-04-29"} \ No newline at end of file +{"version": "1.7.0", "release_date": "2023-07-17"} \ No newline at end of file From 029ce724233cfc6fdcacb13fb0afed16f1f71fc9 Mon Sep 17 00:00:00 2001 From: kitabatake1013 <62418605+kitabatake1013@users.noreply.github.com> Date: Mon, 17 Jul 2023 11:30:11 +0900 Subject: [PATCH 11/13] fix locale setting (#37) --- AppBase.py | 6 ++++++ DefaultSettings.py | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/AppBase.py b/AppBase.py index 0b3b8e4..5917e6e 100644 --- a/AppBase.py +++ b/AppBase.py @@ -33,6 +33,12 @@ def __init__(self): #各種初期設定 self.InitLogger() self.LoadSettings() + # localeは「ja_JP」のような形式。設定ファイルの定義ミスにより「_」ではなく「-」を使っていたため、必要に応じて最初に設定ファイルを書き換える。 + locale_old = self.config["general"]["locale"] + if "-" in locale_old: + locale_new = locale_old.replace("-", "_") + self.log.warn("Fixed locale setting: %s -> %s" % (locale_old, locale_new)) + self.config["general"]["locale"] = locale_new try: if self.config["general"]["locale"]!=None: locale.setlocale(locale.LC_TIME,self.config["general"]["locale"]) diff --git a/DefaultSettings.py b/DefaultSettings.py index 62239ad..d65b403 100644 --- a/DefaultSettings.py +++ b/DefaultSettings.py @@ -10,7 +10,7 @@ def get(): config["general"]={ "language": "ja-JP", "fileVersion": "101", - "locale": "ja-JP", + "locale": "ja_JP", "autoHide": False, "minimizeOnExit": True, } From b3e7a03eb36fb807aecb2ee22e01d2bf2995274c Mon Sep 17 00:00:00 2001 From: Kazto Kitabatake Date: Mon, 17 Jul 2023 12:38:48 +0900 Subject: [PATCH 12/13] support generic --- recorder.py | 2 +- sources/ydl.py | 12 +++++++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/recorder.py b/recorder.py index ffbd5c1..7686d83 100644 --- a/recorder.py +++ b/recorder.py @@ -40,7 +40,7 @@ def __init__(self, source, stream, userName, time, movie="", *, header={}, userA """ # 配信開始日時がとれなかったことを示すフラグ self.timeIsNone = time is None - if type(time) == int: + if type(time) in (int, float): time = datetime.datetime.fromtimestamp(time) elif time is None: time = datetime.datetime.now() diff --git a/sources/ydl.py b/sources/ydl.py index 6a45e95..63dd08c 100644 --- a/sources/ydl.py +++ b/sources/ydl.py @@ -60,5 +60,15 @@ def download(self, url): self.log.error("unsupported: %s" % _type) simpleDialog.errorDialog(_("%sのダウンロードは現在サポートされていません。") % _type) return - r = recorder.Recorder(self, info["url"], "%(user)s(%(extractor)s)" % {"user": info["uploader"], "extractor": info["extractor"]}, datetime.datetime.strptime(info["upload_date"], "%Y%m%d"), info["id"], header=info["http_headers"], userAgent="", ext=info["ext"]) + url = info["url"] + user = "%(user)s(%(extractor)s)" % {"user": info.get("uploader", "unknown_user"), "extractor": info.get("extractor", "unknown_service")} + if "timestamp" in info.keys(): + time = info["timestamp"] + elif "upload_date" in info.keys(): + time = datetime.datetime.strptime(info["upload_date"], "%Y%m%d") + else: + time = None + id = info["id"] + headers = info.get("http_headers", {}) + r = recorder.Recorder(self, url, user, time, id, header=headers, userAgent="", ext=info["ext"]) r.start() From b68a51040bd89ecd92c80741a4b45b7877d4746f Mon Sep 17 00:00:00 2001 From: Kazto Kitabatake Date: Mon, 17 Jul 2023 12:42:48 +0900 Subject: [PATCH 13/13] update readme --- public/readme.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/public/readme.txt b/public/readme.txt index 910e620..84e5e2e 100644 --- a/public/readme.txt +++ b/public/readme.txt @@ -133,6 +133,7 @@ ULTRAをコンピュータから削除する場合は、「ULTRA」フォルダ ・プレイリストやチャンネルなど、複数の動画を含むURLを指定してダウンロードすることができません。必ず、動画のURLを入力してください。 ・動画のダウンロードに当たっては、「yt-dlpで取得した情報を元にffmpegを呼び出す」という方法をとっています。そのため、yt-dlpの対応サービスの内、ダウンロード時に特殊な処理が必要なサービスでは、本ソフトでの動画のダウンロードに失敗する可能性があります。現時点で、「ニコニコ動画」の動画をダウンロードできない事象を確認しています。 ・本ソフトを用いてYouTubeの動画をダウンロードした際、「録画エラー」として何らかのエラーメッセージが表示されることがあります。しかし、ダウンロードに失敗しているのか、成功しているのかは、保存されたファイルを確認しなければ判断できません。そこで、同じ動画を複数回ダウンロードしてしまうことのないよう、録画エラーが発生した場合でも、エラー内容を表示するのみで、直ちに録画処理を終了します(再度録画を開始することはありません)。 +・YouTube動画のアップロード時刻を取得することができません。そのため、「アップロードされた日の0時0分0秒」として処理を行います。また、日時情報をまったく取得できない場合、ダウンロード操作を行った日時を使用します。 第5章 メニューリファレンス ここでは、ULTRAの各メニュー項目について解説します。