0

I'm trying to learn how tu use firebase and its storage option for web apps. So I'm using an older webpage I did to record the save locally a video from webcam. I'm trying to modify it to send the video to the storage instead of downloading it.
Here is the code :
main.html :

<html lang="fr">
    <head>
        <meta charset="utf-8"/>
        <title>Test storage</title>
        <!-- JS -->
            <!-- API -->
            <script src="./javascript/firebase_using.js" type="module"></script>
            <!-- Personal scripts -->
            <script src="./javascript/webcam.js"></script>

        <!-- CSS -->
        <link rel="stylesheet" href="./css/collect.css">
    </head>
    <body>
        <main>
            <div class="content">
                <div class="part user_feedback">
                    <video id="camera" class="camera" src="" width="172" height="172" autoplay></video>
                    <div class="buttons_containors">
                        <button class="button" onclick="startRecording()">Start</button>
                        <button class="button" onclick="stopRecording()">Stop</button>
                    </div>
                </div>

                <div class="part instructions">
                    <video id="demonstration" class="demonstration" src="./ressources page/demo.mp4" width="172" height="172" autoplay loop></video>
                </div>
            </div>
        </main>
    </body>
</html>

classes are used only for css selection, but it's useless to share it here I guess ?

webcam.js :

var recorder = null;
var stream;
var liveStream; 
var blobVideoCouleur;
var URLvideoCouleur;
var FPS = 5;

const contraintes = {
    video: { width: 172, height: 172, frameRate : FPS}
};

window.addEventListener('DOMContentLoaded', demarrerApp); // Waiting for all elements to be loaded

/* FUNCTIONS */

function demarrerApp(){
    initialiseVariables(); // initialising global var
    cameraShow(); // launching camera
}

function initialiseVariables(){
    liveStream = document.getElementById("camera");
}

function cameraShow()
{
    if('mediaDevices' in navigator && 'getUserMedia' in navigator.mediaDevices) {        
        navigator.mediaDevices.getUserMedia(contraintes) 
        .then(function(mediaStream){
            stream = mediaStream;
            liveStream.srcObject = stream;
        })
        .catch (function(error) {
        console.error("CameraShow : Impossible d'accéder à la caméra : %o", error);
        return;
        })
    }else(console.error("CameraShow : getUserMedia indisponible - Mettez le navigateur à jour"))
}

function startRecording()
{
    recorder = new MediaRecorder(stream);
    let chunks = [];

    recorder.ondataavailable = (event) => {
        if (event.data.size > 0) {
            chunks.push(event.data)
        }
    }

    recorder.onstop = () => { 
        const blob = new Blob(chunks, { 
            type: 'video/webm'
        })
        chunks = [];
        URLvideoCouleur = URL.createObjectURL(blob);
        blobVideoCouleur = blob; 
    }
    
    recorder.start(200);
}

async function stopRecording() {

    for (let track of stream.getTracks()) {
        track.stop();
    }
    // sauvegarder("video_de_test.webm", blobVideoCouleur);
}

firebase_using.js :

import { initializeApp } from "https://www.gstatic.com/firebasejs/9.22.0/firebase-app.js";
import { getAnalytics } from "https://www.gstatic.com/firebasejs/9.22.0/firebase-analytics.js";
import { getStorage, ref, uploadBytes} from "https://www.gstatic.com/firebasejs/9.22.0/firebase-storage.js";


// TODO: Add SDKs for Firebase products that you want to use
// https://firebase.google.com/docs/web/setup#available-libraries

// Your web app's Firebase configuration
// For Firebase JS SDK v7.20.0 and later, measurementId is optional
const firebaseConfig = {
    apiKey: "...",
    authDomain: "...",
    projectId: "...",
    storageBucket: "...",
    messagingSenderId: "...",
    appId: "...",
    measurementId: "..."
};

// Initialize Firebase
const app = initializeApp(firebaseConfig);
const analytics = getAnalytics(app);
const storage = getStorage(app);

function say_hello(){
    console.log("Ohayo Sekai!");
}

function sauvegarder(nom, fichier){
    const storageRef = ref(storage, nom);
    uploadBytes(storageRef, fichier).then((snapshot) => {
        console.log("vidéo mise sur le drive");
    });
}    

the function say_hello() is so useless, just a test function for calling something without parameters

So, all this code do not generate any errors. main.html and webcam.js have expected behavior when I use my function for local downloading (note here, page is long enough.) BUT ! When I use sauvegarder function (so when I uncoment the line // sauvegarder("video_de_test.webm", blobVideoCouleur); in webcam.js) I've the error : "Uncaught (in promise) ReferenceError: sauvegarder is not defined" that I don't understand, cause if use few console.log("...") in my js files, I see firebase_use.js is rode properly, and before webcam.js so basically, the function should be defined... shouldn't it ? For me it's the common way to use a function defined in another file, i just have to be careful of the order of the js files in my html.

So I naively tried to move the function into webcam.js, but then it's ref function that's not defined. Is everything in this file useless outside ?! :O So let's move all firebase_use.js at the beggining of webcam.js aaand... new error : It seems I can't use import statement outside of a module. So webcam.js is now imported as a module into the html ? But the functions startRecording() and stopRecording() are no longer available for my two buttons. So the issue come from the parameter `type="module" when I load a script into html ? It made all functions like... "private" ? How can I solve this ?

Thanks for help !

Tsu'Na
  • 13
  • 4
  • I'm not very familiar with `type="module"` but maybe you need to export the function. – Barmar May 23 '23 at 21:22
  • Adding `type="module"` to a script tag isolates it from the global namespace. You need to explicitly attach methods to the global scope for them to be accessible outside the module (e.g. `window.sauvegarder = sauvegarder` at the bottom of your `firebase_using.js` file). See [this thread](https://stackoverflow.com/q/69888029/3068190) for more details. – samthecodingman May 24 '23 at 01:54
  • Additionally, make sure that your `sauvegarder` function correctly returns its promise so that it can be chained to and its errors handled. – samthecodingman May 24 '23 at 01:55
  • Hey @samthecodingman @ Barman ! it works ! excellent ! I'm so happy, it's my first time saving a file out of my computer with a webpage ! Now let's explore all others firebase options !! May i'll check options to send messages and have an awesome "contact" form !!! :D <3 Do one of you two want to use "answer the question" button so i choose your answers as solution ? (to close subject / reputation). How wait ? why a console.log after calling `sauvegarder` don't work ? is it about this promise return ?? – Tsu'Na May 24 '23 at 08:48
  • hoho it seems `uploadBytes` is asynchronous, so using `await` statement before (and defining `sauvegarder` as `async` of course) solves the issue ! – Tsu'Na May 24 '23 at 09:12

0 Answers0