「抖音」直播在线1万+竟如此简单,通过Electron搭建直播间

「抖音」直播在线1万+竟如此简单,通过Electron搭建直播间

小事化巨变,止于尝试始

抖音直播间在线人数突破10000+,原来可以如此简单

最近通过Electron开发了一个小工具,可以实时监控抖音用户粉丝人数变化!我做了一个小试验,在直播间通过这个工具监控"董宇辉"粉丝数数增量,结果几分钟时间直播间就突破了1万+,不得不感叹董宇辉丈母娘们力量强大。

我主要是通过Electron结合抖音网页版用户详情页开发了这个工具,它可以定时获取指定用户的粉丝数并实时显示在界面上。我在直播间通过屏幕分享这个实时在线人数增量的界面,一边和观众互动聊天,一边观察在线人数变化。大家看到在线人数持续增长都很兴奋,纷纷点赞、分享、观看,在线人数增速越来越快,很快就突破了1万大关。

通过这个实验,我发现,只要内容有吸引力,加上数据变化的即时反馈刺激,可以产生很强的爆发效应。我认为这种技术手段虽有些“作弊嫌疑”,但对内容创作者而言也具有很强的指导意义。数据和互动是内容时代的关键,通过数字化手段优化内容传播效果,也是一种创新的尝试。

话不多说上代码:

抓取粉丝数量

export async function dyh() {
  // 1. 获取用户信息
  const data = await fetch(
    'https://www.douyin.com/user/MS4wLjABAAAAInYK7Wk_cCLwFlhAvpgeYFSXDQwUWmemBCsyCYtKOOI',
    {
      headers: {
        accept:
          'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7',
        'accept-language': 'zh-CN,zh;q=0.9,en;q=0.8',
        'cache-control': 'no-cache',
        pragma: 'no-cache',
        'sec-ch-ua': '"Not_A Brand";v="8", "Chromium";v="120", "Google Chrome";v="120"',
        'sec-ch-ua-mobile': '?0',
        'sec-ch-ua-platform': '"macOS"',
        'sec-fetch-dest': 'document',
        'sec-fetch-mode': 'navigate',
        'sec-fetch-site': 'none',
        'sec-fetch-user': '?1',
        'upgrade-insecure-requests': '1'
      },
      referrerPolicy: 'strict-origin-when-cross-origin',
      body: null,
      method: 'GET',
      mode: 'cors',
      credentials: 'include'
    }
  )
  const text = await data.text()
  // 2. 获取粉丝数
  const parsed = /mplatformFollowersCount\":(\d+)/gi.exec(text)

  if (parsed) return Number(parsed[1])

  return 0
}

粉丝数量就在页面中的mplatformFollowersCount字段中,使用正则匹配粉丝数即可,如下图:

定时获取粉丝数量

import { dfzx } from './dfzx'
import { dyh } from './dyh'

let dfzxCount = 0
let dyhCount = 0
let countdown = 0
let timer: NodeJS.Timeout

export async function polling(callback: (count: Douyin) => void) {
  try {
    const count = await dyh()
    if (count > 0) dyhCount = count
  } catch (e) {
    console.error('getDyh', e)
  }

  try {
    const count = await dfzx()
    if (count > 0) dfzxCount = count
  } catch (e) {
    console.error('getDyh', e)
  }

  countdown = Math.floor(Math.random() * 26) + 5 // 随机生成5到30之间的整数

  clearInterval(timer)
  timer = setInterval(() => {
    callback({
      dyhCount,
      dfzxCount,
      countdown: countdown--
    })
  }, 1000)
  setTimeout(() => polling(callback), countdown * 1000)
}

通信与渲染

Electron通信介绍:进程间通信 | Electron (electronjs.org)

流程图如下:一个渲染进程获取粉丝中,一个渲染进程用于最终数据的展示即可,主进程作为数据传递的中转站。

渲染进程一

抓取抖音数据,将数据发送至主进程。这里单开一个窗口用来处理在抖音页面上抓取数据的操作。

import { polling } from './utils/polling'

window.addEventListener('DOMContentLoaded', () => {
  if (window.location.hostname.includes('douyin')) {
    void polling((data) => {
      void ipcRenderer.invoke('douyin', data)
    })
  }
})

主进程

接收渲染进程一消息,发送至渲染进程二,作为最终显示的结果。

import { ipcMain } from 'electron'

// douyinWindow1: 渲染进程一,是单独创建的一个窗口

type Douyin = {
  dyhCount: number
  dfzxCount: number
  countdown: number
}

// 抖音
ipcMain.handle('douyin', (_, info: Douyin) => {
  douyinWindow1.webContents.send('douyin', info)
})

渲染进程二

我们主要操作的进程,用来渲染我们获取到的董宇辉粉丝数据

import { useDouyin } from '@renderer/store/douyin/hooks'

type UserInfo = {
  name: string
  avatar: string
  followers: number
}

function User({ followers, name, avatar }: UserInfo) {
  return (
    <div className="p-2 flex flex-row gap-2 items-center">
      <div className="relative avatar">
        <div className="w-24 rounded-full">
          <img src={avatar} alt="" />
        </div>
        <div className="absolute">
          <span className="loading loading-ring loading-ring-lg text-green-500"></span>
        </div>
      </div>
      <div className="flex flex-col gap-1">
        <div className="text-[20px] text-white">{name}</div>
        <div className="text-[22px] text-white/90">{`${followers / 10000}万`}</div>
      </div>
    </div>
  )
}

