souzatharsis / podcastfy

An Open Source Python alternative to NotebookLM's podcast feature: Transforming Multimodal Content into Captivating Multilingual Audio Conversations with GenAI
https://www.podcastfy.ai
Apache License 2.0
955 stars 100 forks source link

[Windows] Critical Error when generation audio #165

Open Aditya-Rajgor opened 4 hours ago

Aditya-Rajgor commented 4 hours ago

I am running issue when generating audio. Here's my code.

%pip install ipython
from IPython.display import Audio, display
# Generate transcript only
from podcastfy.client import generate_podcast

user_input_text = "Some text"

def embed_audio(audio_file):
    """
    Embeds an audio file in the notebook, making it playable.

    Args:
        audio_file (str): Path to the audio file.
    """
    try:
        display(Audio(audio_file))
        print(f"Audio player embedded for: {audio_file}")
    except Exception as e:
        print(f"Error embedding audio: {str(e)}")

audio_file_path = generate_podcast(text=user_input_text, transcript_only=True)

audio_file_from_transcript = generate_podcast(
    transcript_file=audio_file_path,
    tts_model="elevenlabs",
    # api_key_label="elevenlabs"
)
embed_audio(audio_file_from_transcript)

Everything works fine, The audio files are being generated, but then I get this error.

NotADirectoryError [WinError 267] The directory name is invalid: 'data/audio/tmp/tmpvx99hy0y\\1_question.mp3'

Anyone know how to troubleshoot this? I am on windows11

souzatharsis commented 3 hours ago

Thank you for reporting this issue.

I've merged a fix now. Please update, try again and let me know if it's solved your problem.

Fixed audio generation in Windows OS issue: Normalize path separators for cross-platform compatibility

Aditya-Rajgor commented 3 hours ago

@souzatharsis , Thanks for the quick response. The error still persist.

Traceback

