﻿
{"id":27699,"date":"2025-03-28T18:47:09","date_gmt":"2025-03-28T18:47:09","guid":{"rendered":"https:\/\/www.gencayyildiz.com\/blog\/?p=27699"},"modified":"2025-03-28T18:49:46","modified_gmt":"2025-03-28T18:49:46","slug":"nette-ai-destegiyle-text-to-speech-tts-ve-speech-to-text-stt-operasyonlari","status":"publish","type":"post","link":"https:\/\/www.gencayyildiz.com\/blog\/nette-ai-destegiyle-text-to-speech-tts-ve-speech-to-text-stt-operasyonlari\/","title":{"rendered":".NET&#8217;te AI Deste\u011fiyle Text-to-Speech (TTS) ve Speech-to-Text (STT) Operasyonlar\u0131"},"content":{"rendered":"<div id=\"fb-root\"><\/div>\n<p>Merhaba,<\/p>\n<p>Bu i\u00e7eri\u011fimizde ses ve metin aras\u0131nda d\u00f6n\u00fc\u015f\u00fcm i\u015flemlerine kar\u015f\u0131l\u0131k gelen <em>Text-to-Speech (TTS)<\/em> ve <em>Speech-to-Text (STT)<\/em> kavramlar\u0131n\u0131 ele alacak ve .NET ekosisteminde bu kavramlar do\u011frultusunda pratiksel operasyonlar\u0131 nas\u0131l ger\u00e7ekle\u015ftirebilece\u011fimizi deneyimleyece\u011fiz.<\/p>\n<h4>Text-to-Speech (TTS) ve Speech-to-Text (STT) Nedir?<\/h4>\n<p>\u0130lk olarak bu kavramlar\u0131 tam olarak izah ederek ba\u015flayal\u0131m istiyorum. Bunun i\u00e7in a\u015fa\u011f\u0131daki tablo \u00fczerinden mukayeseli bir incelemede bulunmam\u0131z yeterli olacakt\u0131r kanaatindeyim;<\/p>\n<table>\n<thead>\n<tr>\n<th style=\"text-align:left;width:24%;\">Kriter<\/th>\n<th style=\"text-align:left;width:38%;\">Text-to-Speech (TTS)<\/th>\n<th style=\"text-align:left;width:38%;\">Speech-to-Text (STT)<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td style=\"text-align:left;\"><strong>Anlam\u0131<\/strong><\/td>\n<td style=\"text-align:left;font-size:12px;\">Yaz\u0131l\u0131 metni sesli konu\u015fmaya d\u00f6n\u00fc\u015ft\u00fcr\u00fcr.<\/td>\n<td style=\"text-align:left;font-size:12px;\">Konu\u015fulan sesi yaz\u0131l\u0131 metne d\u00f6n\u00fc\u015ft\u00fcr\u00fcr.<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left;\"><strong>Girdi T\u00fcr\u00fc<\/strong><\/td>\n<td style=\"text-align:left;font-size:12px;\">Metin<\/td>\n<td style=\"text-align:left;font-size:12px;\">Ses (konu\u015fma, video, mikrofon)<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left;\"><strong>\u00c7\u0131kt\u0131 T\u00fcr\u00fc<\/strong><\/td>\n<td style=\"text-align:left;font-size:12px;\">Ses<\/td>\n<td style=\"text-align:left;font-size:12px;\">Metin<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left;\"><strong>Kullan\u0131m Alanlar\u0131<\/strong><\/td>\n<td style=\"text-align:left;font-size:12px;\">\n<ul>\n<li>Siri, Google Assistant gibi sesli asistanlar<\/li>\n<li>E-kitap okuma uygulamalar\u0131<\/li>\n<li>Navigasyon sistemleri<\/li>\n<li>Engelli bireyler i\u00e7in okuma yard\u0131mc\u0131lar\u0131<\/li>\n<\/ul>\n<\/td>\n<td style=\"text-align:left;font-size:12px;\">\n<ul>\n<li>Sesli komut sistemleri<\/li>\n<li>Otomatik yazma ve dikte uygulamalar\u0131<\/li>\n<li>Toplant\u0131 notlar\u0131n\u0131n \u00f6zetlenmesi<\/li>\n<li>Canl\u0131 altyaz\u0131 (closed caption) sistemleri<\/li>\n<li>\u00c7a\u011fr\u0131 merkezi otomasyonlar\u0131<\/li>\n<\/ul>\n<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left;\"><strong>Kullan\u0131c\u0131 Yararlar\u0131<\/strong><\/td>\n<td style=\"text-align:left;font-size:12px;\">\n<ul>\n<li>Okuma kolayl\u0131\u011f\u0131<\/li>\n<li>Eri\u015filebilirlik<\/li>\n<li>G\u00f6rme engellilere yard\u0131m<\/li>\n<\/ul>\n<\/td>\n<td style=\"text-align:left;font-size:12px;\">\n<ul>\n<li>Konu\u015farak yazma kolayl\u0131\u011f\u0131<\/li>\n<li>H\u0131z ve zaman kazan\u0131m\u0131<\/li>\n<li>Pratiklik<\/li>\n<\/ul>\n<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left;\"><strong>Teknik Zorluklar<\/strong><\/td>\n<td style=\"text-align:left;font-size:12px;\">Do\u011fal ve ak\u0131c\u0131 ses \u00fcretimi yapmak<\/td>\n<td style=\"text-align:left;font-size:12px;\">Farkl\u0131 aksanlar\u0131, ses kalitesini ve arka plan seslerini ay\u0131rt etmek<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left;\"><strong>Pop\u00fcler \u00d6rnekler<\/strong><\/td>\n<td style=\"text-align:left;font-size:12px;\">\n<ul>\n<li>Google TTS<\/li>\n<li>Amazon Polly<\/li>\n<li>Microsoft Azure TTS<\/li>\n<\/ul>\n<\/td>\n<td style=\"text-align:left;font-size:12px;\">\n<ul>\n<li>Google Speech-to-Text<\/li>\n<li>IBM Watson STT<\/li>\n<li>Microsoft Azure Speech<\/li>\n<\/ul>\n<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left;\"><strong>Dil \u0130\u015fleme Y\u00f6ntemi<\/strong><\/td>\n<td style=\"text-align:left;font-size:12px;\">Metni analiz edip telaffuz ve tonlama kurallar\u0131na g\u00f6re seslendirir.<\/td>\n<td style=\"text-align:left;font-size:12px;\">Ses dalgalar\u0131n\u0131 analiz edip fonetik olarak metne d\u00f6n\u00fc\u015ft\u00fcr\u00fcr.<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left;\"><strong>Kimin \u0130\u00e7in \u0130deal?<\/strong><\/td>\n<td style=\"text-align:left;font-size:12px;\">\n<ul>\n<li>Okuma ihtiyac\u0131 duyanlar<\/li>\n<li>G\u00f6rme engeli olanlar<\/li>\n<li>Uzun metinleri dinlemek isteyenler<\/li>\n<li>Yol veya seyir halinde(\u00f6zellikle \u015fof\u00f6rler i\u00e7in) bir metni incelemek isteyenler<\/li>\n<\/ul>\n<\/td>\n<td style=\"text-align:left;font-size:12px;\">\n<ul>\n<li>Yazma yerine konu\u015farak i\u015flem yapmak isteyenler<\/li>\n<li>Dakik yazmaya zaman\u0131 olmayanlar<\/li>\n<li>Yazma engeli olanlar<\/li>\n<\/ul>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<blockquote><p><em>Text-to-Speech (TTS) ve Speech-to-Text (STT), uygulamalar\u0131m\u0131zda yapay zeka destekli ileti\u015fimi kolayla\u015ft\u0131rd\u0131\u011f\u0131 i\u00e7in g\u00fcnl\u00fck hayatta ve i\u015f s\u00fcre\u00e7lerinde s\u0131k\u00e7a tercih edilmeye ba\u015flanm\u0131\u015f teknolojilerdir.<\/em><\/p><\/blockquote>\n<p>Evet, bu yakla\u015f\u0131mlar\u0131n ne oldu\u011funu tam teferruatl\u0131 masaya yat\u0131rd\u0131\u011f\u0131m\u0131za g\u00f6re art\u0131k pratik olarak uygulamaya ge\u00e7ebiliriz. Her iki yakla\u015f\u0131m i\u00e7in gerekli olan modelleri Hugging Face \u00fczerinden kullanaca\u011f\u0131z. Tabi burada bahsetmem gereken \u00f6nemli bir husus vard\u0131r ki; o da, yapaca\u011f\u0131m\u0131z \u00e7al\u0131\u015fmalar\u0131n <a href=\"https:\/\/www.gencayyildiz.com\/blog\/semantic-kernel-nedir-deepseek-r1-esliginde-net-acisindan-derinlemesine-degerlendirelim\/\" target=\"_blank\">Semantic Kernel<\/a> entegrasyonuyla de\u011fil de bizzat HuggingFace model API&#8217;leri \u00fczerinden olaca\u011f\u0131d\u0131r. <em>Neden?<\/em> diye sorarsan\u0131z e\u011fer, Semantic Kernel&#8217;\u0131n \u015fu anda daha \u00e7ok text generation, text classification vs. gibi metin tabanl\u0131 modeller i\u00e7in optimize edilmi\u015f olmas\u0131 ve bundan kaynakl\u0131 Semantic Kernel \u00fczerinden TTS ve STT modellerinin do\u011frudan \u00e7al\u0131\u015fmas\u0131n\u0131n \u015fimdilik pek m\u00fcmk\u00fcn olmamas\u0131d\u0131r.<\/p>\n<p>Velhas\u0131l&#8230;<\/p>\n<h4>Temel Yap\u0131land\u0131rmalar<\/h4>\n<p>\u015eimdi bu \u00e7al\u0131\u015fmalar\u0131n yap\u0131labilmesi i\u00e7in bir Asp.NET Core uygulamas\u0131 olu\u015ftural\u0131m ve \u00fczerinde a\u015fa\u011f\u0131daki gibi yap\u0131land\u0131rmalarda bulunarak hali haz\u0131r bir zemin olu\u015ftural\u0131m;<\/p>\n<ul>\n<li>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\nvar builder = WebApplication.CreateBuilder(args);\r\n\r\nbuilder.Services.AddHttpClient(&quot;HuggingFaceAPI&quot;, httpClient =&gt;\r\n{\r\n    httpClient.BaseAddress = new Uri(&quot;https:\/\/api-inference.huggingface.co&quot;);\r\n    httpClient.DefaultRequestHeaders.Add(HeaderNames.Authorization, $&quot;Bearer {builder.Configuration&#x5B;&quot;HuggingFace:APIKey&quot;]}&quot;);\r\n});\r\n<\/pre>\n<\/div>\n<p>Modellerin API&#8217;lerine istekte bulunabilmek i\u00e7in header&#8217;\u0131nda &#8216;<em>Authorization<\/em>&#8216; key&#8217;ine kar\u015f\u0131l\u0131k bearer token&#8217;\u0131 verilmi\u015f ve base address&#8217;i de bar\u0131nd\u0131ran hali haz\u0131rda bir <code>HttpClient<\/code> getirecek olan yap\u0131land\u0131rmada bulunal\u0131m. Burada i\u00e7eri\u011fin devam\u0131nda, her iki modeli Hugging Face \u00fczerinden kullanaca\u011f\u0131m\u0131zdan dolay\u0131 her ikisinde de base address&#8217;in ayn\u0131 oldu\u011funu, sadece endpoint&#8217;in path&#8217;inde modele g\u00f6re de\u011fi\u015fikliklerin s\u00f6z konusu olaca\u011f\u0131n\u0131 g\u00f6receksiniz. O y\u00fczden s\u00fcrekli ayn\u0131 i\u015fi yapacak <code>HttpClient<\/code> nesnesi olu\u015fturmamak ve benzer request endpoint&#8217;ini yazmamak i\u00e7in bu \u015fekilde yap\u0131land\u0131rmada bulunmay\u0131 tercih ettim.\n<\/li>\n<li>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\nbuilder.Services.AddCors(options =&gt;\r\n    options.AddDefaultPolicy(policy =&gt;\r\n    {\r\n        policy.AllowAnyOrigin().AllowAnyHeader().AllowAnyMethod();\r\n    }));\r\n.\r\n.\r\n.\r\nvar app = builder.Build();\r\napp.UseCors();\r\n<\/pre>\n<\/div>\n<p>G\u00fcn\u00fcn sonunda client&#8217;\u0131 bir frontend uygulamas\u0131 olarak tasarlayaca\u011f\u0131m\u0131zdan dolay\u0131 \u015fimdiden CORS politikalar\u0131n\u0131 da yap\u0131land\u0131ral\u0131m.\n<\/li>\n<li>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\napp.UseDefaultFiles();\r\napp.UseStaticFiles();\r\n<\/pre>\n<\/div>\n<p>\u0130\u00e7eri\u011fimiz s\u00fcrecinde client uygulamas\u0131n\u0131 basitinden geli\u015ftirip vur ge\u00e7 yaparak h\u0131zl\u0131ca i\u015fimizi g\u00f6rebilemek i\u00e7in direkt <code>wwwroot<\/code> dosyas\u0131 i\u00e7erisinde <code>default.html<\/code>, <code>default.html<\/code>, <code>index.html<\/code> ya da <code>index.html<\/code> isimlerinden birinde static bir dosya olarak ayarlayaca\u011f\u0131z. Uygulamay\u0131 aya\u011fa kald\u0131r\u0131r kald\u0131rmaz, taray\u0131c\u0131da herhangi bir path&#8217;e ihtiya\u00e7 duyulmaks\u0131z\u0131n direkt host \u00fczerinden client uygulamas\u0131n\u0131n a\u00e7\u0131lmas\u0131n\u0131 istiyorsak <code>UseDefaultFiles<\/code> middleware&#8217;ini kullanmal\u0131y\u0131z. Benzer \u015fekilde wwwroot i\u00e7erisindeki dosyalara eri\u015fimin olabilmesi i\u00e7in de <code>UseStaticFiles<\/code> middleware&#8217;ini.\n<\/li>\n<li>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n.\r\n.\r\n.\r\nbuilder.Services.AddDirectoryBrowser();\r\n\r\nvar app = builder.Build();\r\n.\r\n.\r\n.\r\nstring webRootPath = Path.Combine(Directory.GetCurrentDirectory(), &quot;wwwroot&quot;, &quot;audio_outputs&quot;);\r\nif (!Directory.Exists(webRootPath))\r\n    Directory.CreateDirectory(webRootPath);\r\n\r\nIFileProvider fileProvider = new PhysicalFileProvider(Path.Combine(builder.Environment.WebRootPath, &quot;audio_outputs&quot;));\r\n\r\napp.UseStaticFiles(new StaticFileOptions\r\n{\r\n    FileProvider = fileProvider,\r\n    RequestPath = &quot;\/audio_outputs&quot;\r\n});\r\n\r\napp.UseDirectoryBrowser(new DirectoryBrowserOptions\r\n{\r\n    FileProvider = fileProvider,\r\n    RequestPath = &quot;\/audio_outputs&quot;\r\n});\r\n<\/pre>\n<\/div>\n<p>AI modelinin \u00fcretece\u011fi \u00e7\u0131kt\u0131lar\u0131 <code>wwwroot<\/code> i\u00e7erisindeki bir klas\u00f6rde tutmak isteyebiliriz. Misal olarak; Text-to-Speech neticesinde \u00fcretilen ses dosyas\u0131n\u0131 <em>audio_outputs<\/em> isimli bir klas\u00f6rde depolamak isteyece\u011fimizi varsayal\u0131m. Bunun i\u00e7in <strong><em>10<\/em><\/strong> ile <strong><em>12.<\/em><\/strong> sat\u0131r aral\u0131\u011f\u0131nda oldu\u011fu gibi bu klas\u00f6r\u00fcn var olup olmad\u0131\u011f\u0131n\u0131 kontrol edelim, yoksa olu\u015ftural\u0131m. <strong><em>16<\/em><\/strong> ile <strong><em>20.<\/em><\/strong> sat\u0131r aral\u0131\u011f\u0131nda oldu\u011fu gibi de bu kontrol edilen klas\u00f6r\u00fc static files olarak ayarlayal\u0131m ve <strong><em>22<\/em><\/strong> ile <strong><em>26.<\/em><\/strong> sat\u0131r aral\u0131\u011f\u0131ndaki gibi de yine bu klas\u00f6r dizinini browser&#8217;dan girilebilecek \u015fekilde yap\u0131land\u0131ral\u0131m. Tabi taray\u0131c\u0131dan static dosyalar\u0131n eri\u015filebilir k\u0131l\u0131nabilmesi i\u00e7in de <strong><em>4.<\/em><\/strong> sat\u0131rda oldu\u011fu gibi <code>AddDirectoryBrowser<\/code> servisini uygulamaya ekleyelim.\n<\/li>\n<\/ul>\n<p>Evet, art\u0131k TTS ve STT \u00e7al\u0131\u015fmalar\u0131 i\u00e7in gerekli altyap\u0131ya sahip bir Asp.NET Core uygulamam\u0131z var diyebiliriz. Bu uygulaman\u0131n b\u00fct\u00fcnsel olarak yap\u0131land\u0131rma \u00f6zetini a\u015fa\u011f\u0131 b\u0131rakarak art\u0131k hususi olarak esas i\u015flevlere odaklanabiliriz;<\/p>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\nusing AI_TextToSpeech_And_SpeechToText_Example;\r\nusing Microsoft.Extensions.FileProviders;\r\nusing Microsoft.Net.Http.Headers;\r\nusing System.Net.Mime;\r\nusing System.Text;\r\nusing System.Text.Json;\r\n\r\nvar builder = WebApplication.CreateBuilder(args);\r\n\r\nbuilder.Services.AddHttpClient(&quot;HuggingFaceAPI&quot;, httpClient =&gt;\r\n{\r\n    httpClient.BaseAddress = new Uri(&quot;https:\/\/api-inference.huggingface.co&quot;);\r\n    httpClient.DefaultRequestHeaders.Add(HeaderNames.Authorization, $&quot;Bearer {builder.Configuration&#x5B;&quot;HuggingFace:APIKey&quot;]}&quot;);\r\n});\r\n\r\nbuilder.Services.AddCors(options =&gt;\r\n    options.AddDefaultPolicy(policy =&gt;\r\n    {\r\n        policy.AllowAnyOrigin().AllowAnyHeader().AllowAnyMethod();\r\n    }));\r\n\r\nbuilder.Services.AddDirectoryBrowser();\r\n\r\nvar app = builder.Build();\r\napp.UseCors();\r\n\r\n#region index.html - style.css\r\napp.UseDefaultFiles();\r\napp.UseStaticFiles();\r\n#endregion\r\n\r\n#region wwwroot\/audio_outputs\r\nstring webRootPath = Path.Combine(Directory.GetCurrentDirectory(), &quot;wwwroot&quot;, &quot;audio_outputs&quot;);\r\nif (!Directory.Exists(webRootPath))\r\n    Directory.CreateDirectory(webRootPath);\r\n\r\nIFileProvider fileProvider = new PhysicalFileProvider(Path.Combine(builder.Environment.WebRootPath, &quot;audio_outputs&quot;));\r\n\r\napp.UseStaticFiles(new StaticFileOptions\r\n{\r\n    FileProvider = fileProvider,\r\n    RequestPath = &quot;\/audio_outputs&quot;\r\n});\r\n\r\napp.UseDirectoryBrowser(new DirectoryBrowserOptions\r\n{\r\n    FileProvider = fileProvider,\r\n    RequestPath = &quot;\/audio_outputs&quot;\r\n});\r\n#endregion\r\n\r\n\/\/Endpoints...\r\n\r\napp.Run();\r\n\r\n<\/pre>\n<\/div>\n<h4>.NET&#8217;te Text-to-Speech Uygulamas\u0131<\/h4>\n<p>Text-to-Speech i\u00e7in onlarca model aras\u0131ndan \u015fimdilik \u00fccretsiz kullan\u0131ma sahip olan <a href=\"https:\/\/huggingface.co\/facebook\/mms-tts-tur\" target=\"_blank\"><code>facebook\/mms-tts-tur<\/code><\/a> modelini kullan\u0131yor olaca\u011f\u0131z. Bu model, MMS (Massively Multilingual Speech) projesinin bir par\u00e7as\u0131 olarak Meta (Facebook AI) taraf\u0131ndan geli\u015ftirilmi\u015f ve T\u00fcrk\u00e7e i\u00e7in e\u011fitilmi\u015f bir TTS modelidir. Y\u00fczlerce dilde metinden do\u011fal ses sentezi yapabilen bu model ile \u00e7ok kaliteli ses d\u00f6n\u00fc\u015f\u00fcmleri ger\u00e7ekle\u015ftirilebilmektedir. Ancak ultra insans\u0131 olmayan(yani yapayl\u0131k seviyesi %10-15 civar\u0131nda olan) yap\u0131s\u0131 nedeniyle, \u00f6zellikle uzun c\u00fcmlelerde robotik ton sezilebilmektedir. \u00d6zel telaffuz ayarlar\u0131 ve optimizasyonlar\u0131 yap\u0131lamasada buna ra\u011fmen her t\u00fcrl\u00fc metni konu\u015fmaya \u00e7evirebilmektedir. Lisans olarak <em style=\"font-size:12px;\">CC-BY-NC 4.0<\/em> kapsam\u0131nda oldu\u011fu i\u00e7in kullan\u0131ld\u0131\u011f\u0131 yaz\u0131l\u0131mlarda \u00f6zellikle Meta\/Facebook&#8217;a at\u0131fta bulunulmas\u0131 ve sadece ki\u015fisel, akademik veya ara\u015ft\u0131rma ama\u00e7l\u0131 kullan\u0131mlar\u0131n d\u0131\u015f\u0131nda ticari kullan\u0131lmamas\u0131 gerekmektedir. Yani ticari kullan\u0131m i\u00e7in \u00f6zel lisans veya izin gerekebilmektedir.<\/p>\n<p>Bu modeli a\u015fa\u011f\u0131daki gibi kullanarak client&#8217;tan gelecek olan metinsel i\u00e7eri\u011fin rahatl\u0131kla ses kayd\u0131n\u0131 elde edebiliriz;<\/p>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\nrecord TextToSpeechRequest(string Text);\r\n<\/pre>\n<\/div>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\napp.MapPost(&quot;\/text-to-speech&quot;, async (IHttpClientFactory httpClientFactory, HttpContext httpContext) =&gt;\r\n{\r\n    try\r\n    {\r\n        HttpClient httpClient = httpClientFactory.CreateClient(&quot;HuggingFaceAPI&quot;);\r\n\r\n        using StreamReader streamReader = new StreamReader(httpContext.Request.Body);\r\n        string requestBody = await streamReader.ReadToEndAsync();\r\n        TextToSpeechRequest request = JsonSerializer.Deserialize&lt;TextToSpeechRequest&gt;(requestBody)!;\r\n\r\n        var requestData = new\r\n        {\r\n            inputs = request.Text\r\n        };\r\n\r\n        StringContent stringContent = new(\r\n            JsonSerializer.Serialize(requestData),\r\n            Encoding.UTF8,\r\n            MediaTypeNames.Application.Json\r\n            );\r\n\r\n        Console.WriteLine(&quot;Ses olu\u015fturuluyor...&quot;);\r\n\r\n        HttpResponseMessage response = await httpClient.PostAsync(&quot;models\/facebook\/mms-tts-tur&quot;, stringContent);\r\n        if (response.IsSuccessStatusCode)\r\n        {\r\n            byte&#x5B;] audioBytes = await response.Content.ReadAsByteArrayAsync();\r\n            string outputPath = Path.Combine(Directory.GetCurrentDirectory(), &quot;wwwroot&quot;, &quot;audio_outputs&quot;, $&quot;output_{DateTime.Now:yyyyMMddHHmmss}.wav&quot;);\r\n\r\n            \/\/Ses dosyas\u0131 kaydediliyor\r\n            File.WriteAllBytes(outputPath, audioBytes);\r\n            httpContext.Response.ContentType = &quot;audio\/wav&quot;;\r\n            await httpContext.Response.Body.WriteAsync(audioBytes);\r\n        }\r\n        else\r\n        {\r\n            string error = await response.Content.ReadAsStringAsync();\r\n            Console.WriteLine($&quot;API Hatas\u0131\\t: {response.StatusCode}&quot;);\r\n            Console.WriteLine($&quot;Hata Detay\u0131\\t: {error}&quot;);\r\n        }\r\n    }\r\n    catch (Exception ex)\r\n    {\r\n        Console.WriteLine($&quot;Hata olu\u015ftu\\t: {ex.Message}&quot;);\r\n    }\r\n});\r\n<\/pre>\n<\/div>\n<p>Dikkat ederseniz; <code>\/text-to-speech<\/code> endpoint&#8217;ini olu\u015fturarak, <strong><em>5.<\/em><\/strong> sat\u0131rda biraz \u00f6nce yap\u0131land\u0131rd\u0131\u011f\u0131m\u0131z &#8216;<em>HuggingFaceAPI<\/em>&#8216; ad\u0131nda <code>HttpClient<\/code> nesnesinden talep edip, olu\u015fturuyoruz. Devam\u0131nda client&#8217;tan gelen metni <code>TextToSpeechRequest<\/code> t\u00fcr\u00fcnde yakalay\u0131p, bunu <strong><em>24.<\/em><\/strong> sat\u0131rda ilgili modelin API&#8217;sine post iste\u011fiyle g\u00f6nderiyoruz. E\u011fer bu istek neticesi ba\u015far\u0131l\u0131ysa AI modeli bizlere g\u00f6nderilen metinin ses dosyas\u0131n\u0131 d\u00f6nd\u00fcrecektir. <strong><em>27.<\/em><\/strong> sat\u0131rda bu ses dosyas\u0131n\u0131 al\u0131yoruz ve sonras\u0131nda belirtilen dizine at\u0131yoruz.<\/p>\n<p>\u0130\u015fte bu kadar \ud83d\ude42<\/p>\n<h4>.NET&#8217;te Sppech-to-Text Uygulamas\u0131<\/h4>\n<p>Speech-to-Text i\u00e7in de OpenAI taraf\u0131ndan geli\u015ftirilen ve Automatic Speech Recognition (ASR) ile konu\u015fma \u00e7evirisi g\u00f6revlerinde kullan\u0131lan <a href=\"https:\/\/huggingface.co\/openai\/whisper-large-v3-turbo\" target=\"_blank\"><code>openai\/whisper-large-v3-turbo<\/code><\/a> AI modelini kullanaca\u011f\u0131z. MIT lisans\u0131yla sunuldu\u011fu i\u00e7in ticari ya da de\u011fil t\u00fcm projelerde rahatl\u0131kla kullan\u0131labilmektedir. Ayr\u0131ca \u00fccretsizdir. <code>whisper-large-v3-turbo<\/code>, \u00f6nceki <code>large-v3<\/code> modeline k\u0131yasla optimize edilerek 8 kat daha h\u0131zl\u0131 \u00e7al\u0131\u015fmakta ve buna ra\u011fmen transkripsiyon kalitesinde \u00f6nemsiz bir d\u00fczeyde d\u00fc\u015f\u00fc\u015fle ciddi performans art\u0131\u015f\u0131 sa\u011flamaktad\u0131r. T\u00fcm bunlar\u0131n yan\u0131nda 99 farkl\u0131 dil deste\u011fiyle geni\u015f bir kullan\u0131m yelpazesi sunmakta ve genellikle canl\u0131 yay\u0131nlarda, anl\u0131k \u00e7evirilerde ve daha az donan\u0131m kayna\u011f\u0131 gerektiren y\u00fcksek performans gerektiren s\u00fcre\u00e7lerde tercih edilmektedir.<\/p>\n<p>Bu modeli de a\u015fa\u011f\u0131daki gibi i\u015fleyerek haz\u0131r olan ya da mikrofondan elde edilen ses dosyalar\u0131n\u0131 metinsel ifadeye d\u00f6n\u00fc\u015ft\u00fcrebiliriz;<\/p>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\napp.MapPost(&quot;\/speech-to-text&quot;, async (IHttpClientFactory httpClientFactory, HttpContext httpContext) =&gt;\r\n{\r\n    try\r\n    {\r\n        IFormCollection form = await httpContext.Request.ReadFormAsync();\r\n        IFormFile? file = form.Files.GetFile(&quot;audio&quot;);\r\n\r\n        if (file is { Length: 0 } or null)\r\n        {\r\n            httpContext.Response.StatusCode = 400;\r\n            await httpContext.Response.WriteAsJsonAsync(new { Error = &quot;Ses dosyas\u0131 bulunamad\u0131&quot; });\r\n            return;\r\n        }\r\n\r\n        using MemoryStream memoryStream = new();\r\n        await file.CopyToAsync(memoryStream);\r\n        byte&#x5B;] audioBytes = memoryStream.ToArray();\r\n\r\n        HttpClient httpClient = httpClientFactory.CreateClient(&quot;HuggingFaceAPI&quot;);\r\n\r\n        ByteArrayContent byteArrayContent = new(audioBytes);\r\n        byteArrayContent.Headers.Add(HeaderNames.ContentType, &quot;audio\/wav&quot;);\r\n\r\n        \/\/Whisper small modeli kullan\u0131l\u0131yor | H\u0131zl\u0131 ve g\u00fcvenilir!\r\n        HttpResponseMessage response = await httpClient.PostAsync(&quot;models\/openai\/whisper-large-v3-turbo&quot;, byteArrayContent);\r\n        string responseContent = await response.Content.ReadAsStringAsync();\r\n        Console.WriteLine($&quot;API Yan\u0131t\u0131\\t: {responseContent}&quot;);\r\n        if (!response.IsSuccessStatusCode)\r\n        {\r\n            httpContext.Response.StatusCode = (int)response.StatusCode;\r\n            await httpContext.Response.WriteAsJsonAsync(new { Error = $&quot;API Hatas\u0131\\t:{responseContent}&quot; });\r\n            return;\r\n        }\r\n\r\n        \/\/Whisper modeli i\u00e7in \u00f6zel yan\u0131t format\u0131 ayarlan\u0131yor\r\n        Dictionary&lt;string, string&gt;? result = JsonSerializer.Deserialize&lt;Dictionary&lt;string, string&gt;&gt;(responseContent);\r\n        string? text = result?.GetValueOrDefault(&quot;text&quot;, &quot;&quot;);\r\n\r\n        if (string.IsNullOrEmpty(text))\r\n        {\r\n            httpContext.Response.StatusCode = 500;\r\n            await httpContext.Response.WriteAsJsonAsync(new { Error = &quot;Metin \u00e7evrilemedi!&quot; });\r\n            return;\r\n        }\r\n\r\n        await httpContext.Response.WriteAsJsonAsync(new { Text = text });\r\n    }\r\n    catch (Exception ex)\r\n    {\r\n        Console.WriteLine($&quot;Hata\\t: {ex.Message}&quot;);\r\n        httpContext.Response.StatusCode = 500;\r\n        await httpContext.Response.WriteAsJsonAsync(new { Error = $&quot;Sunucu hatas\u0131\\t: {ex.Message}&quot; });\r\n    }\r\n})\r\n    .DisableAntiforgery();\r\n<\/pre>\n<\/div>\n<p>Yukar\u0131daki kod blo\u011funa g\u00f6z atarsan\u0131z e\u011fer; <strong><em>5<\/em><\/strong> ile <strong><em>22.<\/em><\/strong> sat\u0131r aral\u0131\u011f\u0131nda gelen ses dosyas\u0131n\u0131 <code>ByteArrayContent<\/code> t\u00fcr\u00fcnde elde ediyoruz  ve bu veriyi <strong><em>25.<\/em><\/strong> sat\u0131rda AI modeline g\u00f6ndererek handle edilmesini ba\u015flat\u0131yoruz. Devam\u0131nda ise gelen text verisini ay\u0131klay\u0131p, response olarak d\u00f6nd\u00fcr\u00fcyoruz.<\/p>\n<p>Ve evet&#8230; Bu i\u015flem de bu kadar \ud83d\ude42<\/p>\n<p>\u015eimdi gelin bu i\u015flevsellikleri g\u00f6rselle\u015ftirerek kullanmam\u0131z\u0131 sa\u011flayacak olan client&#8217;\u0131n geli\u015ftirmesini ger\u00e7ekle\u015ftirelim.<\/p>\n<h4>Client Tasar\u0131m\u0131 ve Geli\u015ftirilmesi<\/h4>\n<p>\u00d6ncelikle a\u015fa\u011f\u0131daki gibi estetik ve romantizm anlay\u0131\u015f\u0131na dayanan bir tasar\u0131mda bulunal\u0131m;<\/p>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n&lt;!DOCTYPE html&gt;\r\n&lt;html lang=&quot;tr&quot;&gt;\r\n&lt;head&gt;\r\n    &lt;meta charset=&quot;UTF-8&quot;&gt;\r\n    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot;&gt;\r\n    &lt;title&gt;Ses-Metin D\u00f6n\u00fc\u015ft\u00fcr\u00fcc\u00fc&lt;\/title&gt;\r\n    &lt;link href=&quot;style.css&quot; rel=&quot;stylesheet&quot; \/&gt;\r\n&lt;\/head&gt;\r\n&lt;body&gt;\r\n    &lt;div class=&quot;tab-container&quot;&gt;\r\n        &lt;h1 style=&quot;text-align: center; margin-bottom: 20px;&quot;&gt;Ses D\u00f6n\u00fc\u015ft\u00fcr\u00fcc\u00fc&lt;\/h1&gt;\r\n        &lt;div class=&quot;tab-buttons&quot;&gt;\r\n            &lt;button onclick=&quot;showTab('tts')&quot; class=&quot;tab-button active&quot;&gt;Metin-Ses&lt;\/button&gt;\r\n            &lt;button onclick=&quot;showTab('stt')&quot; class=&quot;tab-button&quot;&gt;Ses-Metin&lt;\/button&gt;\r\n        &lt;\/div&gt;\r\n    &lt;\/div&gt;\r\n\r\n    &lt;div id=&quot;tts&quot; class=&quot;tab-content container active&quot;&gt;\r\n        &lt;h2&gt;Metin-Ses D\u00f6n\u00fc\u015ft\u00fcr\u00fcc\u00fc&lt;\/h2&gt;\r\n        &lt;textarea id=&quot;inputText&quot; placeholder=&quot;T\u00fcrk\u00e7e metin girin...&quot;&gt;&lt;\/textarea&gt;\r\n        &lt;button onclick=&quot;convertToSpeech()&quot;&gt;Sese D\u00f6n\u00fc\u015ft\u00fcr&lt;\/button&gt;\r\n        &lt;div id=&quot;ttsStatus&quot; class=&quot;status&quot;&gt;&lt;\/div&gt;\r\n        &lt;audio id=&quot;audioPlayer&quot; controls style=&quot;display: none; margin-top: 20px; width: 100%;&quot;&gt;&lt;\/audio&gt;\r\n    &lt;\/div&gt;\r\n\r\n    &lt;div id=&quot;stt&quot; class=&quot;tab-content container&quot;&gt;\r\n        &lt;h2&gt;Ses-Metin D\u00f6n\u00fc\u015ft\u00fcr\u00fcc\u00fc&lt;\/h2&gt;\r\n        &lt;div id=&quot;audioControls&quot;&gt;\r\n            &lt;button id=&quot;recordButton&quot; onclick=&quot;toggleRecording()&quot;&gt;Kay\u0131t Ba\u015flat&lt;\/button&gt;\r\n            &lt;input type=&quot;file&quot; id=&quot;audioFile&quot; accept=&quot;audio\/*&quot; style=&quot;display: none;&quot;&gt;\r\n            &lt;button onclick=&quot;document.getElementById('audioFile').click()&quot;&gt;Ses Dosyas\u0131 Se\u00e7&lt;\/button&gt;\r\n        &lt;\/div&gt;\r\n        &lt;div id=&quot;sttStatus&quot; class=&quot;status&quot;&gt;&lt;\/div&gt;\r\n        &lt;textarea id=&quot;outputText&quot; placeholder=&quot;D\u00f6n\u00fc\u015ft\u00fcr\u00fclen metin burada g\u00f6r\u00fcnecek...&quot; readonly&gt;&lt;\/textarea&gt;\r\n    &lt;\/div&gt;\r\n    &lt;script src=&quot;script.js&quot;&gt;&lt;\/script&gt;\r\n&lt;\/body&gt;\r\n&lt;\/html&gt; \r\n<\/pre>\n<\/div>\n<p>Bu tasar\u0131mda kulland\u0131\u011f\u0131m\u0131z <code>style.css<\/code> dosyas\u0131n\u0131n i\u00e7eri\u011fini haddinden fazla uzun oldu\u011fu i\u00e7in burada sunmayaca\u011f\u0131m. Amma velakin <code>script.js<\/code> dosyas\u0131n\u0131n i\u00e7eri\u011fini masaya yat\u0131raca\u011f\u0131z.<\/p>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\nlet mediaRecorder;\r\nlet audioChunks = &#x5B;];\r\nlet isRecording = false;\r\n\r\nfunction showTab(tabId) {\r\n    document.querySelectorAll('.tab-content').forEach(tab =&gt; tab.classList.remove('active'));\r\n    document.querySelectorAll('.tab-button').forEach(btn =&gt; btn.classList.remove('active'));\r\n    document.getElementById(tabId).classList.add('active');\r\n    document.querySelector(`button&#x5B;onclick=&quot;showTab('${tabId}')&quot;]`).classList.add('active');\r\n}\r\n\r\nasync function convertToSpeech() {\r\n    const inputText = document.getElementById('inputText').value;\r\n    const statusDiv = document.getElementById('ttsStatus');\r\n    const audioPlayer = document.getElementById('audioPlayer');\r\n    const button = document.querySelector('#tts button');\r\n\r\n    if (!inputText) {\r\n        statusDiv.className = 'status error';\r\n        statusDiv.textContent = 'L\u00fctfen bir metin girin.';\r\n        return;\r\n    }\r\n\r\n    try {\r\n        button.disabled = true;\r\n        statusDiv.className = 'status';\r\n        statusDiv.textContent = 'Ses olu\u015fturuluyor...';\r\n\r\n        const response = await fetch('\/text-to-speech', {\r\n            method: 'POST',\r\n            headers: {\r\n                'Content-Type': 'application\/json',\r\n            },\r\n            body: JSON.stringify({ Text: inputText })\r\n        });\r\n\r\n        if (!response.ok) {\r\n            throw new Error(`HTTP error! status: ${response.status}`);\r\n        }\r\n\r\n        const audioBlob = await response.blob();\r\n        const audioUrl = URL.createObjectURL(audioBlob);\r\n\r\n        audioPlayer.src = audioUrl;\r\n        audioPlayer.style.display = 'block';\r\n        await audioPlayer.play();\r\n\r\n        statusDiv.className = 'status success';\r\n        statusDiv.textContent = 'Ses ba\u015far\u0131yla olu\u015fturuldu!';\r\n    } catch (error) {\r\n        statusDiv.className = 'status error';\r\n        statusDiv.textContent = `Hata olu\u015ftu: ${error.message}`;\r\n        console.error('Error:', error);\r\n    } finally {\r\n        button.disabled = false;\r\n    }\r\n}\r\n\r\nasync function toggleRecording() {\r\n    const recordButton = document.getElementById('recordButton');\r\n    const statusDiv = document.getElementById('sttStatus');\r\n\r\n    if (!isRecording) {\r\n        try {\r\n            const stream = await navigator.mediaDevices.getUserMedia({ audio: true });\r\n            mediaRecorder = new MediaRecorder(stream);\r\n            audioChunks = &#x5B;];\r\n\r\n            mediaRecorder.ondataavailable = (event) =&gt; {\r\n                audioChunks.push(event.data);\r\n            };\r\n\r\n            mediaRecorder.onstop = async () =&gt; {\r\n                const audioBlob = new Blob(audioChunks, { type: 'audio\/wav' });\r\n                await convertSpeechToText(audioBlob);\r\n            };\r\n\r\n            mediaRecorder.start();\r\n            isRecording = true;\r\n            recordButton.textContent = 'Kay\u0131t Durdur';\r\n            recordButton.classList.add('recording');\r\n            statusDiv.className = 'status success';\r\n            statusDiv.textContent = 'Kay\u0131t yap\u0131l\u0131yor...';\r\n        } catch (error) {\r\n            statusDiv.className = 'status error';\r\n            statusDiv.textContent = `Mikrofon eri\u015fim hatas\u0131: ${error.message}`;\r\n        }\r\n    } else {\r\n        mediaRecorder.stop();\r\n        isRecording = false;\r\n        recordButton.textContent = 'Kay\u0131t Ba\u015flat';\r\n        recordButton.classList.remove('recording');\r\n    }\r\n}\r\n\r\ndocument.getElementById('audioFile').addEventListener('change', async (event) =&gt; {\r\n    const file = event.target.files&#x5B;0];\r\n    if (file) {\r\n        await convertSpeechToText(file);\r\n    }\r\n});\r\n\r\nasync function convertSpeechToText(audioData) {\r\n    const statusDiv = document.getElementById('sttStatus');\r\n    const outputText = document.getElementById('outputText');\r\n\r\n    try {\r\n        statusDiv.className = 'status';\r\n        statusDiv.textContent = 'Ses metne d\u00f6n\u00fc\u015ft\u00fcr\u00fcl\u00fcyor...';\r\n\r\n        const formData = new FormData();\r\n        formData.append('audio', audioData);\r\n\r\n        const response = await fetch('\/speech-to-text', {\r\n            method: 'POST',\r\n            body: formData\r\n        });\r\n\r\n        if (!response.ok) {\r\n            throw new Error(`HTTP error! status: ${response.status}`);\r\n        }\r\n\r\n        const result = await response.json();\r\n        outputText.value = result.text;\r\n        statusDiv.className = 'status success';\r\n        statusDiv.textContent = 'Ses ba\u015far\u0131yla metne d\u00f6n\u00fc\u015ft\u00fcr\u00fcld\u00fc!';\r\n    } catch (error) {\r\n        statusDiv.className = 'status error';\r\n        statusDiv.textContent = `Hata olu\u015ftu: ${error.message}`;\r\n        console.error('Error:', error);\r\n    }\r\n}\r\n<\/pre>\n<\/div>\n<p>Evet, burada a\u015fa\u011f\u0131daki g\u00f6rselde oldu\u011fu gibi i\u015flevsel olarak mevzu bahis olan her iki d\u00f6n\u00fc\u015f\u00fcm\u00fc ger\u00e7ekle\u015ftirecek nitelikte bir tasar\u0131mla aray\u00fcz haz\u0131rlanm\u0131\u015ft\u0131r.<a href=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2025\/03\/NETte-AI-Destegiyle-Text-to-Speech-TTS-ve-Speech-to-Text-STT-Operasyonlari.gif\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2025\/03\/NETte-AI-Destegiyle-Text-to-Speech-TTS-ve-Speech-to-Text-STT-Operasyonlari.gif\" alt=\".NET&#039;te AI Deste\u011fiyle Text-to-Speech (TTS) ve Speech-to-Text (STT) Operasyonlar\u0131\" width=\"800\" height=\"424\" class=\"aligncenter size-full wp-image-27707\" \/><\/a>Bu client, hem html hem de script olarak <code>wwwroot<\/code> dizinine  eklendi\u011fi taktirde, uygulaman\u0131n temel yap\u0131land\u0131rmas\u0131nda bulundu\u011fumuz <code>UseDefaultFiles<\/code> middleware&#8217;i sayesinde direkt uygulama aya\u011fa kald\u0131r\u0131l\u0131r kald\u0131r\u0131lmaz a\u00e7\u0131lacakt\u0131r. B\u00f6ylece testlerimizi h\u0131zl\u0131ca ger\u00e7ekle\u015ftirebilmekte ve TTS ve STT d\u00f6n\u00fc\u015f\u00fcmlerinin orta \u015feker de olsa ba\u015far\u0131yla ger\u00e7ekle\u015fti\u011fini g\u00f6zlemleyebilmekteyiz.<\/p>\n<p>Evet&#8230; Nihai olarak, bu i\u00e7eri\u011fimizde Text-to-Speech (TTS) ve Speech-to-Text (STT) yakla\u015f\u0131mlar\u0131n\u0131n Hugging Face \u00fczerinden ilgili modeller e\u015fli\u011finde API arac\u0131l\u0131\u011f\u0131yla basit bir \u015fekilde entegrasyonlar\u0131n\u0131 ele alm\u0131\u015f bulunuyoruz.<\/p>\n<p>\u0130lgilenenlerin faydalanmas\u0131 dile\u011fiyle&#8230;<br \/>\nSonraki yaz\u0131lar\u0131mda g\u00f6r\u00fc\u015fmek \u00fczere&#8230;<br \/>\n\u0130yi \u00e7al\u0131\u015fmalar&#8230;<\/p>\n<p>Not : \u00d6rnek \u00e7al\u0131\u015fmaya a\u015fa\u011f\u0131daki GitHub adresinden eri\u015febilirsiniz.<br \/>\n<a href=\"https:\/\/github.com\/gncyyldz\/AI_TextToSpeech_And_SpeechToText_Example\" target=\"_blank\">https:\/\/github.com\/gncyyldz\/AI_TextToSpeech_And_SpeechToText_Example<\/a><\/p>\n<!-- AddThis Advanced Settings generic via filter on the_content --><!-- AddThis Share Buttons generic via filter on the_content -->","protected":false},"excerpt":{"rendered":"<p>Merhaba, Bu i\u00e7eri\u011fimizde ses ve metin aras\u0131nda d\u00f6n\u00fc\u015f\u00fcm i\u015flemlerine kar\u015f\u0131l\u0131k gelen Text-to-Speech (TTS) ve Speech-to-Text (STT) kavramlar\u0131n\u0131 ele alacak ve .NET ekosisteminde bu kavramlar do\u011frultusunda pratiksel operasyonlar\u0131 nas\u0131l ger\u00e7ekle\u015ftirebilece\u011fimizi deneyimleyece\u011fiz. Text-to-Speech (TTS) ve Speech-to-Text&#46;&#46;&#46;<!-- AddThis Advanced Settings generic via filter on get_the_excerpt --><!-- AddThis Share Buttons generic via filter on get_the_excerpt --><\/p>\n","protected":false},"author":1,"featured_media":27709,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[5222,5220],"tags":[5288,5223,5286,5287,5284,5285,5225],"class_list":["post-27699","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-llm","category-yapay-zeka-ai","tag-hugging-face","tag-llm","tag-speech-to-text","tag-stt","tag-text-to-speech","tag-tts","tag-yapay-zeka"],"amp_enabled":true,"_links":{"self":[{"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/posts\/27699","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/comments?post=27699"}],"version-history":[{"count":13,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/posts\/27699\/revisions"}],"predecessor-version":[{"id":27714,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/posts\/27699\/revisions\/27714"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/media\/27709"}],"wp:attachment":[{"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/media?parent=27699"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/categories?post=27699"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/tags?post=27699"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}