0%

好困~好困~好困
现在是打完疫苗的2小时三十分,我真的好困啊

webRTC

运行srs,http-flv拉流,并进行webRTC的流输出。
开发机运行srs,本地推rtmp到开发机,同时本地通过webRTC拉流,可以实现。但是webRTC不支持组播,此方案不可行。

WebRTC目前不能对组播提供支持

RTSP

服务端支持RTSP推流有解决方案,客户端是web浏览器

  1. 不支持UDP,进而不支持基于UDP的RTP和RTSP
  2. 不支持插件,插件能接收RTSP流但是主流浏览器已逐渐不再支持插件
  3. FLASH已不再支持,因此不能采用RTSP转RTMP方案

候选方案如下

  1. H5Stream(收费) https://www.cnblogs.com/Vince-blogs/p/8608076.html
  2. html5_rtsp_player + streamedian(收费) https://github.com/Streamedian/html5_rtsp_player
  3. jsmpeg https://github.com/phoboslab/jsmpeg
  4. WebAssembly+ffmpeg demo:https://github.com/ringcrl/FFmpeg

EasyDarwin https://github.com/EasyDarwin/EasyDarwin is awesome!

RTSP单播验证

RTSP单播推EasyDarwin,本机ffmpeg配合浏览器拉流

实验目的:

  1. 验证RTSP推流可实现
  2. 验证RTSP拉流可实现
  3. 验证浏览器的RTSP拉流可实现

实验过程:

  1. 本地ffmpeg推流到服务端EasyDarwin

    ffmpeg -f avfoundation -framerate 30 -video_size 1280x720 -i “0” -rtsp_transport udp -vcodec h264 -f rtsp “rtsp://10.227.22.22/allhands/stream_yuyao”

  2. 本地运行打开webSocket模块 websocket-relay.js

    node websocket-relay.js supersecret 8081 8082

  3. 本地运行ffmpeg转码,将rtsp转为websocket

    ffmpeg -i “rtsp://10.227.22.22/allhands/stream_yuyao” -q 0 -f mpegts -codec:v mpeg1video http://127.0.0.1:8081/supersecret

  4. 本地打开view-stream.html页面(可以用任意http-server),观察输出

实验结论:

  1. RTSP单播推流可行
  2. 浏览器配合ffmpeg拉RTSP可行

当前风险点

  1. 浏览器不支持UDP拉流,据大佬将即使用webassembly预编译FFMPEG也不行
  2. 浏览器不支持IGMP协议
  3. CPU占用、延迟、并发、画面可靠性还未知

新年快到来了,祝愿一切安好。

我决定在30岁之前不再打游戏了

三十歳前にゲームをやるなのことが決めた

软链接

创建命令: ln -s 原文件 软连接
更新命令: ln -snf 原文件 软连接

  1. 原文件可以是d(文件夹)
  2. 软连接相当于一个文件,就是数据块(block)比较特殊,存放着原文件的路径。
  3. 软连接有着新的inode号以及用户数据块
  4. 原文件删除则软链接的文件内容也被清除

ps: 在一个文件系统中,inode是文件索引的唯一标识

硬链接

创建命令: ln 原文件 硬链接

  1. 原文件不可以是d,因为. 和 ..也是硬链接,创建文件硬链接会造成循环嵌套
  2. 硬链接与原文件具有相同的inode号
  3. 源文件删除不会影响硬链接内容

find查询

1
2
3
4
5
6
7
8
在/home下查询data.txt的软链接
find /home -lname data.txt

在/home下查询data.txt的所有硬链接
find /home -samefile data.txt

在/home下查询data.txt的所有硬链接
find /home -inum <inode号>

工作空(hua)闲(shui)时间搞出了一个非常简单的流媒体直播网站,一起来瞧瞧~
快乐点播:请戳这里
(只支持PC端上几个主流的浏览器,而且记得允许flash)

使用说明

映入眼帘的是清新爽朗的用户界面(滑稽)

随意点进去,就可以观看直播啦

实现原理

代码实际上非常简单,使用js拉取公共直播流,不需要自己推流,js中的核心代码长这样

1
2
3
4
5
6
<video id="my-player" class="video-js vjs-default-skin vjs-big-play-centered" controls preload="auto"
autoplay="autoplay" poster="//vjs.zencdn.net/v/oceans.png" width="960" height="540" data-setup='{}'>

<source src="http://ivi.bupt.edu.cn/hls/cctv1hd.m3u8" type="application/x-mpegURL" />

