自己搭建简单的直播平台 自己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
-
-
-
播放测试工具:
-
VLC播放器: 下载地址
-
打开→网络串流→输入rtmp://localhost/live/test123
五、网络配置注意事项
-
防火墙设置:
-
允许1935(RTMP)和8080(HLS)端口通过防火墙
-
控制面板→Windows Defender防火墙→高级设置→入站规则→新建规则
-
-
局域网访问:
-
确保Android设备和Windows在同一局域网
-
使用
ipconfig
查看Windows本机IP,替换代码中的"localhost"
-
-
外网访问(可选):
-
需要路由器端口映射(1935和8080)
-
建议使用DDNS服务获取固定域名
-
六、常见问题解决
-
推流连接失败:
-
检查Nginx/SRS是否正常运行
-
检查防火墙设置
-
使用telnet测试端口连通性:
telnet 192.168.x.x 1935
-
-
播放卡顿:
-
降低推流分辨率(如720p)
-
调整码率(如1500kbps)
-
在ExoPlayer中启用缓冲优化:
-
-
延迟过高:
-
使用低延迟配置:
-
-
-
-
安卓开发 直接上一个简单代码吧
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(); } } }