(在答案底部更新了特定问题的最终解决方案。)
你不能
在这种情况下(以及大多数其他情况),音频和视频编码在涉及到确切生成的文件大小时是不可预测的。请记住,在编码时也无法预测源材料的特征和对最终文件大小的影响。如果您正在“即时”转码,您正在做两件事 1) 压缩,2) 丢失数据。 mp3 输出格式无法做到这一点。
您可能...如果:编码是无损的,并且您的算法已针对非常具体的源材料特征(采样率、样本大小等)进行了调整以及未压缩的源格式和目标格式。但这不是你的情况。
至于标题:不要发送! Content-Length 标头不是 HTTP 1.1 要求。这样做有缺点(进度条在文件结束之前永远无法知道 100% 完成了什么;也不可能存在“剩余时间”),但我猜你可以没有它。
基于 cmets 的最终讨论:
使用浏览器,我得到了您所描述的行为。使用这个 curl 命令(有助于调试像这样的低级疼痛),它也不起作用:
curl --trace-ascii trace0.txt "http://dmpwap.net/playmp3.php?b=128&file=Red_Hot_Chili_Peppers_-_15_-_Fortune_Faded.mp3" > test0.mp3
我得到 0 个字节,并在我的跟踪中看到这个:
manoa:~ stu$ cat trace0.txt == Info: About to connect() to dmpwap.net port 80 (#0)
== Info: Trying 64.191.50.69... == Info: connected
== Info: Connected to dmpwap.net (64.191.50.69) port 80 (#0)
=> Send header, 213 bytes (0xd5)
0000: GET /playmp3.php?b=128&file=Red_Hot_Chili_Peppers_-_15_-_Fortune
0040: _Faded.mp2 HTTP/1.1
0055: User-Agent: curl/7.19.4 (universal-apple-darwin10.0) libcurl/7.1
0095: 9.4 OpenSSL/0.9.8k zlib/1.2.3
00b4: Host: dmpwap.net
00c6: Accept: */*
00d3:
<= Recv header, 17 bytes (0x11)
0000: HTTP/1.1 200 OK
<= Recv header, 19 bytes (0x13)
0000: Connection: close
<= Recv header, 37 bytes (0x25)
0000: Date: Fri, 11 Dec 2009 14:04:58 GMT
<= Recv header, 27 bytes (0x1b)
0000: Server: Microsoft-IIS/6.0
<= Recv header, 27 bytes (0x1b)
0000: X-Powered-By: PHP/5.2.9-2
<= Recv header, 35 bytes (0x23)
0000: Content-Transfer-Encoding: binary
<= Recv header, 26 bytes (0x1a)
0000: Content-Type: audio/mpeg
<= Recv header, 2 bytes (0x2)
0000:
<= Recv data, 0 bytes (0x0)
== Info: Closing connection #0
但是....
如果我添加一个--tcp-nodelay 选项,效果很好!例如:
curl --tcp-nodelay --trace-ascii trace1.txt "http://dmpwap.net/playmp3.php?b=128&file=Red_Hot_Chili_Peppers_-_15_-_Fortune_Faded.mp3" > test1.mp3
它返回了 3219104 个字节。 trace.txt 如下所示:
== Info: About to connect() to dmpwap.net port 80 (#0)
== Info: Trying 64.191.50.69... == Info: TCP_NODELAY set
== Info: connected
== Info: Connected to dmpwap.net (64.191.50.69) port 80 (#0)
=> Send header, 213 bytes (0xd5)
0000: GET /playmp3.php?b=128&file=Red_Hot_Chili_Peppers_-_15_-_Fortune
0040: _Faded.mp3 HTTP/1.1
0055: User-Agent: curl/7.19.4 (universal-apple-darwin10.0) libcurl/7.1
0095: 9.4 OpenSSL/0.9.8k zlib/1.2.3
00b4: Host: dmpwap.net
00c6: Accept: */*
00d3:
<= Recv header, 17 bytes (0x11)
0000: HTTP/1.1 200 OK
<= Recv header, 19 bytes (0x13)
0000: Connection: close
<= Recv header, 37 bytes (0x25)
0000: Date: Fri, 11 Dec 2009 13:56:47 GMT
<= Recv header, 27 bytes (0x1b)
0000: Server: Microsoft-IIS/6.0
<= Recv header, 27 bytes (0x1b)
0000: X-Powered-By: PHP/5.2.9-2
<= Recv header, 35 bytes (0x23)
0000: Content-Transfer-Encoding: binary
<= Recv header, 26 bytes (0x1a)
0000: Content-Type: audio/mpeg
<= Recv header, 2 bytes (0x2)
0000:
<= Recv data, 1258 bytes (0x4ea)
0000: ID3.......TENC.......Lavf52.23.1...d.... ..=....w......oq......0
... {many lines}
0180: UUUUUU
== Info: Closing connection #0
我可以毫无问题地听这首歌(3m21s、立体声、mpga、48kHz、128kbps)。
所以,我的理论是,因为流中有连续的 0x00 字节,客户端在想 “好的,我得到了 0x00, 0x00...并且没有发送任何其他内容,连接必须结束." 但是在 curl 客户端上设置了 --tcp-nodelay 选项,它不会发生。
我的候选解决方案:禁用Nagel's algorithm(在套接字选项上设置 TCP 无延迟)服务器端,至少对于这些转码请求连接。这将防止缓冲,我怀疑这会导致连接被丢弃。