Audiosteuerung

Permalink

Was ist die Aufgabe eines Podcatchers? Abspielen von Podcasts natürlich.

Die entscheidende Frage hierzu ist ob ich aus einer Liste von Links zu einzelnen Episoden einen auswählen und abspielen kann. Der Versuchsaufbau zur Klärung dieser Frage besteht in einem Audio-Tag…

<div id="player">
  <h2>Player</h2>
    <audio controls="controls" preload="none" title="http://meta.metaebene.me/media/cre/cre197-ipv6.mp3">
      <source src="http://meta.metaebene.me/media/cre/cre197-ipv6.mp3" type="audio/mpeg">
    </audio>
</div>

…und einer Liste mit Links zu MP3-Dateien

<div id="playlist">
  <h2>Playlist</h2>
  <ul class="entries">
    <li>
      <h3 class="title"><a href="http://meta.metaebene.me/media/cre/cre202-hackerfilme.mp3">CRE202 Hackerfilme</a></h3>
    </li>
    <li>
      <h3 class="title"><a href="http://meta.metaebene.me/media/cre/cre201-hoehlenforschung.mp3">CRE201 Höhlenforschung</a></h3>
    </li>
    <li>
      <h3 class="title"><a href="http://meta.metaebene.me/media/cre/cre200-stadtplanung.mp3">CRE200 Stadtplanung</a></h3>
    </li>
  </ul>
</div>

Ein wenig Javascript lässt sich hier wohl nicht vermeiden und daher greife ich für alles weitere auf JQuery zurück.

Manipulieren des Audio-Tags

Um einem Audio-Tag einen neuen Track unterzuschieben muss ich das src-Attribut des source-Elements neu setzen. Das ist schon alles. Um das ganze etwas aufzuhübschen wird auch gleich noch das title-Attribute des Audio-Elements gesetzt und der passende Eintrag in der Liste mit einer zusätzlichen Klasse markiert damit ich ihn hervorheben kann. In Javascript sieht das dann so aus:

var activateTrack = function(trackurl) {
  "use strict";
  var audioTag = $('#player audio')[0];
  if (trackurl) {
    $('#playlist').find('.activeTrack').removeClass('activeTrack');
    $('#playlist').find('.title a[href="' + trackurl + '"]').closest('li').addClass('activeTrack');
    $(audioTag).find('source[type="audio/mpeg"]').attr('src', trackurl);
    $(audioTag).attr('title', trackurl);
  }
};

Um eine bestimmte Episode abzuspielen verwende ich eine weitere Funktion in Zusammenspiel mit einem Eventhandler für das canplay-Event des Audio-Elements.

var playTrack = function(trackurl) {
  "use strict";
  var audioTag = $('#player audio')[0];
  if (trackurl) {
    activateTrack(trackurl);
    audioTag.load();
  }
};
$('#player audio').on('canplay', function() {
  this.play();
});

Die Funktion play() des Audio-Tags wird nicht direkt in playTrack() aufgerufen weil der Browser Chrome manchmal Schluckauf bekommt wenn man einen Track starten möchte der noch nicht ausreichend weit geladen wurde. Dem konnte ich abhelfen indem ich lediglich das Laden der neuen Episode anstoße und dann wartet bis die Audiodatei abspielbar ist bevor ich sie starte. Das Event canplay ist hierfür genau das richtige.

Die Qual der Wahl

Mit den obigen Funktionen ist es nun kein Problem mehr durch anklicken eines Listenpunkts die darin angegebene Episode abzuspielen. Ein einfacher click-Eventhandler löst bereits die Aufgabenstellung:

$('#playlist').on('click', 'li', function(event) {
    event.preventDefault();
    event.stopPropagation();
    playTrack($(this).find('.title a').attr('href'));
});

Zusatzfunktionen

Als kleinen Bonus zu diesem erfolgreichen Schritt auf dem Weg zu meinem eigenen Podcatcher möchte ich noch drei weitere Interaktionen zwischen Player und Playlist vorstellen,

Automatischer Wechsel zum nächsten Track

Um am Ende eines Tracks automatisch zum nächsten Eintrag der Liste zu wechseln verwende ich einen weiteren Eventhandler und eine kleine Hilfsmethode:

var nextTrack = function() {
  "use strict";
  var activeTrack = $('#playlist').find('.activeTrack');
  return activeTrack.next().find('.title a').attr('href');
};
$('#player audio').on('ended', function() {
  playTrack(nextTrack());
});

Mit der Funktion nextTrack() ermittele ich anhand der Klasse ‘activeTrack’ den aktuellen Titel in der Playlist und gebe die URL des nachfolgenden Tracks aus. Diese URL wird dann am Ende des laufenden Tracks durch den Handler für das ended-Event aus der Media-API verwendet um gleich den nächsten Track zu starten.

Vorheriger Track und nächster Track

Mit der gleichen Funktion nextTrack() und ihrem Gegenstück previousTrack() kann ich auch recht komfortable zwischen den einzelnen Titeln in der Liste springen. Dazu füge ich meinem Markup nur noch zwei Buttons und passende Eventhandler hinzu die diese Funktionen aufrufen.

var previousTrack = function() {
  "use strict";
  var activeTrack = $('#playlist').find('.activeTrack');
  return activeTrack.prev().find('.title a').attr('href');
};
$('#player #playPreviousTrack').on('click', function() {
  playTrack(previousTrack());
});

Probleme und Einschränkungen

Durch die Einschränkung auf MP3-Dateien kommen leider einige Browser nicht für den Podcatcher in Frage. Opera und Iron zum Beispiel unterstützen, wohl aus Lizenzgründen, das MP3-Format nicht. Auf der anderen Seite bieten viele Podcasts lediglich MP3’s an. Was mich zu bewegt alle Browser außer Googles Chrome vorläufig außen vor zu lassen. Der Internet Explorer könnte auch funktionieren – interessiert mich aber momentan nicht da er auf Android nicht verfügbar ist.

Ausblick

Wer mag kann sich das Ergebnis auch begutachten und sich ein paar Episoden des Podcasts CRE anhören.

Als nächsten Schritt werde ich darüber nachgrübeln wie ich überhaupt meine Playlist zusammenstelle.