prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  torchaudio has to be optional
  @bpopeters 
  The last change https://github.com/OpenNMT/OpenNMT-py/pull/1144/files
  made torchaudio a requirement, not an optional one as it should be.
  
  Can you fix it please ?
  Thanks.
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `onmt/inputters/audio_dataset.py`
  Content:
  ```
  1 # -*- coding: utf-8 -*-
  2 import os
  3 from tqdm import tqdm
  4 
  5 import torch
  6 import torchaudio
  7 import librosa
  8 import numpy as np
  9 
  10 from onmt.inputters.dataset_base import DatasetBase
  11 
  12 
  13 class AudioDataset(DatasetBase):
  14     data_type = 'audio'  # get rid of this class attribute asap
  15 
  16     @staticmethod
  17     def sort_key(ex):
  18         """ Sort using duration time of the sound spectrogram. """
  19         return ex.src.size(1)
  20 
  21     @staticmethod
  22     def extract_features(audio_path, sample_rate, truncate, window_size,
  23                          window_stride, window, normalize_audio):
  24         # torchaudio loading options recently changed. It's probably
  25         # straightforward to rewrite the audio handling to make use of
  26         # up-to-date torchaudio, but in the meantime there is a legacy
  27         # method which uses the old defaults
  28         sound, sample_rate_ = torchaudio.legacy.load(audio_path)
  29         if truncate and truncate > 0:
  30             if sound.size(0) > truncate:
  31                 sound = sound[:truncate]
  32 
  33         assert sample_rate_ == sample_rate, \
  34             'Sample rate of %s != -sample_rate (%d vs %d)' \
  35             % (audio_path, sample_rate_, sample_rate)
  36 
  37         sound = sound.numpy()
  38         if len(sound.shape) > 1:
  39             if sound.shape[1] == 1:
  40                 sound = sound.squeeze()
  41             else:
  42                 sound = sound.mean(axis=1)  # average multiple channels
  43 
  44         n_fft = int(sample_rate * window_size)
  45         win_length = n_fft
  46         hop_length = int(sample_rate * window_stride)
  47         # STFT
  48         d = librosa.stft(sound, n_fft=n_fft, hop_length=hop_length,
  49                          win_length=win_length, window=window)
  50         spect, _ = librosa.magphase(d)
  51         spect = np.log1p(spect)
  52         spect = torch.FloatTensor(spect)
  53         if normalize_audio:
  54             mean = spect.mean()
  55             std = spect.std()
  56             spect.add_(-mean)
  57             spect.div_(std)
  58         return spect
  59 
  60     @classmethod
  61     def make_examples(
  62         cls,
  63         data,
  64         src_dir,
  65         side,
  66         sample_rate,
  67         window_size,
  68         window_stride,
  69         window,
  70         normalize_audio,
  71         truncate=None
  72     ):
  73         """
  74         Args:
  75             data: sequence of audio paths or path containing these sequences
  76             src_dir (str): location of source audio files.
  77             side (str): 'src' or 'tgt'.
  78             sample_rate (int): sample_rate.
  79             window_size (float) : window size for spectrogram in seconds.
  80             window_stride (float): window stride for spectrogram in seconds.
  81             window (str): window type for spectrogram generation.
  82             normalize_audio (bool): subtract spectrogram by mean and divide
  83                 by std or not.
  84             truncate (int): maximum audio length (0 or None for unlimited).
  85 
  86         Yields:
  87             a dictionary containing audio data for each line.
  88         """
  89         assert src_dir is not None and os.path.exists(src_dir),\
  90             "src_dir must be a valid directory if data_type is audio"
  91 
  92         if isinstance(data, str):
  93             data = cls._read_file(data)
  94 
  95         for i, line in enumerate(tqdm(data)):
  96             audio_path = os.path.join(src_dir, line.strip())
  97             if not os.path.exists(audio_path):
  98                 audio_path = line.strip()
  99 
  100             assert os.path.exists(audio_path), \
  101                 'audio path %s not found' % (line.strip())
  102 
  103             spect = AudioDataset.extract_features(
  104                 audio_path, sample_rate, truncate, window_size,
  105                 window_stride, window, normalize_audio
  106             )
  107 
  108             yield {side: spect, side + '_path': line.strip(),
  109                    side + '_lengths': spect.size(1), 'indices': i}
  110
  ```
  --- END FILES ---
  
  Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.
  
  Here is an example:
  
  ```diff
  diff --git a/examples/server_async.py b/examples/server_async.py
  --- a/examples/server_async.py
  +++ b/examples/server_async.py
  @@ -313,4 +313,4 @@
   
   
   if __name__ == "__main__":
  -    asyncio.run(run_async_server("."), debug=True)
  +    asyncio.run(run_async_server(), debug=True)
  diff --git a/examples/server_sync.py b/examples/server_sync.py
  --- a/examples/server_sync.py
  +++ b/examples/server_sync.py
  @@ -313,5 +313,5 @@
   
   
   if __name__ == "__main__":
  -    server = run_sync_server(".")
  +    server = run_sync_server()
       server.shutdown()
  
  ```
  
