? Okuma Hesaplanıyor... Okuma: %0
0

MyBB İçin Ücretsiz Konu Seslendirme (Text-to-Speech) Modifikasyonu Nasıl Yapılır?

WordPress, XenForo veya vBulletin gibi popüler içerik yönetim sistemlerinde sıklıkla karşılaştığımız "Bu konuyu/mesajı dinle" özelliği, kullanıcı deneyimini ve erişilebilirliği artıran son derece pratik bir fonksiyondur.

Harici yapay zeka seslendirme servislerinin yüksek abonelik ve API maliyetleri göz önüne alındığında, bu tür bir özelliği bütçesiz şekilde çözmek oldukça avantajlıdır. Bu rehberde, tarayıcıların yerel Web Speech API teknolojisini kullanarak MyBB forum sitenize özel, tamamen ücretsiz ve responsive (mobil uyumlu) bir Konu Seslendirme Modifikasyonu entegre etmeyi adım adım inceleyeceğiz.

Modifikasyonun Öne Çıkan Özellikleri
Sıfır Maliyet: Üçüncü taraf ücretli AI servislerine ihtiyaç duymadan doğrudan kullanıcının tarayıcı ses motorunu kullanır.
Akıllı Metin Temizleme: Alıntıları (blockquote), kod bloklarını, imzaları, butonları ve görselleri atlayarak yalnızca asıl mesaj metnini seslendirir.
Türkçe Desteği: Sistemde yüklü olan tr-TR dil paketlerini önceliklendirir.
Kontrol Paneli: Oynat, duraklat, durdur ve okuma hızı (0.75x - 2x) seçenekleri sunar.
Mobil Uyumlu: CSS flex yapısı sayesinde tüm cihazlarda sorunsuz görünür.

Önemli UyarıDüzenlemeye başlamadan önce üzerinde değişiklik yapacağınız şablonların ve temanızın yedeğini almayı unutmayın.


Adım Adım Kurulum Rehberi

Adım 1: CSS Stil Dosyasının Oluşturulması
İlk olarak oynatıcı panelinin tasarımını ve mobil uyumluluğunu sağlayacak CSS kodlarını ekliyoruz.
  • Admin KP Sağ ok Temalar ve Şablonlar yolunu izleyin.
  • Kullandığınız temayı açıp CSS Oluştur butonuna tıklayın.
  • Form alanlarını aşağıdaki gibi doldurun:
  • Stil Adı: seslioku.css
  • İlişkilendirilen: Genel Stil (Kendi içeriğimi yazmak istiyorum)
  • Aşağıdaki kodları yapıştırıp kaydedin:

Kod:
.tts-player {
    margin: 15px 0;
    padding: 14px;
    background: #f5f5f5;
    border: 1px solid #d7d7d7;
    border-radius: 6px;
    font-family: Arial, Helvetica, sans-serif;
}

.tts-title {
    font-size: 17px;
    font-weight: bold;
    margin-bottom: 10px;
    color: #333;
}

.tts-controls {
    display: flex;
    flex-wrap: wrap;
    gap: 7px;
    margin-bottom: 10px;
}

.tts-button {
    border: 1px solid #cfcfcf;
    background: #ffffff;
    color: #333;
    padding: 8px 13px;
    border-radius: 4px;
    cursor: pointer;
    font-size: 13px;
    transition: all 0.2s ease;
}

.tts-button:hover:not(:disabled) {
    background: #eeeeee;
}

.tts-button:disabled {
    opacity: 0.5;
    cursor: not-allowed;
}

.tts-settings {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-top: 5px;
    font-size: 13px;
}

#tts-speed {
    padding: 5px 7px;
    border: 1px solid #ccc;
    border-radius: 4px;
    background: #fff;
}

.tts-status {
    margin-top: 10px;
    font-size: 12px;
    color: #666;
}

