動画切り出し用スクリプト vlc-clip ver4
注意書き
.exe版は多分うまく動かないのでPy版を環境に合わせて書き換えて使って下さいね
目次
概要
動画を再生しながら素材集めをしたいときに便利なスクリプトです。動画を再生中、ボタンを押すと(あるいは設定したキーを押すと)ボタンを押した瞬間前後の指定した範囲を別の動画ファイルとして書き出すコマンドを生成、実行することができます。
Ver4からスクリプト名をvlc-clipに変えました。
このスクリプトについて
過去にVLC-animeという同名・同目的のスクリプトを開発し、公開していますが、互換性はありません。
ver 1 (現在非公開) :python-vlcを用いたメディアプレーヤー。コードが難解で開発に行き詰まり諦め
ver 2 (https://ytpmv.info/vlc-anime/) :VLCの拡張機能として作成。lua言語。VLC側で私の求める機能が実装されていない(削除された)ためver 3の開発を決断。ver 2を使ってもいいよ。
ver 3 (ココ):VLCのremote control interfaceをPythonで操作。python-vlcを用いないためexe化が可能になった。
ダウンロード
Python版とexe版が含まれます。
Python版を用いる場合は、以下のライブラリを導入してください
- PySimpleGUI
参考
このスクリプトの作成にあたり、以下のコードを参考にしています
- https://stackoverflow.com/a/61485122
- https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Media_Player_VLC_Based.py
導入
VLCをインストールしていることが必要です。
書き出し時にffmpegを使用します。https://ffmpeg.org/download.htmlより各自の環境に合わせてダウンロードしてください。
Python版では、インストールしていないライブラリがある場合は導入してください。
Python版、exe版共通して、setting.iniの内容を各自の環境に合わせて変更してください。
キーコンフィグについて
私の場合はテンキーで操作することを前提に作成しているため、それ用の設定にしてあります。各自使いやすいように設定してください。引用符無しでkey_〇〇 = a の形になるように記入してください。
使い方
まずコマンドプロンプトを起動し、VLCをインストールしたフォルダで以下のコマンドを実行します。
vlc --intf rc --rc-host 127.0.0.1:44500
これを行わない場合、ウィンドウが応答しなくなります。

次にスクリプトを実行します。

loadボタンを押し、ファイルを選択。再生が始まります。
動画を再生しつつ、切り出したいシーンを見つけたらcutボタンを押します。
切り出したいシーンをすべて見つけ、それぞれでcutボタンを押したら、最後にGenerate .bat and runボタンを押します。
別ウィンドウでコマンドが実行されます。
もしファイルが出力されていない場合は、再生していた動画ファイルと同じフォルダにコマンドが記載されたbatファイルが生成されるので、それを確認してください。
他にも、再生速度の調整、スキップ、戻る、一時停止の機能があります。
以上。活用してね。
コード
初心者プログラマーなので色々アレなのは勘弁
####################################################################################### # VLC-anime ver3.0 # # 2021/01/14 # # Written by Maimai (Twitter:@Maimai22015,@Maimai22016/YTPMV.info) # # Read https://ytpmv.info/vlc-anime-v3 # ####################################################################################### import PySimpleGUI as sg from sys import platform as PLATFORM import socket import threading import datetime import subprocess import configparser import os #------- Config ------------------------# inifile = configparser.ConfigParser() inifile.read(os.getcwd() + '/setting.ini', 'UTF-8') print(inifile.get('SETTING', 'save_path')) ffmpeg_path = inifile.get('SETTING', 'ffmpeg_path') start_pos = inifile.get('SETTING', 'start_pos') cut_length = inifile.get('SETTING', 'cut_length') save_path = inifile.get('SETTING', 'save_path') ''' ffmpeg command ffmpeg -ss <time> -t <length> -i "<input file>" -map 0 -map -0:s -map_chapters -1 -vcodec libx264 -preset medium -tune animation "<output file>" -codec:a libfdk_aac -y ''' ffmpeg_cmd1 = " -ss " ffmpeg_cmd2 = " -t " ffmpeg_cmd3 = " -i \"" ffmpeg_cmd4 = "\" -map 0 -map -0:s -map_chapters -1 -vcodec libx264 -preset medium -tune animation \"" ffmpeg_cmd5 = "\" -codec:a libfdk_aac -y" #------- Key config --------------------# key_pause = inifile.get('KEYCONFIG', 'key_pause2') key_pause2 = " " key_stop = inifile.get('KEYCONFIG', 'key_stop') key_normnal = inifile.get('KEYCONFIG', 'key_normnal') key_faster = inifile.get('KEYCONFIG', 'key_faster') key_slower = inifile.get('KEYCONFIG', 'key_slower') key_load = inifile.get('KEYCONFIG', 'key_load') key_back10s = inifile.get('KEYCONFIG', 'key_back10s') key_skip10s = inifile.get('KEYCONFIG', 'key_skip10s') key_screenshot = inifile.get('KEYCONFIG', 'key_screenshot') key_cut = inifile.get('KEYCONFIG', 'key_cut') key_run = inifile.get('KEYCONFIG', 'key_run') #------- GUI definition & setup --------# sg.theme('DarkBlue') def btn(name): # a PySimpleGUI "User Defined Element" (see docs) return sg.Button(name, size=(8, 1), pad=(1, 1)) layout = [[ sg.Button('load')], #'''sg.T('command: '),sg.Input(default_text='', size=(10, 1), key='-VLC_Control_Command-'),btn('cmd run'),''' [btn('stop'),btn('screenshot')], [btn('10s <-'),btn('pause'),btn('-> 10s')], [btn('normal'),btn('slower'),btn('faster')], [btn('cut'),sg.Button('Generate .bat and run', size=(17, 1), pad=(1, 1))], [sg.Text('Load media to start', key='-MESSAGE_AREA-')]] window = sg.Window('VLC-anime ver.3', layout, element_justification='center', finalize=True, resizable=True,return_keyboard_events=True, use_default_focus=False) #------------ Media Player Setup ---------# class player(): def __init__(self): self.is_initiated = False self.SEEK_TIME = 10 self.MAX_VOL = 512 self.MIN_VOL = 0 self.DEFAULT_VOL = 256 self.VOL_STEP = 13 self.current_vol = self.DEFAULT_VOL self.source_path="" self.bat_list =[] def toggle_play(self,filepath): #Start playing. if not self.is_initiated: self.is_initiated = True self.thrededreq("loop off") self.thrededreq("volume 100") self.thrededreq('strack -1') self.thrededreq("add "+filepath.replace('/', '\\')) print("Init Playing") return self.thrededreq("pause") print("Toggle play") def load(self): self.source_path = None self.source_path = sg.popup_get_file('Select file.','select file.') if self.source_path is not None: print('input file is '+self.source_path) self.toggle_play(self.source_path) pass def stop(self): self.is_initiated=False self.thrededreq("stop") pass def volup(self): self.current_vol = self.current_vol + self.VOL_STEP self.thrededreq("volume " + str(self.current_vol)) print("Volume up") pass def voldown(self): self.current_vol = self.current_vol - self.VOL_STEP self.thrededreq("volume " + str(self.current_vol)) print("Volume Down") pass def seek(self, forward: bool): if player.is_playing()==1: length = self.get_length() cur = self.get_time() if (forward): seekable = cur + self.SEEK_TIME else: seekable = cur - self.SEEK_TIME if seekable > length: seekable = length - 5 if seekable < 0: seekable = 0 self.thrededreq("seek " + str(seekable)) print("Seek: ",seekable," Cur: ",cur,"Len: ",length) pass def is_playing(self): is_playing=self.req("is_playing") try: return int(self.req("is_playing")) except: return 0 def get_time(self): try: return int(self.req("get_time")) except: return None def get_length(self): try: return int(self.req("get_length")) except: return None def cmd_run(self,cmd_text): print(self.req(cmd_text)) #self.thrededreq(cmd_text) pass def cut(self): if self.is_initiated == True and self.source_path !=None: out_filename = self.source_path.split("/")[-1] out_filename = save_path + out_filename.rsplit(".",1)[0] + "_{:02d}-{:02d}.".format(player.get_time()//60, player.get_time() % 60) + out_filename.rsplit(".",1)[-1] print("export to: "+ out_filename) bat_cmd = ffmpeg_path + ffmpeg_cmd1 + str(self.get_time()+int(start_pos)) + ffmpeg_cmd2 + str(cut_length) + ffmpeg_cmd3 + self.source_path + ffmpeg_cmd4 + out_filename + ffmpeg_cmd5 print(bat_cmd) self.bat_list.append(bat_cmd) def run(self): if self.bat_list == []: return else: bat_path = self.source_path.rsplit("/",1)[0] + "/vlc-anime-" + datetime.datetime.now().strftime('%Y%m%d-%H-%M-%S')+".bat" print(bat_path) with open(bat_path, mode='a') as f: f.write('\n'.join(self.bat_list)) subprocess.Popen(bat_path, creationflags=subprocess.CREATE_NEW_CONSOLE) self.bat_list = [] def _timeinfo(self, msg): length = self.req(msg, True).split("\r\n") if (len(length) < 2): return None length = length[1].split(" ") if (len(length) < 2): return None try: num = int(length[1]) return num except: return None def req(self, msg: str, full=False): try: with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock: # Connect to server and send data sock.settimeout(0.7) sock.connect(('127.0.0.1', 44500)) response = "" received = "" sock.sendall(bytes(msg + '\n', "utf-8")) # if True: try: while (True): received = (sock.recv(1024)).decode() response = response + received if full: b = response.count("\r\n") if response.count("\r\n") > 1: sock.close() break else: if response.count("\r\n") > 0: sock.close() break except: response = response + received pass sock.close() return response except: return None pass def thrededreq(self, msg): threading.Thread(target=self.req, args=(msg,)).start() #'vlc --intf rc --rc-host 127.0.0.1:44500' you need to run the vlc player from command line to allo controlling it via TCP player=player() #------------ The Event Loop ------------# while True: event, values = window.read(timeout=500) # run with a timeout so that current location can be updated if event == sg.WIN_CLOSED: break if event == 'stop' or event ==key_stop: player.stop() if event == 'pause' or event ==key_pause or event ==key_pause2: player.thrededreq("pause") if event == 'faster' or event ==key_faster: player.thrededreq("faster") if event == 'slower' or event == key_slower: player.thrededreq('slower') if event == 'normal' or event ==key_normnal: player.thrededreq('normal') if event == 'load' or event == key_load: player.load() if event == "10s <-" or event ==key_back10s: player.seek(0) if event =='-> 10s' or event ==key_skip10s: player.seek(1) if event == 'screenshot' or event ==key_screenshot: player.thrededreq('snapshot') if event == 'cmd run': if values['-VLC_Control_Command-']!='': player.cmd_run(values['-VLC_Control_Command-']) if event =='cut' or event ==key_cut: player.cut() if event == 'Generate .bat and run' or event ==key_run: player.run() # update elapsed time if there is a video loaded and the player is playing if player.is_playing()==1: try: window['-MESSAGE_AREA-'].update("{:02d}:{:02d} / {:02d}:{:02d}".format(player.get_time()//60, player.get_time() % 60,player.get_length()//60, player.get_length() % 60)) except: window['-MESSAGE_AREA-'].update('Load media to start' if player.is_playing() == 0 else 'Ready to play media' ) else: window['-MESSAGE_AREA-'].update('Load media to start' if player.is_playing() == 0 else 'Ready to play media' ) window.close()ツイート
コメントする?