Jak skonfigurować strumienie audio na żywo w urządzeniu zgodnym z DLNA?

54

Czy istnieje sposób na przesyłanie strumieniowe obrazu wyjściowego karty dźwiękowej z naszego pulpitu LTS amd64 12.04.1 na urządzenie zewnętrzne zgodne z DLNA w naszej sieci? Wybieranie treści multimedialnych w udostępnianych katalogach za pomocą Rygel, miniDLNA i uShare jest zawsze w porządku - ale jak dotąd nie udało nam się uzyskać strumienia audio na żywo do klienta za pośrednictwem DLNA.

Pulseaudio twierdzi, że ma serwer mediów DLNA / UPnP, który razem z Rygel powinien to zrobić. Ale nie udało nam się go uruchomić.

Wykonaliśmy kroki opisane w live.gnome.org , tę odpowiedź tutaj, a także w innym podobnym przewodniku .


W 12.04 LTS możemy wybrać lokalne urządzenie audio lub nasz strumień GST-Launch w kliencie DLNA, ale Rygel wyświetla następujący komunikat i klient stwierdza, że ​​osiągnął koniec listy odtwarzania:

(rygel:7380): Rygel-WARNING **: rygel-http-request.vala:97: Invalid seek request

Na kliencie nie było sposobu na słuchanie strumieni audio na żywo.


Dopiero po aktualizacji dystrybucji do 14.04 LTS byliśmy w stanie wybrać transmisję na żywo na naszych rendererach DLNA z ustawień ładnie opisanych w poniższej odpowiedzi . Musieliśmy jednak wybrać ustalony strumień po rozpoczęciu Rygel i nie byliśmy w stanie zepchnąć nowego strumienia do naszych urządzeń UPnP. Metadane audio nie zostały przesłane.


Czy istnieją inne alternatywy dla przesyłania dźwięku z naszej karty dźwiękowej jako strumienia na żywo do klienta DLNA?

Takkat
źródło
Czy można uniknąć strumieniowania DLNA za pomocą odbiornika? Moim rozwiązaniem jest przekazanie strumienia pulseaudio przez HTTP, zobacz więcej tutaj: sandalov.org/blog/1441
DmitrySandalov
Niestety nie, naprawdę chcę, aby DLNA działało, ponieważ DLNA jest szeroko implementowana na różnych klientach (telewizorach, odbiornikach AV, odtwarzaczach Blueray itp.).
Takkat
Takkat, rozwiązanie, o którym mówię, rozwiązało problem przesyłania strumieniowego do mojego AVR. Jeśli naprawdę chcesz uruchomić serwer DLNA, miałem pozytywne doświadczenia z Rygel + Pulseaudio 12.04 (po 'pacmd moduł modułu modułu-http-protokół-tcp'), 12.10 otrzymałem te same ostrzeżenia „Nieprawidłowe żądanie wyszukiwania” .
Dmitrij Sandałow
@DmitrySandalov: byłoby naprawdę fajnie, gdybyś podzielił się szczegółami na temat tego, jak udało Ci się skonfigurować Rygla do strumieniowego przesyłania wyjścia pulseaudio.
Takkat

Odpowiedzi:

63

Pulseaudio-DLNA

Stworzyłem mały serwer, który wykrywa wszystkie renderery upnp w twojej sieci i dodaje je jako ujścia do pulseaudio. Dzięki temu możesz kontrolować każdą aplikację za pomocą pavucontrol, aby grać na urządzeniach UPNP.

Tego rodzaju wygody zawsze chciałem mieć do czynienia z urządzeniami upnp w systemie Linux.

Aplikację można zainstalować ze źródła lub pakietu DEB do pobrania z git lub po dodaniu do naszych źródeł oficjalnej ppa: qos / pulseaudio-dlna projektu:

sudo apt-get update && sudo apt-get install pulseaudio-dlna

Następnie uruchamiamy pulseaudio-dlna z wiersza poleceń z następującymi opcjami:

pulseaudio-dlna [--host <host>] [--port <port>] [--encoder <encoder>] [--renderer-urls <urls>] [--debug]
pulseaudio-dlna [-h | --help | --version]

Zobacz także pulseaudio-dlna „About”, aby uzyskać więcej.

Gdy obecny był renderer DLNA, możemy go wybrać z menu dźwięku jako zlew wyjściowy:

wprowadź opis zdjęcia tutaj

Massimo
źródło
3
Świetna aplikacja - dziękuję! Działa dobrze na moich urządzeniach, w tym na Samsung Smart TV (UE40ES6100). Tylko uwaga: potrzebowaliśmy również python-requestsjako zależności i mogliśmy wybrać renderer z domyślnych kontrolek audio - nie trzeba instalować pavucontrol.
Takkat
Cieszę się ze to lubisz. Właśnie zaktualizowałem plik README. Dzięki za podpowiedź!
Massimo,
2
Świetne rozwiązanie. Dzięki. Ale mam jedno pytanie: opóźnienie odtwarzania wynosi kilka sekund (10 sekund po naciśnięciu pauzy w VLC). Czy jest to „funkcja” DLNA, czy jest jakiś sposób na jej ograniczenie? Więc DLNA nie ma sensu podczas odtwarzania wideo lub grania? :(
JPT,
2
Opóźnienie wynika z zapełnienia bufora HTTP. Utrzymuje odtwarzanie strumienia na wypadek problemów z połączeniem (słabe Wi-Fi itp.). Jeśli chcesz zmniejszyć opóźnienie, użyj kodeka, który wymaga dużej przepustowości ( wav ), aby szybciej wypełnić ten bufor. Połączenie kablowe zawsze pomaga. W przeciwnym razie jest to bardzo specyficzne dla implementacji oprogramowania układowego producenta. Np. Mam opóźnienie z Cocy około 1 sekundy. Sonos Zagraj w 1 z wav: 1 sekunda, z mp3: 5 sekund. Wszystko połączone kablem. Ale nie pozbędziesz się go całkowicie. Głównym celem są książki muzyczne i audio. Wszystko, co nie musi być zsynchronizowane.
Massimo,
1
@JPT i wszyscy inni szukają sposobu, aby naprawić opóźnienie (dla mnie 10 sekund ): Używając shairport-sync , uruchamiam zlew AirPlay na moim RaspberryPi równolegle do zlewu DLNA i muszę powiedzieć, że opóźnienia są znacznie krótsze (~ 2 s, aby uruchomić; zatrzymanie jest natychmiastowe). To powiedziawszy, bardzo dziękuję Massimo, ponieważ zapominając o opóźnieniu, pulseaudio-dlna działa jak urok i jest naprawdę trywialna w instalacji! (AirPlay był dla mnie trochę trudniejszy do skonfigurowania.)
Balu,
8

Pavucontrol to brakujący element tej układanki! Ustawiłem też wszystko poprawnie, a urządzenie zewnętrzne (telewizor LG) pokazywało, że dźwięk jest odtwarzany, ale nie słyszałem żadnego dźwięku. Dzisiaj zainstalowałem pavucontrol i kiedy go otworzyłem, znalazłem opcję kierowania dźwięku przez serwer DLNA. Opcja DLNA jest wyświetlana tylko wtedy, gdy dźwięk jest odtwarzany przez odtwarzacz do pulseaudio. wprowadź opis zdjęcia tutaj

jumbli
źródło
Dziękujemy za udostępnienie tego. Jak skonfigurowałeś serwer DLNA? Dla mnie atm Rygel rezygnuje z raczej nieprzydatnych błędów.
Takkat,
Mam tylko normalne ustawienia. Użyłem tego samego linku, o którym wspomniałeś w swoim poście. [GstLaunch] enabled = true launch-items = audiotestsrc; audiotestsrc-title = Desktop Live Streaming! audiotestsrc-mime = audio / mpeg audiotestsrc-launch = urządzenie pulsesrc = upnp.monitor! lamemp3enc target = jakość jakość = 6
jumbli
Dziwne. Dzięki Rhythmbox segfault zniknął, ale wciąż dostaję tylko Invalid seek requestod Rygla. Są tam katalogi medialne, ale mój strumień GST jest zawsze EOF.
Takkat
Świetny dodatek, pozwala ustawić zlew dla każdej aplikacji, która może odtwarzać dźwięk! Mogę słuchać muzyki z mojego dużego zestawu stereo i zachować wideo lub dźwięki gier na moim komputerze. Dzięki!
sprężynowy
To rozwiązało mój problem, gdy wszystko było połączone i grało, ale brakowało tylko dźwięku!
easwee
4

Przykro mi, że nie mogę w ogóle pomóc Rygelowi, ale może istnieć alternatywa, która może Ci pomóc.

Zasadą jest, aby program nagrał strumień do pliku audio, a następnie uruchom miniDLNA z niestandardową konfiguracją, która wskazuje katalog, w którym znajduje się strumień.

Przykład: Powiedzmy, że pracujemy w ~ / stream /. Utwórz ~ / stream / minidlna.conf

network_interface=wlan0
media_dir=/home/<user>/stream/
friendly_name=Live Audio Stream
db_dir=/home/<user>/stream/
album_art_names=Cover.jpg/cover.jpg/AlbumArtSmall.jpg/albumartsmall.jpg/AlbumArt.jpg/albumart.jpg/Album.jpg/album.jpg/Folder.jpg/folder.jpg/Thumb.jpg/thumb.jpg
inotify=no
enable_tivo=no
strict_dlna=no
notify_interval=900
serial=12345678
model_number=1

Następnie zapisz strumień do pliku audio w tym katalogu. Googling dla „FFmpeg nagrywanie dźwięku karty dźwiękowej” dał to polecenie

ffmpeg -f alsa -i default -acodec flac ~/stream/OutputStream.flac

ale nie miałem z tym dużo szczęścia. Inną opcją jest vlc, jeśli masz GUI i to nie działa.

Następnie uruchom miniDLNA w innym oknie terminala:

minidlna -d -f ~/stream/minidlna.conf -P ~/stream/minidlna.pid

To powinno znaleźć OutputStream.flac a następnie być dostępne z urządzeniem sieciowym.

Mam nadzieję, że jeśli jeszcze tego nie rozwiązałeś, masz kilka pomysłów.

mtdevans
źródło
1
Obiecujące podejście - dziękuję - ale wymaga dalszego dopracowania. Po dzisiejszym szybkim teście z miniDLNA nie udało mi się rozpoznać pliku strumienia przez mojego klienta DLNA. Ponadto strumienie wytwarzane przez ffmpeg wydają się raczej słabe (szum statyczny). Jestem przy tym i daję ci znać.
Takkat
Do tej pory jesteśmy w stanie wygenerować plik audio flac lub mp3 z zlewu audio za pomocą ffmpeg lub avconv. Jednak ten plik nie zostanie rozpoznany przez miniDLNA, chyba że zakończymy nagrywanie. Następnie możemy ponownie otworzyć ten plik na kliencie DLNA podczas nagrywania innej instancji, ale strumień zawsze zaczyna się od początku nagrania i zatrzymuje się w momencie, w którym zaczęliśmy nasłuchiwać na kliencie. Jakieś pomysły, jak to przezwyciężyć?
Takkat
Czy masz na myśli to, że po przerwaniu procesu ffmpeg, aby zatrzymać nagrywanie, dopiero wtedy plik jest rozpoznawany przez miniDLNA? Czy też jakość dźwięku jest lepsza? Wypróbuję to na moim komputerze i sprawdzę, czy uda mi się ponownie uruchomić. (W ubiegłym roku miałem coś podobnego do transkodowania filmów w locie)
mtdevans
Tak, po pierwsze. Za drugim razem mogę uzyskać do niego dostęp od klienta, ale zaczyna się od początku (tj. Za każdym razem, gdy zaczynałem nagrywać) i zatrzymuje się w środku (tj. Dokładnie po upływie czasu między rozpoczęciem nagrywania a rozpoczęciem odbierania na kliencie). Audio jest teraz w porządku, musiałem wyłączyć dupleks.
Takkat
4

Jednym z pomysłów, które musiałem przesyłać strumieniowo „to, co słyszę” do renderera DLNA (takiego jak WDTV), było serwerowanie strumienia za pomocą VLC jako strumienia HTTP pulse://alsa_output.xxx.monitorjako wejściowego i transkodowanie go do formatu MP3 lub FLAC. Następnie chciałem użyć punktu kontrolnego DLNA, aby renderer mógł odtwarzać strumień. VLC obsługuje poprawnie transkodowany strumień, ale nie pozwala ustawić typu MIME, więc renderer odmawia jego odtworzenia.

Następnym pomysłem było napisanie serwera http w pythonie, który zamiast tego obsługuje strumień. Pobiera strumień audio z impulsu za pomocą parec, koduje go za pomocą flac( lamelub cokolwiek chcesz) i poprawnie ustawia typ MIME.

Działa z następującym (bardzo prostym) skryptem:

#!/usr/bin/python

import BaseHTTPServer
import SocketServer
import subprocess

PORT = 8080
# run "pactl list short |grep monitor" to see what monitors are available
# you may add a null sink for streaming, so that what is streamed is not played back locally
# add null sink with "pactl load-module module-null-sink"
MONITOR = 'null.monitor'
MIMETYPE = 'audio/flac'
ENCODER = 'flac - -c --channels 2 --bps 16 --sample-rate 44100 --endian little --sign signed'
BUFFER = 65536

class Handler(BaseHTTPServer.BaseHTTPRequestHandler):
def do_HEAD(s):
    print s.client_address, s.path, s.command
    s.send_response(200)
    s.send_header('content-type', MIMETYPE)
    s.end_headers()
def do_GET(s):
    s.do_HEAD()
    pa = subprocess.Popen('parec -d {} | {}'.format(MONITOR, ENCODER), shell = True, bufsize = BUFFER, stdout = subprocess.PIPE)
    while True:
        data = pa.stdout.read(1024)
        if len(data) == 0: break
        s.wfile.write(data)
    print 'stream closed'


httpd = SocketServer.TCPServer(("", PORT), Handler)

print "listening on port", PORT

try:
httpd.serve_forever()
except KeyboardInterrupt:
pass

httpd.server_close()

Dostosuj parametry, uruchom go i skieruj renderer DLNA na swój komputer. Działa to dla mnie z WDTV jako rendererem i telefonem z Androidem z BubbleUPnP jako punktem kontrolnym (możesz wpisać URL strumienia podczas ręcznego dodawania nowego elementu do listy odtwarzania). Ale powinien działać z każdym urządzeniem zgodnym z DLNA.

Adam
źródło
4

UWAGA: To rozwiązanie działa, ale Massimo zaproponowało nowsze i prawdopodobnie lepsze rozwiązanie .

Oto odpowiedź na Ubuntu 14.04 (również przetestowana i działająca 15.04 ), dla kompletności:

  1. zainstaluj potrzebne pakiety: sudo apt-get install rygel rygel-preferences rygel-gst-launch

  2. utwórz plik ~/.config/rygel.confzawierający następujące elementy:

    [GstLaunch]
    enabled=true
    title=@REALNAME@'s stream
    launch-items=myaudioflac;myaudiompeg
    
    myaudioflac-title=FLAC audio on @HOSTNAME@
    myaudioflac-mime=audio/flac
    myaudioflac-launch=pulsesrc device=upnp.monitor ! flacenc quality=8
    
    myaudiompeg-title=MPEG audio on @HOSTNAME@
    myaudiompeg-mime=audio/mpeg
    myaudiompeg-launch=pulsesrc device=upnp.monitor ! lamemp3enc target=quality quality=6
    
    [Playbin]
    enabled=true
    title=Audio/Video playback on @REALNAME@'s computer
    
    [general]
    interface=
    upnp-enabled=true
    
    [MediaExport]
    uris=
    
  3. Wykonaj następujące polecenia z wiersza poleceń (w razie potrzeby można je umieścić w skrypcie):

    pactl load-module module-http-protocol-tcp
    pactl load-module module-rygel-media-server 
    rygel &
    
  4. Uruchom paprefspolecenie i upewnij się, że obie opcje DLNA są włączone (zaznaczone) na karcie „Serwer sieciowy”.

  5. Odtwórz dźwięk na komputerze. Uruchom pavucontrolprogram i na karcie „Odtwarzanie” zmień urządzenie wyjściowe na „Streaming DLNA / UPnP”.

W tym momencie powinieneś być w stanie odtwarzać strumienie MPEG i FLAC z klienta DLNA (renderer / punkt kontrolny).

UWAGA: może być konieczne ponowne uruchomienie komputera (lub ponowne uruchomienie pulsu), aby wszystko zaczęło działać.

znak
źródło
3

Skrypt Pythona od Adama jest właśnie tym, czego potrzebowałem. Znakomity. Rygel z gst-launch nie działa z jednym z moich rendererów, ale ten skrypt działa z oboma. W moim przypadku pobieram strumień audio z squeezelite (dla squeezebox) i wysyłam do renderera. Skrypt działa również w oryginalnej formie, jeśli pobiera dane z monitora pulseaudio, jeśli jest to potrzebne.

Niewiele o tym wiedząc, udało mi się wprowadzić kilka dodatków do skryptu, które:

i) zezwól na uruchomienie go ze skryptu powłoki i zakończenie z SIGTERM / SIGKILL (instrukcja „oprócz” obejmuje teraz „systemexit”)