</video>

通过给src一个url来拉流,目前测试了hlv格式和rmtp格式,有一个问题是其中一个封装格式在使用go模板类替换src时会出现视频黑屏的情况,这个后续再考虑一下解决办法

后面两个链接是视频点播,原理也是差不多的,只不过通过一个server把本地文件地址转成url再传给src即可,当然线上环境需要使用对象存储。

代码已开源,戳我看看

北京站的中央广场
商旅游人 熙熙攘攘
街灯耸立 万人来朝
街边的少年 你嘴角上扬
心仪的姑娘 就快要出场
绰约背影 她立在中央
风儿轻吻 撒一地金黄
美人呵
他在这儿

context.Background() 返回一个空的Context,这个空的Context一般用于整个Context树的根节点。然后我们使用context.WithCancel(parent)函数,创建一个可取消的子Context,然后当作参数传给goroutine使用,这样就可以使用这个子Context跟踪这个goroutine。

在goroutine中,使用select调用<-ctx.Done()判断是否要结束,如果接受到值的话,就可以返回结束goroutine了;如果接收不到,就会继续进行监控。

那么是如何发送结束指令的呢?这就是示例中的cancel函数啦,它是我们调用context.WithCancel(parent)函数生成子Context的时候返回的,第二个返回值就是这个取消函数,它是CancelFunc类型的。我们调用它就可以发出取消指令,然后我们的监控goroutine就会收到信号,就会返回结束。

context监控多个goroutine的实例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
func main() {
ctx, cancel := context.WithCancel(context.Background())
go watch(ctx,"【监控1】")
go watch(ctx,"【监控2】")
go watch(ctx,"【监控3】")

time.Sleep(10 * time.Second)
fmt.Println("可以了,通知监控停止")
cancel()
//为了检测监控过是否停止,如果没有监控输出,就表示停止了
time.Sleep(5 * time.Second)
}

func watch(ctx context.Context, name string) {
for {
select {
case <-ctx.Done():
fmt.Println(name,"监控退出,停止了...")
return
default:
fmt.Println(name,"goroutine监控中...")
time.Sleep(2 * time.Second)
}
}
}

示例中启动了3个监控goroutine进行不断的监控,每一个都使用了Context进行跟踪,当我们使用cancel函数通知取消时,这3个goroutine都会被结束。这就是Context的控制能力,它就像一个控制器一样,按下开关后,所有基于这个Context或者衍生的子Context都会收到通知,这时就可以进行清理操作了,最终释放goroutine,这就优雅的解决了goroutine启动后不可控的问题。

节选自大佬:https://www.flysnow.org/2017/05/12/go-in-action-go-context.html 戳链接获取更多

切片比数组的方便之处在于其长度可变,在append超出cap时可自动扩容,一次性扩充大小和具体情况有关,我测试的结果是每次扩容先×2,还不够则再线性增长

关于slice有两个注意点

slice的初始化问题
1
2
var arr = []int {0, 1, 2, 3, 4, 5, 6}
s1 := arr[0, 4]

注意这里s1初始化后为0, 1, 2, 3
slice这种方式初始化是左闭右开区间

slice的拷贝问题
1
2
3
var arr = []int {0, 1, 2, 3, 4, 5, 6}
s1 := arr[0, 4]
s2 := arr[1, 3]

如此初始化相当于一个引用,因此s1, s2存在内存重叠,改动s2会使s1发生改变

1
2
3
4
5
var arr = []int {0, 1, 2, 3, 4, 5, 6}
s1 := make([]int, 4)
copy(s1, arr[0:4])
s2 := make([]int, 2)
copy(s2, arr[1:3])

若如此,则为内容拷贝,不会发生改一变二的情况

刚拿到一台mac十分激动,办了一件蠢事。。。

文件结构是这样的,templates是空文件夹

当我执行如下命令
cp * ./templates
出现了templates的无限嵌套,移到回收站以后如下图

尝试清空回收站却提示templates被占用,官网给出的解决方案均无法解决。。.

后来参考网上一位大佬的方法解决了问题

1
2
cd ~/.Trash
rm -rf *

其中

-f:强制删除文件或目录
-r或-R:递归处理,将指定目录下的所有文件与子目录一并处理

终于还是用到了这句rm -rf * 看来危险的文件嵌套要用危险的方法来解决。。微盟删库跑路的哥们也是这么干的?

PS:
最近发现了这个娱乐项目,可以愉快地添加表情包了~