oaubert / python-vlc

Python vlc bindings
GNU Lesser General Public License v2.1
384 stars 110 forks source link

name 'vlc' not defined #251

Closed rhodso closed 1 year ago

rhodso commented 1 year ago

Hi, I'm getting a weird python error. I can import the vlc library just fine, but when I try to use it, for example, setting up an instance (with vlc.Instance(), it throws the error NameError: name vlc is not defined

Here's what I've tried so far:

I've also uninstalled and reinstalled both VLC and the python-vlc package, to no avail

I'm using Windows 10 (but developing for use on a linux system), using python 3.10.2 I'm also running the python environment in a venv, so maybe that has something to do with it. I've tried running it outside of the venv, but that's not made any difference either

I'm out of ideas for now, any suggestions?

mrJean1 commented 1 year ago

Try typing one of the following lines:

  python  vlc.py  -v

or if vlc.py was pip-installed:

  python  -m  vlc  -v
rhodso commented 1 year ago

vlc.py was pip installed, here's the output:

vlc.py: 3.0.18121 (Wed Nov 16 12:04:29 2022 3.0.18)
libVLC: 3.0.18 Vetinari (0x3001200)
plugins: C:\Program Files\VideoLAN\VLC
Python: 3.10.2 (64bit) Windows 10
mrJean1 commented 1 year ago

So, at least on Windows 10 vlc.py should work. Try running a video like

  python  -m  vlc  <video_file_name>

Then type ? to see more single-key options. After that, try the same 2 lines on Linux and that should provide some clue what's wrong.

rhodso commented 1 year ago

I've not tried getting anything running on linux just yet. That'll (probably) be running on a raspberry pi on headless mode, or at least my laptop that has arch on it

Here's a screenshot that I took while the video was playing - I was trying to get it to recognise some input, but that didn't appeart to happen output

Here's a screenshot that I took when the video ended. The issue of not recognising input is still there, so I'm unable to close the vlc player directly, but can close it by closing the terminal image

mrJean1 commented 1 year ago

The VLC.App must be installed and must be working properly on its own. Only then, python-vlc vlc.py can work … as long as vlc.py can find the libvlc.dll or -.so library included in the VLC.App.

rhodso commented 1 year ago

VLC is installed and working fine: image

mrJean1 commented 1 year ago

This is Windows, isn't it? What about Linux and Raspberry? Does the plain VLC.App run on those?

Btw, the errors and not being able to quit are a vlc.py issue on Windows. Try using the tkvlc.py example with Python 3.11.2 on Windows. Download that from the python-vlc web site and use the command line:

  python  tkvlc.py  <video_file_name>

One final comment, make sure to use the 64-bit VLC.App with vlc.py in 64-bit Python. Or use the 32-bit version of both.

rhodso commented 1 year ago

That appears to have worked image

I'll go try the other stuff with python 3.11.2 and see what happens

rhodso commented 1 year ago

Still getting the same error in the initial script I had the issue in

image

Using the following: Python 3.11.2 (64 bit) python-vlc 3.0.18121 (from pip install) VLC Application 3.0.18 64 bit

I'm also still developing the script so I'm just concerned with getting it working on Windows for the moment, I'll deal with linux when I've actually got something I can test

I can try it on linux if you think that'll help, though

mrJean1 commented 1 year ago

A NameError usually means undefined object. In the script core.py there a line somewhere like this one

  import vlc

or maybe -just a guess-

  from main import vlc

In any case, first get the script to work on one platform (Windows or Linux) before moving to the other and then yet an other.

rhodso commented 1 year ago

Currently I have the following in core.py:

os.add_dll_directory(r"C:\\Program Files\\VideoLAN\\VLC")

# Some other code

try:
        logging.info(msg="Importing libraries...")
        # TODO: Add other needed libraries here
        import yt_dlp
        import vlc
 except ImportError:
        # Log which libraries failed to import
        logging.error(msg="Failed to import libraries: " + str(sys.exc_info()[1]))