golden_diff: diff --git a/onmt/inputters/audio_dataset.py b/onmt/inputters/audio_dataset.py
  --- a/onmt/inputters/audio_dataset.py
  +++ b/onmt/inputters/audio_dataset.py
  @@ -3,9 +3,6 @@
   from tqdm import tqdm
   
   import torch
  -import torchaudio
  -import librosa
  -import numpy as np
   
   from onmt.inputters.dataset_base import DatasetBase
   
  @@ -21,6 +18,9 @@
       @staticmethod
       def extract_features(audio_path, sample_rate, truncate, window_size,
                            window_stride, window, normalize_audio):
  +        import torchaudio
  +        import librosa
  +        import numpy as np
           # torchaudio loading options recently changed. It's probably
           # straightforward to rewrite the audio handling to make use of
           # up-to-date torchaudio, but in the meantime there is a legacy
  
verification_info: {"golden_diff": "diff --git a/onmt/inputters/audio_dataset.py b/onmt/inputters/audio_dataset.py\n--- a/onmt/inputters/audio_dataset.py\n+++ b/onmt/inputters/audio_dataset.py\n@@ -3,9 +3,6 @@\n from tqdm import tqdm\n \n import torch\n-import torchaudio\n-import librosa\n-import numpy as np\n \n from onmt.inputters.dataset_base import DatasetBase\n \n@@ -21,6 +18,9 @@\n     @staticmethod\n     def extract_features(audio_path, sample_rate, truncate, window_size,\n                          window_stride, window, normalize_audio):\n+        import torchaudio\n+        import librosa\n+        import numpy as np\n         # torchaudio loading options recently changed. It's probably\n         # straightforward to rewrite the audio handling to make use of\n         # up-to-date torchaudio, but in the meantime there is a legacy\n", "issue": "torchaudio has to be optional\n@bpopeters \r\nThe last change https://github.com/OpenNMT/OpenNMT-py/pull/1144/files\r\nmade torchaudio a requirement, not an optional one as it should be.\r\n\r\nCan you fix it please ?\r\nThanks.\n", "before_files": [{"content": "# -*- coding: utf-8 -*-\nimport os\nfrom tqdm import tqdm\n\nimport torch\nimport torchaudio\nimport librosa\nimport numpy as np\n\nfrom onmt.inputters.dataset_base import DatasetBase\n\n\nclass AudioDataset(DatasetBase):\n    data_type = 'audio'  # get rid of this class attribute asap\n\n    @staticmethod\n    def sort_key(ex):\n        \"\"\" Sort using duration time of the sound spectrogram. \"\"\"\n        return ex.src.size(1)\n\n    @staticmethod\n    def extract_features(audio_path, sample_rate, truncate, window_size,\n                         window_stride, window, normalize_audio):\n        # torchaudio loading options recently changed. It's probably\n        # straightforward to rewrite the audio handling to make use of\n        # up-to-date torchaudio, but in the meantime there is a legacy\n        # method which uses the old defaults\n        sound, sample_rate_ = torchaudio.legacy.load(audio_path)\n        if truncate and truncate > 0:\n            if sound.size(0) > truncate:\n                sound = sound[:truncate]\n\n        assert sample_rate_ == sample_rate, \\\n            'Sample rate of %s != -sample_rate (%d vs %d)' \\\n            % (audio_path, sample_rate_, sample_rate)\n\n        sound = sound.numpy()\n        if len(sound.shape) > 1:\n            if sound.shape[1] == 1:\n                sound = sound.squeeze()\n            else:\n                sound = sound.mean(axis=1)  # average multiple channels\n\n        n_fft = int(sample_rate * window_size)\n        win_length = n_fft\n        hop_length = int(sample_rate * window_stride)\n        # STFT\n        d = librosa.stft(sound, n_fft=n_fft, hop_length=hop_length,\n                         win_length=win_length, window=window)\n        spect, _ = librosa.magphase(d)\n        spect = np.log1p(spect)\n        spect = torch.FloatTensor(spect)\n        if normalize_audio:\n            mean = spect.mean()\n            std = spect.std()\n            spect.add_(-mean)\n            spect.div_(std)\n        return spect\n\n    @classmethod\n    def make_examples(\n        cls,\n        data,\n        src_dir,\n        side,\n        sample_rate,\n        window_size,\n        window_stride,\n        window,\n        normalize_audio,\n        truncate=None\n    ):\n        \"\"\"\n        Args:\n            data: sequence of audio paths or path containing these sequences\n            src_dir (str): location of source audio files.\n            side (str): 'src' or 'tgt'.\n            sample_rate (int): sample_rate.\n            window_size (float) : window size for spectrogram in seconds.\n            window_stride (float): window stride for spectrogram in seconds.\n            window (str): window type for spectrogram generation.\n            normalize_audio (bool): subtract spectrogram by mean and divide\n                by std or not.\n            truncate (int): maximum audio length (0 or None for unlimited).\n\n        Yields:\n            a dictionary containing audio data for each line.\n        \"\"\"\n        assert src_dir is not None and os.path.exists(src_dir),\\\n            \"src_dir must be a valid directory if data_type is audio\"\n\n        if isinstance(data, str):\n            data = cls._read_file(data)\n\n        for i, line in enumerate(tqdm(data)):\n            audio_path = os.path.join(src_dir, line.strip())\n            if not os.path.exists(audio_path):\n                audio_path = line.strip()\n\n            assert os.path.exists(audio_path), \\\n                'audio path %s not found' % (line.strip())\n\n            spect = AudioDataset.extract_features(\n                audio_path, sample_rate, truncate, window_size,\n                window_stride, window, normalize_audio\n            )\n\n            yield {side: spect, side + '_path': line.strip(),\n                   side + '_lengths': spect.size(1), 'indices': i}\n", "path": "onmt/inputters/audio_dataset.py"}], "after_files": [{"content": "# -*- coding: utf-8 -*-\nimport os\nfrom tqdm import tqdm\n\nimport torch\n\nfrom onmt.inputters.dataset_base import DatasetBase\n\n\nclass AudioDataset(DatasetBase):\n    data_type = 'audio'  # get rid of this class attribute asap\n\n    @staticmethod\n    def sort_key(ex):\n        \"\"\" Sort using duration time of the sound spectrogram. \"\"\"\n        return ex.src.size(1)\n\n    @staticmethod\n    def extract_features(audio_path, sample_rate, truncate, window_size,\n                         window_stride, window, normalize_audio):\n        import torchaudio\n        import librosa\n        import numpy as np\n        # torchaudio loading options recently changed. It's probably\n        # straightforward to rewrite the audio handling to make use of\n        # up-to-date torchaudio, but in the meantime there is a legacy\n        # method which uses the old defaults\n        sound, sample_rate_ = torchaudio.legacy.load(audio_path)\n        if truncate and truncate > 0:\n            if sound.size(0) > truncate:\n                sound = sound[:truncate]\n\n        assert sample_rate_ == sample_rate, \\\n            'Sample rate of %s != -sample_rate (%d vs %d)' \\\n            % (audio_path, sample_rate_, sample_rate)\n\n        sound = sound.numpy()\n        if len(sound.shape) > 1:\n            if sound.shape[1] == 1:\n                sound = sound.squeeze()\n            else:\n                sound = sound.mean(axis=1)  # average multiple channels\n\n        n_fft = int(sample_rate * window_size)\n        win_length = n_fft\n        hop_length = int(sample_rate * window_stride)\n        # STFT\n        d = librosa.stft(sound, n_fft=n_fft, hop_length=hop_length,\n                         win_length=win_length, window=window)\n        spect, _ = librosa.magphase(d)\n        spect = np.log1p(spect)\n        spect = torch.FloatTensor(spect)\n        if normalize_audio:\n            mean = spect.mean()\n            std = spect.std()\n            spect.add_(-mean)\n            spect.div_(std)\n        return spect\n\n    @classmethod\n    def make_examples(\n        cls,\n        data,\n        src_dir,\n        side,\n        sample_rate,\n        window_size,\n        window_stride,\n        window,\n        normalize_audio,\n        truncate=None\n    ):\n        \"\"\"\n        Args:\n            data: sequence of audio paths or path containing these sequences\n            src_dir (str): location of source audio files.\n            side (str): 'src' or 'tgt'.\n            sample_rate (int): sample_rate.\n            window_size (float) : window size for spectrogram in seconds.\n            window_stride (float): window stride for spectrogram in seconds.\n            window (str): window type for spectrogram generation.\n            normalize_audio (bool): subtract spectrogram by mean and divide\n                by std or not.\n            truncate (int): maximum audio length (0 or None for unlimited).\n\n        Yields:\n            a dictionary containing audio data for each line.\n        \"\"\"\n        assert src_dir is not None and os.path.exists(src_dir),\\\n            \"src_dir must be a valid directory if data_type is audio\"\n\n        if isinstance(data, str):\n            data = cls._read_file(data)\n\n        for i, line in enumerate(tqdm(data)):\n            audio_path = os.path.join(src_dir, line.strip())\n            if not os.path.exists(audio_path):\n                audio_path = line.strip()\n\n            assert os.path.exists(audio_path), \\\n                'audio path %s not found' % (line.strip())\n\n            spect = AudioDataset.extract_features(\n                audio_path, sample_rate, truncate, window_size,\n                window_stride, window, normalize_audio\n            )\n\n            yield {side: spect, side + '_path': line.strip(),\n                   side + '_lengths': spect.size(1), 'indices': i}\n", "path": "onmt/inputters/audio_dataset.py"}]}