WebAPI之访问连接媒体输入设备

文章目录

  • 一、Web API 接口文档
  • 二、采集音频
    • 2-1 record.html
    • 2-2 record.js
    • 2-3 后端响应
    • 2-4 执行结果


提示:以下是本篇文章正文内容,Java系列学习将会持续更新

一、Web API 接口文档

1.Navigator 接口表示用户代理的状态和标识。它允许脚本查询它和注册自己进行一些活动。
Navigator

2.mediaDevices 是 Navigator 只读属性,返回一个 MediaDevices 对象,该对象可提供对相机和麦克风等媒体输入设备的连接访问,也包括屏幕共享。
Navigator.mediaDevices

3.MediaDevices.getUserMedia() 会提示用户给予使用媒体输入的许可,媒体输入会产生一个媒体流(MediaStream),里面包含了请求的媒体类型的轨道。此流可以包含一个视频轨道、一个音频轨道,也可能是其它轨道类型。
MediaDevices.getUserMedia()

语法:

// 指定请求的媒体类型(音频、视频)
var constraints = { audio: true, video: true };
// 它返回一个 Promise 对象,成功后会resolve回调一个 MediaStream 对象
var promise = navigator.mediaDevices.getUserMedia(constraints);

4.Promise 是一个对象,它代表了一个异步操作的最终完成或者失败。本质上 Promise 是一个函数返回的对象,我们可以在它上面绑定回调函数,这样我们就不需要在一开始把回调函数作为参数传入这个函数了。
使用 Promise

语法:

// 绑定回调函数
promise.then(成功时调用的函数)
	   .catch(失败时调用的函数)

5.MediaRecorder 是 MediaStream Recording API 提供的用来进行媒体轻松录制的接口,他需要通过调用 MediaRecorder() 构造方法进行实例化。
MediaRecorder

事件处理:

// 该事件可用于获取录制的媒体资源
MediaRecorder.ondataavailable
// 用来处理 start 事件,该事件在媒体开始录制时触发
MediaRecorder.onstart
// 用来处理 stop 事件,该事件会在媒体录制结束时
MediaRecorder.onstop

回到目录…

二、采集音频

2-1 record.html

DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>用户中心title>
head>
<body>
    <input type="text" id="title">
    <button id="stop">停止录制button>
    
    <audio controls>audio>
    <script src="./js/record.js">script>
body>
html>

2-2 record.js

// 发送 Ajax 请求
function upload(title, content) {
    var xhr = new XMLHttpRequest()
    // 由于我们要把声音放在请求体中发送,所以必须使用 post 方法
    // 这里是 ajax 发起的请求,所以,后续要怎么处理完全是 js 决定的
    // 所以,这里就不使用 *.do 这种 URL 了
    xhr.open('post', `/studio/track/record.json?title=${title}`)
    xhr.onload = function() {
        console.log(this.status)
        console.log(this.responseText)
    }
    xhr.send(content)
}

// 为了让 js 代码可以在所有资源都加载完成后才去执行,就入口代码放在 window 的 load 事件处理中
window.onload = function() {
    // 执行这个方法的时候,说明所有资源都被加载好了

    if(!navigator.mediaDevices.getUserMedia) {
        alert("该浏览器不支持媒体访问,请更换浏览器!")
        return
    }

    var constraints = { audio: true }
    var promise = navigator.mediaDevices.getUserMedia(constraints)

    // stream 的类型就是 MediaStream (媒体流)
    // 里面有从麦克风采集到的声音
    function onSuccess(stream) {
        alert('用户授权成功')

        var mediaRecorder = new MediaRecorder(stream)
        // 当开始录制后,这个方法会被调用
        mediaRecorder.onstart = function () {
            console.log('开始录制')
        }

        // 放置过程中录制下来的声音数据
        var data = []
        // 当数据可用时,会被调用
        mediaRecorder.ondataavailable = function(evt) {
            console.log('数据可用')
            console.log(evt)
            // evt.data 是一个 Blob 类型的,表示录制下来的声音片段的对象
            data.push(evt.data)
        }
        // 当停止录制后(一切完成),这个方法会被调用
        mediaRecorder.onstop = function() {
            console.log('停止录制')
            console.log(data)
            // 将一组数据,组成一个统一的数据
            var title = document.querySelector('#title').value.trim()
            var type = "audio/ogg; codecs=opus"
            var blob = new Blob(data, {
                // 类型认为是死规定
                type: type
            })
            // 将数据生成一个方便播放的 URL
            var url = URL.createObjectURL(blob)
            console.log(url)

            // 找到 audio 元素,修改 src 属性,让页面上的
            // 音频播放器可以播放我们录制下来的声音
            var oAudio = document.querySelector('audio')
            oAudio.src = url

            upload(title, blob)
        }

        document.querySelector('#stop').onclick = function() {
            mediaRecorder.stop()
        }

        // 开始录制,每1s生成一次数据
        mediaRecorder.start(1000)
    }

    function onError(error) {
        alert('授权过程中出现了错误: ' + error)
    }

    promise.then(onSuccess).catch(onError)
}

回到目录…

2-3 后端响应

ObjectMapper使用详细介绍

@WebServlet("/studio/track/record.json")
public class RecordJsonServlet extends HttpServlet {
    private final ObjectMapper objectMapper = new ObjectMapper();
    private final TrackRepo trackRepo = new TrackRepo();

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("utf-8");
        String title = req.getParameter("title");
        String type = req.getHeader("Content-Type");
        Log.println("title: " + title);
        Log.println("type: " + type);

        UserVO currentUser = null;
        HttpSession session = req.getSession(false);
        if (session != null) {
            currentUser = (UserVO) session.getAttribute("currentUser");
        }


        resp.setCharacterEncoding("utf-8");
        resp.setContentType("application/json");
        PrintWriter writer = resp.getWriter();
        if (currentUser == null) {
            Log.println("用户未登录");
            HashMap<String, Boolean> result = new HashMap<>();
            result.put("result", false);
            String json = objectMapper.writeValueAsString(result);
            Log.println(json);
            writer.println(json);
            return;
        }

        trackRepo.insert(currentUser.uid, title, type, req.getInputStream());
        Log.println("将数据保存到数据库表中");

        HashMap<String, Boolean> result = new HashMap<>();
        result.put("result", true);
        String json = objectMapper.writeValueAsString(result);
        Log.println(json);
        writer.println(json);

        // 完整的音频数据放在 InputStream(请求体)
//        ServletInputStream is = req.getInputStream();
//        try (OutputStream os = new FileOutputStream("D:\\upload" + title + ".ogg")) {
//            byte[] buf = new byte[4096];
//            while (true) {
//                int n = is.read(buf);
//                Log.println("读到了: " + n);
//                if (n == -1) {
//                    break;
//                }
//                os.write(buf, 0, n);
//            }
//            os.flush();
//        }
    }
}

2-4 执行结果

  1. 允许访问连接
    WebAPI之访问连接媒体输入设备_第1张图片
  2. 授权成功
    WebAPI之访问连接媒体输入设备_第2张图片
  3. 录制音频
    WebAPI之访问连接媒体输入设备_第3张图片

回到目录…


总结:
提示:这里对文章进行总结:
以上就是今天的学习内容,本文是WebAPI的学习,实现了一个上传音频的小应用,如何访问连接媒体输入设备,如何通过Ajax发出请求,后端做出响应处理音频数据。之后的学习内容将持续更新!!!

你可能感兴趣的:(项目模块,媒体,前端,java)