Skip to content

Web Setup

Hirdaya Shrestha edited this page Sep 14, 2026 · 1 revision

hAudiotagger supports web via WebAssembly. This page covers the required configuration for web deployment.

Requirements

  • Flutter 3.0.0+
  • Dart SDK 3.6.0+
  • Cross-origin isolation enabled

Cross-Origin Isolation

WebAssembly shared memory requires cross-origin isolation. Your host page must send these headers:

Cross-Origin-Opener-Policy: same-origin
Cross-Origin-Embedder-Policy: require-corp

Without these headers, the WASM module will fail to load with a shared memory error.

Local Development

Flutter Run

flutter run -d chrome \
  --web-header=Cross-Origin-Opener-Policy=same-origin \
  --web-header=Cross-Origin-Embedder-Policy=require-corp

Flutter Build

flutter build web

Then serve with a server that sends the required headers.

Production Deployment

Netlify

Create netlify.toml:

[[headers]]
  for = "/*"
  [headers.values]
    Cross-Origin-Opener-Policy = "same-origin"
    Cross-Origin-Embedder-Policy = "require-corp"

Vercel

Create vercel.json:

{
  "headers": [
    {
      "source": "/(.*)",
      "headers": [
        { "key": "Cross-Origin-Opener-Policy", "value": "same-origin" },
        { "key": "Cross-Origin-Embedder-Policy", "value": "require-corp" }
      ]
    }
  ]
}

Apache

Create or edit .htaccess:

<IfModule mod_headers.c>
  Header set Cross-Origin-Opener-Policy "same-origin"
  Header set Cross-Origin-Embedder-Policy "require-corp"
</IfModule>

Nginx

location / {
    add_header Cross-Origin-Opener-Policy "same-origin";
    add_header Cross-Origin-Embedder-Policy "require-corp";
}

GitHub Pages

GitHub Pages doesn't support custom headers. Use a proxy service like Cloudflare Workers or Netlify for production.

For local testing, use the Flutter run command with headers.

API Differences on Web

On the web, file path APIs are not available. Use the *FromBytes variants:

Native API Web API
read(path) readFromBytes(bytes)
write(path, tag) writeToBytes(bytes, tag)
update(path, changes) updateFromBytes(bytes, changes)
getChapters(path) getChaptersFromBytes(bytes)
getExtended(path) getExtendedFromBytes(bytes)

Example: Web App

import 'dart:typed_data';
import 'package:flutter/material.dart';
import 'package:file_picker/file_picker.dart';
import 'package:haudiotagger/haudiotagger.dart';

class WebAudioMetadata extends StatefulWidget {
  @override
  State<WebAudioMetadata> createState() => _WebAudioMetadataState();
}

class _WebAudioMetadataState extends State<WebAudioMetadata> {
  Tag? _tag;
  Uint8List? _fileBytes;
  
  Future<void> _pickFile() async {
    final result = await FilePicker.platform.pickFiles(
      type: FileType.audio,
    );
    
    if (result != null && result.files.first.bytes != null) {
      setState(() {
        _fileBytes = result.files.first.bytes;
      });
      await _readMetadata();
    }
  }
  
  Future<void> _readMetadata() async {
    if (_fileBytes == null) return;
    
    final tag = await Haudiotagger.readFromBytes(_fileBytes!);
    setState(() {
      _tag = tag;
    });
  }
  
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Audio Metadata (Web)')),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            ElevatedButton(
              onPressed: _pickFile,
              child: Text('Pick Audio File'),
            ),
            if (_tag != null) ...[
              SizedBox(height: 20),
              Text('Title: ${_tag!.title}'),
              Text('Artist: ${_tag!.trackArtist}'),
              Text('Album: ${_tag!.album}'),
            ],
          ],
        ),
      ),
    );
  }
}

Troubleshooting

"SharedArrayBuffer is not defined"

Cross-origin isolation is not enabled. Check that your server is sending the required headers.

WASM fails to load

Ensure you're using a production build (flutter build web) and serving the files from a proper web server, not file:// protocol.

Performance on web

WebAssembly runs single-threaded. For large batch operations, consider using the native platforms (Android, iOS, desktop) which support parallel processing via rayon.


Clone this wiki locally