作为一个喜欢搬运 YouTube 视频的网友,我发现将视频下载下来再上传到 B 站十分繁琐,因此我决定开发一个小工具,能够方便快捷地将 YouTube 视频下载并上传至 B 站,以节省我的时间和精力。
语言:Python
主要借助:request库、yt-dlp、biliup
完整代码:
from PIL import Image
import json
import sys
import requests
import yt_dlp
import subprocess
from biliup.plugins.bili_webup import BiliBili, Data
def download(url):
# 初始化
video_info = {}
audio_ydl_opts = {
'format': 'bestaudio/best',
'postprocessors': [{
'key': 'FFmpegExtractAudio',
'preferredcodec': 'mp3',
}],
'outtmpl': './resource/%(channel)s/%(id)s'
}
video_ydl_opts = {
'format' : 'bv[height<=1080][ext=mp4]+ba[ext=m4a]',
'outtmpl': './resource/%(channel)s/%(id)s.mp4'
}
# 下载音频
with yt_dlp.YoutubeDL(audio_ydl_opts) as ydl:
ydl.download(url)
with yt_dlp.YoutubeDL(video_ydl_opts) as ydl:
# 获取视频信息
extract_info = ydl.extract_info(url, download=False)
video_info['id'] = extract_info['id']
video_info['title'] = extract_info['title']
video_info['description'] = extract_info['description']
video_info['url'] = extract_info['webpage_url']
video_info['categories'] = extract_info['categories']
video_info['tags'] = extract_info['tags']
video_info['video_path'] = f"./resource/{extract_info['channel']}/{extract_info['id']}.mp4"
video_info['audio_path'] = f"./resource/{extract_info['channel']}/{extract_info['id']}.mp3"
video_info['thumbnail_path'] = f"./resource/{extract_info['channel']}/{extract_info['id']}.png"
# 下载视频
ydl.download(url)
# 下载壁纸,并转换成可以上传的格式
imgData = requests.get(extract_info['thumbnail']).content
with open(f"./resource/{extract_info['channel']}/{extract_info['id']}.webp", "wb") as handler:
handler.write(imgData)
im = Image.open(f"./resource/{extract_info['channel']}/{extract_info['id']}.webp").convert("RGB")
im.save(f"./resource/{extract_info['channel']}/{extract_info['id']}.png")
return video_info
# 上传
def upload(video_info):
return_code = subprocess.run([
'./biliup', 'upload', f"{video_info['video_path']}",
'--copyright', '2',
'--cover', f"{video_info['thumbnail_path']}",
'--desc', f"{video_info['description'][:99]}",
'--source', f'{video_info["url"][:79]}',
'--tag', 'youtube',
'--title', f'{video_info["title"]}',
])
print("return code:", return_code)
if __name__ == "__main__":
# 获取url
url = sys.argv[1]
# 下载
video_info = download(url)
# 上传
upload(video_info)
注:本文解析的源码基于API25,部分内容来自于《Android开发艺术探索》。HeaderAndroidView事件分发的机制可以说是Android开发者必知点之一,一般在面试的过程中肯定也有涉及。之前重新梳理了一下View事件的分发,所以为了有所记录,下定决心要写一篇关于View事件分发的博客。虽然很早之前也写了一篇关于事件分发的博客《AndroidonTouch事件传递机制解析》,但是在这篇中分析不够全面,Activity和ViewGroup没有涉及到。那么就来“再续前缘”吧。事件分发可以说分为三个部分,一个是Activity然后是ViewGroup最后是View我们在分析事件分发时,也会依次按照这三个部分来入手。因为最后的View部分在之前已经分析过了(也就是《AndroidonTouch事件传递机制解析》),所以今天的内容里关于View部分的就不再讲了,大家可以自己去这篇博客中接着看下去。好咯,下面就是我们的showtime!Activity先入手第一部分:Activity。ActivitydispatchTouchEvent(MotionEventev)在Activity的
Promise方法5.1、all方法Promise.all方法,提供了并行执行异步操作的能力,并且在所有异步操作完成之后,统一返回所有结果。具体使用如:Promise.all([ newPromise(resolve=>resolve('a')), newPromise(resolve=>resolve('b')), ]).then(res=>{ console.log('all',res)//【'a','b'】 })复制all接收到的是一个数组,数组长度取决于Promise的个数。一些游戏类的素材比较多的应用,打开网页时,预先加载需要用到的各类资源,所有的都加载完后,再进行页面的初始化。5.2、race方法race翻译成中文:赛跑。就是谁跑得最快,谁才能触碰到终点的胜利线。Promise.race用法与all一样,只是返回结果上不同,它返回的是执行最快的那个Promise的结果。Promise.race([ newPromise(resolve=> setTim
作者:RossTaylor编译:ronghuaiyang导读2020年PaperswithCode中最顶流的论文,代码和benchmark。PaperswithCode中收集了各种机器学习的内容:论文,代码,结果,方便发现和比较。通过这些数据,我们可以了解ML社区中,今年哪些东西最有意思。下面我们总结了2020年最热门的带代码的论文、代码库和benchmark。2020顶流论文 Tan等人的EfficientDet是2020年在PaperswithCode上被访问最多的论文。 EfficientDet:ScalableandEfficientObjectDetection—Tanetalhttps://paperswithcode.com/paper/efficientdet-scalable-and-efficient-objectFixingthetrain-testresolutiondiscrepancy—Touvronetalhttps://paperswithcode.com/paper/fixing-the-train-test-resolution-discrepanc
AIDL是Android中IPC(Inter-ProcessCommunication)方式中的一种,AIDL是AndroidInterfacedefinitionlanguage的缩写(对于小白来说,AIDL的作用是让你可以在自己的APP里绑定一个其他APP的service,这样你的APP可以和其他APP交互。)AIDL只是Android中众多进程间通讯方式中的一种方式,AIDL和Messenger的区别:Messenger不适用大量并发的请求:Messenger以串行的方式来处理客户端发来的消息,如果大量的消息同时发送到服务端,服务端仍然只能一个个的去处理。Messenger主要是为了传递消息:对于需要跨进程调用服务端的方法,这种情景不适用Messenger。Messenger的底层实现是AIDL,系统为我们做了封装从而方便上层的调用。AIDL适用于大量并发的请求,以及涉及到服务端端方法调用的情况AIDL通信的原理:首先看这个文件有一个叫做proxy的类,这是一个代理类,这个类运行在客户端中,其实AIDL实现的进程间的通信并不是直接的通信,客户端和服务端都是通过proxy来进行通信
1、Vue路由,路由的基本概念与原理。答:1)、路由是一个比较广义和抽象的概念,路由的本质就是对应关系。 2)、在开发中,路由分为,后端路由和前端路由。 3)、后端路由,根据不同的用户URL请求,返回不同的内容。后端路由的本质就是URL请求地址与服务器资源之间的对应关系。后端路由根据不同的URL地址分发不同的资源。 4)、前端路由,根据不同的用户事件,显示不同的页面内容。本质就是用户事件与事件处理函数之间的对应关系。前端路由负责事件监听,触发事件后,通过事件函数渲染不同内容。2、SPA(SinglePageApplication)。答:1)、后端路由的渲染,就叫做后端渲染(存在性能问题)。 2)、Ajax前端渲染,前端渲染提供性能,但是不支持浏览器的前进后退操作。 3)、SPA(SinglePageApplication)单页面应用程序,整个网站只有一个界面,内容的变化通过Ajax局部更新实现,同时支持浏览器地址栏的前进和后退操作。 4)、SPA实现原理之一就是基于URL地址的hash,hash的变化会导致浏览器记录访问历史的变化,但是hash的变化不会触发新的URL请求。 5)、在实
深度强化学习报道来源:王小惟的知乎https://zhuanlan.zhihu.com/p/70127847编辑:DeepRL论文下载方法:pdf合集下载见文章末尾DRL领域交流与讨论加微信:NeuronDance关于DeepMind:DeepMind,位于英国伦敦,是由人工智能程序师兼神经科学家戴密斯·哈萨比斯(DemisHassabis)等人联合创立,是前沿的人工智能企业,其将机器学习和系统神经科学的最先进技术结合起来,建立强大的通用学习算法。最初成果主要应用于模拟、电子商务、游戏开发等商业领域。目前,Google旗下的DeepMind已经成为AI领域的明星,据外媒2016年6月8日,DeepMind欲将其算法应用到医疗保健行业,包括计划在5年内使用机器学习处理英国国家医疗服务体系。本文对DeepMind公司几年以来的72篇文章做了简短的解读,对涉及到的知识点进行了汇总,并且为各位爱好者提供了论文的pdf合集(72篇论文合集,通过文章末尾下载地址直接获取)12015-ICML-workshop-MassivelyParallelMethodsforDeepReinforcement
一、枚举定义及使用 枚举的定义在其他许多的语言中都有实现,举例来说,比如C中的枚举,枚举值在未赋值的情况下默认从0开始递增或从上一个枚举值开始递增,值类型可以是整数或字符类型,实质只能保存整型:enum{ A='d',//d的ascii码值 B,//e的ascii码值 C,//f的ascii码值 D=10, E,//11 };复制Rust中的枚举与C中的枚举不同,功能非常强大,可以用枚举表达更多的可能性数据。看一下基本的枚举定义://定了一个性别的枚举 enumGender{ Male, Female, }复制这里面不同的是,Male和Female不是变量,而是枚举值,而不像是C中会访问到相应的数字。 #[derive(Debug)] enumGender{ Male, Female, } println!("{:?},{:?}",Gender::Male,Gender::Female); -----输出----- Male,Female复制虽然输出看上去是字符串类型,但实际是枚举Gender类型 //这样是编译不通过的 ifGender::
TheGoBlogAnnouncingAppEngine’sNewGo1.11Runtime16October2018AppEnginelaunchedexperimentalsupportforGoin2011.Inthesubsequentyears,theGocommunityhasgrownsignificantlyandhassettledonidiomaticpatternsforcloud-basedapplications.Today,GoogleCloudisannouncinganewGo1.11runtimefortheAppEnginestandardenvironmentthatprovidesallthepowerofAppEngine—thingslikepayingonlyforwhatyouuse,automaticscaling,andmanagedinfrastructure—whilesupportingidiomaticGo.StartingwithGo1.11,GoonAppEnginehasnolimitsonapplicationstru
1/* 2 3 42006年10月01日 5 6SQLServer数据库的高级操作 7(1)批处理 8(2)变量 9(3)逻辑控制 10(4)视图 11(5)函数 12(6)高级查询 13 14*/ 15 16(1)批处理 17将多条SQL语句作为一个整体去编译,生成一个执行计划,然后,执行! 18理解批处理的关键在于"编译",对于由多条语句组成的一个批处理, 19如果在编译时,其中,有一条出现语法错误,将会导致编译失败! 20 21createtablet 22( 23aint, 24bint 25) 26 27--注释 28--如果多行注释中包含了批处理的标识符go 29--在编译的过程中代码将会被go分割成多个部分来分批编译 30--多行注释的标记将会被分隔而导致编译出错 31--以下几条语句是三个非常经典的批处理 32--你猜一下会添加几条记录! 33/* 34insertintotvalues(1,1) 35go 36*/ 37insertintotvalues(2,2) 38go 39/* 40insertintotvalues(3,3) 41*/ 42
本周三,VR小报系列沙龙第五期在北京中关村领创空间成功举办。今年随着VR设备的逐渐增加,VR视频也越来越受到关注。本期沙龙以“VR视频的不同表现形式探索”为主题,邀请了幻维世界视频制作人陈祥文、指挥家VR影视制作总监罗子元、大麦VRCTO张涛、87870VR内容负责人隗合磊、小花秀VR商务市场总监李诗卉。嘉宾分别从VR网剧拍摄,VR视频制作、VR话剧、室外VR短片、VR直播等VR视频细分领域与大家分享制作VR视频的经验,以及不同类型的视频在拍摄或运营上的注意点。首先,由速途网络总编辑孟祥龙为大家介绍了速途网络和VR小报品牌栏目发展现状,以及速途最近推出速途影业和大娱乐营销所拥有的众多资源。之后,幻维世界视频制作人陈祥文围绕《67号宇宙》的创作灵感、影片剧情设计还有拍摄与后期制作展开话题,介绍了后期制作的方式,以及探讨了现场环境对拍摄的影响。指挥家VR影视制作总监罗子元以VR交互视频的制作为题,向大家介绍CG制作的VR交互视频:观众可以在影视中与内容产生互动,与硬件配合会有更多触觉、真实等增强体验。随后与大家分享了目前VR制作的主要工艺流程及CG与实拍混合制作、眼控技术、视域动态分配串流
本文为翻译文,原文地址:http://shiro.apache.org/10-minute-tutorial.html 介绍 欢迎来到ApacheShiro的10分钟教程! 通过这个教程,你会明白一个开发人员如何在他们的应用中使用Shiro,并且你也能够在10分钟内做到。 概述 什么是ApacheShiro? ApacheShiro是一个强大、易用的Java安全框架,它在身份验证、授权、加密、会话管理方面,为开发人员提供直观、全面的解决方案。 ApacheShiro能做什么事情? 它能做很多事情。不过我们不想在入门阶段就全部展开。如果你想知道它能帮你做什么,请查阅我们专门描述特性的网页。如果你好奇我们的起源和为什么我们存在,请查阅描述我们的历史和任务的网页。 好了,现在我们开始吧。 请注意: Shiro能运行在任何环境,无论简单的命令行,抑或大型的Web应用集群,不过我们在此快速入门会用最简单的例子,比如Java的main方法。这样,你就能了解这些API。 复制 下载 保证已经安装JDK1.6+、Maven3.0.3+ 在下载页下载最新的“SourceCodeDistribution
背景为了提高页面性能,减少白屏时间,我的详情页面接收上游列表传过来的一个参数cover,这是一张在上一个列表页面已经加载过了的图片链接,当跳转到我的页面时,首先将这张图片显示出来(浏览器已有缓存),这样能极大减少页面白屏时间。当然,为了防止被XSS,我对这张图片做了严格的过滤。直到有一天,领导转给我一个链接,点开一看,中间赫然一张不雅图呈现在眼前,顿时傻眼了,立马拷贝链接,拿到cover解码一看,外部“非法链接“,领导说你页面被XSS了。好吧,可能被“XSS”了,于是决定对图片域名加了一层校验:图片域名必须是我司域名。然后以百米冲刺速度修改,验证,发布,刷新CDN……于是,问题解决了吗?好像解决了!好像又没完全解决?那如何才算解决了呢?让我们一起走进XSS的世界!前言跨站脚本攻击,英文是:CrossSiteScript,缩写应该是CSS,但是为了和CSS(CascadingStyleSheet)层叠样式有所区别,所在安全领域叫做“XSS”。在上世纪90年代,这种攻击主要是跨域攻击,而一个网站就是一个域名,所以叫“跨站脚本攻击”。但是发展到今天,是否跨域已经不重要了,由于这个历史原因,X
题目:输入两个链表,找出它们的第一个公共结点,链表结点的定义如下: 1structListNode 2{ 3intm_nKey; 4ListNode*m_pNext; 5}复制 一共三种方法解答此题目: 方法1:双层遍历链表,复杂度为O(m*n) 方法2:有两个栈存储链表结点模拟从后往前遍历 方法3:先计算出两个链表长度,然后使得较长的链表先走k步与短链表对齐再一起向后比较 这里我们只介绍方法三 我们以链表: 1->2->3->6->7 4->5->6->7为例 1.先计算出链表1长度为5链表2长度为4 2.链表1比链表2长一个结点那么让链表1先走一步到结点2 3.两个链表同时向后遍历并比较遇到相同的结点返回并结束 简单实现如下: 1#include<iostream> 2usingnamespacestd; 3 4structListNode 5{ 6intm_nKey; 7ListNode*m_pNext; 8}; 9 10voidPrintListNode(List
下面实现的功能是zip文件中的图像文件解压到当前目录下,用jdk自带的处理zip文件的代码处理的,但是不能处理中文名称的文件,要不然就会出错。 Java代码 import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; /** * 不能处理中文文件名
线段树上维护最大子段和是在每个节点上维护四元组\((mx,lm,rm,sum)\),但现在有全局加操作,线段树就不能直接维护了。 考虑如何维护\(lm\),\(rm\)同理,设\(pre(x)\)为长度为\(x\)的前缀和的值,\(add\)为当前全局加的和,则\(add\timesx+pre(x)\)是可能成为\(lm\)的值,将\((x,pre(x))\)看作点对,能成为\(lm\)的点都在上凸包上,维护出上凸包后,在凸包上二分即可得到当前最值。 发现\(mx\)维护时需要合并\(rm_{ls}\)和\(lm_{rs}\),这里的合并即为闵可夫斯基和。 若在凸包上二分,复杂度就为\(O(m\log^2n)\)。将询问离线,按全局加的值排序,即为询问的斜率单调增,直接在凸包上记录一个指针,就能做到\(O(m\logn)\)了。 #include<bits/stdc++.h> #definemaxn1200010 #defineinf100000000000000 #definels(cur<<1) #definers(cur<<1|1) #defi
2018ACM-ICPCWorldFinalsProblemD.GemIsland 题目大意 有 n n n个人,初始每个人手上有一颗宝石,每天等概率有一颗宝石变为两颗,求 d d d天后宝石数最多的 r r r个人的期望宝石总数。 1 ≤ n , d ≤ 500 1\len,d\le500 1≤n,d≤500, 1 ≤ r ≤ n 1\ler\len 1≤r≤n 题解 首先通过手玩样例可以发现,最终的每种状态出现的次数都是相等的,均为 d ! d! d!次,不同的操作方案有 n ∗ ( n + 1 ) ∗ . . . ∗ ( n + d − 1 ) n*(n+1)*...*(n+d-1) n∗(n+1)∗...∗(n+d−1)即 ( n + d − 1 ) ! ( n − 1
最近在做第三方支付功能,其中支付宝用了条码支付这种高大上的新支付方式,话说还有比较常见的是支付宝扫码支付,这两种有什么区别呢,很简单,就是扫码支付是消费者用手机主动扫码再支付,条码支付是商家用扫码枪主动扫码再支付。那么为何选择条码支付呢,因为这个速度快,从扫消费者手机上的条码或二维码,到支付完成,那是瞬间的事,不过要是触发了需要密码的时候,还是需要消费者在手机上输入支付密码后才能完成消费的。 介绍完了条码支付后,给个文档接口吧:支付宝条码支付。条码支付整个流程主要需要的API包含:支付接口alipay.trade.pay,查询订单接口alipay.trade.query,撤销订单接口alipay.trade.cancel,申请退款接口alipay.trade.refund。这些东西都在支付宝提供的SDK里面包含了,我们就不用重新造轮子了,支付宝已经提供了很好很强大的SDK了,只是这个生成的dll有点大。 那么要想使用这个功能,首先是需要一个支付宝商家账号的,这个是前置条件。然后需要设置好APPID,这个可以到这个网址获取支付宝APPID,获取好之后,还需要用OPENSSL软
在我的日常运维当中还没有dg库,趁着最近不是很忙,自己搭建个DG库测试下,我的环境是centos6.5磁盘目录一致,数据库版本是11gR2-11.0.0.4 首先安装两个虚拟机,设置好网络,也可以安装好一个再克隆过去,然后安装数据库软件不安装实例,下面是我做实验时的笔记,欢迎大家评论交流。 1.配置主库静态监听及tnsSID_LIST_LISTENER1=(SID_LIST=(SID_DESC=(GLOBAL_DBNAME=ortest)(ORACLE_HOME=/oracle/app/product/11.2.0/dbhome_1)(SID_NAME=ortest)))LISTENER1=(DESCRIPTION_LIST=(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=dg1)(PORT=1522)))) 创建静态监听我试了好久才成功。大家可以直接拷贝这块的,根据自己的主机名修改,注意下缩进。tnsPUBLIC=(DESCRIPTION= (ADDRESS=(PROTOCOL=TCP)(HOST=dg1)(PORT=1521))(A
SUIDLINUX 1.从passwd说起 普通用户可以使用passwd命令来修改自己的密码,但大家都知道修改密码需要保存到/etc/shadow文件中,但从shadow文件中可以看到只有root用户可写,那么普通用户是如何修改这个文件的呢? ls-l/etc/shadow -rw-r-----1rootshadow1404Nov72019/etc/shadow复制 我们先看passwd命令的权限,可以看到该文件属于root:root,对于用户、组、其它的可执行权限分别为s,x,x,x可以理解,这个s的用处是什么呢? ls-l`whichpasswd` -rwsr-xr-x1rootroot54256May172017/usr/bin/passwd复制 实际上s是SUID权限,这个文件表示非所有者在执行这个文件时,会临时以所有者的权限执行,也就是passwd在普通用户执行时,可以获取root权限,从而将修改的密码保存到了/etc/passwd权限。当然如果不想普通用户修改自己的密码,可以把passwd的SUID权限拿掉。 同理,也存在SGID权限。 2.应用 如果平时遇到一个