We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
The 'speaker' field in the stcmds dataset is incorrect
The file 20170001P00001I0001.wav is spoken by a female, 
and the file 20170001P00001A0001.wav is spoken by a male.
But they have the same speaker ID P00001

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `lhotse/recipes/stcmds.py`
Content:
```
1 """
2 Stcmds is an open-source  Chinese Mandarin corpus by Surfingtech (www.surfing.ai), containing utterances from 855 speakers, 102600 utterances;
3 Publicly available on https://www.openslr.org/resources/38
4 ST-CMDS (110 hours)
5 
6 """
7 import logging
8 import os
9 import shutil
10 import tarfile
11 from collections import defaultdict
12 from pathlib import Path
13 from typing import Dict, Optional, Union
14 
15 from tqdm.auto import tqdm
16 
17 from lhotse import fix_manifests, validate_recordings_and_supervisions
18 from lhotse.audio import Recording, RecordingSet
19 from lhotse.supervision import SupervisionSegment, SupervisionSet
20 from lhotse.utils import Pathlike, resumable_download, safe_extract
21 
22 
23 def text_normalize(line: str):
24     """
25     Modified from https://github.com/wenet-e2e/wenet/blob/main/examples/multi_cn/s0/local/stcmds_data_prep.sh#L42
26     paste -d' ' $data/utt.list $data/text.list |\
27     sed 's/，//g' |\
28     tr '[a-z]' '[A-Z]' |\
29     awk '{if (NF > 1) print $0;}' > $data/train/text
30     """
31     line = line.replace("，", "")
32     line = line.upper()
33     return line
34 
35 
36 def download_stcmds(
37     target_dir: Pathlike = ".",
38     force_download: bool = False,
39     base_url: str = "http://www.openslr.org/resources",
40 ) -> Path:
41     """
42     Downdload and untar the dataset
43     :param target_dir: Pathlike, the path of the dir to storage the dataset.
44     :param force_download: Bool, if True, download the tars no matter if the tars exist.
45     :param base_url: str, the url of the OpenSLR resources.
46     :return: the path to downloaded and extracted directory with data.
47     """
48     url = f"{base_url}/38"
49     target_dir = Path(target_dir)
50     target_dir.mkdir(parents=True, exist_ok=True)
51     corpus_dir = target_dir / "stcmds"
52     dataset_tar_name = "ST-CMDS-20170001_1-OS.tar.gz"
53     for tar_name in [dataset_tar_name]:
54         tar_path = target_dir / tar_name
55         extracted_dir = corpus_dir / tar_name[:-7]
56         completed_detector = extracted_dir / ".completed"
57         if completed_detector.is_file():
58             logging.info(f"Skipping download of because {completed_detector} exists.")
59             continue
60         resumable_download(
61             f"{url}/{tar_name}", filename=tar_path, force_download=force_download
62         )
63         shutil.rmtree(extracted_dir, ignore_errors=True)
64         with tarfile.open(tar_path) as tar:
65             safe_extract(tar, path=corpus_dir)
66         completed_detector.touch()
67 
68     return corpus_dir
69 
70 
71 def prepare_stcmds(
72     corpus_dir: Pathlike, output_dir: Optional[Pathlike] = None
73 ) -> Dict[str, Dict[str, Union[RecordingSet, SupervisionSet]]]:
74     """
75     Returns the manifests which consist of the Recordings and Supervisions
76     :param corpus_dir: Pathlike, the path of the data dir.
77     :param output_dir: Pathlike, the path where to write the manifests.
78     :return: a Dict whose key is the dataset part, and the value is Dicts with the keys 'recordings' and 'supervisions'.
79     """
80     corpus_dir = Path(corpus_dir)
81     assert corpus_dir.is_dir(), f"No such directory: {corpus_dir}"
82     if output_dir is not None:
83         output_dir = Path(output_dir)
84         output_dir.mkdir(parents=True, exist_ok=True)
85 
86     path = corpus_dir / "ST-CMDS-20170001_1-OS"
87     transcript_dict = {}
88     for text_path in path.rglob("**/*.txt"):
89         idx = text_path.stem
90         logging.info(f"processing stcmds transcript  {text_path}")
91         with open(text_path, "r", encoding="utf-8") as f:
92             for line in f:
93                 line = text_normalize(line)
94                 transcript_dict[idx] = line
95 
96     manifests = defaultdict(dict)
97     dataset_parts = ["train"]
98     for part in tqdm(
99         dataset_parts,
100         desc="process stcmds audio, it needs waste about 2169 seconds time.",
101     ):
102         logging.info(f"Processing stcmds {part}")
103         recordings = []
104         supervisions = []
105         for audio_path in path.rglob("**/*.wav"):
106             idx = audio_path.stem
107             speaker = "".join(list(idx)[8:14])
108             if idx not in transcript_dict:
109                 logging.warning(f"No transcript: {idx}")
110                 logging.warning(f"{audio_path} has no transcript")
111                 continue
112             text = transcript_dict[idx]
113             if not audio_path.is_file():
114                 logging.warning(f"No such file: {audio_path}")
115                 continue
116             recording = Recording.from_file(audio_path)
117             recordings.append(recording)
118             segment = SupervisionSegment(
119                 id=idx,
120                 recording_id=idx,
121                 start=0.0,
122                 duration=recording.duration,
123                 channel=0,
124                 language="Chinese",
125                 speaker=speaker,
126                 text=text.strip(),
127             )
128             supervisions.append(segment)
129 
130         recording_set = RecordingSet.from_recordings(recordings)
131         supervision_set = SupervisionSet.from_segments(supervisions)
132 
133         recording_set, supervision_set = fix_manifests(recording_set, supervision_set)
134         validate_recordings_and_supervisions(recording_set, supervision_set)
135 
136         if output_dir is not None:
137             supervision_set.to_file(output_dir / f"stcmds_supervisions_{part}.jsonl.gz")
138             recording_set.to_file(output_dir / f"stcmds_recordings_{part}.jsonl.gz")
139 
140         manifests[part] = {"recordings": recording_set, "supervisions": supervision_set}
141 
142     return manifests
143
```
--- 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()

