朗读者项目

本文详细记录了一个朗读者项目的开发过程,包括需求分析、实施可行性、技术难点解决、ER图设计、数据库创建及代码开发。项目旨在实现用户注册登录、上传音频章节、播放音频等功能,通过学习前端录制上传技术,克服了技术挑战。
摘要由CSDN通过智能技术生成

前言:对于之前系统地学习java之路,现在面临找工作,发现对项目的询问比较多,之前只是把自己的项目挂在了github上,还是总结一下比较好。

一、需求分析
第一眼就看上了这个项目,觉得一个可以实现用户注册登录,上传音频章节信息图书资料的项目对我而言十分合适,其中有JDBC编程实现的注册登录上传书籍等静态文本内容数据库交互操作。又有上传音频播放这种比较新鲜我没有学习过的点。拿来做项目真是极好的。

进入正题:做朗读者网的需求重点是实现小说上传和音频的上传,用户的注册和登录。
之后可以增加其他的拓展性需求,比如加个视频,美化下界面,实现用户管理,个人中心什么的。

二、实施可行性
从需求分析也能得出,目前我的水平只有开发学生信息管理系统登录注册功能时MVC那一套后端的开发,这次的开发,我的技术难点在于从头开发,相当于前端那一套得研究一下,录制音频的方法也得好好学习一下子。
可以解决:用户注册登录,添加书籍章节。
技术难点:录制音频,上传音频,播放音频。前端页面的开发。

三、技术难点解决
结合菜鸟编程和csdn上的教程找到一个视频的录制上传。
record.html文件
`

开始录制

预览

停止

录制中

下载
`

以及JavaScript


// document 是在浏览器中运行时一直存在的一个变量,表示的意思是代表文档树
// html Document Object Model Tree    DOM 树
// document 粗糙的可以理解成这棵树的根

// getElementById 从树上,根据 id,找到对应的结点(标签)
let preview = document.getElementById("preview"); 
let recording = document.getElementById("recording");
let startButton = document.getElementById("startButton");
let stopButton = document.getElementById("stopButton");
let downloadButton = document.getElementById("downloadButton");

function wait(delayInMS) {
   
    // setTimeout(执行什么方法,多少毫秒之后)
    // 类似 Java 中的定时器(Timer)
    // 设定一个闹钟一样的效果
    return new Promise(resolve => setTimeout(resolve, delayInMS));
}

function startRecording(stream, lengthInMS) {
   
    console.log("开始录制");

    let recorder = new MediaRecorder(stream);   // 定义一个媒体录制对象
    let data = [];

    // 当(on) 数据(data)可用(available) 时,执行该方法
    recorder.ondataavailable = function (event) {
   
        console.log("数据可用");
        // event.data 录制下来的视频和音频数据,存入 data 数组
        data.push(event.data);  // 线性表的尾插
    };

    // 开始录制
    recorder.start();

    // resolve 成功的时候应该执行的方法,对应 then 传入的方法
    // reject 失败的时候应该执行的方法,对应 catch 传入的方法
    let stopped = new Promise(function (resolve, reject) {
   
        recorder.onstop = resolve;
        recorder.onerror = function(event) {
    
            reject(event.name);
        }
    });

    // 持续 lengthInMS 时间后,执行 then 中的方法
    let recorded = wait(lengthInMS).then(
        function() {
   
            // 20 秒之后
            // 判断 recorder 是否还在录制,如果还在录制 == "recording",则,停止录制
            if (recorder.state == "recording") {
   
                console.log("停止录制");
                recorder.stop();
            }
        }
    );

    return Promise.all([
        stopped,
        recorded
    ])
    .then(() => data);
}

