How to transcode audio/video content with net/http and ffmpeg

blov · · 1099 次点击    
这是一个分享于 的资源,其中的信息可能已经有所发展或是发生改变。
<p>I&#39;m building a desktop application(golang + html5) and part of this I need to serve various audio/video files stored on the local disk. Think of a something like VLC or Kodi(<a href="https://kodi.tv/about/software">https://kodi.tv/about/software</a>). The issue is that some video formats(i.e. .avi) are not supported by the browser so I need to transcode and serve them on the fly. Does anyone know how could I do that? </p> <p>Basically I need to get an io.ReadSheeker[1] so that I can pass it to http.ServeContent[2]. The main issue seems to be how to get an io.ReadSheeker out of os.Exec[3] as this is the only way (AFAIK) to execute ffmpeg commands. </p> <p>[1] <a href="https://golang.org/pkg/io/#ReadSeeker">https://golang.org/pkg/io/#ReadSeeker</a></p> <p>[2] <a href="https://golang.org/pkg/net/http/#ServeContent">https://golang.org/pkg/net/http/#ServeContent</a></p> <p>[3] <a href="https://golang.org/pkg/os/exec/">https://golang.org/pkg/os/exec/</a></p> <hr/>**评论:**<br/><br/>jerf: <pre><p>You can not get a ReadSeeker out of an OS command execution, because that stream is fundamentally unseekable. The only thing you could do is store the entire result of the stream somewhere and seek on that... which is basically &#34;do a batch transcode and then serve that&#34;, and you still would not be able to seek forward into the stream.</p> <p>To be able to seek into a transcoded stream would basically require a lot of guessing about how far forward the user tried to seek, then pass a command to ffmpeg asking it to start transcoding the source video at that time offset, all complicated by the fact the browser tends to want to communicate in terms of byte offsets rather than time offsets. It&#39;s possible, I think, since some projects seem to do it, but it&#39;s a lot of tricky work.</p> <p>You say you&#39;ve looked into other media servers and they don&#39;t have all the features you want. At least in some cases, this may be because the features you want are not possible (you&#39;d be surprised what certain containers or formats simply can&#39;t do), or they may be so challenging that nobody has even tried to get them correct. You&#39;d really want to look at how they work to see exactly how to do it.</p> <p>And I should warn you that this is very <em>very</em> fiddly code prone to breaking every time ffmpeg upgrades and even the major projects dedicated to these things tend to break distressingly often. I&#39;d suggest making double-sure you&#39;ve got good reason to be wading into this swamp. It&#39;s really rather frustrating stuff to work with for hobby reasons. I find it rather frustrating just trying to get consistent DVD transcoding out ffmpeg, and even with that rather tightly constraining the incoming data I still have more trouble than I ought to with this stuff.</p></pre>WarMovieStenographer: <pre><p>Any recommendations on golang specific transcoders? It&#39;s not necessary to be capable of streaming.</p></pre>brokenprogram: <pre><p>Go is not very suitable for transcoding thus the reason why we have no pure Go transcoder. Furthermore ffmpeg is quite hard to match regardless the programming language. Shortly said Go was not designed for this kind of tasks.</p></pre>SilentWeaponQuietWar: <pre><p>Maybe you are trying to do this from scratch for learning purposes. Otherwise, check out this package:</p> <p><a href="https://github.com/nareix/joy4" rel="nofollow">https://github.com/nareix/joy4</a></p></pre>brokenprogram: <pre><p>It&#39;s actually for a real project not only for learning purpose. joy4 seems to lack various features (e.g. mkv container, flac audio etc ). I also had a hard time to find out how it actually works (e.g. equivalent of <code>ffmpeg -i $inpath -c:a $outaudio -c:v $outVideo, -lossless 1 -f $outContainer $outPath</code>)</p></pre>ZetaHunter: <pre><p>What about <a href="https://github.com/shimberger/gohls" rel="nofollow">gohls</a>? I&#39;ve been using it locally for a while.</p></pre>jiimji: <pre><p>It&#39;s not clear what is going on here.</p> <p>are you serving real time video streams ? then you need a video streaming server, not go.</p> <p>If it&#39;s just static video files you need to convert and serve then just use ffmpeg, and serve them with a CDN that accepts ranged requests.</p></pre>brokenprogram: <pre><p>I&#39;ve edited the question. Hopefully now is more clear. I need to transcode video streams on the fly. Basically the client browses through its own media library using a html5 application downloaded on its computer (part of this application is also a Go http server which runs background to serve the html, index the media files etc) so everything is local(i.e. no CDN or external network requests).</p> <p>I don&#39;t need a &#34;video streaming server&#34;. HTML5 video tag[0] works using the html protocol. That means plain GET requests using the Range header to seek through the video content. </p> <p>The only issue is that html5/browsers support only various codecs and containers(e.g. webm/vp9). So I need to convert the unsupported video files before to serve them (using http.ServeFile[1]). </p> <p>However simply converting the file and storing it requires additional space on disk and provides a poor user experience(the user has to wait until the whole file is converted which usually takes a long time). So I would like to convert the file on the fly/while it&#39;s being served/played. To do that I think I need to implement http.ServeContent[2]. If ffmpeg would be a pure Go library it would be quite straightforward but as it&#39;s not I&#39;m seeking advice here from people familiar with both Go and ffmpeg.</p> <p>[0] <code>&lt;video controls&gt; &lt;source src=&#34;http://localhost:8080/file?q=/volumes/users/brokenuser/movies/movie.mp4&#34;&gt; &lt;/video</code></p> <p>[1] <a href="https://golang.org/pkg/net/http/#ServeFile" rel="nofollow">https://golang.org/pkg/net/http/#ServeFile</a></p> <p>[2] <a href="https://golang.org/pkg/net/http/#ServeContent" rel="nofollow">https://golang.org/pkg/net/http/#ServeContent</a></p></pre>theGeekPirate: <pre><p>I believe what you&#39;re looking for is a video decoder in JS. On mobile, but I&#39;m almost certain there&#39;s a few out there already.</p> <p>That way, there&#39;s no transcoding mess to deal with.</p> <p>JS video players would work as well.</p></pre>brokenprogram: <pre><p>I&#39;m not aware of many/any such decoder and I doubt there will be any given JS&#39;s performance issues. ffmpeg seems to be the gold standard for decoding in terms of both performance and versatility . </p></pre>theGeekPirate: <pre><p>You could always use cgo and hook into an existing C/C++ library as well.</p> <p>In fact, this would be a nice library to have in the ecosystem!</p></pre>Growlizing: <pre><p>I looked into this a few months ago and decided it was too much work to even attempt as a hobby project. The most promising approach would probably be to get some good bindings to ffmpeg, but that is also a great task.</p></pre>jfgeiger: <pre><p>Live transcoding isn&#39;t going to work well no matter how you do it.</p> <p>If you&#39;re calling out to ffmpeg, you could try to give ffmpeg a port you&#39;re listening on and use the Go app as a proxy for the stream that is produced.</p></pre>

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

1099 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传