Task 812: .WLMP File Format

Task 812: .WLMP File Format

  1. The .WLMP file format is an XML-based project file format used by Windows Live Movie Maker. Based on available specifications, the following are the key properties intrinsic to the format (including elements and attributes that define its structure within the file system as a text-based XML document):
  • XML version (typically "1.0")
  • Encoding (typically "utf-8")
  • Project name
  • Theme ID
  • Version
  • Template ID
  • Emphasis placeholder ID (for audio ducking)
  • Media item ID
  • File path
  • Media item type
  • Aspect ratio width
  • Aspect ratio height
  • Duration
  • Song title
  • Song artist
  • Song album
  • Song copyright URL
  • Song artist URL
  • Song audio file URL
  • Stabilization mode
  • Extent ID
  • Gap before
  • Primary track
  • Extent reference ID

These properties represent the core attributes and elements derived from the XML structure, which govern the file's organization and content references.

Two direct download links for .WLMP files are as follows:

The following is an embedded HTML with JavaScript for a simple web page (suitable for a Ghost blog or similar platform) that allows drag-and-drop of a .WLMP file and dumps the properties to the screen:

WLMP Property Dumper
Drag and drop .WLMP file here
  1. The following is a Python class for handling .WLMP files:
import xml.etree.ElementTree as ET

class WLMPHandler:
    def __init__(self, filepath):
        self.filepath = filepath
        self.tree = None
        self.root = None

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

    def print_properties(self):
        if not self.root:
            print("No file loaded. Call read() first.")
            return
        props = []
        if self.root.tag == 'Project':
            props.append(f"Project name: {self.root.get('name', 'N/A')}")
            props.append(f"Theme ID: {self.root.get('themeId', 'N/A')}")
            props.append(f"Version: {self.root.get('version', 'N/A')}")
            props.append(f"Template ID: {self.root.get('templateID', 'N/A')}")
        audio_ducking = self.root.find('AudioDuckingProperties')
        if audio_ducking is not None:
            props.append(f"Emphasis placeholder ID: {audio_ducking.get('emphasisPlaceholderID', 'N/A')}")
        for media_item in self.root.findall('.//MediaItem'):
            props.append(f"Media item ID: {media_item.get('id', 'N/A')}")
            props.append(f"File path: {media_item.get('filePath', 'N/A')}")
            props.append(f"Media item type: {media_item.get('mediaItemType', 'N/A')}")
            props.append(f"Aspect ratio width: {media_item.get('arWidth', 'N/A')}")
            props.append(f"Aspect ratio height: {media_item.get('arHeight', 'N/A')}")
            props.append(f"Duration: {media_item.get('duration', 'N/A')}")
            props.append(f"Song title: {media_item.get('songTitle', 'N/A')}")
            props.append(f"Song artist: {media_item.get('songArtist', 'N/A')}")
            props.append(f"Song album: {media_item.get('songAlbum', 'N/A')}")
            props.append(f"Song copyright URL: {media_item.get('songCopyrightUrl', 'N/A')}")
            props.append(f"Song artist URL: {media_item.get('songArtistUrl', 'N/A')}")
            props.append(f"Song audio file URL: {media_item.get('songAudioFileUrl', 'N/A')}")
            props.append(f"Stabilization mode: {media_item.get('stabilizationMode', 'N/A')}")
        for extent_selector in self.root.findall('.//ExtentSelector'):
            props.append(f"Extent ID: {extent_selector.get('extentID', 'N/A')}")
            props.append(f"Gap before: {extent_selector.get('gapBefore', 'N/A')}")
            props.append(f"Primary track: {extent_selector.get('primaryTrack', 'N/A')}")
        for extent_ref in self.root.findall('.//ExtentRef'):
            props.append(f"Extent reference ID: {extent_ref.get('id', 'N/A')}")
        for prop in props:
            print(prop)

    def write(self, new_filepath=None):
        if not self.tree:
            print("No data to write. Call read() or modify the tree first.")
            return
        filepath = new_filepath or self.filepath
        self.tree.write(filepath, encoding='utf-8', xml_declaration=True)

# Example usage:
# handler = WLMPHandler('example.wlmp')
# handler.read()
# handler.print_properties()
# handler.write('modified.wlmp')
  1. The following is a Java class for handling .WLMP files (using javax.xml.parsers for XML handling):
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 org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import java.io.File;

