{"id":33003423,"url":"https://github.com/aalto-speech/speaker-diarization","last_synced_at":"2025-12-25T07:07:18.818Z","repository":{"id":66988731,"uuid":"53589074","full_name":"aalto-speech/speaker-diarization","owner":"aalto-speech","description":"Speaker diarization scripts, based on AaltoASR","archived":false,"fork":false,"pushed_at":"2019-01-03T10:32:13.000Z","size":1609,"stargazers_count":190,"open_issues_count":3,"forks_count":38,"subscribers_count":19,"default_branch":"master","last_synced_at":"2024-06-05T13:44:26.961Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/aalto-speech.png","metadata":{"files":{"readme":"README.html","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2016-03-10T14:04:29.000Z","updated_at":"2024-05-18T00:59:27.000Z","dependencies_parsed_at":"2023-05-16T18:15:24.663Z","dependency_job_id":null,"html_url":"https://github.com/aalto-speech/speaker-diarization","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/aalto-speech/speaker-diarization","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aalto-speech%2Fspeaker-diarization","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aalto-speech%2Fspeaker-diarization/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aalto-speech%2Fspeaker-diarization/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aalto-speech%2Fspeaker-diarization/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/aalto-speech","download_url":"https://codeload.github.com/aalto-speech/speaker-diarization/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aalto-speech%2Fspeaker-diarization/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28022940,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-12-25T02:00:05.988Z","response_time":58,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-11-13T15:00:25.029Z","updated_at":"2025-12-25T07:07:18.812Z","avatar_url":"https://github.com/aalto-speech.png","language":"Python","funding_links":[],"categories":["Software"],"sub_categories":["Framework"],"readme":"\u003c!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\"\u003e\n\u003chtml xmlns=\"http://www.w3.org/1999/xhtml\"\u003e\n\u003chead\u003e\n  \u003cmeta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" /\u003e\n  \u003cmeta http-equiv=\"Content-Style-Type\" content=\"text/css\" /\u003e\n  \u003cmeta name=\"generator\" content=\"pandoc\" /\u003e\n  \u003ctitle\u003e\u003c/title\u003e\n  \u003cstyle type=\"text/css\"\u003ecode{white-space: pre;}\u003c/style\u003e\n  \u003cstyle type=\"text/css\"\u003e\ndiv.sourceCode { overflow-x: auto; }\ntable.sourceCode, tr.sourceCode, td.lineNumbers, td.sourceCode {\n  margin: 0; padding: 0; vertical-align: baseline; border: none; }\ntable.sourceCode { width: 100%; line-height: 100%; }\ntd.lineNumbers { text-align: right; padding-right: 4px; padding-left: 4px; color: #aaaaaa; border-right: 1px solid #aaaaaa; }\ntd.sourceCode { padding-left: 5px; }\ncode \u003e span.kw { color: #007020; font-weight: bold; } /* Keyword */\ncode \u003e span.dt { color: #902000; } /* DataType */\ncode \u003e span.dv { color: #40a070; } /* DecVal */\ncode \u003e span.bn { color: #40a070; } /* BaseN */\ncode \u003e span.fl { color: #40a070; } /* Float */\ncode \u003e span.ch { color: #4070a0; } /* Char */\ncode \u003e span.st { color: #4070a0; } /* String */\ncode \u003e span.co { color: #60a0b0; font-style: italic; } /* Comment */\ncode \u003e span.ot { color: #007020; } /* Other */\ncode \u003e span.al { color: #ff0000; font-weight: bold; } /* Alert */\ncode \u003e span.fu { color: #06287e; } /* Function */\ncode \u003e span.er { color: #ff0000; font-weight: bold; } /* Error */\ncode \u003e span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */\ncode \u003e span.cn { color: #880000; } /* Constant */\ncode \u003e span.sc { color: #4070a0; } /* SpecialChar */\ncode \u003e span.vs { color: #4070a0; } /* VerbatimString */\ncode \u003e span.ss { color: #bb6688; } /* SpecialString */\ncode \u003e span.im { } /* Import */\ncode \u003e span.va { color: #19177c; } /* Variable */\ncode \u003e span.cf { color: #007020; font-weight: bold; } /* ControlFlow */\ncode \u003e span.op { color: #666666; } /* Operator */\ncode \u003e span.bu { } /* BuiltIn */\ncode \u003e span.ex { } /* Extension */\ncode \u003e span.pp { color: #bc7a00; } /* Preprocessor */\ncode \u003e span.at { color: #7d9029; } /* Attribute */\ncode \u003e span.do { color: #ba2121; font-style: italic; } /* Documentation */\ncode \u003e span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */\ncode \u003e span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */\ncode \u003e span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */\n  \u003c/style\u003e\n\u003c/head\u003e\n\u003cbody\u003e\n\u003ch1 id=\"speaker-diarization-scripts-readme\"\u003eSpeaker Diarization scripts README\u003c/h1\u003e\n\u003cp\u003eThis README describes the various scripts available for doing manual segmentation of media files, for annotation or other purposes, for speaker diarization, and converting from-to the file formats of several related tools.\u003c/p\u003e\n\u003cp\u003eThe scripts are either in \u003ccode\u003epython2\u003c/code\u003e or \u003ccode\u003eperl\u003c/code\u003e, but interpreters for these should be readily available.\u003c/p\u003e\n\u003cp\u003ePlease send any questions/suggestions to \u003ca href=\"mailto:antonio.macias.ojeda@gmail.com\"\u003eantonio.macias.ojeda@gmail.com\u003c/a\u003e\u003c/p\u003e\n\u003ch2 id=\"installation-instructions\"\u003eInstallation instructions\u003c/h2\u003e\n\u003cp\u003eMost of these scripts depend on the \u003ccode\u003eaku\u003c/code\u003e tools that are part of the \u003ccode\u003eAaltoASR\u003c/code\u003e package that you can find \u003ca href=\"https://github.com/aalto-speech/AaltoASR\"\u003ehere\u003c/a\u003e. You should compile that for your platform first, following \u003ca href=\"https://github.com/aalto-speech/AaltoASR/blob/develop/INSTALLATION.md\"\u003ethese\u003c/a\u003e instructions.\u003c/p\u003e\n\u003cp\u003eIn this \u003ccode\u003espeaker-diarization\u003c/code\u003e directory:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eAdd a symlink to the folder \u003ccode\u003eAaltoASR/\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eAdd a symlink to the folder \u003ccode\u003eAaltoASR/build\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eAdd a symlink to \u003ccode\u003eAaltoASR/build/aku/feacat\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eMake sure the \u003ccode\u003effmpeg\u003c/code\u003e executable is on path or add a symlink to it too.\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eFor example, if you have cloned and built \u003ccode\u003eAaltoASR\u003c/code\u003e into the \u003ccode\u003e../AaltoASR\u003c/code\u003e path (relative to \u003ccode\u003espeaker-diarization\u003c/code\u003e):\u003c/p\u003e\n\u003cdiv class=\"sourceCode\"\u003e\u003cpre class=\"sourceCode bash\"\u003e\u003ccode class=\"sourceCode bash\"\u003e\u003cspan class=\"ex\"\u003espeaker-diarization\u003c/span\u003e$ ln -s ../AaltoASR ./\n\u003cspan class=\"ex\"\u003espeaker-diarization\u003c/span\u003e$ ln -s ../AaltoASR/build ./\n\u003cspan class=\"ex\"\u003espeaker-diarization\u003c/span\u003e$ ln -s ../AaltoASR/build/aku/feacat ./\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\n\u003cp\u003eWould work.\u003c/p\u003e\n\u003cp\u003eYou probably want to use \u003ccode\u003espk-diarization2.py\u003c/code\u003e since that one calls the \u003cem\u003e2\u003c/em\u003e versions of some scrips, while \u003ccode\u003espk-diarization.py\u003c/code\u003e uses an old, \u003ccode\u003ematlab\u003c/code\u003e-based \u003ccode\u003eVAD\u003c/code\u003e that is hard to configure and deprecated.\u003c/p\u003e\n\u003ch2 id=\"mseg.py\"\u003emseg.py\u003c/h2\u003e\n\u003cp\u003eScript to help perform manual segmentation of a media file, it can be any media file type supported by \u003ccode\u003emplayer\u003c/code\u003e. It's only dependency is a \u003ccode\u003ePython-mplayer\u003c/code\u003e wrapper that can be installed locally by executing:\u003c/p\u003e\n\u003cpre\u003e\u003ccode\u003e$ pip install --user mplayer.py\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eAfter that executing it is just:\u003c/p\u003e\n\u003cpre\u003e\u003ccode\u003e$ ./mseg.py /path/to/mediafile -o outputfile\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eThe output file is optional. It also supports the invocation:\u003c/p\u003e\n\u003cpre\u003e\u003ccode\u003e$ ./mseg.py /path/to/mediafile -o outputfile -i inputfile\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eTo continue a previously saved segmentation session. Once in the program, the controls are:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eQuit: \u003cem\u003eesc\u003c/em\u003e or \u003cem\u003eq\u003c/em\u003e\u003c/li\u003e\n\u003cli\u003ePause: \u003cem\u003ep\u003c/em\u003e\u003c/li\u003e\n\u003cli\u003eMark position: \u003cem\u003espace\u003c/em\u003e\u003c/li\u003e\n\u003cli\u003eManually edit mark: \u003cem\u003ee\u003c/em\u003e\u003c/li\u003e\n\u003cli\u003eAdd manual mark: \u003cem\u003ea\u003c/em\u003e\u003c/li\u003e\n\u003cli\u003eRemove mark: \u003cem\u003er\u003c/em\u003e\u003c/li\u003e\n\u003cli\u003eFaster speed: \u003cem\u003eUp\u003c/em\u003e\u003c/li\u003e\n\u003cli\u003eSlower speed: \u003cem\u003eDown\u003c/em\u003e\u003c/li\u003e\n\u003cli\u003eRewind: \u003cem\u003eLeft\u003c/em\u003e\u003c/li\u003e\n\u003cli\u003eFast Forward: \u003cem\u003eRight\u003c/em\u003e\u003c/li\u003e\n\u003cli\u003eScroll down marks: \u003cem\u003epgDwn\u003c/em\u003e\u003c/li\u003e\n\u003cli\u003eScroll up marks: \u003cem\u003epgUp\u003c/em\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eThe media file starts as paused, so to start reproduction just hit the \u003cem\u003ep\u003c/em\u003e key.\u003c/p\u003e\n\u003ch2 id=\"mseg2elan.py\"\u003emseg2elan.py\u003c/h2\u003e\n\u003cp\u003eScript to convert from mseg output to Elan file format.\u003c/p\u003e\n\u003cp\u003eUsage:\u003c/p\u003e\n\u003cpre\u003e\u003ccode\u003e$ ./mseg2elan.py msoutputfile -o outputfile\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eIf \u003ccode\u003eoutputfile\u003c/code\u003e is not specified, the output will be sent to the stdout. Once in Elan, segments can be easily fine tuned by changing to the segmentation mode, in Options-\u0026gt;Segmentation Mode.\u003c/p\u003e\n\u003ch2 id=\"aku2elan.py\"\u003eaku2elan.py\u003c/h2\u003e\n\u003cp\u003eScript to convert from AKU recipes to Elan file format.\u003c/p\u003e\n\u003cp\u003eUsage:\u003c/p\u003e\n\u003cpre\u003e\u003ccode\u003e$ ./aku2elan.py recipe -o outputfile\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eIf \u003ccode\u003eoutputfile\u003c/code\u003e is not specified, the output will be sent to the \u003ccode\u003estdout\u003c/code\u003e. Once in Elan, segments can be easily fine tuned by changing to the segmentation mode, in Options-\u0026gt;Segmentation Mode.\u003c/p\u003e\n\u003ch2 id=\"elan2aku.py\"\u003eelan2aku.py\u003c/h2\u003e\n\u003cp\u003eScript to convert from Elan file format to AKU recipes.\u003c/p\u003e\n\u003cp\u003eUsage:\u003c/p\u003e\n\u003cpre\u003e\u003ccode\u003e$ ./elan2aku.py elanoutputfile -o akurecipe\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eIf \u003ccode\u003eakurecipe\u003c/code\u003e is not specified, the output will be sent to the \u003ccode\u003estdout\u003c/code\u003e.\u003c/p\u003e\n\u003ch2 id=\"mseg_to_textgrid.pl\"\u003emseg_to_textgrid.pl\u003c/h2\u003e\n\u003cp\u003eScript to convert from mseg output to praat file format.\u003c/p\u003e\n\u003cp\u003eUsage:\u003c/p\u003e\n\u003cpre\u003e\u003ccode\u003e$ perl mseg_to_textgrid.pl msfile \u0026gt; outputfile\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eIf \u003ccode\u003eoutputfile\u003c/code\u003e is not specified, the output will be sent to the \u003ccode\u003estdout\u003c/code\u003e.\u003c/p\u003e\n\u003ch2 id=\"voice-detection2.py\"\u003evoice-detection2.py\u003c/h2\u003e\n\u003cp\u003eCreates an \u003ccode\u003eAKU\u003c/code\u003e recipe from the \u003ccode\u003egenerate_exp.py\u003c/code\u003e output (\u003ccode\u003e.exp\u003c/code\u003e files).\u003c/p\u003e\n\u003cp\u003eFor full help, use:\u003c/p\u003e\n\u003cpre\u003e\u003ccode\u003e$ ./voice-detection2.py -h\u003c/code\u003e\u003c/pre\u003e\n\u003ch2 id=\"vad-performance.py\"\u003evad-performance.py\u003c/h2\u003e\n\u003cp\u003eRates the performance of a Voice Activity Detection recipe in \u003ccode\u003eAKU\u003c/code\u003e format, such as those created with \u003ccode\u003evoice-detection.py\u003c/code\u003e. To measure the performance, another recipe with ground truth should be provided.\u003c/p\u003e\n\u003cp\u003eFor full help, use:\u003c/p\u003e\n\u003cpre\u003e\u003ccode\u003e$ ./vad-performance.py -h\u003c/code\u003e\u003c/pre\u003e\n\u003ch2 id=\"spk-change-detection.py\"\u003espk-change-detection.py\u003c/h2\u003e\n\u003cp\u003ePerforms speaker turn segmentation over audio, using a distance measure such as GLR, KL2 or BIC, and sliding or growing window. It requires an input recipe file in \u003ccode\u003eAKU\u003c/code\u003e format pointing to the audio files, and preferably with turns of speech/non-speech already processed, and a features file for each wav to process, in the format outputted by the \u003ccode\u003efeacat\u003c/code\u003e program of the \u003ccode\u003eAKU\u003c/code\u003e suite.\u003c/p\u003e\n\u003cp\u003eFor full help, use:\u003c/p\u003e\n\u003cpre\u003e\u003ccode\u003e$ ./spk-change-detection.py -h\u003c/code\u003e\u003c/pre\u003e\n\u003ch2 id=\"spk-change-performance.py\"\u003espk-change-performance.py\u003c/h2\u003e\n\u003cp\u003eRates the performance of a speaker turn segmentation recipe in \u003ccode\u003eAKU\u003c/code\u003e format, such as those created with \u003ccode\u003espk-change-detection.py\u003c/code\u003e. To measure the performance, another recipe with ground truth should be provided.\u003c/p\u003e\n\u003cp\u003eFor full help, use:\u003c/p\u003e\n\u003cpre\u003e\u003ccode\u003e$ ./spk-change-performance.py -h\u003c/code\u003e\u003c/pre\u003e\n\u003ch2 id=\"spk-clustering.py\"\u003espk-clustering.py\u003c/h2\u003e\n\u003cp\u003ePerforms speaker turn clustering over audio. It requires a speaker segmentation recipe in AKU format, such as those created with \u003ccode\u003espk-change-detection.py\u003c/code\u003e, and a features file for each wav file to process, in the format outputted by the feacat program of the AKU suite.\u003c/p\u003e\n\u003cp\u003eFor full help, use:\u003c/p\u003e\n\u003cpre\u003e\u003ccode\u003e$ ./spk-clustering.py -h\u003c/code\u003e\u003c/pre\u003e\n\u003ch2 id=\"spk-time.py\"\u003espk-time.py\u003c/h2\u003e\n\u003cp\u003eCalculates per-speaker speaking time from a speaker-tagged recipe in \u003ccode\u003eAKU\u003c/code\u003e format.\u003c/p\u003e\n\u003cp\u003eFor full help, use:\u003c/p\u003e\n\u003cpre\u003e\u003ccode\u003e$ ./spk-time.py -h\u003c/code\u003e\u003c/pre\u003e\n\u003ch2 id=\"spk-diarization2.py\"\u003espk-diarization2.py\u003c/h2\u003e\n\u003cp\u003ePerforms full speaker diarization over media file. If the media is not a \u003ccode\u003ewav\u003c/code\u003e file it tries to convert it to wav using \u003ccode\u003effmpeg\u003c/code\u003e. It then calls \u003ccode\u003egenerate_exp.py\u003c/code\u003e, \u003ccode\u003evoice-detection.py\u003c/code\u003e, \u003ccode\u003espk-change-detection.py\u003c/code\u003e and \u003ccode\u003espk-clustering.py\u003c/code\u003e in succession.\u003c/p\u003e\n\u003cp\u003eFor full help, use:\u003c/p\u003e\n\u003cpre\u003e\u003ccode\u003e$ ./spk-diarization2.py -h\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eNotes:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003ePaths for the other scripts and features must be provided.\u003c/li\u003e\n\u003cli\u003eSince this script is a convenient wrapper for the other scripts of the family, it doesn't have options for all the settings of the other scripts, just some defaults. If you want to tune them, edit this script directly.\u003c/li\u003e\n\u003cli\u003eSome scripts have a \u003cem\u003e2\u003c/em\u003e version. Usage of that one is preferable.\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/body\u003e\n\u003c/html\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faalto-speech%2Fspeaker-diarization","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Faalto-speech%2Fspeaker-diarization","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faalto-speech%2Fspeaker-diarization/lists"}