Task 043: .ASX File Format

Task 043: .ASX File Format

File Format Specifications for the .ASX File Format

The .ASX file format is an Advanced Stream Redirector metafile used primarily with Windows Media Player. It is based on XML syntax and serves as a playlist format to direct media players to streaming or local media files, typically in ASF (Advanced Systems Format) or other compatible formats. The format supports version 3.0 as the standard syntax, with backward compatibility for earlier versions. Metafiles are encoded in ANSI or UTF-8 and must begin with the  tag. The structure allows for metadata, playback controls, and references to media content.

1. List of All Properties Intrinsic to the .ASX File Format

The properties of the .ASX file format refer to the XML elements and attributes that define its structure and content. These are intrinsic to the format itself, governing how the file is parsed and interpreted by media players. Below is a comprehensive list based on the official specifications:

ASX (Root Element): Defines the metafile. Attributes:

  • VERSION: Decimal number (required, typically "3.0").
  • PREVIEWMODE: "YES" or "NO" (optional, default "NO"; enables preview mode).
  • BANNERBAR: "AUTO" or "FIXED" (optional, default "AUTO"; controls banner space reservation).

ABSTRACT: Provides a brief description of the metafile or entry. No attributes; contains text content.

AUTHOR: Specifies the author of the metafile or entry. No attributes; contains text content.

BANNER: Defines a banner graphic. Attributes:

  • HREF: URL to the banner image.

BASE: Sets a base URL for relative references. Attributes:

  • HREF: Base URL string.

COPYRIGHT: Indicates copyright information. No attributes; contains text content.

DURATION: Specifies the playback duration for an entry. Attributes:

  • VALUE: Time in "HH:MM:SS.f" format.

ENDMARKER: Defines the end point of playback in an entry. Attributes:

  • NUMBER: Frame number.
  • NAME: Marker name.

ENTRY: Represents a media item in the playlist. Attributes:

  • CLIENTSKIP: "YES" or "NO" (optional; allows skipping).

ENTRYREF: References another metafile. Attributes:

  • HREF: URL to the external metafile.

EVENT: Triggers an event during playback. Attributes:

  • WHEN: Timing specification.
  • NAME: Event name.

LOGO: Defines a logo image. Attributes:

  • HREF: URL to the logo image.
  • STYLE: Display style.

MOREINFO: Provides additional information links. Attributes:

  • HREF: URL to more information.
  • TARGET: Target frame for the link.

PARAM: Defines custom parameters. Attributes:

  • NAME: Parameter name.
  • VALUE: Parameter value.

PREVIEWDURATION: Sets the duration for preview mode. Attributes:

  • VALUE: Time in "HH:MM:SS.f" format.

REF: References a media file within an entry. Attributes:

  • HREF: URL to the media file.

REPEAT: Controls repetition of entries. Attributes:

  • COUNT: Number of repetitions.

STARTMARKER: Defines the start point of playback in an entry. Attributes:

  • NUMBER: Frame number.
  • NAME: Marker name.

STARTTIME: Specifies the start time for an entry. Attributes:

  • VALUE: Time in "HH:MM:SS.f" format.

TITLE: Provides the title of the metafile or entry. No attributes; contains text content.

These properties can be nested (e.g., ENTRY can contain REF, TITLE, DURATION, etc.), forming a hierarchical structure.

Based on web searches, the following are direct links to .ASX files used for media streaming playlists:

Note: These links were identified from reliable sources but may be subject to availability changes over time. If inaccessible, they represent typical .ASX usage in radio streaming.

3. Ghost Blog Embedded HTML JavaScript for Drag-and-Drop .ASX File Dump

The following is an HTML code snippet with embedded JavaScript that can be embedded in a Ghost blog post. It creates a drop zone where a user can drag and drop an .ASX file. The script reads the file, parses the XML, extracts all properties from the list above, and displays them on the screen.

Drag and drop your .ASX file here.

This code parses the XML and dumps the properties in JSON format to the screen.

4. Python Class for .ASX File Handling

The following Python class uses xml.etree.ElementTree to open, decode (parse), read, write, and print all properties.

import xml.etree.ElementTree as ET

