1. ホーム
  2. python

Watching live videos and playing with CSS animations on Jupyter is so cool!

2022-02-19 08:13:37

Hello, I'm Tiny Ming.

Today I'm going to play around with some front-end stuff on Jupyter:.

  • Playing around with HTML on jupyter: watching MP4 videos on Jupyter
  • Playing around with CSS on Jupyter: setting animation styles for Pandas forms
  • Playing with JavaScript on Jupyter: watching live videos on Jupyter

Let's start with something simple, playing around with HTML on jupyter: the

Watch the video on Jupyter

Watching local videos.

from IPython.display import HTML


def show_video(url, width="100%"):
    html = f"""
"""
    return HTML(html)


show_video("a.mp4", "30%")


Note: Only relative paths are supported, requiring the video file and the ipynb file to be in the same directory or subdirectory

Watch the online video at

show_video("https://www.runoob.com/try/demo_source/mov_bbb.mp4", "70%")


Playing around with CSS on Jupyter.

Making a Pandas table on Jupyter follow the mouse

Rotate.

import pandas as pd
import numpy as np

df = pd.DataFrame(np.random.rand(5, 2), columns=['data1', 'data2'])
df['key1'] = ['a', 'a', 'b', 'b', 'e']
df['key2'] = ['one', 'two', 'one', 'two', 'one']
df.style.set_table_styles([
    {'selector': 'tr',
     'props': [('transition-duration', '1s')]},
    {'selector': 'tr:hover',
     'props': [('transform', ' rotate(360deg)')]}
])


Displacement.

df.style.set_table_styles([
    {'selector': 'tr',
     'props': [('transition-duration', '1s')]},
    {'selector': 'tr:hover',
     'props': [('transform', 'translate(90%)')]}
])


Specific principles.

First set the transition time for the target element, cf. https://www.runoob.com/css3/css3-transitions.html

Then set the special style for mouse-over target elements with the pseudo-class hover.

The two style changes above use two methods of 2D changes, cf. https://www.runoob.com/css3/css3-2dtransforms.html

Finally we play around with JavaScript on Jupyter: the

Executing JavaScript commands

To execute JavaScript in jupyter is simple, directly using the Javascript command to execute.

from IPython.display import Javascript

Javascript("alert('A piece of JavaScript was executed')")


You can see that after execution, the prompt window pops up.

Watching live video on Jupyter

What about the following, we are going to implement watching live B-stream directly on Jupyter. To do both studying and learning (for fun).

The final result to be achieved.

Get a list of live room ids for a given partition

This time we are looking at the live area of

Then we have the list of live ids for that partition.

import requests
from lxml import etree


