How to categorize an AV stream for audio streaming (HTML)

[This article is for Windows 8.x and Windows Phone 8.x developers writing Windows Runtime apps. If you’re developing for Windows 10, see the latest documentation]

This tutorial shows you how to select the correct category for an audio-video (AV) stream to configure it as an audio playback stream.

An AV stream can stream as video with audio, or it can stream as audio only. You can ensure that an AV stream plays in the appropriate mode, by properly initializing it and then selecting a category for it.

What you need to know

Technologies

  • Windows Runtime

Prerequisites

  • You should be familiar with HTML, JavaScript, and events.

Instructions

Step 1: Code for your Default.html file

The Playback Manager (PBM) sample shows you how to configure an AV stream for audio playback. The PBM sample uses the following HTML script to format the screen with the UI elements that allow you to experience its functionality. The sample allows you to select the type of stream (media or communications) that you would like to experiment with. Then you can click a button to start the demo for that particular scenario.

  • Here is the HTML code that the sample uses:

    <!DOCTYPE html>
    <html>
    <head>
        <title>PBM Demo BUILD</title>
    
        <!-- WinJS references -->
        <link href="winjs/css/ui-light.css" rel="stylesheet" type="text/css" />
        <script type="text/javascript" src="WinJS/js/base.js"></script>
        <script type="text/javascript" src="WinJS/js/ui.js"></script>
        <script type="text/javascript" src="WinJS/js/wwaapp.js"></script>
    
        <!-- SDK Base references -->
        <link rel="stylesheet" type="text/css" href="css/base-sdk.css" />
        <script type="text/javascript" src="base-sdk.js"></script>
    
        <!-- Sample references -->
        <link rel="stylesheet" type="text/css" href="css/program.css" />
        <script type="text/javascript" src="program.js"></script>
    </head>
    <body role="application">
        <div id="rootGrid">
            <div id="header" role="contentinfo"></div>
            <div id="content">
                <h1 id="featureLabel">PBM Demo BUILD</h1>
    
                <h2 id="inputLabel">Input</h2>
    
                <div id="input" role="main" aria-labelledby="inputLabel">
                    <div class="options">
                        <h3 id="listLabel">Select scenario:</h3>
                        <select size="7" id="scenarios" aria-labelledby="listLabel">
                            <option selected="selected" value="1">1) Stream type: Media</option>
                            <option value="2">2) Stream type: Communications</option>
                        </select>
                    </div>
                    <div class="details" role="region" aria-labelledby="descLabel" aria-live="assertive">
                        <h3 id="descLabel">Description:</h3>
    
                        <!-- Scenario 1 Input -->
                        <div class="item" id="scenario1Input">
                                <p>Start a media application with "Media" stream category set, listen for PBM Notifications and pause when another media app starts.</p>
                            <button class="action" id="scenario1Open">Try Scenario 1</button>
                            <br /><br />
                        </div>
    
                        <!-- Scenario 2 Input -->
                        <div class="item" id="scenario2Input">
                                <p>Start a media application with "communications" stream type.</p>
                            <button id="scenario2Open">Try Scenario 2</button><br /><br />
                        </div>
    
                    </div>
                </div>
                <h2 id="outputLabel"> Output</h2>
    
                <div id="output" role="region" aria-labelledby="outputLabel" aria-live="assertive">
    
                        <!-- Scenario 1 Output -->
                        <div class="item" id="scenario1Output">
                        </div>
    
                        <!-- Scenario 2 Output -->
                        <div class="item" id="scenario2Output">
                        </div>
                </div>
            </div>
            <div id="footer" role="contentinfo"></div>
        </div>
    </body>
    </html>
    

Step 2: Code for your Default.js file

