Ahoi zusammen.
Die Ausgangslage ist folgende:
Ich habe mir eine Extension für Chrome-ähnliche Browser gebastelt.
Ziel ist es, von einer beliebigen Video/Audio Seite eine mp3 zu erzeugen.
Das funktioniert mit NativeMessagingHosts.
Mein Host ist ein Python-Script, welches youtube.dl einbindet und darüber die videos/audios ergattert.
In Chrome/Chromium/Opera funktioniert der Spaß auch wie er sollte, in Vivaldi nicht ganz.
Hier mal der Host:
[codebox=python file=com.blabla.ytextract]
#!/usr/bin/env python
from __future__ import unicode_literals
import youtube_dl
import struct
import sys
import threading
# Thread that reads messages from the webapp.
def read_thread_func(queue):
message_number = 0
while 1:
# Read the message length (first 4 bytes).
text_length_bytes = sys.stdin.read(4)
if len(text_length_bytes) == 0:
sys.exit(0)
# Unpack message length as 4 byte integer.
text_length = struct.unpack('i', text_length_bytes.encode('utf-8'))[0]
# Read the text (JSON object) of the message.
text = sys.stdin.read(text_length)
# start download function
ytdl()
def logit(msg):
f = open('logfile', 'a')
f.write(msg+"\n")
f.close()
def ytdl():
url = "https://www.youtube.com/watch?v=B7bqAsxee4I"
# Logger Class to know what happens
class MyLogger(object):
def debug(self, msg):
logit("[debug]"+msg)
def warning(self, msg):
logit("[warning]"+msg)
def error(self, msg):
logit("[error]"+msg)
# youtube-dl parameter
path = "/home/user/Downloads/"
ydl_opts = {
'format': 'bestaudio',
'noplaylist' : True,
'outtmpl': path+'%(title)s.%(ext)s',
'verbose': True,
'postprocessors': [{
'key': 'FFmpegExtractAudio',
'preferredcodec': 'mp3',
'preferredquality': '192',
}],
'progress_hooks': [my_hook],
'logger': MyLogger(),
}
with youtube_dl.YoutubeDL(ydl_opts) as ydl:
ydl.download([url])
def Main():
read_thread_func(None)
sys.exit(0)
if __name__ == '__main__':
Main()
[/code]
Videos werden geladen, aber er hängt sich auf, wenn es ans Extrahieren von Audio geht:
[codebox=bash file=logfile]
[download] 100% of 873.61KiB in 00:00
[debug][ffmpeg] Correcting container in "/home/user/Downloads/videotitle.m4a"
[debug][debug] ffmpeg command line: ffmpeg -y -i 'file:/home/user/Downloads/videotitle.m4a' -c copy -f mp4 'file:/home/user/Downloads/videotitle.m4a'
[error]ERROR: Did you mean file:file:/home/user/Downloads/videotitle.m4a?
[error]Traceback (most recent call last):
File "/usr/lib/python3.6/site-packages/youtube_dl/YoutubeDL.py", line 1942, in post_process
files_to_delete, info = pp.run(info)
File "/usr/lib/python3.6/site-packages/youtube_dl/postprocessor/ffmpeg.py", line 530, in run
self.run_ffmpeg(filename, temp_filename, options)
File "/usr/lib/python3.6/site-packages/youtube_dl/postprocessor/ffmpeg.py", line 208, in run_ffmpeg
self.run_ffmpeg_multiple_files([path], out_path, opts)
File "/usr/lib/python3.6/site-packages/youtube_dl/postprocessor/ffmpeg.py", line 204, in run_ffmpeg_multiple_files
raise FFmpegPostProcessorError(msg)
youtube_dl.postprocessor.ffmpeg.FFmpegPostProcessorError: Did you mean file:file:/home/user/Downloads/videotitle.m4a?
[/code]
Ich vermute, das hängt damit zusammen, dass irgendwo ein zweites "file:" in die Befehlszeile rutscht, was in den anderen Browsern nicht passiert.
Nun ist die Frage, warum.
Das Vivaldi-Forum scheint wenig Interesse daran zu haben und die youtube-dl community hat mein Issue geschlossen ohne groß drauf einzugehen.
Findet sich hier jemand, der sich mit der Materie auskennt?
Hat Vivaldi besondere Umgebungsvariablen, die dafür verantwortlich sind?
Wenn ich das script im terminal ausführe, funktioniert es problemlos.
Ich weiß nicht so recht, wo ich anfangen soll zu suchen.
vivaldi, youtube-dl, irgendwas passt nicht mit den Pfaden
- noisefloor
- User
- Beiträge: 3856
- Registriert: Mittwoch 17. Oktober 2007, 21:40
- Wohnort: WW
- Kontaktdaten:
Hallo,
der verwendest ja Python 2, der Youtube Downloader, der importiert wird, ist aber für Python 3.6. Das passt nicht, normalerweise sollte der durch das `import` Statement gar nicht gefunden werden. Hast du dahingehend dein System irgendwie "verbogen"?
Gruß, noisefloor
der verwendest ja Python 2, der Youtube Downloader, der importiert wird, ist aber für Python 3.6. Das passt nicht, normalerweise sollte der durch das `import` Statement gar nicht gefunden werden. Hast du dahingehend dein System irgendwie "verbogen"?
Gruß, noisefloor
- noisefloor
- User
- Beiträge: 3856
- Registriert: Mittwoch 17. Oktober 2007, 21:40
- Wohnort: WW
- Kontaktdaten:
Hallo,
Die Zeile `#!/usr/bin/env python` lädt also den Python 2 Interpreter, normalerweise. Es sei denn, Arch Linux macht da was anders als Ubuntu, Debian, RedHat & Co.
Gruß, noisefloor
Am einfachsten, indem du den Python-Interpreter in einem Terminal startest. Dann wird die Python-Version ausgegeben. Mit dem Aufruf von `python` bekommst du normalerweise Python 2 (bei den meisten Systemen heute 2.7.x), beim Aufruf von `python3` Python 3.x, bei dir also Python 3.6.Woran erkennt man, welche Version ich verwende?
Die Zeile `#!/usr/bin/env python` lädt also den Python 2 Interpreter, normalerweise. Es sei denn, Arch Linux macht da was anders als Ubuntu, Debian, RedHat & Co.
Gruß, noisefloor
@le_mon: python ist normalerweise für Python2 reserviert, nur Archlinux macht da sein eigenes Ding, trotzdem sollte die Shebang-Zeile »#!/usr/bin/env python3« heißen, damit es klar ist und auch auf anderen Systemen läuft. Nächster Punkt ist der __future__-Import, der bei Python3 überflüssig ist und daher sehr stark an Python2 erinnert.
Eingerückt wird immer mit 4 Leerzeichen, nicht mit 2. 1 sollte nicht für den Wahrheitswert True mißbraucht werden. Die ganze read_thread_func sieht seltsam aus. Du schreibst, Du willst Bytes lesen, liest aber Zeichen, und hoffst, dass das nicht irgendwie gültiges UTF8 ist und Du statt dessen 5, 6, oder mehr Bytes liest und Python3 sein Unicode-Wodoo machen kann. Am besten bekommt die Funktion als Argument ein file-objekt das Binärdaten liest, dann kann der Aufrufer entscheiden, wie er die Daten liefern will.
sys.exit sollte außerhalb der Main-Funktion nicht vorkommen. queue, message_number und text werden gar nicht benutzt, so dass die ganze Funktion unnötig ist.
Zum Loggen gibt es schon das logging-Modul, da braucht man nichts Neues erfinden. Klassen gehört auch nicht in eine Funktion; so kann man sie gar nicht testen.
youtube-dl ist so intelligent, die Fehlermeldung zu verstümmeln und nur die letzte Zeile auszugeben, so dass man garantiert nicht die Ursache finden kann. Was ist die Ausgabe, wenn Du ffmpeg direkt startest?
[codebox=bash file=Unbenannt.bsh]
ffmpeg -y -i 'file:/home/user/Downloads/videotitle.m4a' -c copy -f mp4 'file:/home/user/Downloads/videotitle.m4a'[/code]
Eingerückt wird immer mit 4 Leerzeichen, nicht mit 2. 1 sollte nicht für den Wahrheitswert True mißbraucht werden. Die ganze read_thread_func sieht seltsam aus. Du schreibst, Du willst Bytes lesen, liest aber Zeichen, und hoffst, dass das nicht irgendwie gültiges UTF8 ist und Du statt dessen 5, 6, oder mehr Bytes liest und Python3 sein Unicode-Wodoo machen kann. Am besten bekommt die Funktion als Argument ein file-objekt das Binärdaten liest, dann kann der Aufrufer entscheiden, wie er die Daten liefern will.
sys.exit sollte außerhalb der Main-Funktion nicht vorkommen. queue, message_number und text werden gar nicht benutzt, so dass die ganze Funktion unnötig ist.
Zum Loggen gibt es schon das logging-Modul, da braucht man nichts Neues erfinden. Klassen gehört auch nicht in eine Funktion; so kann man sie gar nicht testen.
youtube-dl ist so intelligent, die Fehlermeldung zu verstümmeln und nur die letzte Zeile auszugeben, so dass man garantiert nicht die Ursache finden kann. Was ist die Ausgabe, wenn Du ffmpeg direkt startest?
[codebox=bash file=Unbenannt.bsh]
ffmpeg -y -i 'file:/home/user/Downloads/videotitle.m4a' -c copy -f mp4 'file:/home/user/Downloads/videotitle.m4a'[/code]
Hu...
Danke vorerst.
Ich hab mir die Codeschnipsel irgendwie zusammen gesucht und muss gestehen, das dies mein 1. Pythonversuch ist.
Werde mir den Sonntag gönnen um alles nochmal auf den 3.6 Standard zu bringen und dann berichten.
Fühle mich hier gut aufgehoben und werde öfter reinschauen
Danke vorerst.
Ich hab mir die Codeschnipsel irgendwie zusammen gesucht und muss gestehen, das dies mein 1. Pythonversuch ist.
Werde mir den Sonntag gönnen um alles nochmal auf den 3.6 Standard zu bringen und dann berichten.
Fühle mich hier gut aufgehoben und werde öfter reinschauen
back again,
Shebang angepasst, Leerzeichen sind nun alle korrekt und überflüssiges Zeug habe ich rausgeworfen. Ändert sich aber nichts am Verhalten, dass der Fehler mit dem file:file: auftaucht:
INFO: Dies tritt nur im Vivaldi Browser auf, Opera und Chrome/chromium tun was ihnen gesagt wird.
Bisher sieht der code folgendermaßen aus:
hier die ffmpeg line, wenn ich sie manuell ausführe:
Zur seltsamen read_msg:
So oder ähnlich habe ich das aus den examples vondeveloper.chrome.com übernommen.
Gesendet wird die Nachricht per
[codebox=javascript file=Unbenannt.js]
chrome.runtime.sendNativeMessage('com.my_company.my_application',
{ text: "Hello" },
function(response) {
console.log("Received " + response);
});[/code]
Ich verstehe das so, dass die ersten 4 "bytes" nur die Länge der Nachricht angeben und kein utf-8 enthalten können.
Oder bin ich da völlig unterbelichtet? Sagts mir. Ich bin neu in dieser Materie
Shebang angepasst, Leerzeichen sind nun alle korrekt und überflüssiges Zeug habe ich rausgeworfen. Ändert sich aber nichts am Verhalten, dass der Fehler mit dem file:file: auftaucht:
Code: Alles auswählen
youtube_dl.utils.DownloadError: ERROR: Did you mean file:file:/home/user/testvideo.m4a?
Bisher sieht der code folgendermaßen aus:
Code: Alles auswählen
#!/usr/bin/env python3
import sys
import json
import struct
import youtube_dl
import taglib
import logging
logging.basicConfig(filename='logfile',level=logging.DEBUG)
class MyLogger(object):
def debug(self, msg):
logging.debug(msg)
def warning(self, msg):
logging.warning(msg)
def error(self, msg):
logging.error(msg)
def getInfo(url):
#kommt noch
def download(url):
def my_hook(g):
if g['status'] == 'finished':
send_msg('{"status":"converting"}')
path = "/home/user/"
destination = path+'%(title)s.%(ext)s'
ydl_opts = {
'format': 'bestaudio',
'noplaylist' : True,
'outtmpl': destination,
'verbose': True,
'keepvideo': True,
'postprocessors': [{
'key': 'FFmpegExtractAudio',
'preferredcodec': 'mp3',
'preferredquality': '192',
}],
'progress_hooks': [my_hook],
'logger': MyLogger(),
}
with youtube_dl.YoutubeDL(ydl_opts) as ydl:
info = ydl.extract_info(str(url), download=False)
#download_target = ydl.prepare_filename(info)
ydl.download([url])
# Function to send a message to chrome.
def send_msg(MSG_DICT):
# Converts dictionary into string containing JSON format.
msg_json = json.dumps([MSG_DICT], separators=(",", ":"))
# Encodes string with UTF-8.
msg_json_utf8 = msg_json.encode("utf-8")
# Writes the message size. (Writing to buffer because writing bytes object.)
sys.stdout.buffer.write(struct.pack("i", len(msg_json_utf8)))
# Writes the message itself. (Writing to buffer because writing bytes object.)
sys.stdout.buffer.write(msg_json_utf8)
sys.stdout.flush()
# Function to read a message from chrome.
def read_msg():
# Reads the first 4 bytes of the message (which designates message length).
text_length_bytes = sys.stdin.buffer.read(4)
# Unpacks the first 4 bytes that are the message length. [0] required because unpack returns tuple with required data at index 0.
text_length = struct.unpack("i", text_length_bytes)[0]
# Reads and decodes the text (which is JSON) of the message.
text_undecoded = sys.stdin.buffer.read(text_length).decode("utf-8")
# [...] Then use the data.
msg = json.loads(text_undecoded)
if 'getinfo' in msg:
vidinfo = getInfo(msg['getinfo'])
send_msg(vidinfo)
if 'download' in msg:
download(msg['download'])
def Main():
read_msg()
sys.exit(0)
if __name__ == '__main__':
Main()
hier die ffmpeg line, wenn ich sie manuell ausführe:
Code: Alles auswählen
% ffmpeg -y -i 'file:/testvideo.m4a' -c copy -f mp4 'file:/testvideo.temp.m4a'
ffmpeg version 3.3.1 Copyright (c) 2000-2017 the FFmpeg developers
built with gcc 6.3.1 (GCC) 20170306
configuration: --prefix=/usr --disable-debug --disable-static --disable-stripping --enable-avisynth --enable-avresample --enable-fontconfig --enable-gmp --enable-gnutls --enable-gpl --enable-ladspa --enable-libass --enable-libbluray --enable-libfreetype --enable-libfribidi --enable-libgsm --enable-libiec61883 --enable-libmodplug --enable-libmp3lame --enable-libopencore_amrnb --enable-libopencore_amrwb --enable-libopenjpeg --enable-libopus --enable-libpulse --enable-libschroedinger --enable-libsoxr --enable-libspeex --enable-libssh --enable-libtheora --enable-libv4l2 --enable-libvidstab --enable-libvorbis --enable-libvpx --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxcb --enable-libxvid --enable-netcdf --enable-shared --enable-version3
libavutil 55. 58.100 / 55. 58.100
libavcodec 57. 89.100 / 57. 89.100
libavformat 57. 71.100 / 57. 71.100
libavdevice 57. 6.100 / 57. 6.100
libavfilter 6. 82.100 / 6. 82.100
libavresample 3. 5. 0 / 3. 5. 0
libswscale 4. 6.100 / 4. 6.100
libswresample 2. 7.100 / 2. 7.100
libpostproc 54. 5.100 / 54. 5.100
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'file:/testvideo.m4a':
Metadata:
major_brand : dash
minor_version : 0
compatible_brands: iso6mp41
creation_time : 2017-05-27T20:05:31.000000Z
Duration: 00:00:23.66, start: 0.000000, bitrate: 95 kb/s
Stream #0:0(und): Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, mono, fltp, 39 kb/s (default)
Metadata:
creation_time : 2017-05-27T20:05:31.000000Z
handler_name : SoundHandler
Output #0, mp4, to 'file:/testvideo.temp.m4a':
Metadata:
major_brand : dash
minor_version : 0
compatible_brands: iso6mp41
encoder : Lavf57.71.100
Stream #0:0(und): Audio: aac (LC) ([64][0][0][0] / 0x0040), 44100 Hz, mono, fltp, 39 kb/s (default)
Metadata:
creation_time : 2017-05-27T20:05:31.000000Z
handler_name : SoundHandler
Stream mapping:
Stream #0:0 -> #0:0 (copy)
Press [q] to stop, [?] for help
size= 275kB time=00:00:23.63 bitrate= 95.4kbits/s speed=1.63e+03x
video:0kB audio:270kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 1.739545%
So oder ähnlich habe ich das aus den examples vondeveloper.chrome.com übernommen.
Gesendet wird die Nachricht per
[codebox=javascript file=Unbenannt.js]
chrome.runtime.sendNativeMessage('com.my_company.my_application',
{ text: "Hello" },
function(response) {
console.log("Received " + response);
});[/code]
Ich verstehe das so, dass die ersten 4 "bytes" nur die Länge der Nachricht angeben und kein utf-8 enthalten können.
Oder bin ich da völlig unterbelichtet? Sagts mir. Ich bin neu in dieser Materie
Zuletzt geändert von le_mon am Sonntag 28. Mai 2017, 15:03, insgesamt 1-mal geändert.
Ich habe etwas nachgeforscht und herausgefunden, dass mein Script wunderbarst funktioniert, wenn ich das zusätzliche Paket entferne:
Sieht wohl so aus, als ob die ffmpeg-version, die dieses Paket bereit stellt, nicht das kann, was meine Version im System (local/ffmpeg 1:3.3.1-8)kann und dies zu Problemen mit den Pfaden führt. Außerdem hat die vivaldi-ffmpeg version manchmal ein Problem mit dem opus codec, welcher von ffprobe nciht korrekt erkannt wird, mit der System-Version allerdings schon.
Das selbe Spiel ist in Opera der Fall, nur mit Chromium scheint beides zu gehen.
Gibt es ne Möglichkeit, Python zu sagen, welche Umgebungspfade es nutzen soll?
Code: Alles auswählen
aur/vivaldi-ffmpeg-codecs 58.0.3029.82-1 (70) (3,48)
additional support for proprietary codecs for vivaldi
Das selbe Spiel ist in Opera der Fall, nur mit Chromium scheint beides zu gehen.
Gibt es ne Möglichkeit, Python zu sagen, welche Umgebungspfade es nutzen soll?
Falls es jemand interessiert:
Ich hab mal alles auf GitHub gestellt:
https://github.com/le-mon/vid2mp3/
Ich hab mal alles auf GitHub gestellt:
https://github.com/le-mon/vid2mp3/