3

I am developing one application that makes use of the wavesurfer.js package. The code is all built in HTML, and it is being rendered using Jinja2 (inside FastAPI). As the audio file is uploaded over the Google Cloud Storage, it was chosen to make a signed url, that allows the file to be accessed by about 180 seconds. The curious (and awkward) part of the problem, is that the audio file is being accessed, since I can hear the audio using the wavesurfer interface. However, the waveform is not being drawed and the requisition done to the google cloud file is returning a CORS 'Missing Allow Origin' error (Access-Control-Allow-Origin Header).

I have tried to insert it in many ways, following another issues reported at the community, such as intercepting requisitions using the wavesurfer ajax object, as it follows:

WaveSurfer.util.ajax = function (options) {
    var ajax = Object.create(WaveSurfer.Observer);
    var xhr = new XMLHttpRequest();
    var fired100 = false;

    xhr.open(options.method || 'GET', options.url, true);

    // START added code
    xhr.setRequestHeader("Access-Control-Allow-Origin", "*")
    xhr.setRequestHeader("Authorization", "Bearer {{token}}")
    // END added code

    xhr.responseType = options.responseType || 'json';

    xhr.addEventListener('progress', function (e) {
        ajax.fireEvent('progress', e);
        if (e.lengthComputable && e.loaded == e.total) {
            fired100 = true;
        }
    });

    xhr.addEventListener('load', function (e) {
        if (!fired100) {
            ajax.fireEvent('progress', e);
        }
        ajax.fireEvent('load', e);

        if (200 == xhr.status || 206 == xhr.status) {
            ajax.fireEvent('success', xhr.response, e);
        } else {
            ajax.fireEvent('error', e);
        }
    });

    xhr.addEventListener('error', function (e) {
        ajax.fireEvent('error', e);
    });

    xhr.send();
    ajax.xhr = xhr;
    return ajax;
}

Forcing the token and the 'origins' and 'Access-Control-Allow-Origin' headers when I generate the signed url, as it follows:

       file = storage.Blob(file_path, self.bucket)

        credentials = service_account.Credentials.from_service_account_file('app/credentials.json', scopes=['https://www.googleapis.com/auth/cloud-platform'])
        auth_req = rq.Request()
        credentials.refresh(auth_req)
        token = credentials.token
        headers = {
            'Origin': '*',
            'Access-Control-Allow-Origin': '*'
        }
        url = file.generate_signed_url(expiration=180, version='v4', access_token=token, headers=headers)

Or even placing the 'xhr' object inside the WaveSurfer.create({...}), as it follows:

let wavesurfer = WaveSurfer.create({
    container: '#waveform',
    waveColor: 'violet',
    progressColor: 'purple',
    backend: 'MediaElement',
    plugins: [
        WaveSurfer.elan.create({
            url: "{{ elan_file_url }}",
            container: '#annotations',
            tiers: {
                Text: true,
                Comments: true
            }
        }),
        WaveSurfer.regions.create()
    ],
    xhr: { 
        cache: 'default', 
        mode: 'cors', 
        method: 'GET', 
        credentials: 'same-origin', 
        redirect: 'follow', 
        referrer: 'client', 
        headers: [
            { key: 'Authorization', value: 'Bearer {{ token }}' },
            { key: 'Access-Control-Allow-Origin', value: 'origin-list' }
    ]}

As a measure to try to overcome this, I also have attempted to generate the waveform using a repo called 'py-wav2json', that worked (in parts), but the waveform was very away from the expected and I was hoping not to need to generate every single waveform, because it will let the system very overloaded.

Is there any posible measure to overcome this situation?

0 Answers0