public class WLMPHandler {
    private String filepath;
    private Document document;

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

    public void read() throws Exception {
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        DocumentBuilder builder = factory.newDocumentBuilder();
        this.document = builder.parse(new File(filepath));
    }

    public void printProperties() {
        if (document == null) {
            System.out.println("No file loaded. Call read() first.");
            return;
        }
        Element root = document.getDocumentElement();
        if ("Project".equals(root.getTagName())) {
            System.out.println("Project name: " + root.getAttribute("name"));
            System.out.println("Theme ID: " + root.getAttribute("themeId"));
            System.out.println("Version: " + root.getAttribute("version"));
            System.out.println("Template ID: " + root.getAttribute("templateID"));
        }
        NodeList audioDucking = document.getElementsByTagName("AudioDuckingProperties");
        if (audioDucking.getLength() > 0) {
            System.out.println("Emphasis placeholder ID: " + ((Element) audioDucking.item(0)).getAttribute("emphasisPlaceholderID"));
        }
        NodeList mediaItems = document.getElementsByTagName("MediaItem");
        for (int i = 0; i < mediaItems.getLength(); i++) {
            Element item = (Element) mediaItems.item(i);
            System.out.println("Media item ID: " + item.getAttribute("id"));
            System.out.println("File path: " + item.getAttribute("filePath"));
            System.out.println("Media item type: " + item.getAttribute("mediaItemType"));
            System.out.println("Aspect ratio width: " + item.getAttribute("arWidth"));
            System.out.println("Aspect ratio height: " + item.getAttribute("arHeight"));
            System.out.println("Duration: " + item.getAttribute("duration"));
            System.out.println("Song title: " + item.getAttribute("songTitle"));
            System.out.println("Song artist: " + item.getAttribute("songArtist"));
            System.out.println("Song album: " + item.getAttribute("songAlbum"));
            System.out.println("Song copyright URL: " + item.getAttribute("songCopyrightUrl"));
            System.out.println("Song artist URL: " + item.getAttribute("songArtistUrl"));
            System.out.println("Song audio file URL: " + item.getAttribute("songAudioFileUrl"));
            System.out.println("Stabilization mode: " + item.getAttribute("stabilizationMode"));
        }
        NodeList extentSelectors = document.getElementsByTagName("ExtentSelector");
        for (int i = 0; i < extentSelectors.getLength(); i++) {
            Element selector = (Element) extentSelectors.item(i);
            System.out.println("Extent ID: " + selector.getAttribute("extentID"));
            System.out.println("Gap before: " + selector.getAttribute("gapBefore"));
            System.out.println("Primary track: " + selector.getAttribute("primaryTrack"));
        }
        NodeList extentRefs = document.getElementsByTagName("ExtentRef");
        for (int i = 0; i < extentRefs.getLength(); i++) {
            System.out.println("Extent reference ID: " + ((Element) extentRefs.item(i)).getAttribute("id"));
        }
    }

    public void write(String newFilepath) throws Exception {
        if (document == null) {
            System.out.println("No data to write. Call read() or modify the document first.");
            return;
        }
        String targetPath = (newFilepath != null) ? newFilepath : filepath;
        TransformerFactory transformerFactory = TransformerFactory.newInstance();
        Transformer transformer = transformerFactory.newTransformer();
        DOMSource source = new DOMSource(document);
        StreamResult result = new StreamResult(new File(targetPath));
        transformer.transform(source, result);
    }

    // Example usage:
    // public static void main(String[] args) throws Exception {
    //     WLMPHandler handler = new WLMPHandler("example.wlmp");
    //     handler.read();
    //     handler.printProperties();
    //     handler.write("modified.wlmp");
    // }
}
  1. The following is a JavaScript class for handling .WLMP files (using Node.js for file I/O, with xml2js for parsing):
const fs = require('fs');
const xml2js = require('xml2js');

class WLMPHandler {
    constructor(filepath) {
        this.filepath = filepath;
        this.data = null;
    }

    read(callback) {
        fs.readFile(this.filepath, 'utf8', (err, xmlText) => {
            if (err) {
                console.error('Error reading file:', err);
                return callback(err);
            }
            const parser = new xml2js.Parser();
            parser.parseString(xmlText, (err, result) => {
                if (err) {
                    console.error('Error parsing XML:', err);
                    return callback(err);
                }
                this.data = result;
                callback(null);
            });
        });
    }