/* Mobil görünüm uyumluluğu */
@media (max-width: 600px) {
    .tts-player {
        padding: 12px;
    }

    .tts-controls {
        width: 100%;
    }

    .tts-button {
        flex: 1;
        min-width: 80px;
        padding: 9px 6px;
    }

    .tts-settings {
        margin-top: 10px;
    }
}

Adım 2: Postbit Şablonlarının Etiketlenmesi
Seslendirilecek mesajların JavaScript tarafından tespit edilebilmesi için mesaj alanını özel bir sınıfla kapsıyoruz. Yani "Hasan 11.08.2026 tarihinde saat 12.30 da yazdı" gibi mesaj dışı kalıplar okunacak metin kapsamı dışında tutuluyor.

  1. Admin KP Sağ ok Temalar ve Şablonlar Sağ ok Şablonlar sekmesine gidin.
  2. Kullandığınız temanın şablon grubunu genişletin ve Postbit Şablonları grubu altındaki postbit ile postbit_classic şablonlarını açın.
  3. Aşağıdaki kodu bulun:
Kod:
{$post['message']}

Şununla değiştirin ve kaydedin:
Kod:
<div class="tts-post-content">
    {$post['message']}
</div>

Adım 3: JavaScript Seslendirme Mantığının Eklenmesi
Sistemdeki mesajları ayıran, gereksiz HTML elementlerini temizleyen ve seslendirmeyi yöneten ana script kodunu konunun gösterildiği sayfaya ekliyoruz.

  1. Admin KP Sağ ok Şablonlar Sağ ok Konu Gösterim Şablonları bölümünden showthread şablonunu açın.
  2. Sayfanın uygun bir yerine (tercihen sayfa sonundaki kodların üzerine) aşağıdaki JavaScript bloğunu ekleyin:
