c++ - transmitir - Guardar una transmisión mientras se reproduce usando LibVLC
transmitir en vivo youtube android (5)
Utilizando LibVLC , estoy tratando de guardar una transmisión mientras la juego. Este es el código de 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
Guarda la secuencia de video en un archivo example.mpg
. Según this documento, el comando para guardar una secuencia es este:
--sout=file/ps:example.mpg
que he estado utilizando al crear una instancia de vlc.Instance
:
instance = vlc.Instance("--sub-source marq --sout=file/ps:example.mpg")
Pero el problema es que solo guarda la transmisión, no la reproduce simultáneamente.
¿Hay alguna forma (en LibVLC) puedo guardar la transmisión (en un archivo local) mientras la pago?
Aunque, estoy buscando una solución en Python 3.3.1
pero está bien si hay alguna solución C o C ++.
Ayer he creado un tema similar, pero no duplicado.
Idea:
La idea básica es bastante simple. Debe duplicar la secuencia de salida y redirigirla a un archivo. Esto se hace, como Maresh señaló correctamente, usando la directiva sout = # duplicate {...} .
Solución de trabajo:
La siguiente solución funciona en mi máquina ™. Lo he probado en Ubuntu 12.10 con VLC v2.0.3 (TwoFlower) y Python 2.7.1. Creo que también debería funcionar en Python 3 ya que la mayor parte del trabajo pesado lo realiza libVlc de todos modos.
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
Enlaces Útiles
- La ayuda de la línea de comandos fue esencial para descifrar la gran cantidad de opciones de línea de comandos de VLC.
- Capítulo 3 de VLC streaming HowTo . Explica la estructura de la salida del flujo, sus directivas y describe los diversos módulos disponibles. El capítulo 4 muestra algunos ejemplos.
- Documentación de la API de LibVLC en caso de que desee cambiar la opción de medios en tiempo de ejecución
Actualización - Guardar videos de YouTube:
El código anterior no funciona bien con YouTube. Busqué y descubrí que se puede usar una directiva de transcode
adicional para convertir el flujo de video de YouTube a un formato de video normal. Utilicé #transcode{vcodec=mp4v,acodec=mpga,vb=800,ab=128,deinterlace}
- vcodec = mp4v es el formato de video que desea codificar (mp4v es MPEG-4, mpgv es MPEG-1, y también hay h263, DIV1, DIV2, DIV3, I420, I422, I444, RV24, YUY2).
- acodec = mpga es el formato de audio que desea codificar (mpga es MPEG audio layer 2, a52 es A52, es decir, sonido AC3).
- vb = 800 es la tasa de bits de video en Kbit / s.
- ab = 128 es la tasa de bits de audio en Kbit / s.
- desentrelazado le dice a VLC que desentrelace el video sobre la marcha.
El código actualizado se ve así:
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
Un par de puntos importantes:
He utilizado los códecs de audio y video MPEG en la directiva de transcodificación. Parece ser importante usar una extensión coincidente para el archivo de salida (mpg en este caso). De lo contrario, VLC se confunde al abrir el archivo guardado para su reproducción. Tenlo en cuenta si decides cambiar a otro formato de video.
No puede agregar una URL regular de YouTube como filepath. En su lugar, debe especificar la ubicación del video en sí. Esa es la razón por la que la ruta de acceso que he usado se ve tan críptica. Esa ruta de acceso corresponde al video en http://www.youtube.com/watch?v=GQe3JxJHpxQ
. VLC en sí puede extraer la ubicación del video de una URL de YouTube determinada, pero libVLC no lo hace de forma inmediata. Tendrás que escribir tu propio resolver para hacer eso. Vea esta pregunta SO relacionada . Seguí este enfoque para resolver manualmente la ubicación del video para mis pruebas.
¿Intentaste agregar a la lista de opciones la siguiente opción?
--salta pantalla
es decir
instance = vlc.Instance("--sub-source marq --sout=file/ps:example.mpg --sout-display")
¿Quizás necesitas clonar tu salida, como se sugiere en el foro ?
Creo que necesitas duplicar la salida para poder reproducirla y grabarla al mismo tiempo:
vlc.Instance("--sub-source marq --sout=#stream_out_duplicate{dst=display,dst=std{access=file,mux=ts,dst=/path/file.mpg}}")
o
libvlc_media_add_option(media, ":sout=#stream_out_duplicate{dst=display,dst=std{access=file,mux=ts,dst=/path/file.mpg}}")
Hace algún tiempo, en un código de muestra en el sitio web de estado activo, vi a alguien reproduciendo y grabando un archivo MP3 usando VLC usando el módulo vlc.py. Puede echar un vistazo a su código de ejemplo para ver cómo duplicar una secuencia. Copié el código aquí para usted (lo copié de 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()