22

LibVLCを使用して、再生中にストリームを保存しようとしています。これはpythonコードです:

import os
import sys
import vlc

if __name__ == '__main__':
    filepath = <either-some-url-or-local-path>
    movie = os.path.expanduser(filepath)
    if 'http://' not in filepath:
        if not os.access(movie, os.R_OK):
            print ( 'Error: %s file is not readable' % movie )
            sys.exit(1)
    instance = vlc.Instance("--sub-source marq --sout=file/ps:example.mpg")
    try:
        media = instance.media_new(movie)
    except NameError:
        print ('NameError: % (%s vs Libvlc %s)' % (sys.exc_info()[1],
                       vlc.__version__, vlc.libvlc_get_version()))
        sys.exit(1)
    player = instance.media_player_new()
    player.set_media(media)
    player.play()

    #dont exit!
    while(1):
        continue

ビデオ ストリームをファイルに保存しますexample.mpgこのドキュメントによると、ストリームを保存するコマンドは次のとおりです。

--sout=file/ps:example.mpg

のインスタンスを作成するときに使用したものvlc.Instance

instance = vlc.Instance("--sub-source marq --sout=file/ps:example.mpg")

しかし問題は、ストリームを保存するだけで、ストリームを同時に再生しないことです。

支払い中にストリームを(ローカルファイルに)保存できる(LibVLCで)方法はありますか?

ただし、解決策を探していますPython 3.3.1が、CまたはC++の解決策があれば問題ありません。


昨日、同様のトピックを作成しましたが、重複していません。

4

5 に答える 5

12

考え:

基本的な考え方は単純です。出力ストリームを複製してファイルにリダイレクトする必要があります。Mareshが正しく指摘したように、これはsout =#duplicate{...}ディレクティブを使用して行われます。

作業ソリューション:

次の解決策は、私のマシン™で機能します。VLC v2.0.3 (TwoFlower) および Python 2.7.1 を使用して Ubuntu 12.10 でテストしました。いずれにせよ、たいへんな作業は libVlc によって行われるため、Python 3 でも動作するはずです。

import os
import sys
import vlc

if __name__ == '__main__':
    #filepath = <either-some-url-or-local-path>
    movie = os.path.expanduser(filepath)
    if 'http://' not in filepath:
        if not os.access(movie, os.R_OK):
            print ( 'Error: %s file is not readable' % movie )
            sys.exit(1)
    instance = vlc.Instance("--sout=#duplicate{dst=file{dst=example.mpg},dst=display}")
    try:
        media = instance.media_new(movie)
    except NameError:
        print ('NameError: % (%s vs Libvlc %s)' % (sys.exc_info()[1],
                       vlc.__version__, vlc.libvlc_get_version()))
        sys.exit(1)
    player = instance.media_player_new()
    player.set_media(media)
    player.play()

    #dont exit!
    while(1):
        continue

便利なリンク


更新 - YouTube 動画の保存:

上記のコードは、YouTube ではうまく機能しません。いろいろ調べたところ、transcodeYouTube のビデオ ストリームを通常のビデオ フォーマットに変換するために追加のディレクティブを使用できることがわかりました。使った#transcode{vcodec=mp4v,acodec=mpga,vb=800,ab=128,deinterlace}

  • vcodec=mp4v は、エンコードするビデオ形式です (mp4v は MPEG-4、mpgv は MPEG-1 で、h263、DIV1、DIV2、DIV3、I420、I422、I444、RV24、YUY2 もあります)。
  • acodec=mpga は、エンコードするオーディオ形式です (mpga は MPEG オーディオ レイヤー 2、a52 は A52、つまり AC3 サウンドです)。
  • vb=800 は Kbit/s 単位のビデオ ビットレートです。
  • ab=128 は Kbit/s 単位のオーディオ ビットレートです。
  • deinterlace は、VLC にその場でビデオのインターレースを解除するように指示します。

更新されたコードは次のようになります。

import os
import sys
import vlc

if __name__ == '__main__':
    #filepath = <either-some-url-or-local-path>
    filepath = "http://r1---sn-nfpnnjvh-1gil.c.youtube.com/videoplayback?source=youtube&newshard=yes&fexp=936100%2C906397%2C928201%2C929117%2C929123%2C929121%2C929915%2C929906%2C929907%2C929125%2C929127%2C925714%2C929917%2C929919%2C912512%2C912515%2C912521%2C906838%2C904485%2C906840%2C931913%2C904830%2C919373%2C933701%2C904122%2C932216%2C936303%2C909421%2C912711%2C907228%2C935000&sver=3&expire=1373237257&mt=1373214031&mv=m&ratebypass=yes&id=1907b7271247a714&ms=au&ipbits=48&sparams=cp%2Cid%2Cip%2Cipbits%2Citag%2Cratebypass%2Csource%2Cupn%2Cexpire&itag=45&key=yt1&ip=2a02%3A120b%3Ac3c6%3A7190%3A6823%3Af2d%3A732c%3A3577&upn=z3zzcrvPC0U&cp=U0hWSFJOVV9KUUNONl9KSFlDOmt4Y3dEWFo3dDFu&signature=D6049FD7CD5FBD2CC6CD4D60411EE492AA0E9A77.5D0562CCF4E10A6CC53B62AAFFF6CB3BB0BA91C0"
    movie = os.path.expanduser(filepath)
    savedcopy = "yt-stream.mpg"
    if 'http://' not in filepath:
        if not os.access(movie, os.R_OK):
            print ( 'Error: %s file is not readable' % movie )
            sys.exit(1)
    instance = vlc.Instance("--sout=#transcode{vcodec=mp4v,acodec=mpga,vb=800,ab=128,deinterlace}:duplicate{dst=file{dst=%s},dst=display}" % savedcopy)
    try:
        media = instance.media_new(movie)
    except NameError:
        print ('NameError: % (%s vs Libvlc %s)' % (sys.exc_info()[1],
                       vlc.__version__, vlc.libvlc_get_version()))
        sys.exit(1)
    player = instance.media_player_new()
    player.set_media(media)
    player.play()

    #dont exit!
    while(1):
        continue