function startCapturing() {
   
    console.log("点击采集");
    
    // 会触发,申请权限的操作
    let promise = navigator.mediaDevices.getUserMedia({
   
        video: true,        // 申请摄像头权限
        audio: true         // 申请麦克风权限
    });

    // 如果用户同意了,就执行 then 中的方法,如果失败(用户不同意 or 其他失败)会执行 catch 中的方法
    let promise2 = promise.then(function(stream) {
   
        console.log("同意授权");
        // 用户同意了
        // stream 变量就代表录制的视频和音频了
        preview.srcObject = stream;

        // 处理兼容性的,类似 if (!preview.captureStream) { preview.captureStream = preview.mozCaptureStream; }
        preview.captureStream = preview.captureStream || preview.mozCaptureStream;

        // 接着执行的是,当 preview 开始(on) 播放(palying) 时,执行 then 的方法
        // resolve 形参对应的实参就是 xxxx 函数
        return new Promise(function(resolve) {
   
            preview.onplaying = resolve;
        });
    });

    function xxxx() {
   
        return startRecording(preview.captureStream(), 5000); //
    }
    
    promise2.then(xxxx) // 调用 function(resolve) { ... } 这个函数
    .then(function (data) {
   
        console.log("使用录制下来的数据");
        console.log(data);

        let recordedBlob = new Blob(data, {
    type: "video/webm" });
        recording.src = URL.createObjectURL(recordedBlob);
    })
    .catch(e => {
   
        console.log(e);
    });
}

function stopRecording() {
   
    console.log("点击了结束录制");
}

// startButton.addEventListener("click", startRecording);   <-- 和下面的写法,目前可以认为是一样的效果
startButton.onclick = startCapturing;        
// 进行事件绑定,发生了 startButton 的点击(click)事件后,
// 请执行 startRecording
// 这种形态就是俗称的回调函数(callback)
// 当 startButton 上有了 click 事件时,startButton.onclick();


stopButton.onclick = stopRecording;
// 在 stopButton 发生了(on) 点击(click)事件后,执行 stopRecording 函数

在这里插入图片描述
弄出来效果是这样的。到时候只保留音频录制功能就好了。

四:ER图,数据库设计

一个用户可以上传多部小说(1:n)
一个小说可以有多个章节(1:n)
一个章节对应一个音频(1:1)

ER图大概就是:

用户 —> 小说 —>章节 —> 音频
在这里插入图片描述

然后设置表的属性:
Users:uid,username,password
Books:bid,uid,tittle
Sections:sid,bid,name
Audios:aid,sid,uuid,type,content

uuid是逻辑主键,好处是如果audios和别的表合并那aid可能就失效了,但是uuid是独立的主键,永远可用正确。这里就用用。

五、执行建库建表代码和xml文件

create database Audio charset utf8mb4;
use Audio;
create table users (
 uid int primary key auto_increment comment '用户id',
 username varchar(64) not null unique comment '用户名',
 password char(64) not null comment '经过sha-256计算后的用户密码'
);
create table books (
 bid int primary key auto_increment comment '小说id',
 uid int not null comment '上传用户id',
 title varchar(100) not null comment '小说名称'
);
create table sections (
 sid int primary key auto_increment comment '章节id',
 bid int not null comment '属于哪本小说的id',
 name varchar(100) comment '章节名称'
);
create table audios (
 aid int primary key auto_increment comment '音频id',
 sid int not null unique comment '属于哪个章节的id',
 uuid char(36) not null comment 'uuid音频的唯一标识',
 type varchar(20) not null comment '音频类型audio/wmv audio/mp3',
 content longblob default null comment '音频内容'
);

xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <!-- 项目基本信息 -->
    <groupId>zjw</groupId>
    <artifactId>AudioFiction</artifactId>
    <version>1.0-SNAPSHOT</version>


    <!-- war 包形式打包,IDEA会根据这个选项,自动创建 artifacts 选项-->
    <packaging>war</packaging>

    <!-- 项目的字符集 + 字符集选项配置 -->
    <properties>
        <encoding>utf-8</encoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
    </properties>


    <!-- 添加需要的第三方依赖jar包 -->
    <dependencies>

    <!-- 提供 Servlet 提供的标准接口 -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.1.0</version>
            <!-- 这个 jar 包只在开发 + 编译阶段使用,运行阶段不需要 -->
            <scope>provided</scope>
        </dependency>

        <!-- 添加 MySQL Driver 的依赖 -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.47</version>
        </dependency>

        <!-- 添加处理 json 数据的依赖 -->
        <dependency>
            <groupI
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值