在使用FFmpeg进行hls推流输出时,发现配合新版Nginx (1.21) + WebDav组件的http服务器时,即使指定了m3u8切片数量以及删除无用切片的参数:
hls_list_size 5 -hls_flags delete_segments -hls
也没有在服务端正确删除无用切片,查看Nginx日志,发现每次FFmpeg发起的DELETE文件请求,都会跟随一个这样的报错:
DELETE with body is unsupported!
导致虽然FFmpeg删除文件的http请求到了Nginx,但实际并没有删除掉磁盘上的ts切片文件,时间一长,磁盘空间耗尽,然后就尴尬了…
追踪日志中的错误信息检查了下WebDAV模块的源码,发现在这次提交:http://hg.nginx.org/nginx/rev/f609c0ac2972 时,加入了这样的代码:
--- a/src/http/modules/ngx_http_dav_module.c Mon Dec 23 18:56:21 2019 +0300 +++ b/src/http/modules/ngx_http_dav_module.c Mon Dec 23 20:39:27 2019 +0300 @@ -312,7 +312,7 @@ ngx_file_info_t fi; ngx_http_dav_loc_conf_t *dlcf; - if (r->headers_in.content_length_n > 0) { + if (r->headers_in.content_length_n > 0 || r->headers_in.chunked) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "DELETE with body is unsupported"); return NGX_HTTP_UNSUPPORTED_MEDIA_TYPE; @@ -495,7 +495,7 @@ size_t root; ngx_str_t path; - if (r->headers_in.content_length_n > 0) { + if (r->headers_in.content_length_n > 0 || r->headers_in.chunked) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "MKCOL with body is unsupported"); return NGX_HTTP_UNSUPPORTED_MEDIA_TYPE; @@ -549,7 +549,9 @@ ngx_http_dav_copy_ctx_t copy; ngx_http_dav_loc_conf_t *dlcf; - if (r->headers_in.content_length_n > 0) { + if (r->headers_in.content_length_n > 0 || r->headers_in.chunked) { + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, + "COPY and MOVE with body are unsupported"); return NGX_HTTP_UNSUPPORTED_MEDIA_TYPE; }
除了检测请求header中的content_length之外,还额外检查了是否为chunked请求,问题就出在这里!content length肯定没问题,FFmpeg在DELETE时没有发送任何请求body,但是这个chunked嘛…看了下FFmpeg的源码,ffmpeg-4.3.1/libavformat/http.c中的http_connect函数里:
if (post && s->chunked_post)
av_bprintf(&request, "Transfer-Encoding: chunked\r\n");
所以,FFmpeg的处理逻辑是无论什么请求,只要标记了chunked,就都会加上“Transfer-Encoding: chunked”这个header,很显然这个逻辑就和新版WebDAV的逻辑不对付了,同时查了下FFmpeg此时最新代码,发现http.c中依然是这么处理的,虽然貌似可以通过chunked_post这个参数回避这个逻辑,但如果不区分请求类型无脑关闭chunked话,那真正上传切片文件的请求估计又会受到影响,于是做出如下修改:
if (post && s->chunked_post && 0 != strcmp(method, "DELETE"))
av_bprintf(&request, "Transfer-Encoding: chunked\r\n");
对DELETE请求特殊处理,不增加chunked header,重新编译出ffmpeg测试,问题解决。
博主友情提示:
如您在评论中需要提及如QQ号、电子邮件地址或其他隐私敏感信息,欢迎使用>>博主专用加密工具v3<<处理后发布,原文只有博主可以看到。