function App() {
  const { dyhCount, dfzxCount, countdown } = useDouyin()

  return (
    <div
      style={{
        backgroundSize: '100% 100%',
        backgroundPosition: '0 0,100% 0',
        backgroundRepeat: 'no-repeat',
        backgroundImage:
          'linear-gradient(90deg,rgba(26,28,39,0) 0%,#1a1c27 calc(100% - 852px),rgba(32,32,53,.35) 64.63%,rgba(33,33,57,.2) 100%),url(//lf3-cdn-tos.bytegoofy.com/obj/goofy/ies/douyin_web/media/dark_bg_default.51564fca60b7a3da.png)'
      }}
      className="h-screen"
    >
      <div className="fixed left-1/2 -translate-x-1/2 w-[375px] h-[70%] p-5 flex flex-col justify-center gap-3">
        <User
          name="董宇辉"
          followers={dyhCount}
          avatar="https://p3-pc.douyinpic.com/img/aweme-avatar/tos-cn-avt-0015_61ef8a9a0458c96eb5ff0afa94bab7fb~c5_300x300.jpeg?from=2956013662"
        />
        <User
          name="东方甄选"
          followers={dfzxCount}
          avatar="https://p3-pc.douyinpic.com/img/aweme-avatar/tos-cn-avt-0015_34583dc5dc55d5983f8a57fafcbceb6d~c5_300x300.jpeg?from=2956013662"
        />
        <div className="text-white/50 pl-10">
          自动刷新(<span className="text-white/30 text-sm">倒计时{countdown}秒</span>)
        </div>
      </div>
    </div>
  )
}

export default App

实际效果如下图:

接下来就可以去开播了...

还不会开播请接着往下看

开播流程

抖音直播伴侣了解一下:抖音直播伴侣 (douyin.com)

直播场景

添加素材 -> 选择窗口,选择开发的应用程序的窗口即可

直播画面

打开的开发好的应用程序,将其作为直播画面(如下图),被用户看到,我们可以在直播伴侣预览画面,预览之后同步画面,再点击开始直播,这样用户就能看到直播了

直播效果

小提示

直播的时候窗口比例是设置为3:4,在手机上显示效果比较好,但是如果我们开发的时候显示的内容完全撑满窗口,真正直播的时候,会导致内容显示不全,所以我们的内容不能完全撑满窗口,需要留有余地,以便适配不同宽度的手机

我的配置如下:

渲染进程的宽高配置

const mainWindow = new BrowserWindow({
  width: 457,
  height: 812,
  show: false,
  autoHideMenuBar: true,
  // 无边框
  frame: false,
  ...(process.platform === 'linux' ? { icon } : {}),
  webPreferences: {
    preload: join(__dirname, '../preload/index.js'),
    sandbox: false
  },
  resizable: false
})

我们将手机主要可视区域的宽度设置为 375px,并居中显示,可以较好的适配手机画面,避免直播画面被裁切。

function App() {
  return <div className="w-[375px] flex justify-center">主要内容显示区域</div>
}

董宇辉小作文

人生不会一直如你的愿,跌宕起伏才是人生

就像心跳一样,它是有高有低的

每当你觉得你是一个无名之辈,无足轻重

当你觉得未来黯淡无光时,请你记得

七千亿亿亿个原子,只为你一个而活

如果把你身体的DNA连成一条线

你可以从地球到冥王星

所以,你自己,就能完成星际穿越

不得不感叹,董宇辉丈母娘们确实厉害!!!

结尾

点点小♥️吧

阅读更多

「地图」高德JS API地图POI信息层级设置

「地图」高德JS API地图POI信息层级设置

遇到一个关于“修改高德地图POI信息层级”的问题,分享给大家 解决方案 1. 首先POI信息其实是一个AMap.LabelsLayer图层 2. 通过amap.getLayers()获取所有图层,从中找到POI图层,使用AMap.LabelsLayer提供的setzIndex()方法设置层级即可 3. 经过尝试POI图层设置层级大于110,POI文字信息就能覆盖在polyline之上了 效果图 ❤点点关注,点点赞❤ ...End...

作者 Fate Rain
「threejs」滚动效果该如何实现?

「threejs」滚动效果该如何实现?

前因 某一天我在刷抖音时,看到一个UI设计师分享了一个好看的网页滚动动效设计。那种飘逸流畅的动画效果立刻抓住了我的眼球,我脑海里立刻开始想象用代码如何实现这个效果。 于是我把设计师的视频保存下来研究,反复琢磨每个动画细节需要哪些技术来配合。随后我开工码代码,一个个函数、一个个模块地构建起这个动效。在磨合调试的过程中,我时而眉头紧锁,时而按捺不住兴奋的心情。 经常关注优秀的设计作品,尝试用代码实现,这样不仅可以增强自己的编程能力,也可以从中获取乐趣。这种从设计到编码的过程,就像一个创造的闭环。 很高兴可以通过编程让虚拟的代码世界连接起这个美好的现实世界。 设计相关(Figma+dora) 感谢“设计师Cc”提供的稿子 * Figma * Dora: 无代码3D动画 戳这里。对Dora工具有大致了解后,已经大致实现思路,想用代码实现的关键是:滚动 + 关键帧动画 预览 源码🚀 codesandbox 实现 技术选型 3d模型展示: 1. @react-three/fiber: 流行的threejs React 封装 2. @react-thre

作者 Fate Rain
滇公网安备53012902000069号
滇ICP备20005454号-2