打赏

自己搭建简单的直播平台 自己windows电脑(不推荐)android 推流 拉流

使用Nginx搭建RTMP/HLS服务器 

下载Nginx with RTMP模块 因为我是自己的windows电脑 下载地址

  • 下载地址: nginx-win.zip 

  • 解压到*****\nginx目录 (自己的按照路径)
  • 找到nginx.conf (在conf文件夹下)

     在conf/nginx.conf末尾添加RTMP配置:

    rtmp {
        server {
            listen 1935;
            chunk_size 4096;
            
            application live {
                live on;
                record off;
                # HLS配置
                hls on;
                hls_path temp/hls;
                hls_fragment 3s;
                hls_playlist_length 60s;
            }
        }
    }
    
    http {
        server {
            listen 8080;
            
            location /hls {
                types {
                    application/vnd.apple.mpegurl m3u8;
                    video/mp2t ts;
                }
                root temp/;
                add_header Cache-Control no-cache;
            }
        }
    }

     

  • 启动Nginx (你的nginx文件夹根目录下 双击nginx.exe)

然后就是你的推流和拉流,在这个之前你可以下载工具测试一下nginx是否成功 例如:

  • 使用OBS Studio: 下载地址

      • 设置→流:

        • 服务: 自定义

        • 服务器: rtmp://localhost/live

        • 流密钥: test123

    1. 播放测试工具:

      • VLC播放器: 下载地址

      • 打开→网络串流→输入rtmp://localhost/live/test123

        五、网络配置注意事项

        1. 防火墙设置:

          • 允许1935(RTMP)和8080(HLS)端口通过防火墙

          • 控制面板→Windows Defender防火墙→高级设置→入站规则→新建规则

        2. 局域网访问:

          • 确保Android设备和Windows在同一局域网

          • 使用ipconfig查看Windows本机IP,替换代码中的"localhost"

        3. 外网访问(可选):

          • 需要路由器端口映射(1935和8080)

          • 建议使用DDNS服务获取固定域名

        六、常见问题解决

        1. 推流连接失败:

          • 检查Nginx/SRS是否正常运行

          • 检查防火墙设置

          • 使用telnet测试端口连通性: telnet 192.168.x.x 1935

        2. 播放卡顿:

          • 降低推流分辨率(如720p)

          • 调整码率(如1500kbps)

          • 在ExoPlayer中启用缓冲优化:

            java
            DefaultLoadControl loadControl = new DefaultLoadControl.Builder()
                .setBufferDurationsMs(30000, 60000, 1500, 2000)
                .build();

             

        3. 延迟过高:

          • 使用低延迟配置:

            nginx
            rtmp {
                server {
                    listen 1935;
                    interleave on;
                    wait_key on;
                    wait_video on;
                    publish_notify on;
                    drop_idle_publisher 10s;
                    
                    application live {
                        live on;
                        meta copy;
                        idle_streams off;
                        gop_cache off;
                    }
                }
            }

             

安卓开发 直接上一个简单代码吧

implementation 'com.arthenica:mobile-ffmpeg-full:4.4.LTS'
implementation 'com.google.android.exoplayer:exoplayer:2.19.1'
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <com.otaliastudios.cameraview.CameraView
        android:id="@+id/camera_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:cameraFacing="back"
        app:cameraFlash="off" />

    <Button
        android:id="@+id/btn_start"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_centerHorizontal="true"
        android:layout_marginBottom="50dp"
        android:text="开始推流" />

</RelativeLayout>
public class LivePushActivity extends AppCompatActivity {
    private static final String RTMP_URL = "rtmp://你的WindowsIP:1935/live/streamkey";
    private CameraView cameraView;
    private Button btnStart;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_live_push);
        
        cameraView = findViewById(R.id.camera_view);
        btnStart = findViewById(R.id.btn_start);
        
        btnStart.setOnClickListener(v -> {
            if (btnStart.getText().toString().equals("开始推流")) {
                startPushing();
                btnStart.setText("停止推流");
            } else {
                stopPushing();
                btnStart.setText("开始推流");
            }
        });
    }

    private void startPushing() {
        String input = cameraView.getCameraInstance().getCameraSource();
        String command = "-f dshow -i video=" + input + 
                         " -vcodec libx264 -preset ultrafast -tune zerolatency" +
                         " -acodec aac -f flv " + RTMP_URL;
        
        FFmpeg.executeAsync(command, (executionId, returnCode) -> {
            runOnUiThread(() -> Toast.makeText(this, 
                returnCode == 0 ? "推流成功" : "推流失败: "+returnCode, 
                Toast.LENGTH_SHORT).show());
        });
    }

    private void stopPushing() {
        FFmpeg.cancel();
    }
}
public class LivePlayActivity extends AppCompatActivity {
    private SimpleExoPlayer player;
    private PlayerView playerView;
    private String streamUrl;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_live_play);
        
        playerView = findViewById(R.id.player_view);
        streamUrl = "rtmp://你的WindowsIP:1935/live/streamkey"; // 或HLS地址
        
        initializePlayer();
    }

    private void initializePlayer() {
        player = new SimpleExoPlayer.Builder(this).build();
        playerView.setPlayer(player);
        
        MediaSource mediaSource;
        if (streamUrl.contains("m3u8")) {
            mediaSource = new HlsMediaSource.Factory(
                new DefaultDataSourceFactory(this, "ExoPlayerDemo"))
                .createMediaSource(MediaItem.fromUri(Uri.parse(streamUrl)));
        } else {
            // RTMP流
            mediaSource = new ProgressiveMediaSource.Factory(
                new RtmpDataSource.Factory())
                .createMediaSource(MediaItem.fromUri(Uri.parse(streamUrl)));
        }
        
        player.setMediaSource(mediaSource);
        player.prepare();
        player.setPlayWhenReady(true);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (player != null) {
            player.release();
        }
    }
}

 

posted @ 2025-04-14 10:10  张学涛  阅读(96)  评论(0)    收藏  举报