{"id":20055,"date":"2026-09-21T22:29:15","date_gmt":"2026-09-21T20:29:15","guid":{"rendered":"https:\/\/www.lukaswojcik.com\/blog\/werkzeuge\/gapless-playback-encoder-delay-checker\/"},"modified":"2026-09-21T22:31:00","modified_gmt":"2026-09-21T20:31:00","slug":"gapless-playback-encoder-delay-checker","status":"publish","type":"page","link":"https:\/\/www.lukaswojcik.com\/blog\/de\/werkzeuge\/gapless-playback-encoder-delay-checker\/","title":{"rendered":"L\u00fcckenlos-Pr\u00fcfer: Vorlauf und Nachlauf in MP3, AAC, Opus und FLAC"},"content":{"rendered":"<div class=\"lw-gl\" id=\"gl-wurzel\" style=\"background: var(--bg-panel, #1e1e24); padding: 25px; border-radius: 8px; border: 1px solid var(--border, #2a2a35);\">\n<style>\n.lw-gl .gl-zone { border: 2px dashed var(--border, #2a2a35); border-radius: 8px; padding: 22px; text-align: center; }\n.lw-gl .gl-zone.gl-ueber { border-color: var(--accent, #2ba6df); }\n.lw-gl .gl-kacheln { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 10px; margin: 16px 0 4px; }\n.lw-gl .gl-kachel { background: var(--bg-body, #14141a); border: 1px solid var(--border, #2a2a35); border-radius: 8px; padding: 11px 14px; min-width: 0; }\n.lw-gl .gl-kachel-name { font-size: 0.74rem; color: var(--text-secondary, #a0a0b0); text-transform: uppercase; letter-spacing: 0.4px; }\n.lw-gl .gl-kachel-wert { font-family: monospace; font-size: 1.4rem; font-weight: 700; color: var(--text-primary, #e8e8ee); line-height: 1.25; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\n.lw-gl .gl-urteil { border-radius: 8px; padding: 12px 15px; margin-top: 14px; border: 1px solid var(--border, #2a2a35); background: var(--bg-body, #14141a); }\n.lw-gl .gl-urteil-kopf { font-weight: 700; color: var(--text-primary, #e8e8ee); margin-bottom: 4px; }\n.lw-gl .gl-ja .gl-urteil-kopf { color: var(--ok, #7ee787); }\n.lw-gl .gl-teils .gl-urteil-kopf { color: var(--gl-warn); }\n.lw-gl .gl-nein .gl-urteil-kopf { color: var(--fehler, #f0857a); }\n.lw-gl { --gl-warn: #e8a33d; }\n:root[data-theme=\"light\"] .lw-gl { --gl-warn: #8f5300; }\n.lw-gl .gl-tabelle { overflow-x: auto; margin-top: 6px; }\n.lw-gl table { border-collapse: collapse; width: 100%; font-size: 0.86rem; }\n.lw-gl th, .lw-gl td { text-align: left; padding: 6px 10px; border-bottom: 1px solid var(--border, #2a2a35); }\n.lw-gl th { color: var(--text-primary, #e8e8ee); white-space: nowrap; }\n.lw-gl td { color: var(--text-primary, #e8e8ee); }\n.lw-gl td.gl-wert { font-family: monospace; color: var(--text-secondary, #a0a0b0); }\n.lw-gl .gl-h { font-weight: 700; color: var(--text-primary, #e8e8ee); font-size: 0.95rem; margin: 24px 0 8px; }\n.lw-gl .gl-klein { font-size: 0.84rem; color: var(--text-secondary, #a0a0b0); line-height: 1.55; }\n.lw-gl .gl-knopf { background: transparent; color: var(--text-secondary, #a0a0b0); border: 1px solid var(--border, #2a2a35); padding: 9px 14px; border-radius: 6px; cursor: pointer; font-size: 0.9rem; margin-top: 14px; }\n.lw-gl .gl-fehler { color: var(--fehler, #f0857a); font-size: 0.88rem; margin-top: 12px; }\n.lw-gl a { color: var(--accent, #2ba6df); }\n@media (max-width: 480px) {\n    .lw-gl .gl-kacheln { grid-template-columns: 1fr 1fr; gap: 8px; }\n    .lw-gl .gl-kachel-wert { font-size: 1.15rem; }\n    .lw-gl th, .lw-gl td { padding: 6px 6px; }\n}\n<\/style>\n<p style=\"color: var(--text-secondary, #a0a0b0); margin-bottom: 18px;\">Verlustbehaftete Encoder f\u00fcgen am Anfang und am Ende einer Datei Abtastwerte hinzu. Steht in der Datei, wie viele es sind, entfernt ein Abspieler sie wieder und ein Titel geht ohne L\u00fccke in den n\u00e4chsten \u00fcber. Diese Pr\u00fcfung liest genau diese Angaben aus. Nichts wird hochgeladen, die Datei bleibt im Browser.<\/p>\n<div id=\"gl-zone\" class=\"gl-zone\">\n<p style=\"margin: 0 0 12px; color: var(--text-primary, #e8e8ee); font-weight: 700;\">Audiodatei ausw\u00e4hlen<\/p>\n<p>        <button id=\"gl-knopf\" type=\"button\" class=\"button\" style=\"background: var(--accent, #7ee787); color: var(--on-accent, #0b1114); border: none; padding: 11px 22px; border-radius: 6px; font-weight: 700; cursor: pointer;\">Datei w\u00e4hlen<\/button><br \/>\n        <input id=\"gl-datei\" type=\"file\" accept=\"audio\/*,.mp3,.m4a,.mp4,.aac,.opus,.ogg,.oga,.flac,.wav,.wave\" hidden><\/p>\n<p class=\"gl-klein\" style=\"margin: 12px 0 0;\">MP3, M4A\/AAC, Opus, Ogg Vorbis, FLAC und WAV. Gelesen wird nur der Kopf der Datei, nicht der Ton.<\/p>\n<\/p><\/div>\n<div id=\"gl-fehler\" class=\"gl-fehler\" data-mp-mask hidden><\/div>\n<div id=\"gl-ausgabe\" data-mp-mask style=\"margin-top: 18px;\" aria-live=\"polite\" hidden>\n<div id=\"gl-kacheln\" class=\"gl-kacheln\"><\/div>\n<div id=\"gl-urteil\" class=\"gl-urteil\"><\/div>\n<div class=\"gl-h\">Was die Datei angibt<\/div>\n<div class=\"gl-tabelle\">\n<table>\n<thead>\n<tr>\n<th>Feld<\/th>\n<th>Wert<\/th>\n<\/tr>\n<\/thead>\n<tbody id=\"gl-felder\"><\/tbody>\n<\/table><\/div>\n<p>        <button id=\"gl-kopieren\" type=\"button\" class=\"gl-knopf\">Ergebnis kopieren<\/button><br \/>\n        <span id=\"gl-kopiert\" class=\"gl-klein\" style=\"margin-left: 10px;\"><\/span>\n    <\/div>\n<div class=\"gl-h\">Was die Felder bedeuten<\/div>\n<p class=\"gl-klein\" style=\"margin: 0 0 6px;\">Encoder mit Transformation brauchen einen Anlauf: Der erste Block der Ausgabe beschreibt Ton, der vor dem Dateianfang liegt, und der letzte Block reicht \u00fcber das Ende hinaus. Beide Enden werden deshalb mit Abtastwerten gef\u00fcllt, die keine Musik sind.<\/p>\n<p class=\"gl-klein\" style=\"margin: 0 0 6px;\">MP3 tr\u00e4gt die Zahlen im Info- oder Xing-Rahmen, den der Encoder schreibt, zusammen mit seinem Namen. Zu dem dort genannten Vorlauf kommt die Verz\u00f6gerung des Decoders selbst; diese Pr\u00fcfung rechnet daf\u00fcr 529 Abtastwerte hinzu, so viel ergab die Messung zum zugeh\u00f6rigen Artikel.<\/p>\n<p class=\"gl-klein\" style=\"margin: 0 0 6px;\">In MP4 beschreibt die Schnittliste den Anfang, indem sie den Beginn der Spur verschiebt. Das Feld iTunSMPB von Apple nennt beide Enden in Abtastwerten; fehlt es, sagt nur die Dauer der Spur, wo ein Abspieler aufh\u00f6ren soll.<\/p>\n<p class=\"gl-klein\" style=\"margin: 0 0 6px;\">Opus nennt seinen Vorlauf im Kopf, gez\u00e4hlt bei 48 kHz, und die letzte Seite sagt, wie weit der Ton wirklich reicht. RFC 7845 legt beides fest, l\u00fcckenloses Abspielen braucht also kein zus\u00e4tzliches Feld.<\/p>\n<p class=\"gl-klein\" style=\"margin: 0 0 6px;\">FLAC und WAV speichern die genaue Zahl der Abtastwerte, es wird also nichts hinzugef\u00fcgt und nichts muss entfernt werden.<\/p>\n<p class=\"gl-klein\" style=\"margin: 20px 0 0;\">Quellen:<br \/>\n        <a href=\"https:\/\/datatracker.ietf.org\/doc\/html\/rfc7845\" rel=\"noopener\">RFC 7845<\/a> \u00b7<br \/>\n        <a href=\"https:\/\/datatracker.ietf.org\/doc\/html\/rfc9639\" rel=\"noopener\">RFC 9639<\/a> \u00b7<br \/>\n        <a href=\"https:\/\/lame.sourceforge.io\/tech-FAQ.txt\" rel=\"noopener\">LAME tech FAQ<\/a>\n    <\/p>\n<p class=\"gl-klein\" style=\"font-size: 0.8rem; margin: 14px 0 0;\">Gelesen werden nur die K\u00f6pfe der Datei, nicht der Ton. Was ein bestimmter Abspieler mit den Angaben macht, pr\u00fcft dieses Werkzeug nicht; die Werte zeigen, was er tun k\u00f6nnte.<\/p>\n<\/div>\n<p><script>\n(function () {\n    'use strict';\n    const T = {\"dezimal\":\",\",\"einleitung\":\"Verlustbehaftete Encoder f\u00fcgen am Anfang und am Ende einer Datei Abtastwerte hinzu. Steht in der Datei, wie viele es sind, entfernt ein Abspieler sie wieder und ein Titel geht ohne L\u00fccke in den n\u00e4chsten \u00fcber. Diese Pr\u00fcfung liest genau diese Angaben aus. Nichts wird hochgeladen, die Datei bleibt im Browser.\",\"zone_titel\":\"Audiodatei ausw\u00e4hlen\",\"knopf_datei\":\"Datei w\u00e4hlen\",\"zone_hinweis\":\"MP3, M4A\\\/AAC, Opus, Ogg Vorbis, FLAC und WAV. Gelesen wird nur der Kopf der Datei, nicht der Ton.\",\"k_format\":\"Format\",\"k_vorlauf\":\"Vorlauf am Anfang\",\"k_nachlauf\":\"Nachlauf am Ende\",\"k_luecke\":\"L\u00fccke ohne die Angaben\",\"h_angaben\":\"Was die Datei angibt\",\"sp_feld\":\"Feld\",\"sp_wert\":\"Wert\",\"f_format\":\"Format\",\"f_rate\":\"Abtastrate\",\"f_kanaele\":\"Kan\u00e4le\",\"f_rahmen\":\"Info-Rahmen\",\"f_encoder\":\"Encoder\",\"f_vorlauf_roh\":\"Vorlauf in Abtastwerten\",\"f_nachlauf_roh\":\"Nachlauf in Abtastwerten\",\"f_quellrate\":\"Urspr\u00fcngliche Abtastrate\",\"f_granule\":\"Letzte Granule-Position\",\"f_elst\":\"Schnittliste\",\"f_itunsmpb\":\"iTunSMPB\",\"f_tiefe\":\"Bit-Tiefe\",\"f_abtastwerte\":\"Abtastwerte Ton\",\"f_dauer\":\"Dauer\",\"format_mp3\":\"MP3\",\"format_mp4\":\"MP4 \\\/ AAC\",\"format_opus\":\"Opus in Ogg\",\"format_vorbis\":\"Ogg Vorbis\",\"format_flac\":\"FLAC\",\"format_wav\":\"WAV\",\"elst_wert\":\"Start {start}, Dauer {dauer}\",\"itunsmpb_wert\":\"{vorlauf} davor, {nachlauf} danach\",\"wert_keiner\":\"keiner\",\"wert_unbekannt\":\"unbekannt\",\"urteil_ja\":\"L\u00fcckenlos schon durch das Format\",\"urteil_mit_angaben\":\"L\u00fcckenlos nur, wenn die Angaben beachtet werden\",\"urteil_teils\":\"Anfang angegeben, Ende nicht\",\"urteil_nein\":\"Keine Angabe in der Datei\",\"urteil_text_ja\":\"Die Zahl der Tonabtastwerte ergibt sich aus dem Format, ein Decoder endet also genau dort, wo der Titel endet. Von Hand ist nichts zu schneiden.\",\"urteil_text_mit_angaben\":\"Die Datei nennt, wie viele Abtastwerte zum Encoder geh\u00f6ren und nicht zur Musik. Ein Abspieler, der diese Felder liest, f\u00fchrt einen Titel in den n\u00e4chsten; ein Abspieler, der sie \u00fcbergeht, f\u00fcgt die oben genannte L\u00fccke ein.\",\"urteil_text_teils\":\"Den Anfang beschreibt die Schnittliste, das Ende ist nicht eigens beschrieben. Wer zus\u00e4tzlich die Dauer der Spur beachtet, kommt trotzdem auf die richtige L\u00e4nge; wer nur den Anfang beachtet, beh\u00e4lt den Nachlauf als Stille.\",\"urteil_text_nein\":\"Die Datei tr\u00e4gt kein Feld f\u00fcr Vorlauf oder Nachlauf. Jeder Abspieler beh\u00e4lt deshalb die Abtastwerte, die der Encoder hinzugef\u00fcgt hat, und zwischen zwei Titeln bleibt eine L\u00fccke von mindestens 25 ms.\",\"bericht_kopf\":\"Pr\u00fcfung auf l\u00fcckenloses Abspielen\",\"knopf_kopieren\":\"Ergebnis kopieren\",\"kopiert\":\"kopiert\",\"kopieren_fehler\":\"Kopieren nicht m\u00f6glich\",\"fehler_format\":\"Diese Datei geh\u00f6rt zu keinem der hier gelesenen Formate: MP3, M4A\\\/AAC, Opus, Ogg Vorbis, FLAC oder WAV.\",\"fehler_lesen\":\"Die Datei lie\u00df sich nicht lesen.\",\"h_erklaerung\":\"Was die Felder bedeuten\",\"erkl_grund\":\"Encoder mit Transformation brauchen einen Anlauf: Der erste Block der Ausgabe beschreibt Ton, der vor dem Dateianfang liegt, und der letzte Block reicht \u00fcber das Ende hinaus. Beide Enden werden deshalb mit Abtastwerten gef\u00fcllt, die keine Musik sind.\",\"erkl_mp3\":\"MP3 tr\u00e4gt die Zahlen im Info- oder Xing-Rahmen, den der Encoder schreibt, zusammen mit seinem Namen. Zu dem dort genannten Vorlauf kommt die Verz\u00f6gerung des Decoders selbst; diese Pr\u00fcfung rechnet daf\u00fcr 529 Abtastwerte hinzu, so viel ergab die Messung zum zugeh\u00f6rigen Artikel.\",\"erkl_aac\":\"In MP4 beschreibt die Schnittliste den Anfang, indem sie den Beginn der Spur verschiebt. Das Feld iTunSMPB von Apple nennt beide Enden in Abtastwerten; fehlt es, sagt nur die Dauer der Spur, wo ein Abspieler aufh\u00f6ren soll.\",\"erkl_opus\":\"Opus nennt seinen Vorlauf im Kopf, gez\u00e4hlt bei 48 kHz, und die letzte Seite sagt, wie weit der Ton wirklich reicht. RFC 7845 legt beides fest, l\u00fcckenloses Abspielen braucht also kein zus\u00e4tzliches Feld.\",\"erkl_flac\":\"FLAC und WAV speichern die genaue Zahl der Abtastwerte, es wird also nichts hinzugef\u00fcgt und nichts muss entfernt werden.\",\"quellen_titel\":\"Quellen\",\"grenze\":\"Gelesen werden nur die K\u00f6pfe der Datei, nicht der Ton. Was ein bestimmter Abspieler mit den Angaben macht, pr\u00fcft dieses Werkzeug nicht; die Werte zeigen, was er tun k\u00f6nnte.\"};<\/p>\n<p>    function el(id) { return document.getElementById(id); }\n    function text(schluessel, werte) {\n        var s = T[schluessel] || '';\n        return s.replace(\/\\{(\\w+)\\}\/g, function (_, k) { return werte && werte[k] !== undefined ? werte[k] : ''; });\n    }\n    function zahl(wert, stellen) {\n        if (wert === null || wert === undefined || !isFinite(wert)) { return '\u2013'; }\n        var s = Number(wert).toFixed(stellen === undefined ? 1 : stellen);\n        return T.dezimal === ',' ? s.replace('.', ',') : s;\n    }<\/p>\n<p>    \/\/ ---- kleine Leser ------------------------------------------------------\n    function ascii(dv, pos, laenge) {\n        var s = '';\n        for (var i = 0; i < laenge; i++) {\n            if (pos + i >= dv.byteLength) { break; }\n            s += String.fromCharCode(dv.getUint8(pos + i));\n        }\n        return s;\n    }\n    function suchen(dv, muster, von, bis) {\n        var ende = Math.min(bis === undefined ? dv.byteLength : bis, dv.byteLength) - muster.length;\n        for (var i = Math.max(0, von || 0); i <= ende; i++) {\n            var treffer = true;\n            for (var j = 0; j < muster.length; j++) {\n                if (dv.getUint8(i + j) !== muster.charCodeAt(j)) { treffer = false; break; }\n            }\n            if (treffer) { return i; }\n        }\n        return -1;\n    }\n\n    \/\/ ---- MP3 ---------------------------------------------------------------\n    var MP3_RATEN = [[11025, 12000, 8000], [0, 0, 0], [22050, 24000, 16000], [44100, 48000, 32000]];\n\n    function id3Laenge(dv) {\n        if (dv.byteLength < 10 || ascii(dv, 0, 3) !== 'ID3') { return 0; }\n        var g = 0;\n        for (var i = 6; i < 10; i++) { g = (g << 7) | (dv.getUint8(i) &#038; 0x7F); }\n        return g + 10;\n    }\n\n    function mp3Rahmen(dv, von) {\n        for (var i = von; i < Math.min(dv.byteLength - 4, von + 200000); i++) {\n            if (dv.getUint8(i) !== 0xFF || (dv.getUint8(i + 1) &#038; 0xE0) !== 0xE0) { continue; }\n            var b1 = dv.getUint8(i + 1), b2 = dv.getUint8(i + 2), b3 = dv.getUint8(i + 3);\n            var version = (b1 >> 3) & 3, lage = (b1 >> 1) & 3, rateZeiger = (b2 >> 2) & 3;\n            if (version === 1 || lage === 0 || rateZeiger === 3) { continue; }\n            var rate = MP3_RATEN[version][rateZeiger];\n            if (!rate) { continue; }\n            return { pos: i, rate: rate, version: version, lage: lage, kanaele: ((b3 >> 6) & 3) === 3 ? 1 : 2 };\n        }\n        return null;\n    }<\/p>\n<p>    function mp3Lesen(puffer) {\n        var dv = new DataView(puffer);\n        var start = id3Laenge(dv);\n        var rahmen = mp3Rahmen(dv, start);\n        if (!rahmen) { return null; }\n        var i = -1, art = '';\n        for (var k = 0; k < 2; k++) {\n            var m = k === 0 ? 'Info' : 'Xing';\n            var p = suchen(dv, m, rahmen.pos, rahmen.pos + 1200);\n            if (p >= 0 && (i < 0 || p < i)) { i = p; art = m; }\n        }\n        var ergebnis = { typ: 'mp3', rate: rahmen.rate, kanaele: rahmen.kanaele, rahmen: null,\n                         encoder: null, vorlauf: null, nachlauf: null, abtastwerte: null };\n        if (i < 0) { return ergebnis; }\n        var flaggen = dv.getUint32(i + 4), p2 = i + 8;\n        if (flaggen &#038; 1) { ergebnis.rahmenzahl = dv.getUint32(p2); p2 += 4; }\n        if (flaggen &#038; 2) { p2 += 4; }\n        if (flaggen &#038; 4) { p2 += 100; }\n        if (flaggen &#038; 8) { p2 += 4; }\n        ergebnis.rahmen = art;\n        if (p2 + 24 > dv.byteLength) { return ergebnis; }\n        ergebnis.encoder = ascii(dv, p2, 9).replace(\/[^\\x20-\\x7E]\/g, '');\n        var a = dv.getUint8(p2 + 21), b = dv.getUint8(p2 + 22), c = dv.getUint8(p2 + 23);\n        ergebnis.vorlauf = (a << 4) | (b >> 4);\n        ergebnis.nachlauf = ((b & 0x0F) << 8) | c;\n        if (ergebnis.rahmenzahl) {\n            var jeRahmen = rahmen.version === 3 ? 1152 : 576;\n            ergebnis.abtastwerte = ergebnis.rahmenzahl * jeRahmen - ergebnis.vorlauf - ergebnis.nachlauf;\n        }\n        return ergebnis;\n    }\n\n    \/\/ ---- MP4 \/ M4A ---------------------------------------------------------\n    function mp4Kaesten(dv, von, bis, tiefe, sammeln) {\n        var p = von;\n        while (p + 8 <= bis) {\n            var groesse = dv.getUint32(p), name = ascii(dv, p + 4, 4), inhalt = p + 8;\n            if (groesse === 1) { groesse = dv.getUint32(p + 8) * 4294967296 + dv.getUint32(p + 12); inhalt = p + 16; }\n            if (groesse === 0) { groesse = bis - p; }\n            if (groesse < 8 || p + groesse > bis) { break; }\n            sammeln(name, inhalt, p + groesse);\n            if (tiefe > 0 && \/^(moov|trak|mdia|minf|stbl|edts|udta|meta|ilst|----)$\/.test(name)) {\n                var innen = name === 'meta' ? inhalt + 4 : inhalt;\n                mp4Kaesten(dv, innen, p + groesse, tiefe - 1, sammeln);\n            }\n            p += groesse;\n        }\n    }<\/p>\n<p>    function mp4Lesen(puffer) {\n        var dv = new DataView(puffer);\n        var e = { typ: 'mp4', rate: null, kanaele: null, elst: null, itunsmpb: null, dauer: null, zeitbasis: null };\n        var mdhdRate = null, letzterName = null;\n        mp4Kaesten(dv, 0, dv.byteLength, 6, function (name, von, bis) {\n            if (name === 'mvhd') {\n                var v = dv.getUint8(von);\n                e.zeitbasis = v === 1 ? dv.getUint32(von + 20) : dv.getUint32(von + 12);\n            } else if (name === 'mdhd') {\n                var v2 = dv.getUint8(von);\n                mdhdRate = v2 === 1 ? dv.getUint32(von + 20) : dv.getUint32(von + 12);\n                e.rate = e.rate || mdhdRate;\n                e.abtastwerte = v2 === 1 ? dv.getUint32(von + 28) : dv.getUint32(von + 16);\n            } else if (name === 'elst') {\n                var version = dv.getUint8(von), anzahl = dv.getUint32(von + 4);\n                if (anzahl > 0) {\n                    if (version === 1) {\n                        e.elst = { anzahl: anzahl, dauer: dv.getUint32(von + 12) * 4294967296 + dv.getUint32(von + 16),\n                                   start: dv.getInt32(von + 24) };\n                    } else {\n                        e.elst = { anzahl: anzahl, dauer: dv.getUint32(von + 8), start: dv.getInt32(von + 12) };\n                    }\n                }\n            } else if (name === 'mp4a') {\n                e.kanaele = dv.getUint16(von + 16);\n                e.rate = dv.getUint16(von + 24);\n            } else if (name === 'name') {\n                letzterName = ascii(dv, von + 4, bis - von - 4);\n            } else if (name === 'data' && letzterName && \/iTunSMPB\/.test(letzterName)) {\n                var roh = ascii(dv, von + 8, Math.min(120, bis - von - 8));\n                var zahlen = roh.match(\/[0-9A-Fa-f]{8,16}\/g) || [];\n                if (zahlen.length >= 4) {\n                    e.itunsmpb = { vorlauf: parseInt(zahlen[1], 16), nachlauf: parseInt(zahlen[2], 16),\n                                   abtastwerte: parseInt(zahlen[3], 16) };\n                }\n                letzterName = null;\n            }\n        });\n        return e;\n    }<\/p>\n<p>    \/\/ ---- Ogg: Opus und Vorbis ----------------------------------------------\n    function letzteGranule(dv) {\n        for (var i = dv.byteLength - 14; i >= 0 && i > dv.byteLength - 70000; i--) {\n            if (ascii(dv, i, 4) === 'OggS') {\n                var lo = dv.getUint32(i + 6, true), hi = dv.getUint32(i + 10, true);\n                return hi * 4294967296 + lo;\n            }\n        }\n        return null;\n    }<\/p>\n<p>    function oggLesen(puffer) {\n        var dv = new DataView(puffer);\n        var o = suchen(dv, 'OpusHead', 0, 65536);\n        if (o >= 0) {\n            return { typ: 'opus', kanaele: dv.getUint8(o + 9), vorlauf: dv.getUint16(o + 10, true),\n                     quellrate: dv.getUint32(o + 12, true), rate: 48000, granule: letzteGranule(dv) };\n        }\n        var v = suchen(dv, '\\x01vorbis', 0, 65536);\n        if (v >= 0) {\n            return { typ: 'vorbis', kanaele: dv.getUint8(v + 11), rate: dv.getUint32(v + 12, true),\n                     granule: letzteGranule(dv) };\n        }\n        return null;\n    }<\/p>\n<p>    \/\/ ---- FLAC und WAV ------------------------------------------------------\n    function flacLesen(puffer) {\n        var dv = new DataView(puffer);\n        if (ascii(dv, 0, 4) !== 'fLaC' || dv.byteLength < 42) { return null; }\n        var p = 8;                                    \/\/ 4 Kennung + 4 Blockkopf\n        var rate = (dv.getUint8(p + 10) << 12) | (dv.getUint8(p + 11) << 4) | (dv.getUint8(p + 12) >> 4);\n        var kanaele = ((dv.getUint8(p + 12) >> 1) & 7) + 1;\n        var tiefe = (((dv.getUint8(p + 12) & 1) << 4) | (dv.getUint8(p + 13) >> 4)) + 1;\n        var hoch = dv.getUint8(p + 13) & 0x0F;\n        var abtastwerte = hoch * 4294967296 + dv.getUint32(p + 14);\n        return { typ: 'flac', rate: rate, kanaele: kanaele, tiefe: tiefe, abtastwerte: abtastwerte };\n    }<\/p>\n<p>    function wavLesen(puffer) {\n        var dv = new DataView(puffer);\n        if (ascii(dv, 0, 4) !== 'RIFF' || ascii(dv, 8, 4) !== 'WAVE') { return null; }\n        var p = 12, rate = null, kanaele = null, tiefe = null, datenlaenge = null, block = null;\n        while (p + 8 <= dv.byteLength) {\n            var kennung = ascii(dv, p, 4), laenge = dv.getUint32(p + 4, true);\n            if (kennung === 'fmt ') {\n                kanaele = dv.getUint16(p + 10, true);\n                rate = dv.getUint32(p + 12, true);\n                block = dv.getUint16(p + 20, true);\n                tiefe = dv.getUint16(p + 22, true);\n            } else if (kennung === 'data') {\n                datenlaenge = Math.min(laenge, dv.byteLength - p - 8);\n            }\n            p += 8 + laenge + (laenge &#038; 1);\n        }\n        if (!rate) { return null; }\n        return { typ: 'wav', rate: rate, kanaele: kanaele, tiefe: tiefe,\n                 abtastwerte: block ? Math.floor(datenlaenge \/ block) : null };\n    }\n\n    function erkennen(puffer) {\n        var dv = new DataView(puffer);\n        if (dv.byteLength < 16) { return null; }\n        if (ascii(dv, 0, 4) === 'RIFF') { return wavLesen(puffer); }\n        if (ascii(dv, 0, 4) === 'fLaC') { return flacLesen(puffer); }\n        if (ascii(dv, 0, 4) === 'OggS') { return oggLesen(puffer); }\n        if (ascii(dv, 4, 4) === 'ftyp') { return mp4Lesen(puffer); }\n        if (ascii(dv, 0, 3) === 'ID3' || (dv.getUint8(0) === 0xFF &#038;&#038; (dv.getUint8(1) &#038; 0xE0) === 0xE0)) {\n            return mp3Lesen(puffer);\n        }\n        return null;\n    }\n\n    \/\/ ---- Auswertung --------------------------------------------------------\n    var DECODER_MP3 = 529;        \/\/ gemessene Verzoegerung der Decoder, siehe Text\n\n    function auswerten(info) {\n        if (!info) { return null; }\n        var rate = info.rate || 44100;\n        var a = { typ: info.typ, rate: rate, kanaele: info.kanaele || null,\n                  vorlauf: null, nachlauf: null, luecke_ms: null, urteil: 'nein', abtastwerte: info.abtastwerte || null };\n        if (info.typ === 'wav' || info.typ === 'flac') {\n            a.vorlauf = 0; a.nachlauf = 0; a.luecke_ms = 0; a.urteil = 'ja';\n        } else if (info.typ === 'mp3') {\n            if (info.vorlauf === null || info.vorlauf === undefined) {\n                a.urteil = 'nein';\n            } else {\n                a.vorlauf = info.vorlauf + DECODER_MP3;\n                a.nachlauf = info.nachlauf;\n                a.luecke_ms = (a.vorlauf + a.nachlauf) \/ rate * 1000;\n                a.urteil = 'mit_angaben';\n            }\n        } else if (info.typ === 'opus') {\n            a.vorlauf = info.vorlauf;\n            a.nachlauf = null;\n            a.luecke_ms = info.vorlauf \/ 48000 * 1000;\n            a.urteil = 'ja';\n            if (info.granule !== null &#038;&#038; info.granule !== undefined) {\n                a.abtastwerte = Math.max(0, info.granule - info.vorlauf);\n            }\n        } else if (info.typ === 'vorbis') {\n            a.vorlauf = 0; a.nachlauf = 0; a.luecke_ms = 0; a.urteil = 'ja';\n            if (info.granule) { a.abtastwerte = info.granule; }\n        } else if (info.typ === 'mp4') {\n            var vor = null, nach = null;\n            if (info.itunsmpb) { vor = info.itunsmpb.vorlauf; nach = info.itunsmpb.nachlauf; }\n            else if (info.elst &#038;&#038; info.elst.start > 0) { vor = info.elst.start; }\n            a.vorlauf = vor;\n            a.nachlauf = nach;\n            if (vor !== null) {\n                a.luecke_ms = (vor + (nach || 0)) \/ rate * 1000;\n                a.urteil = info.itunsmpb ? 'mit_angaben' : 'teils';\n            } else {\n                a.urteil = 'nein';\n            }\n        }\n        return a;\n    }<\/p>\n<p>    function felder(info, a) {\n        var liste = [];\n        function f(name, wert) { if (wert !== null && wert !== undefined && wert !== '') { liste.push([name, String(wert)]); } }\n        f(T.f_format, T['format_' + info.typ] || info.typ);\n        f(T.f_rate, (info.rate || a.rate) + ' Hz');\n        f(T.f_kanaele, info.kanaele);\n        if (info.typ === 'mp3') {\n            f(T.f_rahmen, info.rahmen || T.wert_keiner);\n            f(T.f_encoder, info.encoder);\n            f(T.f_vorlauf_roh, info.vorlauf === null ? T.wert_keiner : info.vorlauf + ' + ' + DECODER_MP3);\n            f(T.f_nachlauf_roh, info.nachlauf === null ? T.wert_keiner : info.nachlauf);\n        } else if (info.typ === 'opus') {\n            f(T.f_vorlauf_roh, info.vorlauf);\n            f(T.f_quellrate, info.quellrate ? info.quellrate + ' Hz' : null);\n            f(T.f_granule, info.granule);\n        } else if (info.typ === 'mp4') {\n            f(T.f_elst, info.elst ? text('elst_wert', { start: info.elst.start, dauer: info.elst.dauer }) : T.wert_keiner);\n            f(T.f_itunsmpb, info.itunsmpb ? text('itunsmpb_wert', { vorlauf: info.itunsmpb.vorlauf, nachlauf: info.itunsmpb.nachlauf }) : T.wert_keiner);\n        } else if (info.typ === 'flac') {\n            f(T.f_tiefe, info.tiefe ? info.tiefe + ' Bit' : null);\n        } else if (info.typ === 'vorbis') {\n            f(T.f_granule, info.granule);\n        } else if (info.typ === 'wav') {\n            f(T.f_tiefe, info.tiefe ? info.tiefe + ' Bit' : null);\n        }\n        if (a.abtastwerte) {\n            f(T.f_abtastwerte, a.abtastwerte);\n            f(T.f_dauer, zahl(a.abtastwerte \/ (a.rate || 44100), 3) + ' s');\n        }\n        return liste;\n    }<\/p>\n<p>    function bericht(info, a) {\n        var zeilen = [T.bericht_kopf];\n        felder(info, a).forEach(function (z) { zeilen.push(z[0] + ': ' + z[1]); });\n        zeilen.push(T.k_luecke + ': ' + (a.luecke_ms === null ? T.wert_unbekannt : zahl(a.luecke_ms, 1) + ' ms'));\n        zeilen.push(T['urteil_' + a.urteil]);\n        return zeilen.join('\\n');\n    }<\/p>\n<p>    \/\/ ---- Darstellung -------------------------------------------------------\n    function kachel(name, wert) {\n        var d = document.createElement('div');\n        d.className = 'gl-kachel';\n        var n = document.createElement('div'); n.className = 'gl-kachel-name'; n.textContent = name;\n        var w = document.createElement('div'); w.className = 'gl-kachel-wert'; w.textContent = wert;\n        d.appendChild(n); d.appendChild(w);\n        return d;\n    }<\/p>\n<p>    function darstellen(info, a) {\n        var kacheln = el('gl-kacheln'), urteil = el('gl-urteil'), tab = el('gl-felder');\n        if (!kacheln) { return; }\n        kacheln.textContent = '';\n        kacheln.appendChild(kachel(T.k_format, T['format_' + info.typ] || info.typ));\n        kacheln.appendChild(kachel(T.k_vorlauf, a.vorlauf === null ? T.wert_unbekannt : zahl(a.vorlauf \/ (a.rate || 44100) * 1000, 1) + ' ms'));\n        kacheln.appendChild(kachel(T.k_nachlauf, a.nachlauf === null ? T.wert_unbekannt : zahl(a.nachlauf \/ (a.rate || 44100) * 1000, 1) + ' ms'));\n        kacheln.appendChild(kachel(T.k_luecke, a.luecke_ms === null ? T.wert_unbekannt : zahl(a.luecke_ms, 1) + ' ms'));<\/p>\n<p>        urteil.className = 'gl-urteil gl-' + (a.urteil === 'mit_angaben' ? 'teils' : a.urteil);\n        urteil.textContent = '';\n        var kopf = document.createElement('div');\n        kopf.className = 'gl-urteil-kopf';\n        kopf.textContent = T['urteil_' + a.urteil];\n        var txt = document.createElement('div');\n        txt.className = 'gl-klein';\n        txt.textContent = T['urteil_text_' + a.urteil];\n        urteil.appendChild(kopf); urteil.appendChild(txt);<\/p>\n<p>        tab.textContent = '';\n        felder(info, a).forEach(function (z) {\n            var tr = document.createElement('tr');\n            var td1 = document.createElement('td'); td1.textContent = z[0];\n            var td2 = document.createElement('td'); td2.className = 'gl-wert'; td2.textContent = z[1];\n            tr.appendChild(td1); tr.appendChild(td2);\n            tab.appendChild(tr);\n        });\n        el('gl-ausgabe').hidden = false;\n        el('gl-fehler').hidden = true;\n        return a;\n    }<\/p>\n<p>    function fehlerZeigen(s) {\n        var f = el('gl-fehler');\n        if (!f) { return; }\n        f.textContent = s;\n        f.hidden = false;\n        el('gl-ausgabe').hidden = true;\n    }<\/p>\n<p>    var letztes = null;\n    function verarbeiten(puffer) {\n        var info;\n        try { info = erkennen(puffer); } catch (x) { info = null; }\n        if (!info) { fehlerZeigen(T.fehler_format); return null; }\n        var a = auswerten(info);\n        letztes = { info: info, a: a };\n        return darstellen(info, a);\n    }<\/p>\n<p>    function dateiNehmen(datei) {\n        if (!datei) { return; }\n        var leser = new FileReader();\n        leser.onload = function () { verarbeiten(leser.result); };\n        leser.onerror = function () { fehlerZeigen(T.fehler_lesen); };\n        try { leser.readAsArrayBuffer(datei); } catch (x) { fehlerZeigen(T.fehler_lesen); }\n    }<\/p>\n<p>    window.LW_TEST = window.LW_TEST || {};\n    window.LW_TEST.GL = {\n        T: T, erkennen: erkennen, mp3Lesen: mp3Lesen, mp4Lesen: mp4Lesen, oggLesen: oggLesen,\n        flacLesen: flacLesen, wavLesen: wavLesen, auswerten: auswerten, felder: felder,\n        bericht: bericht, darstellen: darstellen, verarbeiten: verarbeiten, zahl: zahl,\n        DECODER_MP3: DECODER_MP3\n    };<\/p>\n<p>    var zone = el('gl-zone'), eingabe = el('gl-datei'), knopf = el('gl-knopf');\n    if (!zone || !eingabe || !knopf) { return; }\n    knopf.addEventListener('click', function () { eingabe.click(); });\n    eingabe.addEventListener('change', function () { dateiNehmen(eingabe.files && eingabe.files[0]); eingabe.value = ''; });\n    ['dragenter', 'dragover'].forEach(function (typ) {\n        zone.addEventListener(typ, function (ev) { ev.preventDefault(); zone.classList.add('gl-ueber'); });\n    });\n    ['dragleave', 'drop'].forEach(function (typ) {\n        zone.addEventListener(typ, function (ev) { ev.preventDefault(); zone.classList.remove('gl-ueber'); });\n    });\n    zone.addEventListener('drop', function (ev) {\n        ev.preventDefault();\n        dateiNehmen(ev.dataTransfer && ev.dataTransfer.files && ev.dataTransfer.files[0]);\n    });\n    var kopieren = el('gl-kopieren'), kopiert = el('gl-kopiert');\n    if (kopieren) {\n        kopieren.addEventListener('click', function () {\n            if (!letztes) { return; }\n            var t = bericht(letztes.info, letztes.a);\n            if (navigator.clipboard && navigator.clipboard.writeText) {\n                navigator.clipboard.writeText(t).then(function () { kopiert.textContent = T.kopiert; },\n                    function () { kopiert.textContent = T.kopieren_fehler; });\n            } else {\n                kopiert.textContent = T.kopieren_fehler;\n            }\n        });\n    }\n})();\n<\/script><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Liest eine Audiodatei im Browser und meldet, was die Datei selbst \u00fcber Vorlauf und Nachlauf angibt: den LAME-Rahmen in MP3, Schnittliste und iTunSMPB in MP4, den Vorlauf in Opus, die Anzahl der Abtastwerte in FLAC. Dazu die L\u00e4nge der L\u00fccke, die ein Abspieler ohne diese Angaben einf\u00fcgt.<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":9283,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"template-tool-base.php","meta":{"footnotes":""},"tags":[92903],"class_list":["post-20055","page","type-page","status-publish","hentry","tag-music-production-de"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v28.1 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>L\u00fcckenlos-Pr\u00fcfer: Vorlauf und Nachlauf in MP3, AAC, Opus und FLAC - Lukas Wojcik - Blog<\/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:\/\/www.lukaswojcik.com\/blog\/de\/werkzeuge\/gapless-playback-encoder-delay-checker\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"L\u00fcckenlos-Pr\u00fcfer: Vorlauf und Nachlauf in MP3, AAC, Opus und FLAC - Lukas Wojcik - Blog\" \/>\n<meta property=\"og:description\" content=\"Liest eine Audiodatei im Browser und meldet, was die Datei selbst \u00fcber Vorlauf und Nachlauf angibt: den LAME-Rahmen in MP3, Schnittliste und iTunSMPB in MP4, den Vorlauf in Opus, die Anzahl der Abtastwerte in FLAC. Dazu die L\u00e4nge der L\u00fccke, die ein Abspieler ohne diese Angaben einf\u00fcgt.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.lukaswojcik.com\/blog\/de\/werkzeuge\/gapless-playback-encoder-delay-checker\/\" \/>\n<meta property=\"og:site_name\" content=\"Lukas Wojcik - Blog\" \/>\n<meta property=\"article:modified_time\" content=\"2026-09-21T20:31:00+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/08\/og-default.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"1200\" \/>\n\t<meta property=\"og:image:height\" content=\"630\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data1\" content=\"2 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/de\\\/werkzeuge\\\/gapless-playback-encoder-delay-checker\\\/\",\"url\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/de\\\/werkzeuge\\\/gapless-playback-encoder-delay-checker\\\/\",\"name\":\"L\u00fcckenlos-Pr\u00fcfer: Vorlauf und Nachlauf in MP3, AAC, Opus und FLAC - Lukas Wojcik - Blog\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/#website\"},\"datePublished\":\"2026-09-21T20:29:15+00:00\",\"dateModified\":\"2026-09-21T20:31:00+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/de\\\/werkzeuge\\\/gapless-playback-encoder-delay-checker\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/de\\\/werkzeuge\\\/gapless-playback-encoder-delay-checker\\\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/de\\\/werkzeuge\\\/gapless-playback-encoder-delay-checker\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Toolbox\",\"item\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/toolbox-2\\\/\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"L\u00fcckenlos-Pr\u00fcfer: Vorlauf und Nachlauf in MP3, AAC, Opus und FLAC\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/#website\",\"url\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/\",\"name\":\"Lukas Wojcik - Blog\",\"description\":\"\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/#\\\/schema\\\/person\\\/895f7604f9b6b71aad9bba33af28d0f9\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/#\\\/schema\\\/person\\\/895f7604f9b6b71aad9bba33af28d0f9\",\"name\":\"Lukas Wojcik\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/07\\\/lw-x2.jpg\",\"url\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/07\\\/lw-x2.jpg\",\"contentUrl\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/07\\\/lw-x2.jpg\",\"width\":424,\"height\":636,\"caption\":\"Lukas Wojcik\"},\"logo\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/07\\\/lw-x2.jpg\"},\"sameAs\":[\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\"]}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"L\u00fcckenlos-Pr\u00fcfer: Vorlauf und Nachlauf in MP3, AAC, Opus und FLAC - Lukas Wojcik - Blog","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:\/\/www.lukaswojcik.com\/blog\/de\/werkzeuge\/gapless-playback-encoder-delay-checker\/","og_locale":"en_US","og_type":"article","og_title":"L\u00fcckenlos-Pr\u00fcfer: Vorlauf und Nachlauf in MP3, AAC, Opus und FLAC - Lukas Wojcik - Blog","og_description":"Liest eine Audiodatei im Browser und meldet, was die Datei selbst \u00fcber Vorlauf und Nachlauf angibt: den LAME-Rahmen in MP3, Schnittliste und iTunSMPB in MP4, den Vorlauf in Opus, die Anzahl der Abtastwerte in FLAC. Dazu die L\u00e4nge der L\u00fccke, die ein Abspieler ohne diese Angaben einf\u00fcgt.","og_url":"https:\/\/www.lukaswojcik.com\/blog\/de\/werkzeuge\/gapless-playback-encoder-delay-checker\/","og_site_name":"Lukas Wojcik - Blog","article_modified_time":"2026-09-21T20:31:00+00:00","og_image":[{"width":1200,"height":630,"url":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/08\/og-default.jpg","type":"image\/jpeg"}],"twitter_card":"summary_large_image","twitter_misc":{"Est. reading time":"2 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/www.lukaswojcik.com\/blog\/de\/werkzeuge\/gapless-playback-encoder-delay-checker\/","url":"https:\/\/www.lukaswojcik.com\/blog\/de\/werkzeuge\/gapless-playback-encoder-delay-checker\/","name":"L\u00fcckenlos-Pr\u00fcfer: Vorlauf und Nachlauf in MP3, AAC, Opus und FLAC - Lukas Wojcik - Blog","isPartOf":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/#website"},"datePublished":"2026-09-21T20:29:15+00:00","dateModified":"2026-09-21T20:31:00+00:00","breadcrumb":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/de\/werkzeuge\/gapless-playback-encoder-delay-checker\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.lukaswojcik.com\/blog\/de\/werkzeuge\/gapless-playback-encoder-delay-checker\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/www.lukaswojcik.com\/blog\/de\/werkzeuge\/gapless-playback-encoder-delay-checker\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.lukaswojcik.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Toolbox","item":"https:\/\/www.lukaswojcik.com\/blog\/toolbox-2\/"},{"@type":"ListItem","position":3,"name":"L\u00fcckenlos-Pr\u00fcfer: Vorlauf und Nachlauf in MP3, AAC, Opus und FLAC"}]},{"@type":"WebSite","@id":"https:\/\/www.lukaswojcik.com\/blog\/#website","url":"https:\/\/www.lukaswojcik.com\/blog\/","name":"Lukas Wojcik - Blog","description":"","publisher":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/#\/schema\/person\/895f7604f9b6b71aad9bba33af28d0f9"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.lukaswojcik.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":["Person","Organization"],"@id":"https:\/\/www.lukaswojcik.com\/blog\/#\/schema\/person\/895f7604f9b6b71aad9bba33af28d0f9","name":"Lukas Wojcik","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/07\/lw-x2.jpg","url":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/07\/lw-x2.jpg","contentUrl":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/07\/lw-x2.jpg","width":424,"height":636,"caption":"Lukas Wojcik"},"logo":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/07\/lw-x2.jpg"},"sameAs":["https:\/\/www.lukaswojcik.com\/blog"]}]}},"_links":{"self":[{"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/pages\/20055","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/comments?post=20055"}],"version-history":[{"count":1,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/pages\/20055\/revisions"}],"predecessor-version":[{"id":20058,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/pages\/20055\/revisions\/20058"}],"up":[{"embeddable":true,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/pages\/9283"}],"wp:attachment":[{"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/media?parent=20055"}],"wp:term":[{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/tags?post=20055"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}