class ASXHandler:
    def __init__(self, filepath):
        self.filepath = filepath
        self.tree = None
        self.root = None
        self.properties = {}

    def read_and_decode(self):
        self.tree = ET.parse(self.filepath)
        self.root = self.tree.getroot()
        self.extract_properties()

    def extract_properties(self):
        if self.root.tag == 'ASX':
            self.properties['VERSION'] = self.root.attrib.get('VERSION')
            self.properties['PREVIEWMODE'] = self.root.attrib.get('PREVIEWMODE')
            self.properties['BANNERBAR'] = self.root.attrib.get('BANNERBAR')
        elements = ['ABSTRACT', 'AUTHOR', 'BANNER', 'BASE', 'COPYRIGHT', 'DURATION', 'ENDMARKER', 'ENTRY', 'ENTRYREF', 'EVENT', 'LOGO', 'MOREINFO', 'PARAM', 'PREVIEWDURATION', 'REF', 'REPEAT', 'STARTMARKER', 'STARTTIME', 'TITLE']
        for el in elements:
            found = self.root.findall('.//' + el)
            if found:
                self.properties[el] = [{'text': tag.text.strip() if tag.text else '', 'attributes': tag.attrib} for tag in found]

    def print_properties(self):
        import json
        print(json.dumps(self.properties, indent=4))

    def write(self, output_filepath):
        if self.tree:
            self.tree.write(output_filepath, encoding='utf-8', xml_declaration=True)

# Usage example:
# handler = ASXHandler('sample.asx')
# handler.read_and_decode()
# handler.print_properties()
# handler.write('output.asx')

5. Java Class for .ASX File Handling

The following Java class uses javax.xml.parsers.DocumentBuilder to open, decode, read, write, and print all properties.

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.w3c.dom.Node;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import java.io.File;
import java.util.HashMap;
import java.util.Map;
import java.util.ArrayList;

public class ASXHandler {
    private String filepath;
    private Document doc;
    private Map<String, Object> properties = new HashMap<>();

    public ASXHandler(String filepath) {
        this.filepath = filepath;
    }

    public void readAndDecode() throws Exception {
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        DocumentBuilder builder = factory.newDocumentBuilder();
        doc = builder.parse(new File(filepath));
        extractProperties();
    }

    private void extractProperties() {
        Element root = doc.getDocumentElement();
        if (root.getTagName().equals("ASX")) {
            properties.put("VERSION", root.getAttribute("VERSION"));
            properties.put("PREVIEWMODE", root.getAttribute("PREVIEWMODE"));
            properties.put("BANNERBAR", root.getAttribute("BANNERBAR"));
        }
        String[] elements = {"ABSTRACT", "AUTHOR", "BANNER", "BASE", "COPYRIGHT", "DURATION", "ENDMARKER", "ENTRY", "ENTRYREF", "EVENT", "LOGO", "MOREINFO", "PARAM", "PREVIEWDURATION", "REF", "REPEAT", "STARTMARKER", "STARTTIME", "TITLE"};
        for (String el : elements) {
            NodeList nodes = doc.getElementsByTagName(el);
            if (nodes.getLength() > 0) {
                ArrayList<Map<String, String>> list = new ArrayList<>();
                for (int i = 0; i < nodes.getLength(); i++) {
                    Node node = nodes.item(i);
                    Map<String, String> map = new HashMap<>();
                    map.put("text", node.getTextContent().trim());
                    for (int j = 0; j < node.getAttributes().getLength(); j++) {
                        Node attr = node.getAttributes().item(j);
                        map.put(attr.getNodeName(), attr.getNodeValue());
                    }
                    list.add(map);
                }
                properties.put(el, list);
            }
        }
    }

    public void printProperties() {
        System.out.println(properties);
    }

    public void write(String outputFilepath) throws Exception {
        TransformerFactory transformerFactory = TransformerFactory.newInstance();
        Transformer transformer = transformerFactory.newTransformer();
        DOMSource source = new DOMSource(doc);
        StreamResult result = new StreamResult(new File(outputFilepath));
        transformer.transform(source, result);
    }

    // Usage example:
    // public static void main(String[] args) throws Exception {
    //     ASXHandler handler = new ASXHandler("sample.asx");
    //     handler.readAndDecode();
    //     handler.printProperties();
    //     handler.write("output.asx");
    // }
}

6. JavaScript Class for .ASX File Handling

The following JavaScript class uses DOMParser to open (via FileReader), decode, read, write (to console or blob), and print properties. Note: File reading requires a browser context with File API.

class ASXHandler {
  constructor(filepath) {
    this.filepath = filepath;
    this.xml = null;
    this.properties = {};
  }

  async readAndDecode() {
    // Assuming Node.js with fs, or browser with fetch/FileReader
    // For simplicity, assume browser fetch for local file (CORS may apply)
    const response = await fetch(this.filepath);
    const text = await response.text();
    const parser = new DOMParser();
    this.xml = parser.parseFromString(text, 'text/xml');
    this.extractProperties();
  }