Internal Server Error: /
Traceback (most recent call last):
  File "C:\Users\adity\OneDrive\Desktop\Projects\firverrr\env\Lib\site-packages\podcastfy\text_to_speech.py", line 118, in convert_to_speech
    self._merge_audio_files(audio_segments, output_file)
  File "C:\Users\adity\OneDrive\Desktop\Projects\firverrr\env\Lib\site-packages\podcastfy\text_to_speech.py", line 180, in _merge_audio_files
    combined += AudioSegment.from_file(file_path, format=self.audio_format)
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\adity\OneDrive\Desktop\Projects\firverrr\env\Lib\site-packages\pydub\audio_segment.py", line 728, in from_file
    info = mediainfo_json(orig_file, read_ahead_limit=read_ahead_limit)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\adity\OneDrive\Desktop\Projects\firverrr\env\Lib\site-packages\pydub\utils.py", line 274, in mediainfo_json
    res = Popen(command, stdin=stdin_parameter, stdout=PIPE, stderr=PIPE)
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\adity\AppData\Local\Programs\Python\Python311\Lib\subprocess.py", line 1022, in __init__    
    self._execute_child(args, executable, preexec_fn, close_fds,
  File "C:\Users\adity\AppData\Local\Programs\Python\Python311\Lib\subprocess.py", line 1491, in _execute_child
    hp, ht, pid, tid = _winapi.CreateProcess(executable, args,
                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
FileNotFoundError: [WinError 2] The system cannot find the file specified

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "C:\Users\adity\AppData\Local\Programs\Python\Python311\Lib\shutil.py", line 619, in _rmtree_unsafe   
    os.unlink(fullname)
PermissionError: [WinError 32] The process cannot access the file because it is being used by another process: 'data/audio/tmp/tmp6xn1qbju\\1_question.mp3'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "C:\Users\adity\AppData\Local\Programs\Python\Python311\Lib\tempfile.py", line 878, in onerror        
    _os.unlink(path)
PermissionError: [WinError 32] The process cannot access the file because it is being used by another process: 'data/audio/tmp/tmp6xn1qbju\\1_question.mp3'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "C:\Users\adity\OneDrive\Desktop\Projects\firverrr\env\Lib\site-packages\django\core\handlers\exception.py", line 55, in inner
    response = get_response(request)
               ^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\adity\OneDrive\Desktop\Projects\firverrr\env\Lib\site-packages\django\core\handlers\base.py", line 197, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\adity\OneDrive\Desktop\Projects\firverrr\podme\podmeapp\views.py", line 36, in home
    audio_file_from_transcript = generate_podcast(
                                 ^^^^^^^^^^^^^^^^^
  File "C:\Users\adity\OneDrive\Desktop\Projects\firverrr\env\Lib\site-packages\podcastfy\client.py", line 316, in generate_podcast
    return process_content(
           ^^^^^^^^^^^^^^^^
  File "C:\Users\adity\OneDrive\Desktop\Projects\firverrr\env\Lib\site-packages\podcastfy\client.py", line 117, in process_content
    text_to_speech.convert_to_speech(qa_content, audio_file)
  File "C:\Users\adity\OneDrive\Desktop\Projects\firverrr\env\Lib\site-packages\podcastfy\text_to_speech.py", line 114, in convert_to_speech
    with tempfile.TemporaryDirectory(dir=self.temp_audio_dir) as temp_dir:
  File "C:\Users\adity\AppData\Local\Programs\Python\Python311\Lib\tempfile.py", line 904, in __exit__       
    self.cleanup()
  File "C:\Users\adity\AppData\Local\Programs\Python\Python311\Lib\tempfile.py", line 908, in cleanup        
    self._rmtree(self.name, ignore_errors=self._ignore_cleanup_errors)
  File "C:\Users\adity\AppData\Local\Programs\Python\Python311\Lib\tempfile.py", line 890, in _rmtree        
    _shutil.rmtree(name, onerror=onerror)
  File "C:\Users\adity\AppData\Local\Programs\Python\Python311\Lib\shutil.py", line 758, in rmtree
    return _rmtree_unsafe(path, onerror)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\adity\AppData\Local\Programs\Python\Python311\Lib\shutil.py", line 621, in _rmtree_unsafe   
    onerror(os.unlink, fullname, sys.exc_info())
  File "C:\Users\adity\AppData\Local\Programs\Python\Python311\Lib\tempfile.py", line 881, in onerror        
    cls._rmtree(path, ignore_errors=ignore_errors)
  File "C:\Users\adity\AppData\Local\Programs\Python\Python311\Lib\tempfile.py", line 890, in _rmtree        
    _shutil.rmtree(name, onerror=onerror)
  File "C:\Users\adity\AppData\Local\Programs\Python\Python311\Lib\shutil.py", line 758, in rmtree
    return _rmtree_unsafe(path, onerror)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\adity\AppData\Local\Programs\Python\Python311\Lib\shutil.py", line 602, in _rmtree_unsafe
    onerror(os.scandir, path, sys.exc_info())
  File "C:\Users\adity\AppData\Local\Programs\Python\Python311\Lib\shutil.py", line 599, in _rmtree_unsafe
    with os.scandir(path) as scandir_it:
         ^^^^^^^^^^^^^^^^
NotADirectoryError: [WinError 267] The directory name is invalid: 'data/audio/tmp/tmp6xn1qbju\\1_question.mp3'


![image](https://github.com/user-attachments/assets/4de94741-739b-48c8-87de-2942dc9c7c03)
![image](https://github.com/user-attachments/assets/8255ba7b-8d05-4d45-b771-b841bee74450)
Aditya-Rajgor commented 3 hours ago

I am using the 0.3.3 latest release.

image

souzatharsis commented 3 hours ago

It's weird because now I'm

temp_file = os.path.join(
                    temp_dir, f"{idx}_{speaker_type}.{self.audio_format}"
                ).replace('\\', '/') 

So you should no longer observe

data/audio/tmp/tmp6xn1qbju\\1_question.mp3

Aditya-Rajgor commented 3 hours ago

Here is the full traceback that I faced running the same on Jupyter notebook.

2024-11-09 00:48:18,202 - podcastfy.client - INFO - Using transcript file: transcript_a51b74a5161641588276af7675b04c46.txt
Error merging audio files: [WinError 2] The system cannot find the file specified
Error converting text to speech: [WinError 267] The directory name is invalid: 'data/audio/tmp/tmpfklfv1ms\\1_question.mp3'
2024-11-09 00:49:20,455 - podcastfy.client - ERROR - An error occurred in the process_content function: [WinError 267] The directory name is invalid: 'data/audio/tmp/tmpfklfv1ms\\1_question.mp3'
2024-11-09 00:49:20,456 - podcastfy.client - ERROR - An error occurred: [WinError 267] The directory name is invalid: 'data/audio/tmp/tmpfklfv1ms\\1_question.mp3'
---------------------------------------------------------------------------
FileNotFoundError                         Traceback (most recent call last)
File ~\OneDrive\Desktop\Projects\web-scrapping\env\Lib\site-packages\podcastfy\text_to_speech.py:118, in TextToSpeech.convert_to_speech(self, text, output_file)
    115 audio_segments = self._generate_audio_segments(
    116     cleaned_text, temp_dir
    117 )
--> 118 self._merge_audio_files(audio_segments, output_file)
    119 logger.info(f"Audio saved to {output_file}")

File ~\OneDrive\Desktop\Projects\web-scrapping\env\Lib\site-packages\podcastfy\text_to_speech.py:180, in TextToSpeech._merge_audio_files(self, audio_files, output_file)
    179 for file_path in audio_files:
--> 180     combined += AudioSegment.from_file(file_path, format=self.audio_format)
    182 # Ensure output directory exists

File ~\OneDrive\Desktop\Projects\web-scrapping\env\Lib\site-packages\pydub\audio_segment.py:728, in AudioSegment.from_file(cls, file, format, codec, parameters, start_second, duration, **kwargs)
    727 else:
--> 728     info = mediainfo_json(orig_file, read_ahead_limit=read_ahead_limit)
    729 if info:

File ~\OneDrive\Desktop\Projects\web-scrapping\env\Lib\site-packages\pydub\utils.py:274, in mediainfo_json(filepath, read_ahead_limit)
    273 command = [prober, '-of', 'json'] + command_args
--> 274 res = Popen(command, stdin=stdin_parameter, stdout=PIPE, stderr=PIPE)
    275 output, stderr = res.communicate(input=stdin_data)

File ~\AppData\Local\Programs\Python\Python311\Lib\subprocess.py:1022, in Popen.__init__(self, args, bufsize, executable, stdin, stdout, stderr, preexec_fn, close_fds, shell, cwd, env, universal_newlines, startupinfo, creationflags, restore_signals, start_new_session, pass_fds, user, group, extra_groups, encoding, errors, text, umask, pipesize, process_group)
   1019             self.stderr = io.TextIOWrapper(self.stderr,
   1020                     encoding=encoding, errors=errors)
-> 1022     self._execute_child(args, executable, preexec_fn, close_fds,
   1023                         pass_fds, cwd, env,
   1024                         startupinfo, creationflags, shell,
   1025                         p2cread, p2cwrite,
   1026                         c2pread, c2pwrite,
   1027                         errread, errwrite,
   1028                         restore_signals,
   1029                         gid, gids, uid, umask,
   1030                         start_new_session, process_group)
   1031 except:
   1032     # Cleanup if the child failed starting.

File ~\AppData\Local\Programs\Python\Python311\Lib\subprocess.py:1491, in Popen._execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, unused_restore_signals, unused_gid, unused_gids, unused_uid, unused_umask, unused_start_new_session, unused_process_group)
   1490 try:
-> 1491     hp, ht, pid, tid = _winapi.CreateProcess(executable, args,
   1492                              # no special security
   1493                              None, None,
   1494                              int(not close_fds),
   1495                              creationflags,
   1496                              env,
   1497                              cwd,
   1498                              startupinfo)
   1499 finally:
   1500     # Child is launched. Close the parent's copy of those pipe
   1501     # handles that only the child should have open.  You need
   (...)
   1504     # pipe will not close when the child process exits and the
   1505     # ReadFile will hang.

FileNotFoundError: [WinError 2] The system cannot find the file specified

During handling of the above exception, another exception occurred:

PermissionError                           Traceback (most recent call last)
File ~\AppData\Local\Programs\Python\Python311\Lib\shutil.py:619, in _rmtree_unsafe(path, onerror)
    618 try:
--> 619     os.unlink(fullname)
    620 except OSError:

PermissionError: [WinError 32] The process cannot access the file because it is being used by another process: 'data/audio/tmp/tmpfklfv1ms\\1_question.mp3'

During handling of the above exception, another exception occurred:

PermissionError                           Traceback (most recent call last)
File ~\AppData\Local\Programs\Python\Python311\Lib\tempfile.py:878, in TemporaryDirectory._rmtree.<locals>.onerror(func, path, exc_info)
    877 try:
--> 878     _os.unlink(path)
    879 # PermissionError is raised on FreeBSD for directories

PermissionError: [WinError 32] The process cannot access the file because it is being used by another process: 'data/audio/tmp/tmpfklfv1ms\\1_question.mp3'

During handling of the above exception, another exception occurred:

NotADirectoryError                        Traceback (most recent call last)
Cell In[7], line 1
----> 1 audio_file_from_transcript = generate_podcast(
      2     transcript_file="transcript_a51b74a5161641588276af7675b04c46.txt",
      3     tts_model="openai", 
      4 )

File ~\OneDrive\Desktop\Projects\web-scrapping\env\Lib\site-packages\podcastfy\client.py:316, in generate_podcast(urls, url_file, transcript_file, tts_model, transcript_only, config, conversation_config, image_paths, is_local, text, llm_model_name, api_key_label, topic)
    314     if image_paths:
    315         logger.warning("Image paths are ignored when using a transcript file.")
--> 316     return process_content(
    317         transcript_file=transcript_file,
    318         tts_model=tts_model,
    319         generate_audio=not transcript_only,
    320         config=default_config,
    321         conversation_config=conversation_config,
    322         is_local=is_local,
    323         text=text,
    324         model_name=llm_model_name,
    325         api_key_label=api_key_label,
    326         topic=topic,
    327     )
    328 else:
    329     urls_list = urls or []

File ~\OneDrive\Desktop\Projects\web-scrapping\env\Lib\site-packages\podcastfy\client.py:117, in process_content(urls, transcript_file, tts_model, generate_audio, config, conversation_config, image_paths, is_local, text, model_name, api_key_label, topic)
    113 random_filename = f"podcast_{uuid.uuid4().hex}.mp3"
    114 audio_file = os.path.join(
    115     output_directories.get("audio", "data/audio"), random_filename
    116 )
--> 117 text_to_speech.convert_to_speech(qa_content, audio_file)
    118 logger.info(f"Podcast generated successfully using {tts_model} TTS model")
    119 return audio_file

File ~\OneDrive\Desktop\Projects\web-scrapping\env\Lib\site-packages\podcastfy\text_to_speech.py:114, in TextToSpeech.convert_to_speech(self, text, output_file)
    112     logger.info(f"Audio saved to {output_file}")
    113 else:
--> 114     with tempfile.TemporaryDirectory(dir=self.temp_audio_dir) as temp_dir:
    115         audio_segments = self._generate_audio_segments(
    116             cleaned_text, temp_dir
    117         )
    118         self._merge_audio_files(audio_segments, output_file)

File ~\AppData\Local\Programs\Python\Python311\Lib\tempfile.py:904, in TemporaryDirectory.__exit__(self, exc, value, tb)
    903 def __exit__(self, exc, value, tb):
--> 904     self.cleanup()

File ~\AppData\Local\Programs\Python\Python311\Lib\tempfile.py:908, in TemporaryDirectory.cleanup(self)
    906 def cleanup(self):
    907     if self._finalizer.detach() or _os.path.exists(self.name):
--> 908         self._rmtree(self.name, ignore_errors=self._ignore_cleanup_errors)

File ~\AppData\Local\Programs\Python\Python311\Lib\tempfile.py:890, in TemporaryDirectory._rmtree(cls, name, ignore_errors)
    887         if not ignore_errors:
    888             raise
--> 890 _shutil.rmtree(name, onerror=onerror)

File ~\AppData\Local\Programs\Python\Python311\Lib\shutil.py:758, in rmtree(path, ignore_errors, onerror, dir_fd)
    756     # can't continue even if onerror hook returns
    757     return
--> 758 return _rmtree_unsafe(path, onerror)

File ~\AppData\Local\Programs\Python\Python311\Lib\shutil.py:621, in _rmtree_unsafe(path, onerror)
    619             os.unlink(fullname)
    620         except OSError:
--> 621             onerror(os.unlink, fullname, sys.exc_info())
    622 try:
    623     os.rmdir(path)

File ~\AppData\Local\Programs\Python\Python311\Lib\tempfile.py:881, in TemporaryDirectory._rmtree.<locals>.onerror(func, path, exc_info)
    879     # PermissionError is raised on FreeBSD for directories
    880     except (IsADirectoryError, PermissionError):
--> 881         cls._rmtree(path, ignore_errors=ignore_errors)
    882 except FileNotFoundError:
    883     pass

File ~\AppData\Local\Programs\Python\Python311\Lib\tempfile.py:890, in TemporaryDirectory._rmtree(cls, name, ignore_errors)
    887         if not ignore_errors:
    888             raise
--> 890 _shutil.rmtree(name, onerror=onerror)

File ~\AppData\Local\Programs\Python\Python311\Lib\shutil.py:758, in rmtree(path, ignore_errors, onerror, dir_fd)
    756     # can't continue even if onerror hook returns
    757     return
--> 758 return _rmtree_unsafe(path, onerror)

File ~\AppData\Local\Programs\Python\Python311\Lib\shutil.py:602, in _rmtree_unsafe(path, onerror)
    600         entries = list(scandir_it)
    601 except OSError:
--> 602     onerror(os.scandir, path, sys.exc_info())
    603     entries = []
    604 for entry in entries:

File ~\AppData\Local\Programs\Python\Python311\Lib\shutil.py:599, in _rmtree_unsafe(path, onerror)
    597 def _rmtree_unsafe(path, onerror):
    598     try:
--> 599         with os.scandir(path) as scandir_it:
    600             entries = list(scandir_it)
    601     except OSError:

NotADirectoryError: [WinError 267] The directory name is invalid: 'data/audio/tmp/tmpfklfv1ms\\1_question.mp3'
souzatharsis commented 2 hours ago

Thanks for sharing your logs, that's helpful. I've pushed a fix. Please let me know if that solved the issue. Otherwise, I will create a VM / docker image later to try and replicate the issue in Windows OS. Thanks for your patience.

Aditya-Rajgor commented 2 hours ago

Thanks for your quick effort! The issue seems to still persist.

It gives this now. Seems like solution is somewhat close.

NotADirectoryError at /
[WinError 267] The directory name is invalid: 'data\\audio\\tmp\\tmp9bbpx3i3\\1_question.mp3'
souzatharsis commented 1 hour ago

OK, it seems Windows requires an absolute path. I've made that fix now. Let me know.

Another question for a Windows user: The below is a valid path on WinOS, right?

data\audio\tmp\tmp9bbpx3i3\1_question.mp3

On Fri, Nov 8, 2024 at 11:38 AM Adi @.***> wrote:

Thanks for your quick effort! The issue seems to still persist.

It gives this now. Seems like solution is somewhat close.

NotADirectoryError at / [WinError 267] The directory name is invalid: 'data\audio\tmp\tmp9bbpx3i3\1_question.mp3'

— Reply to this email directly, view it on GitHub https://github.com/souzatharsis/podcastfy/issues/165#issuecomment-2464922990, or unsubscribe https://github.com/notifications/unsubscribe-auth/ADTMY3P7BDQZ7REVDPMIL5DZ7TEHTAVCNFSM6AAAAABRNNTEHCVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDINRUHEZDEOJZGA . You are receiving this because you were mentioned.Message ID: @.***>

Aditya-Rajgor commented 1 hour ago

Hi, Thanks for the update!!!!

I am getting this one now.

NotADirectoryError: [WinError 267] The directory name is invalid: 'C:\\Users\\user\\OneDrive\\Desktop\\Projects\\docs\\env\\Lib\\site-packages\\podcastfy\\data\\audio\\tmp\\tmpygd2l0xz\\1_question.mp3'