{"id":41694,"date":"2026-05-10T21:03:17","date_gmt":"2026-05-10T18:03:17","guid":{"rendered":"https:\/\/fatihsoysal.com\/blog\/canvas-akisina-ses-ve-muzik-entegre-etmek-mediarecorder-ihracatinda-eksiksiz-bir-yaklasim\/"},"modified":"2026-05-10T21:03:17","modified_gmt":"2026-05-10T18:03:17","slug":"canvas-akisina-ses-ve-muzik-entegre-etmek-mediarecorder-ihracatinda-eksiksiz-bir-yaklasim","status":"publish","type":"post","link":"https:\/\/fatihsoysal.com\/blog\/canvas-akisina-ses-ve-muzik-entegre-etmek-mediarecorder-ihracatinda-eksiksiz-bir-yaklasim\/","title":{"rendered":"Canvas Ak\u0131\u015f\u0131na Ses ve M\u00fczik Entegre Etmek: MediaRecorder \u0130hracat\u0131nda Eksiksiz Bir Yakla\u015f\u0131m"},"content":{"rendered":"<p><body><\/p>\n<h2>Canvas Ak\u0131\u015f\u0131na Ses ve M\u00fczik Entegre Etmek: MediaRecorder \u0130hracat\u0131nda Eksiksiz Bir Yakla\u015f\u0131m<\/h2>\n<p>Web geli\u015ftiricileri i\u00e7in taray\u0131c\u0131 tabanl\u0131 medya i\u015fleme, son y\u0131llarda b\u00fcy\u00fck bir ivme kazand\u0131. \u00d6zellikle interaktif web uygulamalar\u0131nda, kullan\u0131c\u0131lar\u0131n ekran kay\u0131tlar\u0131, \u00e7izim animasyonlar\u0131 veya sunumlar\u0131n\u0131 sesli bir anlat\u0131mla zenginle\u015ftirerek d\u0131\u015fa aktarma ihtiyac\u0131 giderek art\u0131yor. Ancak, <code>canvas.captureStream()<\/code> metodunun varsay\u0131lan olarak yaln\u0131zca video verisi sa\u011flamas\u0131, bu t\u00fcr zengin medya i\u00e7erikleri olu\u015fturmak isteyen geli\u015ftiriciler i\u00e7in \u00f6nemli bir engel te\u015fkil ediyor. Bu makalede, bu temel k\u0131s\u0131tlamay\u0131 a\u015farak, bir tuval (canvas) ak\u0131\u015f\u0131na canl\u0131 seslendirme ve arka plan m\u00fczi\u011fi gibi birden fazla ses kayna\u011f\u0131n\u0131 nas\u0131l entegre edebilece\u011fimizi ve elde etti\u011fimiz bu karma ak\u0131\u015f\u0131 <code>MediaRecorder<\/code> kullanarak eksiksiz bir medya dosyas\u0131 olarak nas\u0131l d\u0131\u015fa aktarabilece\u011fimizi ad\u0131m ad\u0131m inceleyece\u011fiz.<\/p>\n<h2>Web Taray\u0131c\u0131lar\u0131nda Medya Ak\u0131\u015flar\u0131n\u0131n Temelleri: Neden <code>canvas.captureStream()<\/code> Yaln\u0131zca G\u00f6r\u00fcnt\u00fc Sa\u011flar?<\/h2>\n<p>Web \u00fczerinde medya ile \u00e7al\u0131\u015f\u0131rken, temelde <code>MediaStream<\/code> ad\u0131 verilen bir kavramla kar\u015f\u0131la\u015f\u0131r\u0131z. Bu, bir veya daha fazla medya par\u00e7as\u0131n\u0131 (track) i\u00e7eren bir ak\u0131\u015ft\u0131r. Medya par\u00e7alar\u0131, video (<code>VideoTrack<\/code>) veya ses (<code>AudioTrack<\/code>) olabilir. \u00d6rne\u011fin, bir web kameras\u0131ndan al\u0131nan ak\u0131\u015f hem bir video par\u00e7as\u0131n\u0131 hem de bir ses par\u00e7as\u0131n\u0131 i\u00e7erirken, bir mikrofondan al\u0131nan ak\u0131\u015f yaln\u0131zca bir ses par\u00e7as\u0131 i\u00e7erir. Bu ayr\u0131m, farkl\u0131 medya kaynaklar\u0131n\u0131 esnek bir \u015fekilde birle\u015ftirmemize veya i\u015flememize olanak tan\u0131r.<\/p>\n<p><code>HTMLCanvasElement<\/code> aray\u00fcz\u00fcn\u00fcn sa\u011flad\u0131\u011f\u0131 <code>captureStream()<\/code> metodu, tuvalde o an \u00e7izilen i\u00e7eri\u011fi ger\u00e7ek zamanl\u0131 bir video ak\u0131\u015f\u0131 olarak yakalamak i\u00e7in tasarlanm\u0131\u015ft\u0131r. Bu metodun ana amac\u0131, tuvaldeki g\u00f6rsel g\u00fcncellemeleri bir video kayd\u0131na d\u00f6n\u00fc\u015ft\u00fcrmektir. Dolay\u0131s\u0131yla, do\u011fas\u0131 gere\u011fi yaln\u0131zca bir <code>VideoTrack<\/code> i\u00e7eren bir <code>MediaStream<\/code> d\u00f6nd\u00fcr\u00fcr. Bu, tuval \u00fczerinde yapt\u0131\u011f\u0131n\u0131z \u00e7izimlerin, animasyonlar\u0131n veya g\u00f6r\u00fcnt\u00fc i\u015flemelerinin bir video ak\u0131\u015f\u0131na d\u00f6n\u00fc\u015ft\u00fcr\u00fclebilmesini sa\u011flar ancak ses i\u00e7eri\u011fi sa\u011flamaz. Bu tasar\u0131m karar\u0131, tuvalin bir g\u00f6rsel \u00e7\u0131kt\u0131 y\u00fczeyi olmas\u0131 ve do\u011frudan ses \u00fcretme yetene\u011finin olmamas\u0131yla uyumludur. Geli\u015ftiricilerin tuval \u00fczerindeki g\u00f6rsel i\u00e7eri\u011fi kaydederken ses eklemek istemesi durumunda, ses ak\u0131\u015flar\u0131n\u0131n ayr\u0131 olarak y\u00f6netilmesi ve daha sonra video ak\u0131\u015f\u0131yla birle\u015ftirilmesi gerekmektedir.<\/p>\n<p><code>MediaRecorder<\/code> API&#8217;si ise, bir <code>MediaStream<\/code>&#8216;i al\u0131p onu belirli bir formatta (\u00f6rne\u011fin WebM veya MP4) bir medya dosyas\u0131 olarak kaydetmek i\u00e7in kullan\u0131l\u0131r. E\u011fer <code>MediaRecorder<\/code>&#8216;a yaln\u0131zca <code>canvas.captureStream()<\/code> taraf\u0131ndan sa\u011flanan bir ak\u0131\u015f\u0131 verirseniz, elde edece\u011finiz \u00e7\u0131kt\u0131 yaln\u0131zca video i\u00e7eren, sessiz bir dosya olacakt\u0131r. Bu durum, \u00f6zellikle bir ekran kaydedici, bir interaktif ders materyali veya bir sunum arac\u0131 geli\u015ftirirken yetersiz kal\u0131r. Kullan\u0131c\u0131lar\u0131n sesli yorumlar\u0131n\u0131, arka plan m\u00fcziklerini veya di\u011fer ses efektlerini ekleyebilmeleri i\u00e7in, tuvalden gelen video ak\u0131\u015f\u0131na harici ses kaynaklar\u0131n\u0131 dinamik olarak eklememiz gerekir. Bu noktada, Web Audio API&#8217;nin g\u00fcc\u00fcnden faydalanarak farkl\u0131 ses kaynaklar\u0131n\u0131 kar\u0131\u015ft\u0131rma ve tek bir birle\u015fik ses ak\u0131\u015f\u0131 olu\u015fturma ihtiyac\u0131 do\u011far. Bu temel anlay\u0131\u015f, sonraki ad\u0131mlarda izleyece\u011fimiz \u00e7\u00f6z\u00fcm yolunun temelini olu\u015fturmaktad\u0131r.<\/p>\n<h2>Ses Kaynaklar\u0131n\u0131 Haz\u0131rlama: Mikrofon, M\u00fczik ve Daha Fazlas\u0131<\/h2>\n<p>Web tabanl\u0131 bir medya kayd\u0131nda sesin \u00f6nemi yads\u0131namaz. Kullan\u0131c\u0131n\u0131n bir tuval \u00fczerindeki \u00e7izimlerini veya animasyonlar\u0131n\u0131 sesli bir anlat\u0131mla desteklemesi veya arka plan m\u00fczi\u011fi eklemesi, i\u00e7eri\u011fin etkile\u015fimini ve profesyonelli\u011fini art\u0131r\u0131r. Bu b\u00f6l\u00fcmde, kay\u0131t s\u00fcrecine dahil etmek istedi\u011fimiz farkl\u0131 ses kaynaklar\u0131n\u0131 nas\u0131l yakalay\u0131p haz\u0131rlayaca\u011f\u0131m\u0131z\u0131 detayl\u0131ca inceleyece\u011fiz. Mikrofon giri\u015fi, canl\u0131 bir seslendirme i\u00e7in vazge\u00e7ilmezken, arka plan m\u00fczi\u011fi veya \u00f6nceden kaydedilmi\u015f sesler, i\u00e7eri\u011fi zenginle\u015ftirmek i\u00e7in kullan\u0131labilir.<\/p>\n<h3>Mikrofon Giri\u015fini Yakalama: <code>getUserMedia<\/code> ile Ses Kayd\u0131 Nas\u0131l Al\u0131n\u0131r?<\/h3>\n<p>Canl\u0131 bir seslendirme veya kullan\u0131c\u0131 yorumu eklemek i\u00e7in taray\u0131c\u0131dan mikrofon eri\u015fimi almam\u0131z gerekir. Bu i\u015flem, WebRTC API&#8217;sinin bir par\u00e7as\u0131 olan <code>navigator.mediaDevices.getUserMedia()<\/code> metodu arac\u0131l\u0131\u011f\u0131yla ger\u00e7ekle\u015ftirilir. Bu metod, kullan\u0131c\u0131n\u0131n izniyle, yerel bir medya giri\u015f cihaz\u0131ndan (kamera, mikrofon) bir <code>MediaStream<\/code> yakalamam\u0131z\u0131 sa\u011flar. Mikrofonu yakalamak i\u00e7in <code>getUserMedia()<\/code> metoduna bir k\u0131s\u0131tlama (constraints) nesnesi g\u00f6ndermemiz yeterlidir.<\/p>\n<p>A\u015fa\u011f\u0131daki kod blo\u011fu, kullan\u0131c\u0131n\u0131n mikrofonundan bir ses ak\u0131\u015f\u0131 nas\u0131l al\u0131naca\u011f\u0131n\u0131 g\u00f6stermektedir:<\/p>\n<div class=\"code-container\">\n<pre><code>\nasync function getMicrophoneStream() {\n  try {\n    const stream = await navigator.mediaDevices.getUserMedia({ audio: true, video: false });\n    console.log(\"Mikrofon ak\u0131\u015f\u0131 ba\u015far\u0131yla al\u0131nd\u0131.\");\n    return stream;\n  } catch (err) {\n    console.error(\"Mikrofon eri\u015fimi reddedildi veya bir hata olu\u015ftu:\", err);\n    alert(\"Mikrofon eri\u015fimi i\u00e7in izin vermeniz gerekiyor.\");\n    return null;\n  }\n}\n\n\/\/ Kullan\u0131m \u00f6rne\u011fi:\n\/\/ getMicrophoneStream().then(stream => {\n\/\/   if (stream) {\n\/\/     \/\/ Mikrofon ak\u0131\u015f\u0131n\u0131 kullanmaya ba\u015flayabiliriz\n\/\/     \/\/ \u00d6rne\u011fin, bir AudioContext'e ba\u011flayabiliriz\n\/\/   }\n\/\/ });\n  <\/pre>\n<p><\/code>\n<\/div>\n<p>Bu kodda, <code>getUserMedia({ audio: true, video: false })<\/code> ile yaln\u0131zca ses ak\u0131\u015f\u0131 talep etti\u011fimizi belirtiyoruz. Taray\u0131c\u0131, bu iste\u011fi ald\u0131\u011f\u0131nda kullan\u0131c\u0131ya bir izin penceresi g\u00f6sterir. Kullan\u0131c\u0131 izni verdi\u011finde, bir <code>MediaStream<\/code> nesnesi d\u00f6nd\u00fcr\u00fcl\u00fcr. Bu ak\u0131\u015f, daha sonra di\u011fer ses kaynaklar\u0131yla kar\u0131\u015ft\u0131r\u0131lmak \u00fczere kullan\u0131labilir. Hata durumunda (\u00f6rne\u011fin, kullan\u0131c\u0131 izni reddederse veya mikrofon bulunamazsa), bir hata yakalan\u0131r ve kullan\u0131c\u0131ya bilgi verilir. Bu ad\u0131m, canl\u0131 seslendirme yetene\u011fi eklemek i\u00e7in kritik bir \u00f6neme sahiptir.<\/p>\n<h3>M\u00fczik ve Di\u011fer Sesleri Entegre Etme: <code>HTMLAudioElement<\/code> ve <code>AudioContext<\/code><\/h3>\n<p>Canl\u0131 mikrofon giri\u015fine ek olarak, kayd\u0131m\u0131za arka plan m\u00fczi\u011fi veya \u00f6nceden kaydedilmi\u015f ses efektleri eklemek isteyebiliriz. Bu t\u00fcr ses dosyalar\u0131 genellikle bir <code><audio><\/code> HTML elementi arac\u0131l\u0131\u011f\u0131yla y\u00fcklenir ve oynat\u0131l\u0131r. Ancak, bu sesleri do\u011frudan bir <code>MediaRecorder<\/code>'a besleyemeyiz. Bunun yerine, Web Audio API'nin merkezi bir bile\u015feni olan <code>AudioContext<\/code>'i kullanarak bu sesleri i\u015fleyip di\u011fer ses kaynaklar\u0131yla kar\u0131\u015ft\u0131rmam\u0131z gerekir.<\/p>\n<p><code>AudioContext<\/code>, web \u00fczerinde karma\u015f\u0131k ses i\u015flemlerini ger\u00e7ekle\u015ftirmek i\u00e7in g\u00fc\u00e7l\u00fc bir ara\u00e7t\u0131r. Ses kaynaklar\u0131n\u0131 (<code>AudioNode<\/code>'lar) birbirine ba\u011flayarak bir ses grafi\u011fi olu\u015fturmam\u0131z\u0131 sa\u011flar. Bir <code>HTMLAudioElement<\/code>'ten gelen sesi <code>AudioContext<\/code>'e dahil etmek i\u00e7in <code>createMediaElementSource()<\/code> metodunu kullan\u0131r\u0131z. Bu metod, bir <code>HTMLAudioElement<\/code>'i bir <code>AudioNode<\/code>'a d\u00f6n\u00fc\u015ft\u00fcr\u00fcr, b\u00f6ylece onu ses grafi\u011fimize dahil edebiliriz.<\/p>\n<p>A\u015fa\u011f\u0131daki \u00f6rnek, bir m\u00fczik dosyas\u0131n\u0131 nas\u0131l y\u00fckleyece\u011fimizi ve onu <code>AudioContext<\/code>'e nas\u0131l ba\u011flayaca\u011f\u0131m\u0131z\u0131 g\u00f6stermektedir:<\/p>\n<div class=\"code-container\">\n<pre><code>\nasync function loadAndConnectMusic(audioContext, audioUrl) {\n  const audio = new Audio(audioUrl);\n  audio.loop = true; \/\/ M\u00fczik tekrar etsin\n  audio.volume = 0.3; \/\/ Arka plan m\u00fczi\u011fi i\u00e7in sesi biraz k\u0131sabiliriz\n  await audio.play(); \/\/ M\u00fczik \u00e7almaya ba\u015flas\u0131n\n\n  const source = audioContext.createMediaElementSource(audio);\n  console.log(\"M\u00fczik kayna\u011f\u0131 AudioContext'e ba\u011fland\u0131.\");\n  return source; \/\/ Bu source node'u daha sonra di\u011ferleriyle kar\u0131\u015ft\u0131raca\u011f\u0131z\n}\n\n\/\/ Kullan\u0131m \u00f6rne\u011fi:\n\/\/ const audioContext = new (window.AudioContext || window.webkitAudioContext)();\n\/\/ loadAndConnectMusic(audioContext, 'background_music.mp3').then(musicSourceNode => {\n\/\/   \/\/ musicSourceNode'u di\u011fer ses kaynaklar\u0131yla birle\u015ftirebiliriz\n\/\/ });\n  <\/pre>\n<p><\/code>\n<\/div>\n<p>Bu kodda, \u00f6nce bir <code>HTMLAudioElement<\/code> olu\u015fturup bir m\u00fczik dosyas\u0131n\u0131 y\u00fckl\u00fcyoruz. Ard\u0131ndan, <code>audioContext.createMediaElementSource(audio)<\/code> ile bu ses elementini bir <code>AudioNode<\/code>'a d\u00f6n\u00fc\u015ft\u00fcr\u00fcyoruz. Bu <code>source<\/code> d\u00fc\u011f\u00fcm\u00fc, daha sonra mikrofon ak\u0131\u015f\u0131ndan gelen <code>AudioNode<\/code> ile birle\u015ftirilecek ve tek bir \u00e7\u0131k\u0131\u015f ak\u0131\u015f\u0131 olu\u015fturulacakt\u0131r. Bu yakla\u015f\u0131m, sadece m\u00fczik i\u00e7in de\u011fil, ayn\u0131 zamanda \u00f6nceden kaydedilmi\u015f ses efektleri veya di\u011fer medya dosyalar\u0131ndan gelen sesler i\u00e7in de ge\u00e7erlidir. Bu \u015fekilde, farkl\u0131 ses bile\u015fenlerini ayr\u0131 ayr\u0131 y\u00f6netebilir ve <code>AudioContext<\/code>'in esnekli\u011fi sayesinde bunlar\u0131 istedi\u011fimiz gibi kar\u0131\u015ft\u0131rabiliriz.<\/p>\n<h2>G\u00f6rsel ve \u0130\u015fitsel Senkronizasyonun Anahtar\u0131: <code>AudioContext<\/code> ile Ak\u0131\u015flar\u0131 Birle\u015ftirmek<\/h2>\n<p>Farkl\u0131 ses kaynaklar\u0131n\u0131 (mikrofon, m\u00fczik) yakalad\u0131ktan sonraki en kritik ad\u0131m, bu ses ak\u0131\u015flar\u0131n\u0131 tuvalden gelen video ak\u0131\u015f\u0131yla birle\u015ftirmektir. Hat\u0131rlayaca\u011f\u0131n\u0131z \u00fczere, <code>canvas.captureStream()<\/code> yaln\u0131zca bir video par\u00e7as\u0131 (<code>VideoTrack<\/code>) i\u00e7erir ve ses par\u00e7as\u0131 (<code>AudioTrack<\/code>) sa\u011flamaz. Dolay\u0131s\u0131yla, kayd\u0131m\u0131z\u0131n hem g\u00f6r\u00fcnt\u00fcy\u00fc hem de sesi i\u00e7ermesi i\u00e7in, olu\u015fturdu\u011fumuz ses ak\u0131\u015f\u0131n\u0131 bu video ak\u0131\u015f\u0131na eklememiz gerekmektedir. Bu birle\u015ftirme i\u015flemi, Web Audio API'nin sundu\u011fu <code>AudioContext<\/code> ve <code>MediaStreamAudioDestinationNode<\/code> gibi geli\u015fmi\u015f ara\u00e7lar sayesinde m\u00fcmk\u00fcn olmaktad\u0131r.<\/p>\n<p><code>AudioContext<\/code>, ses i\u015fleme grafikleri olu\u015fturmak i\u00e7in kullan\u0131l\u0131r. Bu grafikte, ses kaynaklar\u0131 (\u00f6rne\u011fin mikrofon veya m\u00fczik) d\u00fc\u011f\u00fcmler (nodes) olarak temsil edilir ve bu d\u00fc\u011f\u00fcmler birbirine ba\u011flanarak ses verisi i\u015flenir. Bizim amac\u0131m\u0131z, birden fazla ses kayna\u011f\u0131n\u0131 tek bir ses ak\u0131\u015f\u0131nda birle\u015ftirmek ve bu birle\u015fik ak\u0131\u015f\u0131 bir <code>MediaStream<\/code> olarak d\u0131\u015far\u0131 aktarmakt\u0131r. \u0130\u015fte burada <code>AudioContext.createMediaStreamDestination()<\/code> metodu devreye girer. Bu metod, bir <code>MediaStreamAudioDestinationNode<\/code> olu\u015fturur ve bu d\u00fc\u011f\u00fcm, kendisine ba\u011fl\u0131 olan t\u00fcm seslerin bir <code>MediaStream<\/code> olarak \u00e7\u0131k\u0131\u015f\u0131n\u0131 sa\u011flar. Bu \u00e7\u0131kan <code>MediaStream<\/code>, tek bir <code>AudioTrack<\/code> i\u00e7erir ve bu par\u00e7ay\u0131 tuvalden gelen video ak\u0131\u015f\u0131na ekleyebiliriz.<\/p>\n<p>A\u015fa\u011f\u0131daki ad\u0131mlar ve kod blo\u011fu, bu birle\u015ftirme s\u00fcrecini detayland\u0131rmaktad\u0131r:<\/p>\n<ol>\n<li><strong><code>AudioContext<\/code> Olu\u015fturma<\/strong>: T\u00fcm ses i\u015flemleri i\u00e7in bir <code>AudioContext<\/code> \u00f6rne\u011fi olu\u015fturulur.<\/li>\n<li><strong>Mikrofon Ak\u0131\u015f\u0131n\u0131 Ba\u011flama<\/strong>: <code>getUserMedia()<\/code> ile elde edilen mikrofon <code>MediaStream<\/code>'i, <code>AudioContext.createMediaStreamSource()<\/code> metodu kullan\u0131larak bir <code>MediaStreamAudioSourceNode<\/code>'a d\u00f6n\u00fc\u015ft\u00fcr\u00fcl\u00fcr.<\/li>\n<li><strong>M\u00fczik Ak\u0131\u015f\u0131n\u0131 Ba\u011flama<\/strong>: <code>HTMLAudioElement<\/code> \u00fczerinden y\u00fcklenen m\u00fczik, <code>AudioContext.createMediaElementSource()<\/code> metodu kullan\u0131larak bir <code>MediaElementAudioSourceNode<\/code>'a d\u00f6n\u00fc\u015ft\u00fcr\u00fcl\u00fcr.<\/li>\n<li><strong>Birle\u015ftirme D\u00fc\u011f\u00fcm\u00fc Olu\u015fturma<\/strong>: T\u00fcm ses kaynaklar\u0131n\u0131 birle\u015ftirece\u011fimiz bir <code>GainNode<\/code> olu\u015fturmak iyi bir uygulamad\u0131r. Bu, her bir ses kayna\u011f\u0131n\u0131n ayr\u0131 ayr\u0131 ses seviyesini kontrol etmemize olanak tan\u0131r.<\/li>\n<li><strong>Hedef Ak\u0131\u015f D\u00fc\u011f\u00fcm\u00fc Olu\u015fturma<\/strong>: <code>AudioContext.createMediaStreamDestination()<\/code> metodu ile bir <code>MediaStreamAudioDestinationNode<\/code> olu\u015fturulur. Bu d\u00fc\u011f\u00fcm, t\u00fcm ba\u011fl\u0131 seslerin \u00e7\u0131k\u0131\u015f\u0131n\u0131 bir <code>MediaStream<\/code> olarak sa\u011flar.<\/li>\n<li><strong>Ses Grafi\u011fini Olu\u015fturma<\/strong>: Mikrofon ve m\u00fczik kaynak d\u00fc\u011f\u00fcmleri (iste\u011fe ba\u011fl\u0131 olarak <code>GainNode<\/code>'lar arac\u0131l\u0131\u011f\u0131yla) birle\u015ftirme d\u00fc\u011f\u00fcm\u00fcne ba\u011flan\u0131r, ard\u0131ndan birle\u015ftirme d\u00fc\u011f\u00fcm\u00fc hedef ak\u0131\u015f d\u00fc\u011f\u00fcm\u00fcne ba\u011flan\u0131r.<\/li>\n<li><strong>Video Ak\u0131\u015f\u0131na Ses Ekleme<\/strong>: Tuvalden gelen <code>MediaStream<\/code>'e (<code>canvasStream<\/code>), hedef ak\u0131\u015f d\u00fc\u011f\u00fcm\u00fcnden (<code>destinationStream<\/code>) gelen ses par\u00e7as\u0131 (<code>destinationStream.stream.getAudioTracks()[0]<\/code>) eklenir.<\/li>\n<\/ol>\n<div class=\"code-container\">\n<pre><code>\nasync function combineStreams(canvasStream, microphoneStream, musicAudioElement) {\n  const audioContext = new (window.AudioContext || window.webkitAudioContext)();\n\n  \/\/ 1. Mikrofon ak\u0131\u015f\u0131n\u0131 AudioContext'e ba\u011fla\n  const microphoneSource = audioContext.createMediaStreamSource(microphoneStream);\n  const microphoneGain = audioContext.createGain();\n  microphoneGain.gain.value = 1.0; \/\/ Mikrofon sesi seviyesi\n  microphoneSource.connect(microphoneGain);\n\n  \/\/ 2. M\u00fczik ak\u0131\u015f\u0131n\u0131 AudioContext'e ba\u011fla\n  const musicSource = audioContext.createMediaElementSource(musicAudioElement);\n  const musicGain = audioContext.createGain();\n  musicGain.gain.value = 0.3; \/\/ M\u00fczik sesi seviyesi, arka planda kalmas\u0131 i\u00e7in k\u0131s\u0131k\n  musicSource.connect(musicGain);\n\n  \/\/ 3. T\u00fcm ses kaynaklar\u0131n\u0131 birle\u015ftirici bir d\u00fc\u011f\u00fcme ba\u011fla (iste\u011fe ba\u011fl\u0131, do\u011frudan da ba\u011flanabilir)\n  const masterGain = audioContext.createGain();\n  microphoneGain.connect(masterGain);\n  musicGain.connect(masterGain);\n\n  \/\/ 4. Birle\u015fik sesi bir MediaStream olarak \u00e7\u0131k\u0131\u015f verecek hedef d\u00fc\u011f\u00fcm\u00fc olu\u015ftur\n  const destination = audioContext.createMediaStreamDestination();\n  masterGain.connect(destination);\n\n  \/\/ 5. Tuvalden gelen video ak\u0131\u015f\u0131na, birle\u015ftirilmi\u015f ses ak\u0131\u015f\u0131n\u0131 ekle\n  const combinedStream = new MediaStream();\n  canvasStream.getVideoTracks().forEach(track => combinedStream.addTrack(track));\n  destination.stream.getAudioTracks().forEach(track => combinedStream.addTrack(track));\n\n  console.log(\"Ses ve video ak\u0131\u015flar\u0131 ba\u015far\u0131yla birle\u015ftirildi.\");\n  return combinedStream;\n}\n\n\/\/ Kullan\u0131m \u00f6rne\u011fi (\u00f6nceki fonksiyonlar\u0131 kullanarak):\n\/\/ const canvas = document.getElementById('myCanvas');\n\/\/ const canvasStream = canvas.captureStream(30); \/\/ 30 FPS\n\/\/\n\/\/ const microphoneStream = await getMicrophoneStream(); \/\/ \u00d6nceki b\u00f6l\u00fcmdeki fonksiyon\n\/\/ const backgroundMusic = new Audio('background_music.mp3');\n\/\/ backgroundMusic.loop = true;\n\/\/ await backgroundMusic.play();\n\/\/\n\/\/ const finalStream = await combineStreams(canvasStream, microphoneStream, backgroundMusic);\n\/\/ \/\/ \u015eimdi finalStream hem videoyu hem de kar\u0131\u015ft\u0131r\u0131lm\u0131\u015f sesi i\u00e7eriyor.\n\/\/ \/\/ Bu ak\u0131\u015f\u0131 MediaRecorder'a verebiliriz.\n  <\/pre>\n<p><\/code>\n<\/div>\n<p>Bu karma\u015f\u0131k g\u00f6r\u00fcnen s\u00fcre\u00e7, asl\u0131nda bir ses grafi\u011fi olu\u015fturarak farkl\u0131 ses kanallar\u0131n\u0131 ayn\u0131 \u00e7\u0131k\u0131\u015fa y\u00f6nlendirme mant\u0131\u011f\u0131na dayan\u0131r. <code>destination.stream<\/code> \u00f6zelli\u011fi bize tek bir <code>MediaStream<\/code> verir ve bu ak\u0131\u015f, mikrofon ve m\u00fczi\u011fin birle\u015fik sesini i\u00e7erir. Bu ses ak\u0131\u015f\u0131n\u0131n <code>AudioTrack<\/code>'ini al\u0131p, <code>canvas.captureStream()<\/code>'den gelen video ak\u0131\u015f\u0131n\u0131n \u00fczerine ekledi\u011fimizde, art\u0131k hem g\u00f6rsel hem de i\u015fitsel i\u00e7eri\u011fi bar\u0131nd\u0131ran eksiksiz bir <code>MediaStream<\/code> elde etmi\u015f oluruz. Bu <code>combinedStream<\/code> art\u0131k <code>MediaRecorder<\/code> taraf\u0131ndan kaydedilmeye haz\u0131rd\u0131r ve b\u00f6ylece istedi\u011fimiz zengin medya i\u00e7eri\u011fini olu\u015fturabiliriz. Senkronizasyon sorunlar\u0131n\u0131 en aza indirmek i\u00e7in, t\u00fcm ses kaynaklar\u0131n\u0131n ve tuvalin m\u00fcmk\u00fcn oldu\u011funca e\u015f zamanl\u0131 ba\u015flat\u0131lmas\u0131 \u00f6nemlidir.<\/p>\n<h2>MediaRecorder ile Kay\u0131t ve D\u0131\u015fa Aktarma: Eksiksiz Bir Video Olu\u015fturma<\/h2>\n<p>\u00d6nceki ad\u0131mlarda, tuvalden gelen video ak\u0131\u015f\u0131 ile mikrofon ve arka plan m\u00fczi\u011finden gelen ses ak\u0131\u015flar\u0131n\u0131 ba\u015far\u0131yla birle\u015ftirdik ve tek bir <code>MediaStream<\/code> elde ettik. Art\u0131k bu birle\u015fik ak\u0131\u015f\u0131 al\u0131p, onu taray\u0131c\u0131da bir medya dosyas\u0131 olarak kaydetme ve kullan\u0131c\u0131n\u0131n indirmesi i\u00e7in sunma a\u015famas\u0131na ge\u00e7ebiliriz. Bu i\u015flem i\u00e7in Web API'sinin g\u00fc\u00e7l\u00fc bir bile\u015feni olan <code>MediaRecorder<\/code>'\u0131 kullanaca\u011f\u0131z. <code>MediaRecorder<\/code>, bir <code>MediaStream<\/code>'i belirli bir formatta (\u00f6rne\u011fin WebM, MP4) kaydetmek ve elde edilen veriyi <code>Blob<\/code>'lar halinde d\u0131\u015fa aktarmak i\u00e7in tasarlanm\u0131\u015ft\u0131r.<\/p>\n<h3>Birle\u015ftirilmi\u015f Ak\u0131\u015f\u0131 <code>MediaRecorder<\/code>'a Besleme<\/h3>\n<p><code>MediaRecorder<\/code> nesnesi, kaydedilecek <code>MediaStream<\/code>'i ve iste\u011fe ba\u011fl\u0131 olarak kay\u0131t format\u0131n\u0131 (MIME t\u00fcr\u00fc) belirten bir se\u00e7enekler nesnesini parametre olarak al\u0131r. Birle\u015ftirilmi\u015f ak\u0131\u015f\u0131m\u0131z (<code>combinedStream<\/code>) art\u0131k hem video hem de ses par\u00e7alar\u0131n\u0131 i\u00e7erdi\u011fi i\u00e7in, <code>MediaRecorder<\/code> bu ak\u0131\u015f\u0131 eksiksiz bir \u015fekilde kaydedebilir. MIME t\u00fcr\u00fcn\u00fc belirtmek, taray\u0131c\u0131n\u0131n destekledi\u011fi en iyi format\u0131 se\u00e7mesine yard\u0131mc\u0131 olur ve \u00e7\u0131kt\u0131 dosyas\u0131n\u0131n uyumlulu\u011funu art\u0131r\u0131r.<\/p>\n<p>Yayg\u0131n olarak kullan\u0131lan bir format olan WebM, genellikle taray\u0131c\u0131larda iyi desteklenir ve hem video hem de ses i\u00e7in verimli s\u0131k\u0131\u015ft\u0131rma sa\u011flar. MP4 de pop\u00fcler bir se\u00e7enektir ancak taray\u0131c\u0131 deste\u011fi ve codec se\u00e7imleri konusunda baz\u0131 farkl\u0131l\u0131klar g\u00f6sterebilir.<\/p>\n<div class=\"code-container\">\n<pre><code>\nlet mediaRecorder;\nconst recordedChunks = [];\n\nasync function startRecording(combinedStream) {\n  try {\n    \/\/ Taray\u0131c\u0131n\u0131n destekledi\u011fi en iyi MIME t\u00fcr\u00fcn\u00fc kontrol et\n    const options = { mimeType: 'video\/webm; codecs=vp9,opus' };\n    if (!MediaRecorder.isTypeSupported(options.mimeType)) {\n      console.warn(<code>${options.mimeType} desteklenmiyor, varsay\u0131lan\u0131 deniyorum.<\/code>);\n      options.mimeType = 'video\/webm'; \/\/ Daha genel bir WebM codec'i\n      if (!MediaRecorder.isTypeSupported(options.mimeType)) {\n        console.warn(<code>${options.mimeType} de desteklenmiyor.<\/code>);\n        \/\/ Fallback olarak taray\u0131c\u0131n\u0131n varsay\u0131lan\u0131n\u0131 kullan\n        delete options.mimeType;\n      }\n    }\n\n    mediaRecorder = new MediaRecorder(combinedStream, options);\n\n    mediaRecorder.ondataavailable = (event) => {\n      if (event.data.size > 0) {\n        recordedChunks.push(event.data);\n      }\n    };\n\n    mediaRecorder.onstop = () => {\n      console.log(\"Kay\u0131t durduruldu, veriler haz\u0131r.\");\n      downloadRecording();\n    };\n\n    mediaRecorder.start();\n    console.log(\"Kay\u0131t ba\u015flad\u0131...\");\n    \/\/ Belirli aral\u0131klarla veri toplamak i\u00e7in: mediaRecorder.start(1000); \/\/ Her 1 saniyede bir dataavailable olay\u0131n\u0131 tetikler\n  } catch (error) {\n    console.error(\"Kay\u0131t ba\u015flat\u0131l\u0131rken bir hata olu\u015ftu:\", error);\n    alert(\"Kay\u0131t ba\u015flat\u0131lamad\u0131: \" + error.message);\n  }\n}\n  <\/pre>\n<p><\/code>\n<\/div>\n<p>Bu kod blo\u011funda, <code>MediaRecorder<\/code> nesnesini olu\u015ftururken, <code>combinedStream<\/code>'i ve bir MIME t\u00fcr\u00fcn\u00fc (<code>video\/webm; codecs=vp9,opus<\/code>) sa\u011fl\u0131yoruz. <code>ondataavailable<\/code> olay\u0131, kay\u0131t s\u0131ras\u0131nda belirli aral\u0131klarla veya kay\u0131t durduruldu\u011funda (varsay\u0131lan olarak) tetiklenir ve kaydedilen medya verilerini <code>Blob<\/code> par\u00e7alar\u0131 halinde sa\u011flar. Bu par\u00e7alar\u0131 bir dizide toplar\u0131z. <code>onstop<\/code> olay\u0131 ise kay\u0131t tamamen durduruldu\u011funda tetiklenir ve bu noktada toplanan t\u00fcm <code>Blob<\/code> par\u00e7alar\u0131n\u0131 birle\u015ftirip indirme i\u015flemini ba\u015flat\u0131r\u0131z.<\/p>\n<h3>Kay\u0131t \u0130\u015flemi ve Veri Y\u00f6netimi: Blob'lar ve \u0130ndirme<\/h3>\n<p>Kay\u0131t tamamland\u0131\u011f\u0131nda, <code>recordedChunks<\/code> dizisinde toplanan t\u00fcm <code>Blob<\/code> par\u00e7alar\u0131n\u0131 tek bir b\u00fcy\u00fck <code>Blob<\/code> nesnesinde birle\u015ftirmemiz gerekir. Bu b\u00fcy\u00fck <code>Blob<\/code>, kaydedilen medya dosyas\u0131n\u0131 temsil eder. Ard\u0131ndan, bu <code>Blob<\/code>'u bir URL'ye d\u00f6n\u00fc\u015ft\u00fcrerek kullan\u0131c\u0131ya indirme ba\u011flant\u0131s\u0131 sa\u011flayabiliriz.<\/p>\n<div class=\"code-container\">\n<pre><code>\nfunction stopRecording() {\n  if (mediaRecorder && mediaRecorder.state !== 'inactive') {\n    mediaRecorder.stop();\n    console.log(\"Kay\u0131t durdurma iste\u011fi g\u00f6nderildi.\");\n  }\n}\n\nfunction downloadRecording() {\n  if (recordedChunks.length === 0) {\n    console.warn(\"Kaydedilmi\u015f veri bulunmuyor.\");\n    return;\n  }\n\n  const blob = new Blob(recordedChunks, { type: mediaRecorder.mimeType });\n  const url = URL.createObjectURL(blob);\n  const a = document.createElement('a');\n  document.body.appendChild(a);\n  a.style.display = 'none';\n  a.href = url;\n  a.download = <code>kayit_${new Date().toISOString().slice(0, 19).replace(\/:\/g, '-')}.webm<\/code>;\n  a.click();\n  window.URL.revokeObjectURL(url); \/\/ Belle\u011fi serbest b\u0131rak\n  recordedChunks.length = 0; \/\/ Bir sonraki kay\u0131t i\u00e7in diziyi temizle\n  console.log(\"Kay\u0131t dosyas\u0131 indirilmeye haz\u0131rland\u0131.\");\n}\n\n\/\/ \u00d6rnek kullan\u0131m:\n\/\/ document.getElementById('startButton').addEventListener('click', async () => {\n\/\/   const canvas = document.getElementById('myCanvas');\n\/\/   const canvasStream = canvas.captureStream(30);\n\/\/\n\/\/   const microphoneStream = await getMicrophoneStream();\n\/\/   const backgroundMusic = new Audio('background_music.mp3');\n\/\/   backgroundMusic.loop = true;\n\/\/   await backgroundMusic.play();\n\/\/\n\/\/   const finalStream = await combineStreams(canvasStream, microphoneStream, backgroundMusic);\n\/\/   startRecording(finalStream);\n\/\/ });\n\/\/\n\/\/ document.getElementById('stopButton').addEventListener('click', () => {\n\/\/   stopRecording();\n\/\/ });\n  <\/pre>\n<p><\/code>\n<\/div>\n<p><code>stopRecording()<\/code> fonksiyonu, <code>mediaRecorder.stop()<\/code> \u00e7a\u011fr\u0131s\u0131n\u0131 yaparak kayd\u0131 sonland\u0131r\u0131r. Bu, <code>onstop<\/code> olay\u0131n\u0131n tetiklenmesine ve <code>downloadRecording()<\/code> fonksiyonunun \u00e7al\u0131\u015fmas\u0131na yol a\u00e7ar. <code>downloadRecording()<\/code> fonksiyonu ise toplanan <code>Blob<\/code>'lar\u0131 birle\u015ftirerek bir indirme ba\u011flant\u0131s\u0131 olu\u015fturur ve sanal olarak t\u0131klar. <code>URL.createObjectURL()<\/code> ile olu\u015fturulan URL'lerin, bellek s\u0131z\u0131nt\u0131lar\u0131n\u0131 \u00f6nlemek i\u00e7in <code>URL.revokeObjectURL()<\/code> ile serbest b\u0131rak\u0131lmas\u0131 \u00f6nemlidir. Bu ad\u0131mlar tamamland\u0131\u011f\u0131nda, kullan\u0131c\u0131n\u0131n tuval \u00fczerindeki g\u00f6rsel etkile\u015fimlerini, sesli anlat\u0131m\u0131n\u0131 ve arka plan m\u00fczi\u011fini i\u00e7eren eksiksiz bir medya dosyas\u0131 ba\u015far\u0131yla olu\u015fturulmu\u015f ve indirilmeye haz\u0131r hale getirilmi\u015f olur. Bu s\u00fcre\u00e7, web tabanl\u0131 medya \u00fcretim ara\u00e7lar\u0131n\u0131n temelini olu\u015fturur ve geli\u015ftiricilere zengin i\u00e7erikler olu\u015fturma konusunda b\u00fcy\u00fck esneklik sa\u011flar.<\/p>\n<h2>Geli\u015fmi\u015f Teknikler ve Optimizasyonlar: Performans ve Kullan\u0131c\u0131 Deneyimi<\/h2>\n<p>Yukar\u0131da a\u00e7\u0131klanan temel ad\u0131mlar, tuvalden gelen video ak\u0131\u015f\u0131na ses ve m\u00fczik ekleyerek bir medya dosyas\u0131 olu\u015fturmak i\u00e7in yeterlidir. Ancak, ger\u00e7ek d\u00fcnya uygulamalar\u0131nda daha iyi bir kullan\u0131c\u0131 deneyimi ve performans sa\u011flamak i\u00e7in baz\u0131 geli\u015fmi\u015f teknikler ve optimizasyonlar uygulamak gerekebilir. Bu b\u00f6l\u00fcmde, ses gecikmesi, senkronizasyon, dinamik ses y\u00f6netimi ve taray\u0131c\u0131 uyumlulu\u011fu gibi konulara odaklanarak uygulaman\u0131z\u0131 daha sa\u011flam ve kullan\u0131c\u0131 dostu hale getirme yollar\u0131n\u0131 inceleyece\u011fiz.<\/p>\n<h3>Ses Gecikmesi ve Senkronizasyon Sorunlar\u0131 Nas\u0131l Giderilir?<\/h3>\n<p>Medya ak\u0131\u015flar\u0131yla \u00e7al\u0131\u015f\u0131rken kar\u015f\u0131la\u015f\u0131lan en yayg\u0131n sorunlardan biri, ses ve video aras\u0131ndaki senkronizasyon gecikmeleridir. \u00d6zellikle canl\u0131 mikrofon giri\u015fi kullan\u0131l\u0131rken, sesin vide<\/p>\n","protected":false},"excerpt":{"rendered":"Web geli\u015ftiricileri i\u00e7in taray\u0131c\u0131 tabanl\u0131 medya i\u015fleme, son y\u0131llarda b\u00fcy\u00fck bir ivme kazand\u0131.","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"csco_page_header_type":"","csco_page_load_nextpost":"","csco_page_subscribe_form":"","csco_page_contact_form":"","footnotes":""},"categories":[1],"tags":[],"class_list":{"0":"post-41694","1":"post","2":"type-post","3":"status-publish","4":"format-standard","6":"category-genel","7":"cs-entry","8":"cs-video-wrap"},"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v20.5 (Yoast SEO v25.3.1) - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Canvas Ak\u0131\u015f\u0131na Ses ve M\u00fczik Entegre Etmek: MediaRecorder \u0130hracat\u0131nda Eksiksiz Bir Yakla\u015f\u0131m - Kodlar\u0131n Gizemli D\u00fcnyas\u0131<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/fatihsoysal.com\/blog\/canvas-akisina-ses-ve-muzik-entegre-etmek-mediarecorder-ihracatinda-eksiksiz-bir-yaklasim\/\" \/>\n<meta property=\"og:locale\" content=\"tr_TR\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Canvas Ak\u0131\u015f\u0131na Ses ve M\u00fczik Entegre Etmek: MediaRecorder \u0130hracat\u0131nda Eksiksiz Bir Yakla\u015f\u0131m\" \/>\n<meta property=\"og:description\" content=\"Web geli\u015ftiricileri i\u00e7in taray\u0131c\u0131 tabanl\u0131 medya i\u015fleme, son y\u0131llarda b\u00fcy\u00fck bir ivme kazand\u0131.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/fatihsoysal.com\/blog\/canvas-akisina-ses-ve-muzik-entegre-etmek-mediarecorder-ihracatinda-eksiksiz-bir-yaklasim\/\" \/>\n<meta property=\"og:site_name\" content=\"Kodlar\u0131n Gizemli D\u00fcnyas\u0131\" \/>\n<meta property=\"article:published_time\" content=\"2026-05-10T18:03:17+00:00\" \/>\n<meta name=\"author\" content=\"Fatih Soysal\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Yazan:\" \/>\n\t<meta name=\"twitter:data1\" content=\"Fatih Soysal\" \/>\n\t<meta name=\"twitter:label2\" content=\"Tahmini okuma s\u00fcresi\" \/>\n\t<meta name=\"twitter:data2\" content=\"16 dakika\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/canvas-akisina-ses-ve-muzik-entegre-etmek-mediarecorder-ihracatinda-eksiksiz-bir-yaklasim\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/canvas-akisina-ses-ve-muzik-entegre-etmek-mediarecorder-ihracatinda-eksiksiz-bir-yaklasim\/\"},\"author\":{\"name\":\"Fatih Soysal\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1\"},\"headline\":\"Canvas Ak\u0131\u015f\u0131na Ses ve M\u00fczik Entegre Etmek: MediaRecorder \u0130hracat\u0131nda Eksiksiz Bir Yakla\u015f\u0131m\",\"datePublished\":\"2026-05-10T18:03:17+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/canvas-akisina-ses-ve-muzik-entegre-etmek-mediarecorder-ihracatinda-eksiksiz-bir-yaklasim\/\"},\"wordCount\":2351,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1\"},\"inLanguage\":\"tr\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/fatihsoysal.com\/blog\/canvas-akisina-ses-ve-muzik-entegre-etmek-mediarecorder-ihracatinda-eksiksiz-bir-yaklasim\/#respond\"]}],\"copyrightYear\":\"2026\",\"copyrightHolder\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#organization\"}},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/canvas-akisina-ses-ve-muzik-entegre-etmek-mediarecorder-ihracatinda-eksiksiz-bir-yaklasim\/\",\"url\":\"https:\/\/fatihsoysal.com\/blog\/canvas-akisina-ses-ve-muzik-entegre-etmek-mediarecorder-ihracatinda-eksiksiz-bir-yaklasim\/\",\"name\":\"Canvas Ak\u0131\u015f\u0131na Ses ve M\u00fczik Entegre Etmek: MediaRecorder \u0130hracat\u0131nda Eksiksiz Bir Yakla\u015f\u0131m - Kodlar\u0131n Gizemli D\u00fcnyas\u0131\",\"isPartOf\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#website\"},\"datePublished\":\"2026-05-10T18:03:17+00:00\",\"breadcrumb\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/canvas-akisina-ses-ve-muzik-entegre-etmek-mediarecorder-ihracatinda-eksiksiz-bir-yaklasim\/#breadcrumb\"},\"inLanguage\":\"tr\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/fatihsoysal.com\/blog\/canvas-akisina-ses-ve-muzik-entegre-etmek-mediarecorder-ihracatinda-eksiksiz-bir-yaklasim\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/canvas-akisina-ses-ve-muzik-entegre-etmek-mediarecorder-ihracatinda-eksiksiz-bir-yaklasim\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Anasayfa\",\"item\":\"https:\/\/fatihsoysal.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Canvas Ak\u0131\u015f\u0131na Ses ve M\u00fczik Entegre Etmek: MediaRecorder \u0130hracat\u0131nda Eksiksiz Bir Yakla\u015f\u0131m\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#website\",\"url\":\"https:\/\/fatihsoysal.com\/blog\/\",\"name\":\"Fatihsoysal.com\",\"description\":\"Blog - Yaz\u0131l\u0131m D\u00fcnyas\u0131 Tecr\u00fcbelerim\",\"publisher\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/fatihsoysal.com\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"tr\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1\",\"name\":\"Fatih Soysal\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"tr\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/fatihsoysal.com\/blog\/wp-content\/uploads\/2024\/04\/cropped-replicate-prediction-3kgg1hgjn5rgp0cf0p5tr0jw7w-1.png\",\"contentUrl\":\"https:\/\/fatihsoysal.com\/blog\/wp-content\/uploads\/2024\/04\/cropped-replicate-prediction-3kgg1hgjn5rgp0cf0p5tr0jw7w-1.png\",\"width\":512,\"height\":512,\"caption\":\"Fatih Soysal\"},\"logo\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/image\/\"},\"description\":\"Kullan\u0131m ve kodlama m\u00fckemmeliyetini odak alan uygulamalar olu\u015fturma deneyimine sahip, profesyonel olarak 15+ y\u0131l \u00fczeri deneyime sahip bir yaz\u0131l\u0131m m\u00fchendisi.\",\"url\":\"https:\/\/fatihsoysal.com\/blog\/author\/fatihsoysal\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Canvas Ak\u0131\u015f\u0131na Ses ve M\u00fczik Entegre Etmek: MediaRecorder \u0130hracat\u0131nda Eksiksiz Bir Yakla\u015f\u0131m - Kodlar\u0131n Gizemli D\u00fcnyas\u0131","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/fatihsoysal.com\/blog\/canvas-akisina-ses-ve-muzik-entegre-etmek-mediarecorder-ihracatinda-eksiksiz-bir-yaklasim\/","og_locale":"tr_TR","og_type":"article","og_title":"Canvas Ak\u0131\u015f\u0131na Ses ve M\u00fczik Entegre Etmek: MediaRecorder \u0130hracat\u0131nda Eksiksiz Bir Yakla\u015f\u0131m","og_description":"Web geli\u015ftiricileri i\u00e7in taray\u0131c\u0131 tabanl\u0131 medya i\u015fleme, son y\u0131llarda b\u00fcy\u00fck bir ivme kazand\u0131.","og_url":"https:\/\/fatihsoysal.com\/blog\/canvas-akisina-ses-ve-muzik-entegre-etmek-mediarecorder-ihracatinda-eksiksiz-bir-yaklasim\/","og_site_name":"Kodlar\u0131n Gizemli D\u00fcnyas\u0131","article_published_time":"2026-05-10T18:03:17+00:00","author":"Fatih Soysal","twitter_card":"summary_large_image","twitter_misc":{"Yazan:":"Fatih Soysal","Tahmini okuma s\u00fcresi":"16 dakika"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/fatihsoysal.com\/blog\/canvas-akisina-ses-ve-muzik-entegre-etmek-mediarecorder-ihracatinda-eksiksiz-bir-yaklasim\/#article","isPartOf":{"@id":"https:\/\/fatihsoysal.com\/blog\/canvas-akisina-ses-ve-muzik-entegre-etmek-mediarecorder-ihracatinda-eksiksiz-bir-yaklasim\/"},"author":{"name":"Fatih Soysal","@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1"},"headline":"Canvas Ak\u0131\u015f\u0131na Ses ve M\u00fczik Entegre Etmek: MediaRecorder \u0130hracat\u0131nda Eksiksiz Bir Yakla\u015f\u0131m","datePublished":"2026-05-10T18:03:17+00:00","mainEntityOfPage":{"@id":"https:\/\/fatihsoysal.com\/blog\/canvas-akisina-ses-ve-muzik-entegre-etmek-mediarecorder-ihracatinda-eksiksiz-bir-yaklasim\/"},"wordCount":2351,"commentCount":0,"publisher":{"@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1"},"inLanguage":"tr","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/fatihsoysal.com\/blog\/canvas-akisina-ses-ve-muzik-entegre-etmek-mediarecorder-ihracatinda-eksiksiz-bir-yaklasim\/#respond"]}],"copyrightYear":"2026","copyrightHolder":{"@id":"https:\/\/fatihsoysal.com\/blog\/#organization"}},{"@type":"WebPage","@id":"https:\/\/fatihsoysal.com\/blog\/canvas-akisina-ses-ve-muzik-entegre-etmek-mediarecorder-ihracatinda-eksiksiz-bir-yaklasim\/","url":"https:\/\/fatihsoysal.com\/blog\/canvas-akisina-ses-ve-muzik-entegre-etmek-mediarecorder-ihracatinda-eksiksiz-bir-yaklasim\/","name":"Canvas Ak\u0131\u015f\u0131na Ses ve M\u00fczik Entegre Etmek: MediaRecorder \u0130hracat\u0131nda Eksiksiz Bir Yakla\u015f\u0131m - Kodlar\u0131n Gizemli D\u00fcnyas\u0131","isPartOf":{"@id":"https:\/\/fatihsoysal.com\/blog\/#website"},"datePublished":"2026-05-10T18:03:17+00:00","breadcrumb":{"@id":"https:\/\/fatihsoysal.com\/blog\/canvas-akisina-ses-ve-muzik-entegre-etmek-mediarecorder-ihracatinda-eksiksiz-bir-yaklasim\/#breadcrumb"},"inLanguage":"tr","potentialAction":[{"@type":"ReadAction","target":["https:\/\/fatihsoysal.com\/blog\/canvas-akisina-ses-ve-muzik-entegre-etmek-mediarecorder-ihracatinda-eksiksiz-bir-yaklasim\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/fatihsoysal.com\/blog\/canvas-akisina-ses-ve-muzik-entegre-etmek-mediarecorder-ihracatinda-eksiksiz-bir-yaklasim\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Anasayfa","item":"https:\/\/fatihsoysal.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Canvas Ak\u0131\u015f\u0131na Ses ve M\u00fczik Entegre Etmek: MediaRecorder \u0130hracat\u0131nda Eksiksiz Bir Yakla\u015f\u0131m"}]},{"@type":"WebSite","@id":"https:\/\/fatihsoysal.com\/blog\/#website","url":"https:\/\/fatihsoysal.com\/blog\/","name":"Fatihsoysal.com","description":"Blog - Yaz\u0131l\u0131m D\u00fcnyas\u0131 Tecr\u00fcbelerim","publisher":{"@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/fatihsoysal.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"tr"},{"@type":["Person","Organization"],"@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1","name":"Fatih Soysal","image":{"@type":"ImageObject","inLanguage":"tr","@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/image\/","url":"https:\/\/fatihsoysal.com\/blog\/wp-content\/uploads\/2024\/04\/cropped-replicate-prediction-3kgg1hgjn5rgp0cf0p5tr0jw7w-1.png","contentUrl":"https:\/\/fatihsoysal.com\/blog\/wp-content\/uploads\/2024\/04\/cropped-replicate-prediction-3kgg1hgjn5rgp0cf0p5tr0jw7w-1.png","width":512,"height":512,"caption":"Fatih Soysal"},"logo":{"@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/image\/"},"description":"Kullan\u0131m ve kodlama m\u00fckemmeliyetini odak alan uygulamalar olu\u015fturma deneyimine sahip, profesyonel olarak 15+ y\u0131l \u00fczeri deneyime sahip bir yaz\u0131l\u0131m m\u00fchendisi.","url":"https:\/\/fatihsoysal.com\/blog\/author\/fatihsoysal\/"}]}},"yoast_meta":{"yoast_wpseo_title":"","yoast_wpseo_metadesc":"","yoast_wpseo_canonical":""},"amp_enabled":true,"_links":{"self":[{"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/posts\/41694","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/comments?post=41694"}],"version-history":[{"count":0,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/posts\/41694\/revisions"}],"wp:attachment":[{"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/media?parent=41694"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/categories?post=41694"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/tags?post=41694"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}