  extractProperties() {
    const root = this.xml.getElementsByTagName('ASX')[0];
    if (root) {
      this.properties.VERSION = root.getAttribute('VERSION');
      this.properties.PREVIEWMODE = root.getAttribute('PREVIEWMODE');
      this.properties.BANNERBAR = root.getAttribute('BANNERBAR');
    }
    const elements = ['ABSTRACT', 'AUTHOR', 'BANNER', 'BASE', 'COPYRIGHT', 'DURATION', 'ENDMARKER', 'ENTRY', 'ENTRYREF', 'EVENT', 'LOGO', 'MOREINFO', 'PARAM', 'PREVIEWDURATION', 'REF', 'REPEAT', 'STARTMARKER', 'STARTTIME', 'TITLE'];
    elements.forEach(el => {
      const tags = this.xml.getElementsByTagName(el);
      if (tags.length > 0) {
        this.properties[el] = Array.from(tags).map(tag => ({
          text: tag.textContent.trim(),
          attributes: Array.from(tag.attributes).reduce((acc, attr) => { acc[attr.name] = attr.value; return acc; }, {})
        }));
      }
    });
  }

  printProperties() {
    console.log(JSON.stringify(this.properties, null, 2));
  }

  write(outputFilepath) {
    const serializer = new XMLSerializer();
    const xmlStr = serializer.serializeToString(this.xml);
    // In browser, create blob and download
    const blob = new Blob([xmlStr], { type: 'text/xml' });
    const link = document.createElement('a');
    link.href = URL.createObjectURL(blob);
    link.download = outputFilepath;
    link.click();
  }
}

// Usage example:
// const handler = new ASXHandler('sample.asx');
// await handler.readAndDecode();
// handler.printProperties();
// handler.write('output.asx');

7. C++ Class for .ASX File Handling

The following C++ class uses TinyXML-2 (assume included; a lightweight XML parser) to open, decode, read, write, and print properties. Note: TinyXML-2 must be linked for compilation.

#include <iostream>
#include <map>
#include <vector>
#include <string>
#include "tinyxml2.h"  // Assume TinyXML-2 library is included

using namespace tinyxml2;
using namespace std;

class ASXHandler {
private:
    string filepath;
    XMLDocument doc;
    map<string, vector<map<string, string>>> properties;

public:
    ASXHandler(const string& fp) : filepath(fp) {}

    void readAndDecode() {
        doc.LoadFile(filepath.c_str());
        extractProperties();
    }

    void extractProperties() {
        XMLElement* root = doc.FirstChildElement("ASX");
        if (root) {
            map<string, string> rootAttrs;
            rootAttrs["VERSION"] = root->Attribute("VERSION") ? root->Attribute("VERSION") : "";
            rootAttrs["PREVIEWMODE"] = root->Attribute("PREVIEWMODE") ? root->Attribute("PREVIEWMODE") : "";
            rootAttrs["BANNERBAR"] = root->Attribute("BANNERBAR") ? root->Attribute("BANNERBAR") : "";
            properties["ASX"] = {rootAttrs};
        }
        vector<string> elements = {"ABSTRACT", "AUTHOR", "BANNER", "BASE", "COPYRIGHT", "DURATION", "ENDMARKER", "ENTRY", "ENTRYREF", "EVENT", "LOGO", "MOREINFO", "PARAM", "PREVIEWDURATION", "REF", "REPEAT", "STARTMARKER", "STARTTIME", "TITLE"};
        for (const auto& el : elements) {
            vector<map<string, string>> list;
            XMLElement* tag = doc.FirstChildElement(el.c_str());
            while (tag) {
                map<string, string> map;
                map["text"] = tag->GetText() ? tag->GetText() : "";
                const XMLAttribute* attr = tag->FirstAttribute();
                while (attr) {
                    map[attr->Name()] = attr->Value();
                    attr = attr->Next();
                }
                list.push_back(map);
                tag = tag->NextSiblingElement(el.c_str());
            }
            if (!list.empty()) {
                properties[el] = list;
            }
        }
    }

    void printProperties() {
        for (const auto& prop : properties) {
            cout << prop.first << ": " << endl;
            for (const auto& item : prop.second) {
                for (const auto& kv : item) {
                    cout << "  " << kv.first << ": " << kv.second << endl;
                }
                cout << "---" << endl;
            }
        }
    }

    void write(const string& outputFilepath) {
        doc.SaveFile(outputFilepath.c_str());
    }
};

// Usage example:
// int main() {
//     ASXHandler handler("sample.asx");
//     handler.readAndDecode();
//     handler.printProperties();
//     handler.write("output.asx");
//     return 0;
// }