```

diff --git a/lhotse/recipes/stcmds.py b/lhotse/recipes/stcmds.py
--- a/lhotse/recipes/stcmds.py
+++ b/lhotse/recipes/stcmds.py
@@ -104,7 +104,7 @@
         supervisions = []
         for audio_path in path.rglob("**/*.wav"):
             idx = audio_path.stem
-            speaker = "".join(list(idx)[8:14])
+            speaker = "".join(list(idx)[8:15])
             if idx not in transcript_dict:
                 logging.warning(f"No transcript: {idx}")
                 logging.warning(f"{audio_path} has no transcript")

{"golden_diff": "diff --git a/lhotse/recipes/stcmds.py b/lhotse/recipes/stcmds.py\n--- a/lhotse/recipes/stcmds.py\n+++ b/lhotse/recipes/stcmds.py\n@@ -104,7 +104,7 @@\n         supervisions = []\n         for audio_path in path.rglob(\"**/*.wav\"):\n             idx = audio_path.stem\n-            speaker = \"\".join(list(idx)[8:14])\n+            speaker = \"\".join(list(idx)[8:15])\n             if idx not in transcript_dict:\n                 logging.warning(f\"No transcript: {idx}\")\n                 logging.warning(f\"{audio_path} has no transcript\")\n", "issue": "The 'speaker' field in the stcmds dataset is incorrect\nThe file 20170001P00001I0001.wav is spoken by a female, \r\nand the file 20170001P00001A0001.wav is spoken by a male.\r\nBut they have the same speaker ID P00001\n", "before_files": [{"content": "\"\"\"\nStcmds is an open-source  Chinese Mandarin corpus by Surfingtech (www.surfing.ai), containing utterances from 855 speakers, 102600 utterances;\nPublicly available on https://www.openslr.org/resources/38\nST-CMDS (110 hours)\n\n\"\"\"\nimport logging\nimport os\nimport shutil\nimport tarfile\nfrom collections import defaultdict\nfrom pathlib import Path\nfrom typing import Dict, Optional, Union\n\nfrom tqdm.auto import tqdm\n\nfrom lhotse import fix_manifests, validate_recordings_and_supervisions\nfrom lhotse.audio import Recording, RecordingSet\nfrom lhotse.supervision import SupervisionSegment, SupervisionSet\nfrom lhotse.utils import Pathlike, resumable_download, safe_extract\n\n\ndef text_normalize(line: str):\n    \"\"\"\n    Modified from https://github.com/wenet-e2e/wenet/blob/main/examples/multi_cn/s0/local/stcmds_data_prep.sh#L42\n    paste -d' ' $data/utt.list $data/text.list |\\\n    sed 's/\uff0c//g' |\\\n    tr '[a-z]' '[A-Z]' |\\\n    awk '{if (NF > 1) print $0;}' > $data/train/text\n    \"\"\"\n    line = line.replace(\"\uff0c\", \"\")\n    line = line.upper()\n    return line\n\n\ndef download_stcmds(\n    target_dir: Pathlike = \".\",\n    force_download: bool = False,\n    base_url: str = \"http://www.openslr.org/resources\",\n) -> Path:\n    \"\"\"\n    Downdload and untar the dataset\n    :param target_dir: Pathlike, the path of the dir to storage the dataset.\n    :param force_download: Bool, if True, download the tars no matter if the tars exist.\n    :param base_url: str, the url of the OpenSLR resources.\n    :return: the path to downloaded and extracted directory with data.\n    \"\"\"\n    url = f\"{base_url}/38\"\n    target_dir = Path(target_dir)\n    target_dir.mkdir(parents=True, exist_ok=True)\n    corpus_dir = target_dir / \"stcmds\"\n    dataset_tar_name = \"ST-CMDS-20170001_1-OS.tar.gz\"\n    for tar_name in [dataset_tar_name]:\n        tar_path = target_dir / tar_name\n        extracted_dir = corpus_dir / tar_name[:-7]\n        completed_detector = extracted_dir / \".completed\"\n        if completed_detector.is_file():\n            logging.info(f\"Skipping download of because {completed_detector} exists.\")\n            continue\n        resumable_download(\n            f\"{url}/{tar_name}\", filename=tar_path, force_download=force_download\n        )\n        shutil.rmtree(extracted_dir, ignore_errors=True)\n        with tarfile.open(tar_path) as tar:\n            safe_extract(tar, path=corpus_dir)\n        completed_detector.touch()\n\n    return corpus_dir\n\n\ndef prepare_stcmds(\n    corpus_dir: Pathlike, output_dir: Optional[Pathlike] = None\n) -> Dict[str, Dict[str, Union[RecordingSet, SupervisionSet]]]:\n    \"\"\"\n    Returns the manifests which consist of the Recordings and Supervisions\n    :param corpus_dir: Pathlike, the path of the data dir.\n    :param output_dir: Pathlike, the path where to write the manifests.\n    :return: a Dict whose key is the dataset part, and the value is Dicts with the keys 'recordings' and 'supervisions'.\n    \"\"\"\n    corpus_dir = Path(corpus_dir)\n    assert corpus_dir.is_dir(), f\"No such directory: {corpus_dir}\"\n    if output_dir is not None:\n        output_dir = Path(output_dir)\n        output_dir.mkdir(parents=True, exist_ok=True)\n\n    path = corpus_dir / \"ST-CMDS-20170001_1-OS\"\n    transcript_dict = {}\n    for text_path in path.rglob(\"**/*.txt\"):\n        idx = text_path.stem\n        logging.info(f\"processing stcmds transcript  {text_path}\")\n        with open(text_path, \"r\", encoding=\"utf-8\") as f:\n            for line in f:\n                line = text_normalize(line)\n                transcript_dict[idx] = line\n\n    manifests = defaultdict(dict)\n    dataset_parts = [\"train\"]\n    for part in tqdm(\n        dataset_parts,\n        desc=\"process stcmds audio, it needs waste about 2169 seconds time.\",\n    ):\n        logging.info(f\"Processing stcmds {part}\")\n        recordings = []\n        supervisions = []\n        for audio_path in path.rglob(\"**/*.wav\"):\n            idx = audio_path.stem\n            speaker = \"\".join(list(idx)[8:14])\n            if idx not in transcript_dict:\n                logging.warning(f\"No transcript: {idx}\")\n                logging.warning(f\"{audio_path} has no transcript\")\n                continue\n            text = transcript_dict[idx]\n            if not audio_path.is_file():\n                logging.warning(f\"No such file: {audio_path}\")\n                continue\n            recording = Recording.from_file(audio_path)\n            recordings.append(recording)\n            segment = SupervisionSegment(\n                id=idx,\n                recording_id=idx,\n                start=0.0,\n                duration=recording.duration,\n                channel=0,\n                language=\"Chinese\",\n                speaker=speaker,\n                text=text.strip(),\n            )\n            supervisions.append(segment)\n\n        recording_set = RecordingSet.from_recordings(recordings)\n        supervision_set = SupervisionSet.from_segments(supervisions)\n\n        recording_set, supervision_set = fix_manifests(recording_set, supervision_set)\n        validate_recordings_and_supervisions(recording_set, supervision_set)\n\n        if output_dir is not None:\n            supervision_set.to_file(output_dir / f\"stcmds_supervisions_{part}.jsonl.gz\")\n            recording_set.to_file(output_dir / f\"stcmds_recordings_{part}.jsonl.gz\")\n\n        manifests[part] = {\"recordings\": recording_set, \"supervisions\": supervision_set}\n\n    return manifests\n", "path": "lhotse/recipes/stcmds.py"}], "after_files": [{"content": "\"\"\"\nStcmds is an open-source  Chinese Mandarin corpus by Surfingtech (www.surfing.ai), containing utterances from 855 speakers, 102600 utterances;\nPublicly available on https://www.openslr.org/resources/38\nST-CMDS (110 hours)\n\n\"\"\"\nimport logging\nimport os\nimport shutil\nimport tarfile\nfrom collections import defaultdict\nfrom pathlib import Path\nfrom typing import Dict, Optional, Union\n\nfrom tqdm.auto import tqdm\n\nfrom lhotse import fix_manifests, validate_recordings_and_supervisions\nfrom lhotse.audio import Recording, RecordingSet\nfrom lhotse.supervision import SupervisionSegment, SupervisionSet\nfrom lhotse.utils import Pathlike, resumable_download, safe_extract\n\n\ndef text_normalize(line: str):\n    \"\"\"\n    Modified from https://github.com/wenet-e2e/wenet/blob/main/examples/multi_cn/s0/local/stcmds_data_prep.sh#L42\n    paste -d' ' $data/utt.list $data/text.list |\\\n    sed 's/\uff0c//g' |\\\n    tr '[a-z]' '[A-Z]' |\\\n    awk '{if (NF > 1) print $0;}' > $data/train/text\n    \"\"\"\n    line = line.replace(\"\uff0c\", \"\")\n    line = line.upper()\n    return line\n\n\ndef download_stcmds(\n    target_dir: Pathlike = \".\",\n    force_download: bool = False,\n    base_url: str = \"http://www.openslr.org/resources\",\n) -> Path:\n    \"\"\"\n    Downdload and untar the dataset\n    :param target_dir: Pathlike, the path of the dir to storage the dataset.\n    :param force_download: Bool, if True, download the tars no matter if the tars exist.\n    :param base_url: str, the url of the OpenSLR resources.\n    :return: the path to downloaded and extracted directory with data.\n    \"\"\"\n    url = f\"{base_url}/38\"\n    target_dir = Path(target_dir)\n    target_dir.mkdir(parents=True, exist_ok=True)\n    corpus_dir = target_dir / \"stcmds\"\n    dataset_tar_name = \"ST-CMDS-20170001_1-OS.tar.gz\"\n    for tar_name in [dataset_tar_name]:\n        tar_path = target_dir / tar_name\n        extracted_dir = corpus_dir / tar_name[:-7]\n        completed_detector = extracted_dir / \".completed\"\n        if completed_detector.is_file():\n            logging.info(f\"Skipping download of because {completed_detector} exists.\")\n            continue\n        resumable_download(\n            f\"{url}/{tar_name}\", filename=tar_path, force_download=force_download\n        )\n        shutil.rmtree(extracted_dir, ignore_errors=True)\n        with tarfile.open(tar_path) as tar:\n            safe_extract(tar, path=corpus_dir)\n        completed_detector.touch()\n\n    return corpus_dir\n\n\ndef prepare_stcmds(\n    corpus_dir: Pathlike, output_dir: Optional[Pathlike] = None\n) -> Dict[str, Dict[str, Union[RecordingSet, SupervisionSet]]]:\n    \"\"\"\n    Returns the manifests which consist of the Recordings and Supervisions\n    :param corpus_dir: Pathlike, the path of the data dir.\n    :param output_dir: Pathlike, the path where to write the manifests.\n    :return: a Dict whose key is the dataset part, and the value is Dicts with the keys 'recordings' and 'supervisions'.\n    \"\"\"\n    corpus_dir = Path(corpus_dir)\n    assert corpus_dir.is_dir(), f\"No such directory: {corpus_dir}\"\n    if output_dir is not None:\n        output_dir = Path(output_dir)\n        output_dir.mkdir(parents=True, exist_ok=True)\n\n    path = corpus_dir / \"ST-CMDS-20170001_1-OS\"\n    transcript_dict = {}\n    for text_path in path.rglob(\"**/*.txt\"):\n        idx = text_path.stem\n        logging.info(f\"processing stcmds transcript  {text_path}\")\n        with open(text_path, \"r\", encoding=\"utf-8\") as f:\n            for line in f:\n                line = text_normalize(line)\n                transcript_dict[idx] = line\n\n    manifests = defaultdict(dict)\n    dataset_parts = [\"train\"]\n    for part in tqdm(\n        dataset_parts,\n        desc=\"process stcmds audio, it needs waste about 2169 seconds time.\",\n    ):\n        logging.info(f\"Processing stcmds {part}\")\n        recordings = []\n        supervisions = []\n        for audio_path in path.rglob(\"**/*.wav\"):\n            idx = audio_path.stem\n            speaker = \"\".join(list(idx)[8:15])\n            if idx not in transcript_dict:\n                logging.warning(f\"No transcript: {idx}\")\n                logging.warning(f\"{audio_path} has no transcript\")\n                continue\n            text = transcript_dict[idx]\n            if not audio_path.is_file():\n                logging.warning(f\"No such file: {audio_path}\")\n                continue\n            recording = Recording.from_file(audio_path)\n            recordings.append(recording)\n            segment = SupervisionSegment(\n                id=idx,\n                recording_id=idx,\n                start=0.0,\n                duration=recording.duration,\n                channel=0,\n                language=\"Chinese\",\n                speaker=speaker,\n                text=text.strip(),\n            )\n            supervisions.append(segment)\n\n        recording_set = RecordingSet.from_recordings(recordings)\n        supervision_set = SupervisionSet.from_segments(supervisions)\n\n        recording_set, supervision_set = fix_manifests(recording_set, supervision_set)\n        validate_recordings_and_supervisions(recording_set, supervision_set)\n\n        if output_dir is not None:\n            supervision_set.to_file(output_dir / f\"stcmds_supervisions_{part}.jsonl.gz\")\n            recording_set.to_file(output_dir / f\"stcmds_recordings_{part}.jsonl.gz\")\n\n        manifests[part] = {\"recordings\": recording_set, \"supervisions\": supervision_set}\n\n    return manifests\n", "path": "lhotse/recipes/stcmds.py"}]}