ii) umożliwia zatrzymanie i ponowne uruchomienie skryptu oraz ponowne użycie tego samego portu (ponieważ był to zrestartowany skrypt, którego działanie zwykle kończyło się niepowodzeniem, mówiąc, że nie można otworzyć portu, jeśli moduł renderujący nadal go miał otwarty) - (instrukcja allow_reuse_address = True)

iii) stwórz wersję, która pobiera dane wejściowe ze standardowego wejścia i ponownie próbkuje je, używając sox do wyświetlania w formacie wav (na porcie 8082)

Moja wersja wygląda więc tak:

#!/usr/bin/python

import BaseHTTPServer
import SocketServer
import subprocess

PORT = 8082

MIMETYPE = 'audio/x-wav'
BUFFER = 65536

class Handler(BaseHTTPServer.BaseHTTPRequestHandler):
  def do_HEAD(s):
    print s.client_address, s.path, s.command
    s.send_response(200)
    s.send_header('content-type', MIMETYPE)
    s.end_headers()
  def do_GET(s):
    s.do_HEAD()
    pa = subprocess.Popen('sox -t raw -r 96000 -b 24 -L -e signed -c 2 - -t wav -r 44100 -b 16 -L -e signed -c 2 - ', shell = True, bufsize = BUFFER, stdout = subprocess.PIPE)
    while True:
        data = pa.stdout.read(1024)
        if len(data) == 0: break
        s.wfile.write(data)
    print 'stream closed'

