前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >超火的倒放挑战 - ReverseVoice (微信小程序版 前后端源码) Ts Node Taro

超火的倒放挑战 - ReverseVoice (微信小程序版 前后端源码) Ts Node Taro

作者头像
腾讯NEXT学位
发布2019-12-03 17:10:27
1.1K0
发布2019-12-03 17:10:27
举报
文章被收录于专栏:腾讯NEXT学位

项目地址: https://github.com/smackgg/reversevoice整个项目其实很简单,从本人在抖音和 B 站看到火起来到最终小程序上线也就几天的下班时间就搞定了,11月16日上线至今用户量还是蛮多的(主要当时做的快此类 app 比较少),现在已经出现了大量的更简约更好的倒放挑战 app,本项目开源仅供大家学习~(文中代码需要左右滑动噢!)1体验:小程序二维码

2

功能介绍/实现原理

功能及实现原理简述

① 小程序端用户录音并保存本地

② 录音后将录音文件上传至后端进行倒放处理,并返回处理后的音频 url

③ 小程序端下载 url 文件,提示用户反转成功,将数据做本地 map

④ 用户点击分享,生成分享链接,并将该分享正放、倒放视频均传至后端保存至七牛云

⑤ 同时新建分享 room 保存用户信息,返回 roomId

⑥ 用户分享(海报分享 canvas 动态生成分享码海报)

⑦ 其它用户参加挑战,存储原理同 4,只是增加将挑战者信息了存入 room 的逻辑

音频倒放

① 使用 ffmpeg 进行音频倒放,核心代码:

代码语言:javascript
复制
// 详见 ./server/src/controllers/file.ts => function reverseVoiceimport ffmpegPath from '@ffmpeg-installer/ffmpeg'import ffprobePath from '@ffprobe-installer/ffprobe'import ffmpeg from 'fluent-ffmpeg'ffmpeg.setFfprobePath(ffprobePath.path)ffmpeg.setFfmpegPath(ffmpegPath.path)
ffmpeg(filepath)    .format('mp4')    // 反转    .outputOptions([      '-vf reverse',      '-af areverse',      '-preset',      'superfast',      '-y',    ])    .on('progress', (progress) => {      // send upload progress      console.log('upload-file-progress', progress.percent)    })    .on('error', (err) => {      console.log(`Ffmpeg has been killed${err.message}`)    })    .toFormat('mp3')    // 保存    .save(publicPath + saveFilePath)    .on('end', () => {      // 获取音频信息(时长等)      ffmpeg.ffprobe(publicPath + saveFilePath, (err, metadata) => {        console.log(metadata.format.duration)      })    })小程序录音

小程序录音

① 小程序录音使用官方 api,详细逻辑见 ./wechatapp/pages/index/index.tsx

录音

海报生成 

① 利用 canvas 动态合成分享海报 ./wechatapp/pages/sharePoster 需要动态请求页面小程序码,涉及微信AccessToken鉴权等,详见 ./server/src/controllers/wechat.ts, 下面贴出部分核心代码

代码语言:javascript
复制
// 画图const draw = async () => {  // 绘制之前 loading  Taro.showLoading({    title: '海报生成中...',    mask: true,  })  // 获取图片信息  const [productImgInfo, qrcodeImgInfo] = await Promise.all([    this.getImageInfo(sharePoster), // 获取主图    this.getQrImgInfo(), // 获取二维码图片  ])
  // product image 宽高  const pW = CANVAS_WIDTH  const pH = (pW / productImgInfo.width) * productImgInfo.height
  // canvas 高度  let canvasHeight = pH
  const ctx = Taro.createCanvasContext('canvas', null)
  ctx.fillStyle = '#fff'  ctx.fillRect(0, 0, CANVAS_WIDTH, canvasHeight)
  // 绘制背景图片  ctx.drawImage(sharePoster, 0, 0, pW, pH)
  // 绘制二维码 (因为有角度,需要旋转画布,再旋转回来)  ctx.rotate(-Math.PI / 32)  ctx.translate(-25 * ratio, 10 * ratio)  ctx.drawImage(qrcodeImgInfo.path, QR_LEFT, QR_TOP, QR_WIDTH, QR_WIDTH)  ctx.rotate(Math.PI / 32)  this.setState({    canvasStyle: {      ...this.state.canvasStyle,      height: canvasHeight,    },  })  ctx.stroke()  setTimeout(() => {    Taro.hideLoading()    ctx.draw()  }, 500)}

② 微信分享 HOC 函数 ./wechatapp/components/@withShare

