java实现直播(推拉流)和保存直播视频

密码:2t88

点击这个链接下载需要的和nginx压缩包(我在网址中https:后面加了一个空格,复制粘贴的时候注意删除,不然链接格式发不出去)。

然后打开压缩包里面有两个小压缩包,一个视频视频是用来实验的,用不用没关系。

从网盘下载的

解压到d盘的demo文件夹下,同时将nginx和nginx都解压到当前文件夹下。

减压后

接下来按照步骤进行:

启动nginx:

cmd打开控制台,进入nginx-1.7.11.3-目录,启动。

比如我的放在d盘的demo下,然后命令是:

第一步,跳转到d盘:

d:

第二步,cd到nginx-1.7.11.3-目录:

cd demo/nginx-1.7.11.3-Gryphon

第三步启动nginx:

nginx.exe -c confnginx-win-rtmp.conf

那么正常启动时不会显示内容,而是一直运行。 不要关闭这个控制台页面,就这样吧。

我的控制台启动 nginx 页面

然后可以直接访问ip:80查看nginx是否正常启动

nginx正常启动页面

下载并设置环境变量

步骤一:设置环境变量(步骤不再赘述,这个比较初级)

我直接把截图贴出来:

图片.png

其实这个时候前台推送的流已经可以正常接收并被同一个局域网内的设备拉取了。 但是,如果你自己做,没有前端的配合,或者想确保你之前做的一切都正确,你可以自己模拟一下。 推流,然后自己模拟拉流。

因为我完全是按照教程做的,看来模拟推流只能用VLC播放器,反正我只用了这个测试。

vlc播放器,自行去百度下载即可

然后这里顺便下载了测试视频,当然你也可以用你电脑里的其他视频,打开一个新的控制台,然后输入下面一串命令:

ffmpeg -re -i d:/demo/orange.mp4 -vcodec libx264 -acodec aac -f flv rtmp://ip:1935/live/home

重点来了! ! 首先我之前看教程,人家直接-i.mp4,我复制粘贴运行一直报找不到文件,然后我改成绝对路径就ok了。 其次,这个ip+端口ip你可以写自己的ip。 端口1935设置在nginx配置文件中配置,可以更改。根据需要使用

那么上面的命令中,大概的意思就是将.mp4视频以流的形式用h264进行编码,将flv格式以rtmp的形式推送到ip指向的电脑的/live/home(自——理解,说错了请勿喷,欢迎指点)。

同理,你想要拉流量,就得来这个地方拉。 所以你可以直接复制这个路径,直接在vlc上ctrl+v粘贴网址,粘贴这个网址就可以看到你之前推送的视频了。

输入您之前推送的 URL

如果你能看到你上传的视频,那就说明你成功了! 直播平台搭建完成!视频传输与直播的区别

说到这里可能有人不理解,这不就是视频传输吗? 为什么叫直播呢? 这不是忽悠人吗? 其实不是,这个从细节就能看出来。 如果是视频传输的话,接收者只能从视频的开头开始观看,但和直播不同的是,应该从传输的地方开始观看(不要跟我争论延迟)抖音直播推流地址怎么获取,并且直播应该立即观看,直播结束后也会结束。

因为我们在上面的演示中使用的视频,这可能会让很多人感到困惑,但更好的是,这个视频持续一分钟多,并且流媒体过程不是每秒推送,因此速度相对较快。 推流需要几秒钟,但是我们可以在几秒钟后拉流,很明显一开始每次显示的视频内容都不一样。

同样,如果你还是无法理解或者有疑问,我建议你不要用视频来证明平台的成功。 可以直接调用本地的视频和音频,然后推流到本地,然后用vlc拉流,这样明显直播开始的时候就可以拉下来,而直播的时候就不能立即拉流了直播已关闭。

我觉得做起来比较麻烦,但是也不难。 我在最后列出的技术帖子会有教程。 你可以去看看。

保存实时视频

正如我一开始所说,直播视频保存15天是常态。 那么15天其实可以通过很多方式实现,重点是保存

