1

I found Mozilla's Getting browser microphone permission. It defines a function to request permission and listen to client's microphone as such:

function getLocalStream() {
    navigator.mediaDevices.getUserMedia({video: false, audio: true}).then( stream => {
        window.localStream = stream; // A
        window.localAudio.srcObject = stream; // B
        window.localAudio.autoplay = true; // C
    }).catch( err => {
        console.log("u got an error:" + err)
    });
}

I checked in Chrome, Firefox and Safari - all of them throw an error about window.localAudio being undefined. Where did this tutorial get it from? Was window.localAudio ever a thing? What was it supposed to do?

Robo Robok
  • 21,132
  • 17
  • 68
  • 126
  • tell what you whant to achive – Robert Oct 27 '21 at 12:35
  • 2
    @Robert The question is about where `window.localAudio` is defined, since it’s used in this tutorial. – Sebastian Simon Oct 27 '21 at 12:36
  • 1
    It looks like this code originally comes from [this Medium blog post](//medium.com/samsung-internet-dev/building-an-internet-connected-phone-with-peerjs-775bd6ffebec), which actually goes on to explain the code. I assume, it’s something PeerJS-specific. – Sebastian Simon Oct 27 '21 at 12:37
  • 1
    If you read the text it tells you want it is `window.localAudio` is the id of the audio element on the page. *window.localAudio.srcObject = stream sets the – epascarello Oct 27 '21 at 12:39
  • yeap. but if he whant just pipe strem to speakers he need create audio context and set this as buffer source. – Robert Oct 27 '21 at 12:39
  • 4
    Aha! _“in our HTML, we have an audio element with the ID `localAudio`”_. This uses the very bad practice of relying on this behavior: [Do DOM tree elements with ids become global variables?](/q/3434278/4642212). – Sebastian Simon Oct 27 '21 at 12:39
  • @SebastianSimon oh damn! That's some really poor wording from Mozilla, this blog post you found explains it better. I'm not sure if I agree with this question being a duplicate though. – Robo Robok Oct 27 '21 at 12:44
  • I don't think this is a duplicate either. Yes the linked question takes part in solving this one, but it is not the actual problem. – MauriceNino Oct 27 '21 at 12:47
  • @MauriceNino yeah, exactly. But it's not the first time someone on SO does that this way. Like the "duplicated" post is the answer, but not the question :D – Robo Robok Oct 27 '21 at 12:49
  • @MauriceNino it's like making a question "How much is 2 + 2?" a duplicate of "How much is 1 + 3?". – Robo Robok Oct 27 '21 at 12:50
  • Yep, sad to see that people with enough points, can just do whatever they want on here. The only thing you can do is flag this as "In need of moderator intervention", or get enough people to Vote-reopen this question. – MauriceNino Oct 27 '21 at 12:51
  • Yeah, even I think that duplicate closure is really a stretch. Voted to reopen. – Sebastian Simon Oct 27 '21 at 12:53
  • 1
    So add the missing ` – epascarello Oct 27 '21 at 12:54
  • @SebastianSimon would you like to add it as an answer? – Robo Robok Oct 27 '21 at 12:57
  • @epascarello yup, I figured. – Robo Robok Oct 27 '21 at 12:57
  • @epascarello it was really poorly worded in the tutorial, I actually didn't understand it. "sets the – Robo Robok Oct 27 '21 at 12:59
  • @epascarello The answer is giving a description on why things happen (like in these comments). The next person going through this tutorial & getting the exact same error, will maybe not even get to this answer, because it is burried in the comments and the linked dupe is not giving any info on why `localAudio` is not defined. – MauriceNino Oct 27 '21 at 13:00
  • That is a horrible tutorial in general. Seems odd that is even on MDN – epascarello Oct 27 '21 at 13:00
  • So now you know the answer, answer your question. Add the missing tag, change the code so it does not use bad practices when referencing an element. Bonus, alter the tutorial with a PR on github to add clues you need an audio tag. – epascarello Oct 27 '21 at 13:03
  • @epascarello I'll let Sebastian Simon do that, as he was the one to find the answer first. I'll be happy to reward him. – Robo Robok Oct 27 '21 at 13:04
  • Yes, this should really be reported on [MDN’s GitHub](//github.com/mdn/content/issues). I haven’t checked thoroughly, but there may be plagiarism involved in this article. Regarding this question, I’m really not sure what kind of answer or other action best fits here. Feel free to write an answer. – Sebastian Simon Oct 27 '21 at 13:20
  • @SebastianSimon The things you said in the comment (along with the criticism of the article) would be the best fit in my opinion. – Robo Robok Oct 27 '21 at 13:24
  • @SebastianSimon it also looks like `window.localStream = stream` doesn't do anything special neither and it probably only used to store the stream object globally. – Robo Robok Oct 27 '21 at 13:53

2 Answers2

-1

I will try to give you something more useful than the question you have asked. The function will create the element if it is not present and there are few options available. In the example I'm adding the newly created audio element to the body, but it will work even it is not added - it's a matter of choice.

<html>

<head>
    <script>
        var el;

        function attachStream(stream, el, options) {
            var item;
            var URL = window.URL;
            var element = el;
            var opts = {
                autoplay: true,
                mirror: false,
                muted: false,
                audio: false,
                disableContextMenu: false
            };

            if (options) {
                for (item in options) {
                    opts[item] = options[item];
                }
            }

            if (!element) {
                element = document.createElement(opts.audio ? 'audio' : 'video');
            } else if (element.tagName.toLowerCase() === 'audio') {
                opts.audio = true;
            }

            if (opts.autoplay) element.autoplay = 'autoplay';
            if (opts.muted) element.muted = true;
            if (!opts.audio && opts.mirror) {
                ['', 'moz', 'webkit', 'o', 'ms'].forEach(function(prefix) {
                    var styleName = prefix ? prefix + 'Transform' : 'transform';
                    element.style[styleName] = 'scaleX(-1)';
                });
            }

            element.srcObject = stream;
            return element;
        };

        function getLocalStream() {
            navigator.mediaDevices.getUserMedia({
                video: false,
                audio: true
            }).then(
                stream => {
                    var doesnotexist = !el;
                    el = attachStream(stream, el, {
                        audio: true,
                        autoplay: true
                    });
                    if (doesnotexist) document.body.appendChild(el);
                }
            ).catch(err => {
                console.log("u got an error:" + err)
            });
        }

        window.addEventListener('DOMContentLoaded', (event) => {
            getLocalStream();
        });
    </script>
</head>

<body>
</body>

</html>
Reflective
  • 3,854
  • 1
  • 13
  • 25
-1

The window is an object and the window.localStream is simply creating a new property on the window object.