In the media stream scenario, the PBM sample configures event notifications, and then listens to determine whether or not the active media app has lost focus to another media app. When the active media app loses focus, it sets itself to pause while the new media app starts.

  • Here is the JavaScript code that the sample uses:

    //// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
    //// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
    //// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
    //// PARTICULAR PURPOSE.
    ////
    //// Copyright (c) Microsoft Corporation. All rights reserved
    
    /// <reference path="base-sdk.js" />
    
    
    (function () {
        var audtag = null;
        var mediaControl;
        var isPlaying;
    
        function id(elementId) {
            return document.getElementById(elementId);
        }
    
        function scenario1DoSomething() {
            // Create new audio tag for "media" class
            if(!audtag) {
              audtag = document.createElement('audio');
              audtag.setAttribute("id", "audtag");
              audtag.setAttribute("controls", "true");
              audtag.setAttribute("msAudioCategory", "backgroundcapablemedia");
              audtag.setAttribute("src", "folk_rock.mp3");
              document.getElementById("scenario1Output").appendChild(audtag);
              audtag.load();
            }
        }
    
        function scenario2DoSomething() {
            // Create new audio tag for "communication" class
            if(!audtag) {
              audtag = document.createElement('audio');
              audtag.setAttribute("id", "audtag");
              audtag.setAttribute("controls", "true");
              audtag.setAttribute("msAudioDeviceType", "communications");
              audtag.setAttribute("msAudioCategory", "communications");
              audtag.setAttribute("src", "folk_rock.mp3");
              document.getElementById("scenario2Output").appendChild(audtag);
              audtag.load();
            }
        }
    
        function initialize() {
            // Add any initialization code here
    
            id("scenario1Open").addEventListener("click", scenario1DoSomething, false);
            id("scenario2Open").addEventListener("click", scenario2DoSomething, false);
            id("scenarios").addEventListener("change", onScenarioChanged, false);
    
    
            // Create the media control.
            var mediaControl = Windows.Media.MediaControl;
            // Add event listeners for PBM notifications to illustrate that app is
            // losing/gaining focus, and then pass the audio tag along to the function
            mediaControl.addEventListener("soundlevelchanged", soundLevelChanged, false);
        }
    
    
        function onScenarioChanged() {
            // Do any necessary clean up on the output, the scenario id
            // can be obtained from sdkSample.scenarioId.
            sdkSample.displayStatus("");
    
            if (audtag) {          
                parentNode = document.getElementById("audtag").parentNode;
                parentNode.removeChild(document.getElementById("audtag"));
            }
            audtag = null;
        }
    
        function getTimeStampedMessage(eventCalled) {
            var timeformat = new Windows.Globalization.DateTimeFormatting.DateTimeFormatter("longtime");
            var time = timeformat.format(new Date());    
    
            message = eventCalled + "\t\t" + time;
            return message;
        }
    
        function soundLevelChanged() {
            var soundLevel = Windows.Media.MediaControl.soundLevel;
    
            statusMessagesFunc(soundLevel);
            if (soundLevel !== Windows.Media.SoundLevel.muted) {
                appUnmuted();
            } else {
                appMuted();
            }
        }
    
        function appMuted() {
            var Focus = 1;
    
            if (audtag) {
                if (!audtag.paused) {
                    isPlaying = true;
                    audtag.pause();
                } else {
                    isPlaying = false;
                }
    
                statusMessagesFunc(Focus);
            }
        }
    
        function appUnmuted() {
            var Focus = 2;
    
            if (audtag) {
                if (isPlaying) {
                    audtag.play();
                }
    
              statusMessagesFunc(Focus);
            }
        }
    
        document.addEventListener("DOMContentLoaded", initialize, false);
    
    })();
    

Step 3: Run and test the Playback Manager sample

  • Detailed instructions for building, running and testing this sample are included in the description for this sample. To see the build and other instructions for this sample, refer to the Playback manager Sample.

Remarks

The code that you just built and tested allowed you to initialize an AV steam, and then to select the correct category for it to stream for audio playback. The code then streamed your selected MPEG-Layer 3 (MP3) audio file in the background.

Whenever focus is lost or received, the code checks to determine the Play/Pause state of the stream, and then mutes or unmutes the stream accordingly.

For developer guidance and more information about AV stream categories, see the Quickstart: adding audio in a Windows Store app topic and the Audio Playback in a Windows Store app whitepaper.

Audio Playback in a Windows Store app

Guidelines for developing audio-aware apps

Playback Manager sample

Quickstart: adding audio in a Windows Store app