# Some other code

def play_song(self, url):
        # Get the source url
        source_url = self.get_video(url)

        # Create the vlc instance
        vlc_instance = vlc.Instance()
        vlc_player = vlc_instance.media_player_new()

        # Create the media
        media = vlc_instance.media_new(source_url)

        # Set the media
        vlc_player.set_media(media)

        # Play the media
        vlc_player.play()

def test():
    c = core()
    c.play_song("https://www.youtube.com/watch?v=dQw4w9WgXcQ")

if __name__ == '__main__':
    test()

And then the output of that is just:

2023-03-25 00:04:04,310 Importing libraries...
Traceback (most recent call last):
  File "G:\!Programming\Python\HKMB2\py\core.py", line 126, in <module> 
    test()
  File "G:\!Programming\Python\HKMB2\py\core.py", line 123, in test     
    c.play_song("https://www.youtube.com/watch?v=dQw4w9WgXcQ")
  File "G:\!Programming\Python\HKMB2\py\core.py", line 109, in play_song
    vlc_instance = vlc.Instance()
                   ^^^
NameError: name 'vlc' is not defined

So it's definetly importing the module, but when I go to create the instance it says it's not defined

mrJean1 commented 1 year ago

It is hard to tell, since several pieces are missing.

It seems play_song is a method of some class. Where does it get vlc from?

In any case, this is not a VLC or vlc.py issue. Sorry.

rhodso commented 1 year ago

Ok, so that works. Full code for reference:

# Stanrdard library imports
import os
import logging

# Third party imports
import yt_dlp
import vlc

# Options for the ytdl object
ytdl_opts = {
    'format': 'bestaudio/best',
    'outtmpl': '%(extractor)s-%(id)s-%(title)s.%(ext)s',
    'restrictfilenames': True,
    'noplaylist': True,
    'nocheckcertificate': True,
    'ignoreerrors': False,
    'logtostderr': False,
    'quiet': True,
    'no_warnings': True,
    'default_search': 'auto',
    'source_address': '0.0.0.0' # bind to all IPv4 addresses
}

# Create the YTDL object
ytdl = yt_dlp.YoutubeDL(ytdl_opts)

# Logging options
LOG_TO_FILE = False
LOG_FILE_NAME = "bot.log"

# Delete the log file if it exists
if os.path.isfile(path=LOG_FILE_NAME):
    os.remove(path=LOG_FILE_NAME)

# Set up logging
if LOG_TO_FILE:
    log_handler = logging.basicConfig(format='%(asctime)s %(message)s', filename=LOG_FILE_NAME, encoding='utf-8', level=logging.INFO)
else:
    log_handler = logging.basicConfig(format='%(asctime)s %(message)s', encoding='utf-8', level=logging.INFO)

# Get the source url from the video url
def get_video(url):
    info = ytdl.extract_info(url, download=False)

    formats = info['formats']

    # Get the best audio format
    for f in formats:
        if f.get('acodec') == 'opus':
            best_audio_format = f
            break

    # If we didn't find an opus format, just use the first one
    if not best_audio_format:
        best_audio_format = formats[0]

    # Get the source url
    source_url = best_audio_format['url']

    # Return the source url
    return source_url

# Play the song
def play_song(url):
    # Get the source url
    source_url = get_video(url)

    # Create the vlc instance
    vlc_instance = vlc.Instance()
    vlc_player = vlc_instance.media_player_new()

    # Create the media
    media = vlc_instance.media_new(source_url)

    # Set the media
    vlc_player.set_media(media)

    # Play the media
    vlc_player.play()

# Test here for now
if __name__ == '__main__':
    play_song("https://www.youtube.com/watch?v=dQw4w9WgXcQ")
mrJean1 commented 1 year ago

Great.

rhodso commented 1 year ago

I guess the solution then is to just try moving the imports around and hope lol