Kod:
<script type="text/javascript">
(function() {
    "use strict";

    /* =====================================================
       MYBB KONU SESLENDİRME MANTIĞI
       ===================================================== */

    if (!("speechSynthesis" in window)) {
        var unsupported = document.getElementById("tts-status");
        if (unsupported) {
            unsupported.textContent = "Tarayıcınız seslendirme özelliğini desteklemiyor.";
        }
        return;
    }

    var synth = window.speechSynthesis;
    var playButton = document.getElementById("tts-play");
    var pauseButton = document.getElementById("tts-pause");
    var stopButton = document.getElementById("tts-stop");
    var speedSelect = document.getElementById("tts-speed");
    var statusBox = document.getElementById("tts-status");

    var speechParts = [];
    var currentPart = 0;
    var stopped = true;
    var currentUtterance = null;

    function setStatus(message) {
        if (statusBox) {
            statusBox.textContent = message;
        }
    }

    function getTurkishVoice() {
        var voices = synth.getVoices();
        if (!voices || voices.length === 0) return null;

        var preferred = ["tr-TR", "tr"];

        for (var p = 0; p < preferred.length; p++) {
            for (var i = 0; i < voices.length; i++) {
                var lang = (voices[i].lang || "").toLowerCase();
                if (lang === preferred[p].toLowerCase()) {
                    return voices[i];
                }
            }
        }

        for (var j = 0; j < voices.length; j++) {
            var language = (voices[j].lang || "").toLowerCase();
            if (language.indexOf("tr") === 0) {
                return voices[j];
            }
        }

        return null;
    }

    function getPostContents() {
        var posts = document.querySelectorAll(".tts-post-content");
        var contents = [];

        posts.forEach(function(post) {
            var clone = post.cloneNode(true);

            // Okunması istenmeyen elementlerin temizlenmesi
            var removeSelectors = [
                "blockquote", ".codeblock", ".signature",
                ".post_controls", ".postbit_controls", ".post_buttons",
                "script", "style", "iframe", "button", "input",
                "textarea", "select", "img"
            ];

            removeSelectors.forEach(function(selector) {
                clone.querySelectorAll(selector).forEach(function(element) {
                    element.remove();
                });
            });

            clone.querySelectorAll('[class*="elfsight"]').forEach(function(element) {
                element.remove();
            });

            var text = clone.innerText || clone.textContent || "";
            text = text.replace(/\u00a0/g, " ").replace(/\s+/g, " ").trim();

            if (text.length > 0) {
                contents.push(text);
            }
        });

        return contents;
    }

    function createSpeechParts() {
        var contents = getPostContents();
        speechParts = [];

        contents.forEach(function(text) {
            var sentences = text.match(/[^.!?]+[.!?]+|[^.!?]+$/g);
            if (!sentences) sentences = [text];

            var chunk = "";

            sentences.forEach(function(sentence) {
                sentence = sentence.trim();
                if (!sentence) return;

                if (chunk.length > 0 && chunk.length + sentence.length > 220) {
                    speechParts.push(chunk);
                    chunk = sentence;
                } else {
                    if (chunk.length > 0) chunk += " ";
                    chunk += sentence;
                }
            });

            if (chunk.length > 0) {
                speechParts.push(chunk);
            }
        });
    }

    function speakCurrentPart() {
        if (stopped) return;

        if (currentPart >= speechParts.length) {
            setStatus("Konu tamamlandı.");
            playButton.disabled = false;
            pauseButton.disabled = true;
            stopButton.disabled = true;
            currentPart = 0;
            stopped = true;
            return;
        }

        var text = speechParts[currentPart];
        currentUtterance = new SpeechSynthesisUtterance(text);
        currentUtterance.lang = "tr-TR";
        currentUtterance.rate = parseFloat(speedSelect.value);
        currentUtterance.pitch = 1;
        currentUtterance.volume = 1;

        var voice = getTurkishVoice();
        if (voice) {
            currentUtterance.voice = voice;
        }

        setStatus("Okunuyor... Bölüm " + (currentPart + 1) + " / " + speechParts.length);

        currentUtterance.onend = function() {
            if (!stopped) {
                currentPart++;
                setTimeout(speakCurrentPart, 80);
            }
        };

        currentUtterance.onerror = function(event) {
            if (stopped) return;
            console.log("TTS hatası:", event);
            setStatus("Seslendirme sırasında bir hata oluştu.");
            playButton.disabled = false;
            pauseButton.disabled = true;
            stopButton.disabled = false;
        };

        synth.speak(currentUtterance);
    }

    playButton.addEventListener("click", function() {
        if (speechParts.length === 0) {
            createSpeechParts();
            if (speechParts.length === 0) {
                setStatus("Okunabilecek bir konu içeriği bulunamadı.");
                return;
            }
        }

        if (synth.paused) {
            synth.resume();
            stopped = false;
            setStatus("Okuma devam ediyor...");
            playButton.disabled = true;
            pauseButton.disabled = false;
            stopButton.disabled = false;
            return;
        }

        if (!synth.speaking) {
            stopped = false;
            playButton.disabled = true;
            pauseButton.disabled = false;
            stopButton.disabled = false;
            speakCurrentPart();
        }
    });

    pauseButton.addEventListener("click", function() {
        if (synth.speaking && !synth.paused) {
            synth.pause();
            setStatus("⏸ Okuma duraklatıldı.");
            playButton.disabled = false;
            pauseButton.disabled = true;
        }
    });

    stopButton.addEventListener("click", function() {
        stopped = true;
        synth.cancel();
        currentUtterance = null;
        currentPart = 0;
        setStatus("⏹ Okuma durduruldu.");
        playButton.disabled = false;
        pauseButton.disabled = true;
        stopButton.disabled = true;
    });

    speedSelect.addEventListener("change", function() {
        if (synth.speaking) {
            synth.cancel();
            stopped = false;
            setTimeout(speakCurrentPart, 50);
        }
    });

    if ("onvoiceschanged" in synth) {
        synth.onvoiceschanged = function() {
            getTurkishVoice();
        };
    }

    setStatus("Hazır. Konuyu dinlemek için Oynat'a basın.");
})();
</script>

