Skip to content

Latest commit

 

History

History
110 lines (78 loc) · 6.1 KB

初衷.md

File metadata and controls

110 lines (78 loc) · 6.1 KB

关于搭建个人视频web服务

家里有一台PC Windows 10系统,一直被当家庭数据服务器用。几年前,为了方便在电视盒或手机上远程观看视频,我在上面搭了一个FTP服务。

但最近一段时间,不知什么原因,用小米播放器观看时老是掉线,ES自带的播放器倒是没掉线问题,但偶尔会卡顿,用户体验不好,有点不爽。 于是乎,就有了在PC上搭建一个视频web站点服务的念头。

第一次尝试

现在的视频大多支持视频流的,只要搭建一个web资源共享站点就ok了。搭建资源共享的web服务也很简单,第一时间,我想到了用Python的SimpleHTTPServer来实现。SimpleHTTPServer可将当前目录下的所有文件发布到web server上,从而实现文件共享的目的。在以前的工作中,也曾经常用它来同步文件。

在Python3里,SimpleHTTPServer被整合到http.server中,但用起来也还是很方便。安装Python3后,直接在Windows的cmd命令行输入:

python http.server 8080

然后在浏览器输入:

http://127.0.0.1:8080

即可在浏览器看到目标目录下的所有文件。

整个安装部署过程不到5分钟就完成了,通过手机的浏览器测试,可以显示所有的视频,但在打开视频时,却出错了,视频无法播放。

起初,我以为是MP4格式的视频不支持视频流的缘故,用qtfaststart做了一次视频流格式化,结果还是播放失败。

查看了SimpleHTTPServer的源码,找到了原因。原来,它里面的文件链接请求都是直接通过copyfile来实现的,一个视频1个多G呢,难怪失败了。

   def copyfile(self, source, outputfile):
	# 直接拷贝文件,一个视频1个多GB呢,
        shutil.copyfileobj(source, outputfile)

第二次尝试

看来想当然的方案往往是不够成熟的。接受了前面的教训,进下心来用Google大法看了些人民群众的实现方案。群众们纷纷表示用nginx来做视频流服务器最简单方便了。

刚好,PC也有现成的nginx。只要在nginx.conf里开启autoindex,功能和SimpleHTTPServer类似,也是将当前目录下的所有文件发布到web server上,但它支持视频播放。配置如下:

        location /{
            root D:/Temp;
            index  index.html index.htm;
            autoindex on;
            autoindex_exact_size on;
            autoindex_localtime on;
        }

配置好后,启动nginx服务后,浏览器上打开http://127.0.0.1:8080, 点开一个视频,瞬间播放成功!

整个部署过程不都三分钟,方案非常完美。

但,但在播放第二个视频的时候,它又出错了,又无法完成视频播放了。反复重试了几次后,最后验证了,这个方案是不能播放有中文名称的视频的!。 WK,nginx还不支持中文路径?查看error.log,确实在转码的时候出错了。

failed (1113: No mapping for the Unicode character exists in the target multi-byte code page)

在网上搜索解决方案,也有很多人在Windows平台上遇到了类似的问题,解决问题方案也有,那就是将中文改为英文。 显然,这个解决方案对我不受用,90%以上的视频都是中文名不说,英文对我也不利于浏览和查找了。

还好nginx是开源的,可以翻翻源码,看能不能找出其他的解决方案。之前没看过nginx源码,我也不可能在短时间内看明白,只好直蹦主题,首先从文件打开的地方找。果不其然,在win32下的ngx_open_file函数中找到一点线索,发现文件名参数都是通过utf-8字符串传递的,最后转换为unicode再传给CreateFileW。

	len = NGX_UTF16_BUFLEN;
    	u = ngx_utf8_to_utf16(utf16, name, &len);
    	...
    	fd = CreateFileW(u, mode,
                     FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
                     NULL, create, FILE_FLAG_BACKUP_SEMANTICS, NULL);

显然,在Windows平台下,nginx也是支持有中文名路径的,可能是我的用法不对。

为了验证这个想法,我直接在浏览器中的地址栏中输入视频的全路径,果然,视频就成功播放起来了。但,通过点击web的超链接,播放还是失败的。查看web源码,终于发现了“罪魁祸首”,原来超链接的字符编码是gbk,而不是utf-8。

重新配置nginx.conf,加了句charset utf-8,重启nginx,打开浏览器发现显示全是乱码了,而超链接编码也还是不对,还是无法通过点击超链接来播放视频。看来这是autoindex的一个bug。

于是,又在网上找了下这个bug的资源,查到早有人发现了这个bug,并用Django+nginx成功规避掉了中文名称的bug。即,用Django来做视频索引web页面,然后播放超链接又指回向nginx。

第三次尝试

顺着别人的Django+nginx思路,我在SimpleHTTPServer.py基础上改了个VideoHTTPServer.py。同时启动VideoHTTPServer.py和nginx,然后通过nginx的反向代理来统一入口。终于,完成一个基本能用的web视频服务站点。

nginx配置如下:

        location /{
            root D:/Temp;
            index  index.html index.htm;
            charset utf-8;
            autoindex on;
            autoindex_exact_size on;
            autoindex_localtime on;
        }

  
 	 # 反向代理到python http server
  	location /home {
      		proxy_pass   http://127.0.0.1:8089;
  	}	

最后,如果root路径是中文名,仍然还是有问题的。这个等后续继续解决了……

继续聊nginx中文路径bug

原因是:在ngx_open_dir和ngx_read_dir函数的Windows下的实现,调用的是FindFirstFile和FindNextFile,而传递的参数name在我的环境下是utf-8编码的(nginx.conf是utf-8编码,url也是utf-8),所以这两个函数都不能正常返回路径。此处,正确的做法也是要先调用ngx_utf8_to_utf16转码,再分别调用FindFirstFileW和FindNextFileW。

不过,即使root路径是中文名影响路径的访问,但不影响文件的访问。反过来说,这个bug刚好能帮我屏蔽首页的访问。