python:python-vlc

差分

このページの2つのバージョン間の差分を表示します。

この比較画面へのリンク

両方とも前のリビジョン 前のリビジョン
次のリビジョン
前のリビジョン
python:python-vlc [2020/03/20 16:43] ともやんpython:python-vlc [2021/06/20 06:16] (現在) – [Python 製コマンドライン VLC プレイヤー] ともやん
行 1: 行 1:
-<html> +====== python-vlc - VLC の Python バインディング ====== 
-  <style> +{{linux:vlc-player_icon.jpg?250|リアル世界でのVLC}}\\ 
-    #result pre { +ごめんなさい🙏ブラ男氏が縄張りを主張しちゃいました🐶😅💦\\ 
-      /*height: 200px;*/ + 
-      overflow: scroll; +本家: [[https://www.olivieraubert.net/vlc/python-ctypes/|Python bindings for VLC]]\\ 
-      overflow-x: hidden; +ドキュメント: [[https://www.olivieraubert.net/vlc/python-ctypes/doc/|API Documentation]]\\
-      font-size: 10px; +
-    } +
-  </style> +
-</html> +
-====== python-vlc ======+
  
 ===== インストール ===== ===== インストール =====
 <code powershell> <code powershell>
-pip install python-vlc+$ python3 -m venv py3_vlc 
 +$ . py3_vlc/bin/activate 
 +(py3_vlc) $ pip install python-vlc
 </code> </code>
 <WRAP prewrap 100% #result> <WRAP prewrap 100% #result>
行 24: 行 21:
 </code> </code>
 </WRAP> </WRAP>
 +
 +===== Python 製コマンドライン VLC プレイヤー =====
 +メディアリストをループ再生するサンプルコードである。\\
 +VLC インスタンスは Raspberry Pi をヘッドレスで運用すること前提に <html><code>'--no-video'</code></html> オプションを指定しているので、必要に応じてインスタンスの起動オプションを修正してください。\\
 +<WRAP prewrap 100% #mincode>
 +<code python pyvlcplayer.py>
 +#!/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()
 +</code>
 +</WRAP>
 +
 +===== 使い方 =====
 +**os.walk() に followlinks=True オプションを追加。(シンボルリンクを辿るように指定)**\\
 +**eq** で VLC のイコライザーを設定。\\
 +<WRAP prewrap 100% #mincode>
 +<code>
 +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
 +</code>
 +</WRAP>
 +
 +**Raspberry Pi** をヘッドレスで運用している場合は以下のエラーで動作が不安定になる場合がある。\\
 +<html>
 +<div id="ncolor_result">
 +<pre>
 +>> [<b class=GRN>01f70530</b>] gles2 generic error: <b class=RED>parent window not available</b>
 +[<b class=GRN>01f6fe70</b>] mmal_xsplitter vout display error: <b class=RED>Failed to open Xsplitter:opengles2 module</b>
 +[<b class=GRN>01f70530</b>] xcb generic error: <b class=RED>window not available</b>
 +[<b class=GRN>01f6fe70</b>] mmal_xsplitter vout display error: <b class=RED>Failed to open Xsplitter:xcb_x11 module</b>
 +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.
 +</pre>
 +</div>
 +</html>
 +
 +Python コードを以下のように VLC インスタンスのオプションに <html><code>'--no-video'</code></html> を指定して、ビデオ出力を無効にする。\\
 +<WRAP prewrap 100% #mincode>
 +<code python>
 +    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()
 +</code>
 +</WRAP>
 +
 +<html>
 +<div id="ncolor_result">
 +<pre>
 +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
 +>>
 +</pre>
 +</div>
 +</html>
  
 ===== 参考文献 ===== ===== 参考文献 =====
 [[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/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]]\\
  
  • python/python-vlc.1584690222.txt.gz
  • 最終更新: 2020/03/20 16:43
  • by ともやん