項目地址: https://github.com/smackgg/reversevoicehtml
整個項目其實很簡單,從本人在抖音和 B 站看到火起來到最終小程序上線也就幾天的下班時間就搞定了,11月16日上線至今用戶量仍是蠻多的(主要當時作的快此類 app 比較少😂),如今已經出現了大量的更簡約更好的倒放挑戰 app,本項目開源僅供你們學習~node
擁抱 TypeScript ~react
順便小聲吐槽一下 Taro 對 Ts 的支持仍是不夠啊,但願你們多去給 Taro 提 dts 的 PR ~git
使用 ffmpeg 進行音頻倒放,核心代碼:github
// 詳見 ./server/src/controllers/file.ts => function reverseVoice import 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.tsxmongodb
錄音typescript
利用 canvas 動態合成分享海報 /wechatapp/pages/sharePoster
須要動態請求頁面小程序碼,涉及微信AccessToken鑑權等,詳見 /server/src/controllers/wechat.ts, 下面貼出部分核心代碼npm
// 畫圖 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 組件,方便頁面使用 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
使用 redux
@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: '', } /** .... */ }
微信官方文檔登陸流程
具體實現能夠去看源碼canvas
須要提早安裝:
cd server
npm install
# create the db directory sudo mkdir -p /data/db # give the db correct read/write permissions sudo 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.
mongod # on macOS 10.15 or above the db directory is under home directory mongod --dbpath ~/data/db
npm run build npm start
須要提早安裝:
cd wechatapp
npm install
在 wechatapp/src/utils 目錄下克隆 env.example.ts 文件至同目錄命名爲 .env.ts 文件 此文件兩個參數分別表明本地開發和線上部署的請求地址
npm run dev:weapp // development mode 或者 npm run build:weapp // production mode
選擇導入項目,並選擇 wechatapp/dist 目錄 若本地開發,須要在開發者工具中設置開啓「不校驗合法域名「
MIT