いくつかの重要なポイント:

トランスコード ディレクティブで MPEG オーディオおよびビデオ コーデックを使用しました。出力ファイル (この場合は mpg) に一致する拡張子を使用することが重要なようです。そうしないと、保存したファイルを開いて再生するときに VLC が混乱します。別のビデオ形式に切り替える場合は、この点に注意してください。

通常の YouTube URL をファイルパスとして追加することはできません。代わりに、ビデオ自体の場所を指定する必要があります。これが、私が使用したファイルパスが非常に不可解に見える理由です。そのファイルパスは のビデオに対応しhttp://www.youtube.com/watch?v=GQe3JxJHpxQます。VLC 自体は、特定の YouTube URL からビデオの場所を抽出できますが、libVLC はそのままではそれを行いません。そのためには、独自のリゾルバーを作成する必要があります。この関連する SO の質問を参照してくださいこのアプローチに従って、テスト用のビデオの場所を手動で解決しました。

于 2013-05-26T11:56:37.947 に答える
9

再生と録音を同時に行うには、出力を複製する必要があると思います。

vlc.Instance("--sub-source marq --sout=#stream_out_duplicate{dst=display,dst=std{access=file,mux=ts,dst=/path/file.mpg}}")

また

libvlc_media_add_option(media, ":sout=#stream_out_duplicate{dst=display,dst=std{access=file,mux=ts,dst=/path/file.mpg}}")
于 2013-05-26T10:24:23.267 に答える
1

次のオプションをオプションのリストに追加しようとしましたか?

--sout-display

すなわち

instance = vlc.Instance("--sub-source marq --sout=file/ps:example.mpg --sout-display")
于 2013-05-20T00:27:47.060 に答える
1

少し前に、アクティブ状態の Web サイトのサンプル コードで、誰かが vlc.py モジュールを使用して VLC を使用して MP3 ファイルを再生および録音しているのを見ました。ストリームを複製する方法については、サンプル コードを参照してください。ここにコードをコピーしました ( http://code.activestate.com/recipes/577802-using-vlcpy-to-record-an-mp3-and-save-a-cue-file/からコピーしました):

import vlc
import time
import os

def new_filename(ext = '.mp3'):
    "find a free filename in 00000000..99999999"
    D = set(x[:8] for x in os.listdir('.')
        if (x.endswith(ext) or x.endswith('.cue')) and len(x) == 12)
    for i in xrange(10**8):
        s = "%08i" %i
        if s not in D:         
            return s

def initialize_cue_file(name,instream,audiofile):
    "create a cue file and write some data, then return it"
    cueout = '%s.cue' %name
    outf = file(cueout,'w')
    outf.write('PERFORMER "%s"\n' %instream)
    outf.write('TITLE "%s"\n' %name)
    outf.write('FILE "%s" WAVE\n' %audiofile)
    outf.flush()
    return outf

def initialize_player(instream, audiofile):
    "initialize  a vlc player which plays locally and saves to an mp3file"
    inst = vlc.Instance()   
    p = inst.media_player_new()   
    cmd1 = "sout=#duplicate{dst=file{dst=%s},dst=display}" %audiofile
    cmd2 ="no-sout-rtp-sap"
    cmd3 = "no-sout-standard-sap"
    cmd4 ="sout-keep"
    med=inst.media_new(instream,cmd1,cmd2,cmd3,cmd4)   
    med.get_mrl()    
    p.set_media(med)
    return p, med

def write_track_meta_to_cuefile(outf,instream,idx,meta,millisecs):
    "write the next track info to the cue file"
    outf.write('  TRACK %02i AUDIO\n' %idx)
    outf.write('    TITLE "%s"\n' %meta)
    outf.write('    PERFORMER "%s"\n' %instream)
    m = millisecs // 60000
    s = (millisecs - (m*60000)) // 1000
    hs = (millisecs - (m*60000) - (s*1000)) //10
    ts = '%02i:%02i:%02i'  %(m,s,hs)
    outf.write('    INDEX 01 %s\n' %ts)
    outf.flush()

def test():
    #some online audio stream for which this currently works ....
    instream = 'http://streamer-mtc-aa05.somafm.com:80/stream/1018'
    #if the output filename ends with mp3 vlc knows which mux to use
    ext = '.mp3'
    name = new_filename(ext)
    audiofile = '%s%s' %(name,ext)
    outf = initialize_cue_file(name,instream,audiofile)
    p,med = initialize_player(instream, audiofile)
    p.play()
    np = None
    i = 0
    while 1:
        time.sleep(.1)
        new = med.get_meta(12)
        if new != np:
            i +=1
            t = p.get_time()
            print "millisecs: %i" %t
            write_track_meta_to_cuefile(outf,instream,i,new,t)
            np = new
            print "now playing: %s" %np

if __name__=='__main__':
    test()
于 2013-05-24T13:06:00.460 に答える