代码语言:javascript
复制
// 微信小程序每个页面几乎都需要配置分享的参数,并且需要动态更改分享参数// 所以抽离 HOC 组件,方便页面使用import { ComponentClass } from 'react'
import Taro from '@tarojs/taro'import { connect } from '@tarojs/redux';import defaultShareImg from '@/assets/images/share.png'
type Options = {  title?: string  imageUrl?: string  path?: string}
const defalutOptions: Options = {  title: '你能听懂我说啥么?最近很火的反转录音来啦~',  imageUrl: defaultShareImg,  path: 'pages/index/index',}
function withShare() {  return function demoComponent(Component: ComponentClass) {    @connect(({ user }) => ({      userInfo: user.userInfo    }))    class WithShare extends Component {      $shareOptions?: Options      async componentWillMount() {        Taro.showShareMenu({          withShareTicket: true,        })
        if (super.componentWillMount) {          super.componentWillMount()        }      }
      // 点击分享的那一刻会进行调用      onShareAppMessage() {        // const sharePath = `${path}&shareFromUser=${userInfo.shareId}`        let options = defalutOptions        if (this.$shareOptions) {          options = {            ...defalutOptions,            ...this.$shareOptions,          }        }        return options      }
      render() {        return super.render()      }    }
    return WithShare  }}
export default withShare

使用

代码语言:javascript
复制
@withShare()class Room extends Component {  /** * 指定config的类型声明为: Taro.Config * * 由于 typescript 对于 object 类型推导只能推出 Key 的基本类型 * 对于像 navigationBarTextStyle: 'black' 这样的推导出的类型是 string * 提示和声明 navigationBarTextStyle: 'black' | 'white' 类型冲突, 需要显示声明类型 */  config: Config = {    navigationBarTitleText: '首页',  }
  $shareOptions = {    title: '倒放挑战!你能听懂我倒立洗头~',    path: 'pages/index/index',    imageUrl: '',  }
  /**    ....  */}

微信用户登录流程

微信官方文档登录流程 具体实现可以去看源码

3

项目运行-后端

准备

需要提前安装:

① Install Node.js

② Install MongoDB

开始

① 克隆项目并进入后端目录

代码语言:javascript
复制
cd server

② 安装依赖

代码语言:javascript
复制
npm install

③ 设置 mongoDB

代码语言:javascript
复制
# create the db directorysudo mkdir -p /data/db# give the db correct read/write permissionssudo chmod 777 /data/db
# starting from macOS 10.15 even the admin cannot create directory at root# so lets create the db diretory under the home directory.mkdir -p ~/data/db# user account has automatically read and write permissions for ~/data/db.

④ 启动 mongoDB (Start your mongoDB server (you'll probably want another command prompt)

代码语言:javascript
复制
# create the db directorysudo mkdir -p /data/db# give the db correct read/write permissionssudo chmod 777 /data/db
# starting from macOS 10.15 even the admin cannot create directory at root# so lets create the db diretory under the home directory.mkdir -p ~/data/db# user account has automatically read and write permissions for ~/data/db.

⑤ 打包并运行项目

代码语言:javascript
复制
npm run buildnpm start

4

项目运行-小程序端

准备

需要提前安装:

① Install 微信开发者工具

开始

① 克隆项目并进入小程序目录

代码语言:javascript
复制
cd wechatapp

② 安装依赖

代码语言:javascript
复制
npm install

③ 新建 .env 文件

代码语言:javascript
复制
在 wechatapp/src/utils 目录下克隆 env.example.ts 文件至同目录命名为 .env.ts 文件此文件两个参数分别代表本地开发和线上部署的请求地址

④ 运行项目

代码语言:javascript
复制
npm run dev:weapp // development mode或者 npm run build:weapp // production mode

⑤ 微信开发者工具

代码语言:javascript
复制
选择导入项目,并选择 wechatapp/dist 目录若本地开发,需要在开发者工具中设置开启“不校验合法域名“

License

MIT

原文作者:Rolan

原文链接:

http://www.wxapp-union.com/portal.php?mod=view&aid=5704

好课推荐

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-12-02,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 腾讯NEXT学院 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
数据库
云数据库为企业提供了完善的关系型数据库、非关系型数据库、分析型数据库和数据库生态工具。您可以通过产品选择和组合搭建,轻松实现高可靠、高可用性、高性能等数据库需求。云数据库服务也可大幅减少您的运维工作量,更专注于业务发展,让企业一站式享受数据上云及分布式架构的技术红利!
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档