因为我没有详细了解推流和拉流的代码,所以我认为保存会很复杂,但它比我想象的要简单得多。 我就不讲我的心路历程了,直接汇报一下结果(我想再说一遍,可能有多种实现方式,我只是选择了一种实现方式,并不代表性能是最好的或者是最新的技术):


    org.bytedeco
    javacv
    1.4.3

package io.renren.modules.other.tool;
import java.io.File;
import java.io.IOException;
import org.bytedeco.javacpp.avcodec;
import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.FFmpegFrameRecorder;
import org.bytedeco.javacv.Frame;
import org.bytedeco.javacv.FrameGrabber;
import org.bytedeco.javacv.FrameRecorder;
public class RecordVideoThread extends Thread {
    public String streamURL;// 流地址 网上有自行百度
    public String filePath;// 文件路径
    public Integer id;// 案件id
    
    public void setStreamURL(String streamURL) {
        this.streamURL = streamURL;
    }
    public void setFilePath(String filePath) {
        this.filePath = filePath;
    }
    @Override
    public void run() {
        System.out.println(streamURL);
        // 获取视频源
        FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(streamURL);
        FFmpegFrameRecorder recorder = null;
        try {
            grabber.start();
            Frame frame = grabber.grabFrame();
            if (frame != null) {
                File outFile = new File(filePath);
                if (!outFile.isFile()) {
                    try {
                        outFile.createNewFile();
                    } catch (IOException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
                // 流媒体输出地址,分辨率(长,高),是否录制音频(0:不录制/1:录制)
                recorder = new FFmpegFrameRecorder(filePath, 1080, 1440, 1);
                recorder.setVideoCodec(avcodec.AV_CODEC_ID_H264);// 直播流格式
                recorder.setFormat("flv");// 录制的视频格式
                recorder.setFrameRate(25);// 帧数
                //百度翻译的比特率,默认400000,但是我400000贼模糊,调成800000比较合适
                recorder.setVideoBitrate(800000);
                recorder.start();
                while ((frame != null)) {
                    recorder.record(frame);// 录制
                    frame = grabber.grabFrame();// 获取下一帧
                }
                recorder.record(frame);
                // 停止录制
                recorder.stop();
                grabber.stop();
            }
        } catch (FrameGrabber.Exception e) {
            e.printStackTrace();
        } catch (FrameRecorder.Exception e) {
            e.printStackTrace();
        } finally {
            if (null != grabber) {
                try {
                    grabber.stop();
                } catch (FrameGrabber.Exception e) {
                    e.printStackTrace();
                }
            }
            if (recorder != null) {
                try {
                    recorder.stop();
                } catch (FrameRecorder.Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }
    public static void main(String[] args) {
        RecordVideoThread thread = new RecordVideoThread();
        thread.setFilePath("D:/testOne.flv");
        thread.setStreamURL("rtmp://ip:端口/live/home");
        thread.start();        
    }
}

下面的代码中我写了推流的地址和要保存的文件的文件名。 而且因为这个保存是一个长期执行的方式抖音直播推流地址怎么获取,所以我特地启动了线程来实现。

然后记下顺序:

! ! !必须按顺序进行:先启动方法,再启动直播,再先结束直播,再结束方法

否则将不会保存视频。 具体原因我还没有深究。 不管怎样,我是经过一次又一次的测试才得出这个结论的,这样也能让现场视频得到完整的保留。 这个逻辑也是一致的,按照流程走就可以了。

我的代码存储在D:/.flv中,让我向您展示:

保存的视频

播放保存的视频

其实我的画质就是这样,把代码放在

ecorder.setVideoBitrate(800000);

时间越长越清晰,但也消耗更多空间,我之前尝试过。 43s的视频小于5兆。 那么当小于20兆的时候,差别就来了,所以这个值最好选择一个平衡的值。

然后说说最大的坑:格式问题

现在不知道是我看的所有技术帖子都过时了还是推流的方式不一样了。 反正很多帖子都是mp4格式的,我就傻了。 。 为此,我还特意下载了暴风影音和迅雷来看看。 。 。

昨天调整了一下午,还是没调好。 今天早上在群友的建议下改成了avi,还是不行。 最后改成flv就可以正常播放了。

上面的代码中还有一行:

                // 流媒体输出地址,分辨率(长,高),是否录制音频(0:不录制/1:录制)
                recorder = new FFmpegFrameRecorder(filePath, 1080, 1440, 1);

这行代码的1080和1440也是我自己修改的。 长宽应该是可以自定义的(其实大部分属性都是可以自定义的,只是我没用过所以没仔细看)

其实我主要是卡在视频格式上,但是我在百度上看到我遇到的问题都是千奇百怪。 反正我大概只遇到这两种:一是推流顺序错误导致文件无法保存,二是格式问题打不开。

如果以后使用遇到问题,我们一起讨论。

那么这个直播的实现就差不多是这样了。

还有一些小知识点:

路径问题

只要你喜欢推拉即可,这个 /live/home 不是硬编码的。 比如我们的项目打算采用/live/的形式,因为每个用户都可以直播,这样可以保证每个用户的推拉流都是不同的。 顺便分享一下我们的前端实现页面:

图片.png

图片.png

直播页面,可以在这里写推流地址,也可以写推流地址,正常应该是硬编码的

观看直播页面

端口问题

刚才说了1935是nginx默认的rtmp端口。 这个可以改,但是默认配置是1935(不过我没改过,有兴趣的可以试试)如下图:

配置文件的位置

配置文件中的配置

细节

之前我们直播的时候,发现直播效果贼贼,各种马赛克,中间经过怀疑、调试等功能,发现应该是前端可以设置一些配置来推送溪流。 除特殊情况外,屏幕亮度和清晰度还是有很大影响的。 一切都是由前端来调整的。 反正上面的方法不具备调整后端的能力。 如果你要这么懒,就别浪费时间去找了,交给前端就好了。

扩展问题

刚才说了,这是最简单的方法,也是一种偷懒的方法。 即使是最初的过程也是最简单的过程。 事实上,还有很多事情可以做。

比如美感、微调、清晰度等等。我之前提到过,后端其实也可以做到,只不过相当于把流从前端推到后端,后端解析成一个图片,对其进行处理,然后将其编码成流。 等着别人来拉。

这个过程应该比较容易理解。 多了几步,性能肯定不如现在。 而且要求的难度也比较高。 虽然有现成的框架,但是现在写一行代码并不方便!

顺便推荐三个后端处理框架:

因为我没用过,所以只是给出一个建议,有兴趣的可以自己去看看。 最后列出这三个框架详细介绍的帖子地址。

网络问题

嗯,因为是要在项目中使用,所以一直测试局域网肯定是不合适的。 于是我采用了内网穿透的形式,将自己的工作电脑映射到我们的服务器上,从而实现了外网直播、外网观看。 反正目前为止,四五台电脑,四五部手机,4个推流,5个拉流,保证延迟在5s以内。 另外,因为我是通过内网穿透的方式实现的,这样可能还是会消耗一部分时间,但无论如何也在可以接受的范围之内。

没办法多做,至少说明小规模的推拉流是完全没问题的。

如图,手机推流到外网,电脑外网拉流

添加之前提到的许多技术帖子的链接:

使用以下命令将直播流保存到本地

rtmp和rtsp的区别及适用范围

打造本地直播平台的四种方式

通过+实现H5直播,以及直播相关问题

如何真正让小程序与APP通信并连接麦克风进行直播

HTML5实现视频直播功能详细

如何搭建自己的服务器

到目前为止,我只是调整了功能,实现了一些应该实现的东西,比如推多流、拉多流、保存直播视频等,几乎没有遇到什么问题(性能问题不算)。 感觉比我想象的简单,但也比我想象的复杂,因为我做得太简洁了。 这篇文章就算是这几天的记录了。 如果以后项目中实现了这个功能,有问题我会跟进。

我不得不承认编程的魅力就在于我从头开始做出了一些令人惊叹的功能。 我热爱我所做的事情,现在、仍然如此、永远如此。

本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 1744513473@qq.com 举报,一经查实,本站将立刻删除。
THE END
分享
二维码
< <上一篇
下一篇>>