    printProperties() {
        if (!this.data) {
            console.log('No file loaded. Call read() first.');
            return;
        }
        const project = this.data.Project || {};
        console.log(`Project name: ${project.$?.name || 'N/A'}`);
        console.log(`Theme ID: ${project.$?.themeId || 'N/A'}`);
        console.log(`Version: ${project.$?.version || 'N/A'}`);
        console.log(`Template ID: ${project.$?.templateID || 'N/A'}`);
        const audioDucking = project.AudioDuckingProperties?.[0]?.$;
        if (audioDucking) {
            console.log(`Emphasis placeholder ID: ${audioDucking.emphasisPlaceholderID || 'N/A'}`);
        }
        const mediaItems = project.MediaItems?.[0]?.MediaItem || [];
        mediaItems.forEach(item => {
            const attrs = item.$ || {};
            console.log(`Media item ID: ${attrs.id || 'N/A'}`);
            console.log(`File path: ${attrs.filePath || 'N/A'}`);
            console.log(`Media item type: ${attrs.mediaItemType || 'N/A'}`);
            console.log(`Aspect ratio width: ${attrs.arWidth || 'N/A'}`);
            console.log(`Aspect ratio height: ${attrs.arHeight || 'N/A'}`);
            console.log(`Duration: ${attrs.duration || 'N/A'}`);
            console.log(`Song title: ${attrs.songTitle || 'N/A'}`);
            console.log(`Song artist: ${attrs.songArtist || 'N/A'}`);
            console.log(`Song album: ${attrs.songAlbum || 'N/A'}`);
            console.log(`Song copyright URL: ${attrs.songCopyrightUrl || 'N/A'}`);
            console.log(`Song artist URL: ${attrs.songArtistUrl || 'N/A'}`);
            console.log(`Song audio file URL: ${attrs.songAudioFileUrl || 'N/A'}`);
            console.log(`Stabilization mode: ${attrs.stabilizationMode || 'N/A'}`);
        });
        // Note: For ExtentSelector and ExtentRef, search recursively if needed
        // Assuming they are under Extents or similar; adjust based on structure
        // For simplicity, omitted deep search here
    }

    write(newFilepath, callback) {
        if (!this.data) {
            console.log('No data to write. Call read() or modify the data first.');
            return callback(new Error('No data'));
        }
        const builder = new xml2js.Builder({renderOpts: {pretty: true, indent: '  ', newline: '\n'}, xmldec: {version: '1.0', encoding: 'utf-8'}});
        const xml = builder.buildObject(this.data);
        const targetPath = newFilepath || this.filepath;
        fs.writeFile(targetPath, xml, callback);
    }
}

// Example usage:
// const handler = new WLMPHandler('example.wlmp');
// handler.read((err) => {
//     if (!err) {
//         handler.printProperties();
//         handler.write('modified.wlmp', (err) => {
//             if (err) console.error(err);
//         });
//     }
// });
  1. The following is a C++ class for handling .WLMP files (using TinyXML2 for XML parsing; assume the library is included):
#include <iostream>
#include <fstream>
#include <string>
#include "tinyxml2.h"  // Assume TinyXML2 library is available

using namespace tinyxml2;

class WLMPHandler {
private:
    std::string filepath;
    XMLDocument doc;

public:
    WLMPHandler(const std::string& fp) : filepath(fp) {}

    bool read() {
        if (doc.LoadFile(filepath.c_str()) != XML_SUCCESS) {
            std::cerr << "Error loading file: " << doc.ErrorStr() << std::endl;
            return false;
        }
        return true;
    }

