====== python-vlc - VLC の Python バインディング ====== {{linux:vlc-player_icon.jpg?250|リアル世界でのVLC}}\\ ごめんなさい🙏ブラ男氏が縄張りを主張しちゃいました🐶😅💦\\ 本家: [[https://www.olivieraubert.net/vlc/python-ctypes/|Python bindings for VLC]]\\ ドキュメント: [[https://www.olivieraubert.net/vlc/python-ctypes/doc/|API Documentation]]\\ ===== インストール ===== $ python3 -m venv py3_vlc $ . py3_vlc/bin/activate (py3_vlc) $ pip install python-vlc Collecting python-vlc Downloading python_vlc-3.0.7110-py3-none-any.whl (80 kB) |████████████████████████████████| 80 kB 721 kB/s Installing collected packages: python-vlc Successfully installed python-vlc-3.0.7110 ===== Python 製コマンドライン VLC プレイヤー ===== メディアリストをループ再生するサンプルコードである。\\ VLC インスタンスは Raspberry Pi をヘッドレスで運用すること前提に '--no-video' オプションを指定しているので、必要に応じてインスタンスの起動オプションを修正してください。\\ #!/usr/bin/env python # -*- coding: utf-8 -*- import vlc import os import pathlib import readline # 拡張子は小文字で定義 !! exts = ('.mp3', '.m4a', '.wav', '.wma', '.mpg', '.mov', '.mkv', '.mp4', '.webm') #exts = ('.mp3', '.m4a', '.flac', '.wav') HOME = os.path.expanduser('~') READLINE_HISTORY_FILE = '.pyvlcplayer_history' READLINE_HISTORY_PATH = os.path.join(HOME, READLINE_HISTORY_FILE) EQ_PRESET_BASS_BOOST = [14.5, 15.5, 10.5, 9.3, 10.8, 15.3, 0.0, 2.2, 7.8, 14.6] PATH = '/var/samba/MusicData/TRF' def walk(dir, exts): result = [] for path, dirs, files in os.walk(os.path.join(dir, '.'), followlinks=True): for file in files: #print(file) if file.lower().endswith(exts): dir_path = os.path.abspath(path) result.append(os.path.join(dir_path, file)) return result def printVLCMeta(media, path): title = media.get_meta(vlc.Meta.Title) artist = media.get_meta(vlc.Meta.Artist) album = media.get_meta(vlc.Meta.Album) trackNumber = media.get_meta(vlc.Meta.TrackNumber) trackNumber = trackNumber if not trackNumber is None else 0 trackTotal = media.get_meta(vlc.Meta.TrackTotal) trackTotal = trackTotal if not trackTotal is None else 0 genre = media.get_meta(vlc.Meta.Genre) #url = media.get_meta(vlc.Meta.URL) fileSize = os.path.getsize(path) print(f'Album: {album}') print(f'Title: {title}') print(f'File Size: {fileSize:,} bytes') print(f'Artist: {artist}') print(f'Genre: {genre} Track: {trackNumber: >3}/{trackTotal}') print(f'Path: {path}') #print(f'URL: {url}') def main(): pathlib.Path(READLINE_HISTORY_PATH).touch() readline.read_history_file(READLINE_HISTORY_PATH) flagEQ = False medias = walk(PATH, exts) medias.sort() print(f'Media Count: {len(medias)}') # No Video mode for headless Raspberry Pi vlcInstance = vlc.Instance('--no-video') #mediaList = vlc.MediaList() mediaList = vlcInstance.media_list_new() for index, media in enumerate(medias): print(f'Index: {index: >4} Path: {media}') mediaList.add_media(os.path.join(media[0], media[1])) #mediaListPlayer = vlc.MediaListPlayer() mediaListPlayer = vlcInstance.media_list_player_new() mediaListPlayer.set_media_list(mediaList) mediaListPlayer.set_playback_mode(vlc.PlaybackMode.loop) mediaListPlayer.play() mediaPlayer = mediaListPlayer.get_media_player() print('🎊🎂🍩🍩🍩 libvlc information 🍩🍩🍩🎂🎊') print(f"libvlc version: '{vlc.libvlc_get_version().decode()}' ✨") print(f"libvlc compiler version: '{vlc.libvlc_get_compiler().decode()}' ✨") print(f"libvlc changeset: '{vlc.libvlc_get_changeset().decode()}' ✨\n") while True: print('po: POSITION, i: INDEX/Info, p: PREVIOUS, n: NEXT, q: QUIT') print('eq [frequency band value list]: Equalizer On/Off') # 入力待ちプロンプト data = input('>> ') #POSITION if data == 'po': pos = mediaPlayer.get_position() print(f'Position: {pos}') #INDEX/Info elif data == 'i': media = mediaPlayer.get_media() index = mediaList.index_of_item(media) path = os.path.join(medias[index][0], medias[index][1]) print(f'Index: {index}') printVLCMeta(media, path) #PREVIOUS elif data == 'p': mediaListPlayer.previous() media = mediaPlayer.get_media() index = mediaList.index_of_item(media) fileName = media.get_meta(0) print(f'Previous -> Current Index: {index} File: {fileName}') #NEXT elif data == 'n': mediaListPlayer.next() media = mediaPlayer.get_media() index = mediaList.index_of_item(media) fileName = media.get_meta(0) print(f'Next -> Current Index: {index} File: {fileName}') #Set Equalizer elif data.startswith('eq'): #EQ Set if len(data) > 3 or not flagEQ: flagEQ = True eqFreqs = [] eqAmps = list(map(float, data[3:].split())) if len(eqAmps) == 0: eqAmps = EQ_PRESET_BASS_BOOST bandCount = vlc.libvlc_audio_equalizer_get_band_count() print(f'Band Count: {bandCount}') eq = vlc.AudioEqualizer() for bandIndex in range(bandCount): try: amp = eqAmps[bandIndex] except IndexError: amp = 0 eq.set_amp_at_index(amp, bandIndex) eqFreqs.append(vlc.libvlc_audio_equalizer_get_band_frequency(bandIndex)) print(f'Freq: {" ".join(map(str, eqFreqs))}') print(f'Amp: {" ".join(map(str, eqAmps))}') #EQ Off elif flagEQ: flagEQ = False eq = None print(f'Equalizer: {"On" if flagEQ else "Off"}') mediaPlayer.set_equalizer(eq) #QUIT elif data == 'q': mediaListPlayer.stop() readline.write_history_file(READLINE_HISTORY_PATH) print('Quit.') break if __name__ == '__main__': main() ===== 使い方 ===== **os.walk() に followlinks=True オプションを追加。(シンボルリンクを辿るように指定)**\\ **eq** で VLC のイコライザーを設定。\\ eq <- イコライザー Off の場合は EQ_PRESET_BASS_BOOST で On にする。 Band Count: 10 Freq: 31.25 62.5 125.0 250.0 500.0 1000.0 2000.0 4000.0 8000.0 16000.0 Amp: 20.0 10.5 2.8 9.3 14.8 6.3 0.0 2.2 7.8 15.6 Equalizer: On po: POSITION, i: INDEX/Info, p: PREVIOUS, n: NEXT, q: QUIT eq [frequency band value list]: Equalizer On/Off eq 20 20 20 <- イコライザー 30Hz 60Hz 125Hz を 20.0 dB に設定する。 Band Count: 10 Freq: 31.25 62.5 125.0 250.0 500.0 1000.0 2000.0 4000.0 8000.0 16000.0 Amp: 20.0 20.0 20.0 Equalizer: On po: POSITION, i: INDEX/Info, p: PREVIOUS, n: NEXT, q: QUIT eq [frequency band value list]: Equalizer On/Off eq <- イコライザー On の場合は Off にする。 Equalizer: Off po: POSITION, i: INDEX/Info, p: PREVIOUS, n: NEXT, q: QUIT eq [frequency band value list]: Equalizer On/Off **Raspberry Pi** をヘッドレスで運用している場合は以下のエラーで動作が不安定になる場合がある。\\
>> [01f70530] gles2 generic error: parent window not available
[01f6fe70] mmal_xsplitter vout display error: Failed to open Xsplitter:opengles2 module
[01f70530] xcb generic error: window not available
[01f6fe70] mmal_xsplitter vout display error: Failed to open Xsplitter:xcb_x11 module
i
Index: 0
Album: None
Title: Hello Kiss me No say-a2ZaDrdpwMk.webm
File Size: 23,840,020 bytes
Artist: None
Genre: None Track:   0/0
Path: /var/samba/DataShare/02_YouTubeDLs/05_ぜんぶ君のせいだ。/20160127_A01st_やみかわIMRAD/Hello Kiss me No say-a2ZaDrdpwMk.webm
po: POSITION, i: INDEX/Info, p: PREVIOUS, n: NEXT, q: QUIT
eq [frequency band value list]: Equalizer On/Off
>> q
Quit.
Python コードを以下のように VLC インスタンスのオプションに '--no-video' を指定して、ビデオ出力を無効にする。\\ medias = walk(PATH, exts) medias.sort() print(f'Media Count: {len(medias)}') # No Video mode for headless Raspberry Pi vlcInstance = vlc.Instance('--no-video') #mediaList = vlc.MediaList() mediaList = vlcInstance.media_list_new() for index, media in enumerate(medias): print(f'Index: {index: >4} Path: {media}') mediaList.add_media(os.path.join(media[0], media[1])) #mediaListPlayer = vlc.MediaListPlayer() mediaListPlayer = vlcInstance.media_list_player_new() mediaListPlayer.set_media_list(mediaList) mediaListPlayer.set_playback_mode(vlc.PlaybackMode.loop) mediaListPlayer.play()
Index:   95 Path: ('/var/samba/DataShare/02_YouTubeDLs/05_ぜんぶ君のせいだ。/20210603_ARe04_Q.E.D. bi', '13.ぜんぶ君のせいだ。あおはる-hNuG-hrxzMY.mkv')
Index:   96 Path: ('/var/samba/DataShare/02_YouTubeDLs/05_ぜんぶ君のせいだ。/20210603_ARe04_Q.E.D. bi', '14.ぜんぶ君のせいだ。独唱無題-rBeoKrJFkb0.mkv')
Index:   97 Path: ('/var/samba/DataShare/02_YouTubeDLs/05_ぜんぶ君のせいだ。/20210603_ARe04_Q.E.D. bi', '15.ぜんぶ君のせいだ。無題合唱-N9tuj3sHMXI.mkv')
po: POSITION, i: INDEX/Info, p: PREVIOUS, n: NEXT, q: QUIT
eq [frequency band value list]: Equalizer On/Off
>> i
Index: 2
Album: None
Title: ぜんぶ君のせいだ。「ShitEndプラシーボ」Official MusicVideo-1CsCYcTF9w4.mp4
File Size: 64,454,373 bytes
Artist: None
Genre: None Track:   0/0
Path: /var/samba/DataShare/02_YouTubeDLs/05_ぜんぶ君のせいだ。/20160127_A01st_やみかわIMRAD/ぜんぶ君
のせいだ。「ShitEndプラシーボ」Official MusicVideo-1CsCYcTF9w4.mp4
po: POSITION, i: INDEX/Info, p: PREVIOUS, n: NEXT, q: QUIT
eq [frequency band value list]: Equalizer On/Off
>>
===== 参考文献 ===== [[https://stackoverflow.com/questions/59014318/filenotfounderror-could-not-find-module-libvlc-dll|python - FileNotFoundError: Could not find module 'libvlc.dll' - Stack Overflow]]\\ [[https://stackoverflow.com/questions/28440708/python-vlc-binding-playing-a-playlist/33042754|mp3 - Python VLC binding- playing a playlist - Stack Overflow]]\\ [[https://jellyware.jp/kurage/raspi/python_vlc.html|python-vlcで音楽再生をプログラム制御]]\\ ==== 付録 ==== [[tw>tomoyan596/status/1395470176062115842|あんまし直してる暇も無いので、python-vlcでテキトーに作ったコマンドラインプレーヤーにイコライザーのセットコマンドをテキトーに追加してます😅💦 / Twitter]]\\ [[tw>tomoyan596/status/1401229926762614785|Python製のVLCコマンドラインプレイヤーを、Raspberry Pi Zeroでヘッドレス運用すると、動画データを含む場合にエラーを起こして動作が不安定になっていたので、ビデオ出力を無効化してオーディオ再生できるようにしました😊 / Twitter]]\\