{"id":2270,"date":"2026-06-15T22:31:41","date_gmt":"2026-06-15T22:31:41","guid":{"rendered":"https:\/\/portfolio.arnoldbiffna.com\/?p=2270"},"modified":"2026-07-11T17:32:43","modified_gmt":"2026-07-11T17:32:43","slug":"voice-cloning","status":"publish","type":"post","link":"https:\/\/portfolio.arnoldbiffna.com\/index.php\/2026\/06\/15\/voice-cloning\/","title":{"rendered":"Voice Cloning"},"content":{"rendered":"\n<figure class=\"wp-block-video\"><video controls poster=\"https:\/\/d3od4vl78dd97d.cloudfront.net\/blogpreviews\/voicecloning.jpg\" src=\"https:\/\/d3od4vl78dd97d.cloudfront.net\/blogvideo\/churchill.mp4\"><\/video><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">I am completely amazed at how well voice cloning works locally on my machine.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Components<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">I already had a local MLX Whisper model running, which I use to generate subtitles from video. I thought that was all I needed. Then I asked Codex to build me a voice cloning tool in Python, and it went much deeper than I expected.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The tool ended up using:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Python<\/li>\n\n\n\n<li>FFmpeg and FFprobe<\/li>\n\n\n\n<li>MLX Audio text-to-speech<\/li>\n\n\n\n<li>MLX Whisper transcription<\/li>\n\n\n\n<li>Hugging Face model snapshots<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Warning<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Voice cloning needs to be handled responsibly. Permission, disclosure, and context matter. For this experiment, I used a historical public figure rather than cloning the voice of a living person.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">What the Tool Does<\/h2>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Lets me choose a reference audio or video file<\/li>\n\n\n\n<li>Lets me choose a speech text file<\/li>\n\n\n\n<li>Detects and skips leading silence (<strong><em>FFmpeg<\/em><\/strong>)<\/li>\n\n\n\n<li>Extracts and cleans a reference voice sample (<em><strong>FF<\/strong>mpeg<\/em>)<\/li>\n\n\n\n<li>Transcribes the cleaned reference using an MLX Whisper model (<strong><em>whisper-large-v3-mlx<\/em><\/strong>)<\/li>\n\n\n\n<li>Generates new speech from text using a local MLX Audio model (<strong><em>higgs-audio-v2-3B-mlx-q8<\/em><\/strong>)<\/li>\n<\/ol>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/d3od4vl78dd97d.cloudfront.net\/blogimages\/voicecloneapp.png\" alt=\"\"\/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">The wild part is that all of this runs locally. No cloud service. No subscription API. Just my Mac, some open-source tools, and a Python script that suddenly feels a little <em>too<\/em> powerful.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n","protected":false},"excerpt":{"rendered":"<p>I am completely amazed at how well voice cloning works locally on my machine. Components I already had a local MLX Whisper model running, which I use to generate subtitles from video. I thought that was all I needed. Then I asked Codex to build me a voice cloning tool in Python, and it went &hellip; <a href=\"https:\/\/portfolio.arnoldbiffna.com\/index.php\/2026\/06\/15\/voice-cloning\/\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;Voice Cloning&#8221;<\/span><\/a><\/p>\n","protected":false},"author":2,"featured_media":2279,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[48,57,56],"tags":[],"class_list":["post-2270","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-artificial-intelligence","category-local-ai","category-python"],"_links":{"self":[{"href":"https:\/\/portfolio.arnoldbiffna.com\/index.php\/wp-json\/wp\/v2\/posts\/2270","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/portfolio.arnoldbiffna.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/portfolio.arnoldbiffna.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/portfolio.arnoldbiffna.com\/index.php\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/portfolio.arnoldbiffna.com\/index.php\/wp-json\/wp\/v2\/comments?post=2270"}],"version-history":[{"count":14,"href":"https:\/\/portfolio.arnoldbiffna.com\/index.php\/wp-json\/wp\/v2\/posts\/2270\/revisions"}],"predecessor-version":[{"id":2315,"href":"https:\/\/portfolio.arnoldbiffna.com\/index.php\/wp-json\/wp\/v2\/posts\/2270\/revisions\/2315"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/portfolio.arnoldbiffna.com\/index.php\/wp-json\/wp\/v2\/media\/2279"}],"wp:attachment":[{"href":"https:\/\/portfolio.arnoldbiffna.com\/index.php\/wp-json\/wp\/v2\/media?parent=2270"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/portfolio.arnoldbiffna.com\/index.php\/wp-json\/wp\/v2\/categories?post=2270"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/portfolio.arnoldbiffna.com\/index.php\/wp-json\/wp\/v2\/tags?post=2270"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}