def get_room_ids(room_type="learning"):
    urls = {"study": "https://live.bilibili.com/p/eden/area-tags?visit_id=9ynmsmaiie80&areaId=377&parentAreaId=11& quot;,
            "faceArea": "https://live.bilibili.com/show/yzly?visit_id=3g19a7bxnb60"}
    res = requests.get(urls[room_type])
    res.encoding = res.apparent_encoding
    html = etree.HTML(res.text)
    room_ids = {}
    for a in html.xpath("//ul/li/a"):
        url = a.xpath(". /@href")[0]
        tags = a.xpath(". //text()")
        room_ids[tags[1]] = url[1:url.find(""? ")]
    return room_ids


room_ids = get_room_ids()
room_ids

{'Uncle who teaches modeling': '22590752',
 '
Get the source address of the live feed for the specified live room
After some packet capture analysis, we know that the interface address of the live signal source is
https://api.live.bilibili.com/xlive/web-room/v1/playUrl/playUrl
To get the address of the video source, simply pass 3 parameters to the above connection, which are
cid : cid serial number
qn : Quality of the video played
platform : The format in which the video is played
import requests


def get_live_url(cid, platform='h5'):
    playUrl = 'https://api.live.bilibili.com/xlive/web-room/v1/playUrl/playUrl'
    params = {
        'cid': cid, # cid serial number
        'qn': 10000, # the quality of the played video
        'platform': platform, # the format of the video to be played
        'ptype': 16
    }
    response = requests.get(playUrl, params=params).json()
    text = response['data']['durl']
    url = text[-1]['url']
    return url


可以传入参数web,可以获取flv的流媒体格式:
url = get_live_url(room_ids['璇女神带你学Java'], 'web')
url

'https://d1--cn-gotcha04.bilivideo.com/live-bvc/370442/live_381426464_8387123_1500.flv?cdn=cn-gotcha04&expires=1624877425&len=0&oi=1947748628&pt=web&qn=150&trid=1000a40949329fc44be7ad3f64f48b5e6102&sigparams=cdn,expires,len,oi,pt,qn,trid&sign=04b8a67515e5bc3f16cb4b386adebffb&ptype=0&src=9&sl=1&sk=417e709c171a500&order=4'

对于这种形式的地址,使用网页播放器需要特殊的解码库。由于本地播放器可以直接播放,本人觉得也没有必要开发针对这种格式的网页播放器。 对于上述地址直接粘贴到potplayer播放器中即可播放: 不指定目标参数则指定了参数为h5,最终抓到的将是m3u8格式的直播地址:
url = get_live_url(room_ids['3D游戏建模/zbrush学习'])
url

'https://d1--cn-gotcha103.bilivideo.com/live-bvc/484428/live_137444201_2481017.m3u8?cdn=cn-gotcha03&expires=1624862132&len=0&oi=1947748628&pt=h5&qn=10000&trid=10031734853477fb4f7eba52bedbf0ad4958&sigparams=cdn,expires,len,oi,pt,qn,trid&sign=ff26ba84039442d42c59ae2310768bdc&ptype=0&src=9&sl=1&sk=417e709c171a500&order=4'

这个地址直接粘贴到potplayer中是无法直接播放的,这是因为这个m3u8是一个嵌套的地址(真实的m3u8地址存在于这个文件中),我们将真实的地址提取出来就可以直接粘贴到potplayer进行播放了。 提取代码如下:
def get_real_url(url):
    r = requests.get(url, headers={
                     "User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36"})
    for line in r.text.splitlines():
        if line.startswith("http"):
            url = line
            break
    return url


real_url = get_real_url(url)
print(real_url)

https://236809363.cloudvdn.com/a.m3u8?cdn=cn-gotcha03&domain=d1--cn-gotcha103.bilivideo.com&expires=1624885067&len=0&oi=1947748628&order=4&player=oMgAAAUu2rUWvYwW&pt=h5&ptype=0&qn=10000&secondToken=secondToken%3A3pgIk9iJHnT4GCnoFdgLimMFp-I&sign=dd58d00836aa06776e6f2b0d933a3aee&sigparams=cdn%2Cexpires%2Clen%2Coi%2Cpt%2Cqn%2Ctrid&sk=87af7c4a512d23a&sl=1&src=8&streamid=live-qn%3Alive-qn%2Flive_8086004_8646306&trid=1003e246434329364ba685ff4d5ecff153a0&v3=1

不过我们开发的前端播放器针对嵌套的m3u8地址也是可以直接直播的: 编写针对m3u8数据流的前端播放器 针对这种地址,一般的本地播放器都是无法直接的。我们想要播放这种地址,需要实现一个h5的专门的播放器,具体需要用到两个js文件: video.js videojs-contrib-hls.min.js 找到了两个现成的cdn地址,我们无需下载为本地文件,最终代码为: // videojs 简单使用 var myVideo = videojs('myVideo',{ bigPlayButton : true, textTrackDisplay : false, posterImage: false, errorDisplay : false, }) myVideo.play() // 视频播放 最终打开的效果: 经测试完全顺利实现直播播放。 最终将其中可能变化的部分以{xxx}形式定义出来作为模板,得到template.html文件(留给读者们自行补充)。 开启直播 做完模板我们就可以实现在Jupyter中直播了,代码如下: 效果:
import requests


def get_live_url(cid, platform='h5'):
    playUrl = 'https://api.live.bilibili.com/xlive/web-room/v1/playUrl/playUrl'
    params = {
        'cid': cid, # cid serial number
        'qn': 10000, # the quality of the played video
        'platform': platform, # the format of the video to be played
        'ptype': 16
    }
    response = requests.get(playUrl, params=params).json()
    text = response['data']['durl']
    url = text[-1]['url']
    return url



url = get_live_url(room_ids['璇女神带你学Java'], 'web')
url

'https://d1--cn-gotcha04.bilivideo.com/live-bvc/370442/live_381426464_8387123_1500.flv?cdn=cn-gotcha04&expires=1624877425&len=0&oi=1947748628&pt=web&qn=150&trid=1000a40949329fc44be7ad3f64f48b5e6102&sigparams=cdn,expires,len,oi,pt,qn,trid&sign=04b8a67515e5bc3f16cb4b386adebffb&ptype=0&src=9&sl=1&sk=417e709c171a500&order=4'