SocketServer.TCPServer.allow_reuse_address = True
httpd = SocketServer.TCPServer(("", PORT), Handler)

print "listening on port", PORT

try:
 httpd.serve_forever()

except (KeyboardInterrupt, SystemExit):
 pass

httpd.server_close()
pastim
źródło
1
Znalazłem kilka drobnych problemów z tym skryptem.
pastim
@Adam - po kilku próbach znalazłem kilka drobnych problemów z tym programem. Jednak największym problemem jest to, że przesyłanie strumieniowe zatrzymuje się z błędem 32 (Broken pipe) po czasie, który jest wprost proporcjonalny do ilości wysyłanych danych. W przypadku strumienia jakości 24/96000 jest to nieco ponad godzina. 24/192000 to nieco ponad 30 minut. Dla jakości CD nieco ponad 3 godziny. Po ponownym wybraniu strumienia w module renderującym strumień rozpoczyna się ponownie. Uważam, że rozwiązaniem może być „szyfrowanie fragmentów”. Zastanawiałem się, czy ktoś wyprodukował wersję fragmentaryczną.
pastim
1

Nie jestem pewien, czy będzie to dla ciebie przydatne teraz, ale napisałem post o tym, jak to działa na Ubuntu 12.10:

http://dpc.ucore.info/blog/2012/11/07/dlna-streaming-in-ubuntu-12-dot-10/

dpc.pw
źródło
Dziękuję za podzielenie się tym - dokładnie to, co do tej pory zawsze mi się nie udawało. Z projektu tej witryny chcielibyśmy zachęcić Cię do nakreślenia kroków, które podjąłeś (oprócz zwykłego publikowania linku na swoim blogu), ponieważ linki mogą z czasem zniknąć, przez co Twoja odpowiedź będzie bezużyteczna. Wrócę do ciebie, jak tylko będę mógł to przetestować.
Takkat,
Oto moje dotychczasowe obserwacje: Postępowanie zgodnie z twoim przewodnikiem powoduje awarię Rygla z SEGFAULT podczas wybierania strumienia audio od klienta w 12.04. W 12.10 nie możemy utworzyć strumienia za pomocą GST-Launch. Czegoś brakuje?
Takkat
Pytanie dotyczyło 12.04 i ta odpowiedź dotyczy Ubuntu 12.10, w przeciwnym razie głosowałbym. :)
jdthood
Osoba z przyszłości tutaj: ten link zgnił. : P
Dataashaman