Watching live videos and playing with CSS animations on Jupyter is so cool!
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地址,我们无需下载为本地文件,最终代码为:
最终打开的效果:
经测试完全顺利实现直播播放。
最终将其中可能变化的部分以{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'
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'
関連
-
PythonをベースにしたMUIタイトルバーの最適化
-
PythonによるNumpyの行列演算
-
[解決済み] AxisError: クラスの精度を計算する際、軸1が1次元の配列の境界を外れています。
-
[解決済み] tf.layers.conv2d と tf.contrib.slim.conv2d の相違点
-
[解決済み] 基本ファイルが実行されない → デバイスPRNを初期化できない
-
[解決済み] Python - 'str' オブジェクトに 'close' 属性がありません。
-
[解決済み] env: python ✎: No such file or directory
-
[解決済み] Pythonで.datファイルから読み込んで計算する。
-
[解決済み] heapqライブラリの関数の時間複雑性は?
-
[解決済み] 2つのリスト(お互いを参照している)を全く同じ方法でソートする方法
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】Python - "ValueError: not enough values to unpack (expected 2, got 1)" の修正方法 [閉店].
-
[解決済み】heroku: このアプリのデフォルト言語が検出されない
-
[解決済み] 終了コード -1073741515 (0xC0000135)でプロセス終了
-
[解決済み] AttributeError: モジュール 'matplotlib' には属性 'plot' がありません。
-
[解決済み] TypeError: 'range' オブジェクトはアイテムの割り当てをサポートしていません。
-
[解決済み] Virtualenv OSError - setuptools pip wheel failed with error code 1
-
[解決済み] (python) [Errno 11001] getaddrinfo に失敗しました。
-
[解決済み] Pythonで末尾のゼロを削除する [重複]。
-
TypeError: -でサポートされていないオペランド型: 'list' および 'int'
-
Pythonでansible 2.8を呼び出す