Adım 4: Oynatıcı Panelinin Şablona Yerleştirilmesi
Son olarak ses oynatıcı panelinin sayfa üzerinde nerede görüneceğini belirliyoruz.

  1. Yine showthread şablonu içerisinde kalın.
  2. Aşağıdaki kodu bulun:
Kod:
{$posts}

Hemen altına aşağıdaki HTML panel yapısını ekleyip şablonu kaydedin:
Kod:
{$posts}

<div id="tts-player" class="tts-player" aria-label="Konu seslendirme paneli">
    <div class="tts-title">
        Konuyu Dinle
    </div>

    <div class="tts-controls">
        <button type="button" id="tts-play" class="tts-button">
            ▶ Oynat
        </button>

        <button type="button" id="tts-pause" class="tts-button" disabled>
            ⏸ Duraklat
        </button>

        <button type="button" id="tts-stop" class="tts-button" disabled>
            ⏹ Durdur
        </button>
    </div>

    <div class="tts-settings">
        <label for="tts-speed">Okuma hızı:</label>
        <select id="tts-speed">
            <option value="0.75">0.75x</option>
            <option value="1" selected>1x</option>
            <option value="1.25">1.25x</option>
            <option value="1.5">1.5x</option>
            <option value="2">2x</option>
        </select>
    </div>

    <div id="tts-status" class="tts-status">
        Hazır. Konuyu dinlemek için Oynat'a basın.
    </div>
</div>

Önizleme ve Sonuç
Tüm adımları tamamladıktan sonra, konularınızın altında responsive, işlevsel ve tamamen ücretsiz bir Konu Seslendirme Paneli yer alacaktır.

Resim


Bu metnin taslağı yazar tarafından kaleme alınmış, dil bilgisi ve akıcılık düzenlemeleri Gemini iş birliğiyle tamamlanarak siz kıymetli okuyucularımızın beğenisine sunulmuştur.

DİKKAT

Konuyu Dinle
Hazır. Konuyu dinlemek için Oynat'a basın.

Yazarımız Hasan hakkında: Adım Hasan, ama bir dönem MyBB kullananlar beni Yondaime nicki ile tanırdı. 2009 da başladı web maceram, MyBB, Wordpress, Matematik, Adalet, Bilgisayar Programcılığı, derken şimdide burada bir şeyler yapmaya çalışıyorum :)

user avatar


 

Yazıya herhangi bir yorum yapılmadı

[-]
Hızlı Cevap
Güvenlik Kodu:
Lütfen, resmin üzerindeki harf ve rakamlardan oluşan Güvenlik Kodunu, aşağıdaki metin kutusuna giriniz.
Güvenlik Kodu:
(Büyük/Küçük harf duyarsız)


 
Reklam
Reklam


Kategoriler


Yasal Uyarı
Bu internet sitesi içeriğinde yer alan tüm yazılar Gidenler.Me’ye ait olup, 5846 sayılı Fikir ve Sanat Eserleri Kanunu ve 5237 sayılı Türk Ceza Kanunu kapsamında korunmaktadır. Bu hakları ihlal eden kişiler, 5846 sayılı Fikir ve Sanat eserleri Kanunu ve 5237 sayılı Türk Ceza Kanununda yer alan hukuki ve cezai yaptırımlara tabi olurlar. Gidenler.Me, ilgili yasal işlem başlatma hakkına sahiptir. Gidenler.Me Blog'da yer alan tüm yazılar/makaleler bilgi edinme amacı ile sınırlı olup Gidenler.Me'den izin alınmaksızın değiştirilemez, çoğaltılamaz, yayımlanamaz, dağıtılamaz, umuma iletilemez, başka bir lisana çevrilemez.


Türkçe Çeviri: MyBB, Yazılım: MyBB, © 2002-2026 MyBB Group.
GM v3.0.0.8 Beta theme designed for MyBB