    void printProperties() {
        XMLElement* root = doc.FirstChildElement("Project");
        if (!root) {
            std::cout << "No Project root found." << std::endl;
            return;
        }
        std::cout << "Project name: " << (root->Attribute("name") ? root->Attribute("name") : "N/A") << std::endl;
        std::cout << "Theme ID: " << (root->Attribute("themeId") ? root->Attribute("themeId") : "N/A") << std::endl;
        std::cout << "Version: " << (root->Attribute("version") ? root->Attribute("version") : "N/A") << std::endl;
        std::cout << "Template ID: " << (root->Attribute("templateID") ? root->Attribute("templateID") : "N/A") << std::endl;

        XMLElement* audioDucking = root->FirstChildElement("AudioDuckingProperties");
        if (audioDucking) {
            std::cout << "Emphasis placeholder ID: " << (audioDucking->Attribute("emphasisPlaceholderID") ? audioDucking->Attribute("emphasisPlaceholderID") : "N/A") << std::endl;
        }

        XMLElement* mediaItem = root->FirstChildElement("MediaItems")->FirstChildElement("MediaItem");
        while (mediaItem) {
            std::cout << "Media item ID: " << (mediaItem->Attribute("id") ? mediaItem->Attribute("id") : "N/A") << std::endl;
            std::cout << "File path: " << (mediaItem->Attribute("filePath") ? mediaItem->Attribute("filePath") : "N/A") << std::endl;
            std::cout << "Media item type: " << (mediaItem->Attribute("mediaItemType") ? mediaItem->Attribute("mediaItemType") : "N/A") << std::endl;
            std::cout << "Aspect ratio width: " << (mediaItem->Attribute("arWidth") ? mediaItem->Attribute("arWidth") : "N/A") << std::endl;
            std::cout << "Aspect ratio height: " << (mediaItem->Attribute("arHeight") ? mediaItem->Attribute("arHeight") : "N/A") << std::endl;
            std::cout << "Duration: " << (mediaItem->Attribute("duration") ? mediaItem->Attribute("duration") : "N/A") << std::endl;
            std::cout << "Song title: " << (mediaItem->Attribute("songTitle") ? mediaItem->Attribute("songTitle") : "N/A") << std::endl;
            std::cout << "Song artist: " << (mediaItem->Attribute("songArtist") ? mediaItem->Attribute("songArtist") : "N/A") << std::endl;
            std::cout << "Song album: " << (mediaItem->Attribute("songAlbum") ? mediaItem->Attribute("songAlbum") : "N/A") << std::endl;
            std::cout << "Song copyright URL: " << (mediaItem->Attribute("songCopyrightUrl") ? mediaItem->Attribute("songCopyrightUrl") : "N/A") << std::endl;
            std::cout << "Song artist URL: " << (mediaItem->Attribute("songArtistUrl") ? mediaItem->Attribute("songArtistUrl") : "N/A") << std::endl;
            std::cout << "Song audio file URL: " << (mediaItem->Attribute("songAudioFileUrl") ? mediaItem->Attribute("songAudioFileUrl") : "N/A") << std::endl;
            std::cout << "Stabilization mode: " << (mediaItem->Attribute("stabilizationMode") ? mediaItem->Attribute("stabilizationMode") : "N/A") << std::endl;
            mediaItem = mediaItem->NextSiblingElement("MediaItem");
        }

        XMLElement* extentSelector = doc.FirstChildElement("ExtentSelector");
        while (extentSelector) {
            std::cout << "Extent ID: " << (extentSelector->Attribute("extentID") ? extentSelector->Attribute("extentID") : "N/A") << std::endl;
            std::cout << "Gap before: " << (extentSelector->Attribute("gapBefore") ? extentSelector->Attribute("gapBefore") : "N/A") << std::endl;
            std::cout << "Primary track: " << (extentSelector->Attribute("primaryTrack") ? extentSelector->Attribute("primaryTrack") : "N/A") << std::endl;
            extentSelector = extentSelector->NextSiblingElement("ExtentSelector");
        }

        XMLElement* extentRef = doc.FirstChildElement("ExtentRef");
        while (extentRef) {
            std::cout << "Extent reference ID: " << (extentRef->Attribute("id") ? extentRef->Attribute("id") : "N/A") << std::endl;
            extentRef = extentRef->NextSiblingElement("ExtentRef");
        }
    }

    bool write(const std::string& newFilepath = "") {
        const std::string target = newFilepath.empty() ? filepath : newFilepath;
        if (doc.SaveFile(target.c_str()) != XML_SUCCESS) {
            std::cerr << "Error saving file: " << doc.ErrorStr() << std::endl;
            return false;
        }
        return true;
    }
};

// Example usage:
// int main() {
//     WLMPHandler handler("example.wlmp");
//     if (handler.read()) {
//         handler.printProperties();
//         handler.write("modified.wlmp");
//     }
//     return 0;
// }