0%

为树莓派交叉编译FFMPEG工具

- 参考链接

0x1 下载Raspberrypi 的工具链

1
2
$ git clone  https://github.com/raspberrypi/tools.git
$ cd tools
  • tools目录结构如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    ├── arm-bcm2708
    │   ├── arm-bcm2708hardfp-linux-gnueabi
    │   ├── arm-bcm2708-linux-gnueabi
    │   ├── arm-rpi-4.9.3-linux-gnueabihf
    │   ├── gcc-linaro-arm-linux-gnueabihf-raspbian
    │   └── gcc-linaro-arm-linux-gnueabihf-raspbian-x64
    ├── armstubs
    ├── configs
    ├── mkimage
    ├── pkg
    ├── test_code
    └── usbboot
  • 因为我的操作系统是debian x86_64 ,所以我要使用 gcc-linaro-arm-linux-gnueabihf-raspbian-x64 下面的工具链程序.设置环境变量

    1
    2
    3
    4
    5
    6
    ~$ export TOOLCHIAN_PATH=/home/user/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin
    ~$ export PATH=$PATH:$TOOLCHIAN_PATH
    ~$ export CROSS=arm-linux-gnueabihf-
    ~$ export CROSS_COMPILE=${CROSS}
    ~$ export CC=${CROSS}gcc
    ~$ export GCC=${CC}

CPUInfo

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
~$ cat /proc/cpuinfo
processor : 0
model name : ARMv6-compatible processor rev 7 (v6l)
BogoMIPS : 697.95
Features : half thumb fastmult vfp edsp java tls
CPU implementer : 0x41
CPU architecture: 7
CPU variant : 0x0
CPU part : 0xb76
CPU revision : 7

Hardware : BCM2835
Revision : 000f
Serial : 000000007ea6137d

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
~ $ v4l2-ctl --list-devices

bcm2835-codec-decode (platform:bcm2835-codec):
/dev/video10
/dev/video11
/dev/video12

mmal service -833381080.-107286 (platform:bcm2835-v4l2):
/dev/video0

~ $ v4l2-ctl -D
Driver Info:
Driver name : bm2835 mmal
Card type : mmal service 0.-1087962660
Bus info : platform:bcm2835-v4l2
Driver version : 4.19.97
Capabilities : 0x85200005
Video Capture
Video Overlay
Read/Write
Streaming
Extended Pix Format
Device Capabilities
Device Caps : 0x05200005
Video Capture
Video Overlay
Read/Write
Streaming
Extended Pix Format
~ $ v4l2-ctl -l

User Controls

brightness 0x00980900 (int) : min=0 max=100 step=1 default=50 value=50 flags=slider
contrast 0x00980901 (int) : min=-100 max=100 step=1 default=0 value=0 flags=slider
saturation 0x00980902 (int) : min=-100 max=100 step=1 default=0 value=0 flags=slider
red_balance 0x0098090e (int) : min=1 max=7999 step=1 default=1000 value=1000 flags=slider
blue_balance 0x0098090f (int) : min=1 max=7999 step=1 default=1000 value=1000 flags=slider
horizontal_flip 0x00980914 (bool) : default=0 value=0
vertical_flip 0x00980915 (bool) : default=0 value=0
power_line_frequency 0x00980918 (menu) : min=0 max=3 default=1 value=1
sharpness 0x0098091b (int) : min=-100 max=100 step=1 default=0 value=0 flags=slider
color_effects 0x0098091f (menu) : min=0 max=15 default=0 value=0
rotate 0x00980922 (int) : min=0 max=360 step=90 default=0 value=0 flags=modify-layout
color_effects_cbcr 0x0098092a (int) : min=0 max=65535 step=1 default=32896 value=32896

Codec Controls

video_bitrate_mode 0x009909ce (menu) : min=0 max=1 default=0 value=0 flags=update
video_bitrate 0x009909cf (int) : min=25000 max=25000000 step=25000 default=10000000 value=10000000
repeat_sequence_header 0x009909e2 (bool) : default=0 value=0
h264_i_frame_period 0x00990a66 (int) : min=0 max=2147483647 step=1 default=60 value=60
h264_level 0x00990a67 (menu) : min=0 max=11 default=11 value=11
h264_profile 0x00990a6b (menu) : min=0 max=4 default=4 value=4

Camera Controls

auto_exposure 0x009a0901 (menu) : min=0 max=3 default=0 value=0
exposure_time_absolute 0x009a0902 (int) : min=1 max=10000 step=1 default=1000 value=1000
exposure_dynamic_framerate 0x009a0903 (bool) : default=0 value=0
auto_exposure_bias 0x009a0913 (intmenu): min=0 max=24 default=12 value=12
white_balance_auto_preset 0x009a0914 (menu) : min=0 max=10 default=1 value=1
image_stabilization 0x009a0916 (bool) : default=0 value=0
iso_sensitivity 0x009a0917 (intmenu): min=0 max=4 default=0 value=0
iso_sensitivity_auto 0x009a0918 (menu) : min=0 max=1 default=1 value=1
exposure_metering_mode 0x009a0919 (menu) : min=0 max=2 default=0 value=0
scene_mode 0x009a091a (menu) : min=0 max=13 default=0 value=0

JPEG Compression Controls

compression_quality 0x009d0903 (int) : min=1 max=100 step=1 default=30 value=30

  • 根据查资料所知,设置GCC的安全的CFLAGS指令选项是-O2 -pipe -march=armv6 -mfpu=vfp -mfloat-abi=hard,还可以试一下这个-march=armv6zk -mtune=arm1176jzf-s -mfloat-abi=soft

0x2 编译ffmpeg依赖软件包

  • 下面先要编译安装一些依赖的库,这里用到的x264,libmp3lame,编译的过程出现任何问题,要查看config.log分析处理解决.假设编译安装的目是/home/user 具体可以自己更改.如果编译的东西非常多,会需一个个按依赖顺序逐个编译,如果动态库还要考虑与原系统里的库是ABI兼容的,GCC的版本也是要统一的,如果编译成静态库可以考虑使用该方法.
  • 也可以用另一个方法,在RPi安装好相关的一些库如:sudo apt-get install libssl1.0-dev libbz2-1.0 libmbedcrypto3 libmbedtls-dev nettle-dev libbz2-dev,安装完成之后,把RPi里的系统卡挂载到编译机上面去,指定--sysroot为这个RPi的根系统顶层目录,本文的RPi使用的系统是Raspbian 10,挂载的位置是/media/michael/rootfs,所以要指定--sysroot=/media/michael/rootfs,编译完成后安装路径可以指定为--prefix=/media/michael/root/usr/local.
  • 如果直接使用一张安装了RPi的SD卡挂载做交叉编译的sysroot,需要处理卡里文件系统的一些绝对引用链接文件,它在RPi系统理正常,具体可以参考这里,ffmpeg编译配置前检测到一些系统库的链接是broken,就会认为是没有这个库,在实际会出现ffmpeg无法开启pthread的特性支持.下面是处理它的脚本.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
~$ cat symlinks.sh
#!/bin/bash
cd /media/michael/rootfs/usr/lib/arm-linux-gnueabihf

for L in $(find -type l)
do
ABS=$(readlink $L)
if [[ $ABS =~ ^/ ]]
then
# 这要根据实际情况来改.
# 原来 : /usr/lib/arm-linux-gnueabihf/libanl.so -> /lib/arm-linux-gnueabihf/libanl.so.1
# 修改后 : /usr/lib/arm-linux-gnueabihf/libanl.so -> ../../../lib/arm-linux-gnueabihf/libanl.so.1
RELPATH=$(realpath --relative-to=$L -s ../../$ABS)
echo fixing link of $L to $ABS with $RELPATH
sudo ln -svf $RELPATH $L
fi
done

x264

1
2
3
4
5
~$  git clone http://git.videolan.org/git/x264.git
~$ cd x264 && mkdir build-rpi && cd build-rpi
~$ ../configure --enable-static --enable-shared --cross-prefix=arm-linux-gnueabihf- --host=arm-linux \
--enable-strip --enable-pic --extra-cflags='-O2 -pipe -march=armv6 -mfpu=vfp -mfloat-abi=hard' --prefix=/home/user/
~$ make && make install
  • 如果出现下面错误,禁用--disable-opencl特性.
1
../common/opencl.c:116:27: fatal error: common/oclobj.h: No such file or directory

libmp3lame

1
2
3
4
$ git clone https://github.com/gypified/libmp3lame
$ cd libmp3lame && mkdir build-rpi && build-rpi
$ ../configure --host=arm-linux --prefix=/home/user
$ make && make install
  • 编译完成后的/home/user 目录结构如下:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    $ tree user
    user
    ├── bin
    │   ├── lame
    │   └── x264
    ├── include
    │   ├── lame
    │   │   └── lame.h
    │   ├── x264_config.h
    │   └── x264.h
    ├── lib
    │   ├── libmp3lame.a
    │   ├── libmp3lame.la
    │   ├── libmp3lame.so -> libmp3lame.so.0.0.0
    │   ├── libmp3lame.so.0 -> libmp3lame.so.0.0.0
    │   ├── libmp3lame.so.0.0.0
    │   ├── libx264.a
    │   ├── libx264.so -> libx264.so.148
    │   ├── libx264.so.148
    │   └── pkgconfig
    │   └── x264.pc

安装libvpx

安装 yasm

  • 如果RPi没有安装yasm,这里就要编译一个,libvpx要用到它,还有其它一些编解库可能要用到它.
1
2
3
4
5
6
7
8
9
~$  wget -c https://www.tortall.net/projects/yasm/releases/yasm-1.3.0.tar.gz
~$ cd yasm-1.3 && mkdir build-rpi && cd build-rpi
~$ CROSS=arm-linux-gnueabihf- \
DEFAULT_INCLUDES="-I/media/michael/rootfs/usr/include/arm-linux-gnueabihf -I/media/michael/rootfs/usr/include" \
CFLAGS="-O2 -pipe -march=armv6 -mfpu=vfp -mfloat-abi=hard" \
LDFLAGS="--sysroot=/media/michael/rootfs -L/media/michael/rootfs/usr/lib/arm-linux-gnueabihf" \
../configure --host=arm-linux-gnueabihf --disable-debug --disable-python \
--prefix=/media/michael/rootfs/usr/local
~$ make && make install
  • 编译安装libvpx
1
2
3
4
5
6
7
8
9
10
11
12
~$ git clone https://chromium.googlesource.com/webm/libvpx
~$ cd libvpx && mkdir build-rpi && cd build-rpi
~$ CROSS=arm-linux-gnueabihf- \
CFLAGS="-I/media/michael/rootfs/usr/include -O2 -pipe -march=armv6 -mfpu=vfp -mfloat-abi=hard \
-I/media/michael/rootfs/usr/include/arm-linux-gnueabihf" \
LDFLAGS="--sysroot=/media/michael/rootfs -L/media/michael/rootfs/usr/lib/arm-linux-gnueabihf" \
../configure --target=armv7-linux-gcc --disable-examples --disable-docs --enable-vp9-highbitdepth
--enable-better-hw-compatibility --enable-vp8 --enable-vp9 \
--enable-postproc --enable-vp9-postproc --disable-multithread --enable-realtime-only --enable-shared --enable-runtime-cpu-detect
--enable-webm-io --enable-libyuv --prefix=/media/michael/rootfs/usr/local \
--enable-multi-res-encoding --enable-internal-stats --as=yasm
~$ make && make install

Opus音频

1
2
3
4
5
6
7
8
9
10
~$ git clone https://github.com/xiph/opus.git
~$ cd opus && ./autogen.sh && mkdir build-rpi && cd build-rpi
~$ CROSS=arm-linux-gnueabihf- \
CFLAGS="-I/media/michael/rootfs/usr/include -O2 -pipe -march=armv6 -mfpu=vfp -mfloat-abi=hard \
-I/media/michael/rootfs/usr/local/include -I/media/michael/rootfs/usr/include \
-I/media/michael/rootfs/usr/include/arm-linux-gnueabihf " \
LDFLAGS="--sysroot=/media/michael/rootfs -L/media/michael/rootfs/usr/local/lib -L/media/michael/rootfs/usr/lib" \
../configure --host=arm-linux-gnueabihf --disable-doc --enable-check-asm --enable-float-approx \
--with-sysroot=/media/michael/rootfs --prefix=/media/michael/rootfs/usr/local
~$ make && make install

安装zlib

1
2
3
4
~$ wget -c https://www.zlib.net/zlib-1.2.11.tar.gz
~$ tar xvf zlib-1.2.11.tar.gz && cd zlib-1.2.11 && mkdir build-rpi
~$ cd build-rpi && ../configure --prefix=/home/user
~$ make && make install

RTMP支持

  • rtmpdump这个库有很久没有更新了,如果要使用加密功能,需一些加密库来支持,且它的编译不像是上面的x264,zlib那样,它需要指定--sysroot才能正确的编译与链接原系统的库.
1
~$ git clone https://git.ffmpeg.org/rtmpdump.git

OpenSSL

1
2
3
4
5
6
7
8
9
10
~$ wget -c https://www.openssl.org/source/openssl-1.1.1d.tar.gz
~$ tar xvf openssl-1.1.1d.tar.gz && cd openssl-1.1.1d
~$ export CROSS=arm-linux-gnueabihf
~$ export AR=${CROSS}-ar
~$ export AS=${CROSS}-as
~$ export CC=${CROSS}-gcc
~$ export CXX=${CROSS}-g++
~$ export LD=${CROSS}-ld
~$ ./Configure linux-armv4 --prefix=/home/user --openssldir=/home/user/openssl
~$ make && make install
  • 编译使用OpenSSL支持
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
~$ cd rtmpdump/librtmp
~$ make clean && make CROSS_COMPILE=arm-linux-gnueabihf- \
INC="-I/media/michael/rootfs/usr/include -I/media/michael/rootfs/usr/include/arm-linux-gnueabihf" \
LDFLAGS="--sysroot=/media/michael/rootfs -L/media/michael/rootfs/usr/lib/arm-linux-gnueabihf" \
CFLAGS="-O2 -pipe -march=armv6 -mfpu=vfp -mfloat-abi=hard"
rm -f *.o *.a *.so *.so.1 librtmp.pc
arm-linux-gnueabihf-gcc -Wall -I/media/michael/rootfs/usr/include -I/media/michael/rootfs/usr/include/arm-linux-gnueabihf -DRTMPDUMP_VERSION=\"v2.4\" -DUSE_OPENSSL -O2 -fPIC -c -o rtmp.o rtmp.c
rtmp.c: In function ‘RTMP_ReadPacket’:
rtmp.c:3555:7: warning: variable ‘didAlloc’ set but not used [-Wunused-but-set-variable]
int didAlloc = FALSE;
^
arm-linux-gnueabihf-gcc -Wall -I/media/michael/rootfs/usr/include -I/media/michael/rootfs/usr/include/arm-linux-gnueabihf
-DRTMPDUMP_VERSION=\"v2.4\" -DUSE_OPENSSL -O2 -fPIC -c -o log.o log.c
arm-linux-gnueabihf-gcc -Wall -I/media/michael/rootfs/usr/include -I/media/michael/rootfs/usr/include/arm-linux-gnueabihf
-DRTMPDUMP_VERSION=\"v2.4\" -DUSE_OPENSSL -O2 -fPIC -c -o amf.o amf.c
arm-linux-gnueabihf-gcc -Wall -I/media/michael/rootfs/usr/include -I/media/michael/rootfs/usr/include/arm-linux-gnueabihf
-DRTMPDUMP_VERSION=\"v2.4\" -DUSE_OPENSSL -O2 -fPIC -c -o hashswf.o hashswf.c
arm-linux-gnueabihf-gcc -Wall -I/media/michael/rootfs/usr/include -I/media/michael/rootfs/usr/include/arm-linux-gnueabihf
-DRTMPDUMP_VERSION=\"v2.4\" -DUSE_OPENSSL -O2 -fPIC -c -o parseurl.o parseurl.c
arm-linux-gnueabihf-ar rs librtmp.a rtmp.o log.o amf.o hashswf.o parseurl.o
arm-linux-gnueabihf-ar: creating librtmp.a
arm-linux-gnueabihf-gcc -shared -Wl,-soname,librtmp.so.1 -Wl,-rpath-link,/media/michael/rootfs/usr/lib/arm-linux-gnueabihf
--sysroot=/media/michael/rootfs -L/media/michael/rootfs/usr/lib/arm-linux-gnueabihf -o librtmp.so.1 rtmp.o log.o amf.o hashswf.o
parseurl.o -lssl -lcrypto -lz
ln -sf librtmp.so.1 librtmp.so

GnuTLS

  • 使用GnuTLS来编译,需要在RPi里安装libgnutls28-dev libgmp-dev nettle-dev
1
2
3
4
5
6
7
~$ cd rtmpdump/librtmp
# 在Makefile里的第一行加入或修改prefix变量,可以改成/home/user也可以指向/media/michael/rootfs/usr/local .
~$ make clean && make CFLAGS="-O2 -pipe -march=armv6 -mfpu=vfp -mfloat-abi=hard" \
CROSS_COMPILE=arm-linux-gnueabihf- \
INC="-I/media/michael/rootfs/usr/include -I/media/michael/rootfs/usr/inculde -I/media/michael/rootfs/usr/include/arm-linux-gnueabihf" \
LDFLAGS="--sysroot=/media/michael/rootfs -L/media/michael/rootfs/usr/lib/arm-linux-gnueabihf" \
CRYPTO=GNUTLS SHARED=yes
  • 编译出错,因为使用了gcc-linaro-arm-linux-gnueabihf-raspbian-x64,编译主机是64位.需要安装libc6-dev-armhf-cross
1
2
3
4
5
6
7
arm-linux-gnueabihf-gcc -Wall  -I/media/michael/rootfs/usr/include -DRTMPDUMP_VERSION=\"v2.4\" -DUSE_OPENSSL  -O2 -fPIC   -c -o rtmp.o rtmp.c
In file included from rtmp.c:26:0:
/media/michael/rootfs/usr/include/stdint.h:26:36: fatal error: bits/libc-header-start.h: No such file or directory
#include <bits/libc-header-start.h>
^
compilation terminated.

  • 交叉编译时一定要指--sysroot选项,不然出下面的动态库的链接错误,具体可以打开系统下的/usr/lib/arm-linux-gnueabihf/libc.so查看.
1
2
3
4
5
6
7
8
9
10
arm-linux-gnueabihf-gcc -shared -Wl,-soname,librtmp.so.1 -L/media/michael/rootfs/usr/lib/arm-linux-gnueabihf -o librtmp.so.1
rtmp.o log.o amf.o hashswf.o parseurl.o -lgnutls -lhogweed -lnettle -lgmp -lz
/home/michael/3TB-DISK/github/raspberrypi-chaintools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin/../lib/gcc/
arm-linux-gnueabihf/4.8.3/../../../../arm-linux-gnueabihf/bin/ld: cannot find /lib/arm-linux-gnueabihf/libc.so.6
/home/michael/3TB-DISK/github/raspberrypi-chaintools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin/../lib/gcc/
arm-linux-gnueabihf/4.8.3/../../../../arm-linux-gnueabihf/bin/ld: cannot find /usr/lib/arm-linux-gnueabihf/libc_nonshared.a
/home/michael/3TB-DISK/github/raspberrypi-chaintools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin/../lib/gcc/
arm-linux-gnueabihf/4.8.3/../../../../arm-linux-gnueabihf/bin/ld: cannot find /lib/arm-linux-gnueabihf/ld-linux-armhf.so.3
collect2: error: ld returned 1 exit status
make: *** [Makefile:95: librtmp.so.1] Error 1

0x3 下载并编译FFMPEG

硬件加速相关

  • --enable-decoder=h264_mmal --enable-mmal是需要mmal.h头文件的,--enable-encoder=h264_omx --enable-omx --enable-omx-rpi
    这些是要Openmax的头文件的.原本以为要下载OpenMAX IL头文件,后来发现这一步是不需要的,所有硬件开发的支持文件在RPi里的/opt/vc下面.

  • 如需开启--enable-opengl,需要在RPi安装gl库,如:libopengl-dev libgles-dev libgl-dev libegl-dev libopengl0 libgles2 libgles1.

  • 如果开启drawtext过滤器,也就是往视频上写字,需要加上--enable-libfreetype --enable-libfontconf --enable-libfribidi选项,要先行安装
    libfribidi-dev libfontconfig1-dev libfontconfig1的运行库与头文件.

  • 这里最好新建一个目录用来编译,防止在当前目录下编译污染了当前目录.

  • ffmpeg仓库发现,release/3.4之后无法支持omx硬件加速功能,4.2之后会报WARNING: Disabled h264_omx_encoder because not all dependencies are satisfied: omx的提示警告.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
~$ git clone https://git.ffmpeg.org/ffmpeg.git
~$ cd ffmpeg && mkdir build-rpi && cd build-rpi
~$ export ROOTFS=/media/michael/rootfs
~$ export PKG_CONFIG_PATH=${ROOTFS}/opt/vc/lib/pkgconfig:${ROOTFS}/usr/lib/pkgconfig:${ROOTFS}/usr/lib/arm-linux-gnueabihf/pkgconfig:${ROOTFS}/usr/local/lib/pkgconfig
~$ ./configure --arch=armhf --target-os=linux --disable-doc --disable-htmlpages --disable-manpages --disable-podpages \
--disable-txtpages --enable-librtmp --enable-zlib --enable-bzlib --enable-openssl --enable-shared --enable-static \
--enable-gpl --enable-libx264 --enable-omx --enable-omx-rpi --enable-mmal --enable-nonfree --enable-libopus \
--enable-libfreetype --enable-libfontconfig --enable-libfribidi \
--enable-runtime-cpudetect --enable-postproc --enable-pic --enable-neon --enable-vfp --enable-libvpx \
--enable-cross-compile --cross-prefix=arm-linux-gnueabihf- --enable-libmp3lame --enable-hardcoded-tables --disable-encoders \
--enable-encoder="opus,libopus,libvpx8,libvpx9,vp8_v4l2m2m,h264_omx,mjpeg,mpeg2video,png,libx264,h264_v4l2m2m,flv,mpeg4_v4l2m2m,mpeg4" \
--disable-decoders --enable-decoder="opus,libopus,libvpx8,libvpx9,vp9,vp9_v4l2m2m,vp8,vp8_v4l2m2m,png,mjpeg,h264,mpeg2video,mpeg2_mmal,h264_mmal,rawvideo,flv,mpeg4_mmal,mpeg4_v4l2m2m,vc1_mmal" \
--disable-muxers --enable-muxer="opus,webm,webm_chunk,webm_dash_manifest,dash,avi,mp4,hls,rtp_mpegts,rtsp,mpegts,mjpeg,h264,flv" \
--disable-demuxers --enable-demuxer="dash,webm_dash_manifest,h264,hls,mjpeg,rtp,rtsp,flv" \
--disable-parsers --enable-parser="opus,vp8,vp9,png,h264,mjpeg,mpeg4video" \
--sysroot=/media/michael/rootfs \
--extra-cflags="-I/media/michael/rootfs/usr/include -I/media/michael/rootfs/opt/vc/include/IL \
-I/media/michael/rootfs/opt/vc/include -I/media/michael/rootfs/usr/include/arm-linux-gnueabihf \
-I/media/michael/rootfs/usr/include/freetype2 -I/media/michael/rootfs/usr/include/fribidi \
-O2 -pipe -march=armv6 -mfpu=vfp -mfloat-abi=hard" \
--extra-cxxflags='-O2 -pipe -march=armv6 -mfpu=vfp -mfloat-abi=hard' \
--extra-ldflags="--sysroot=/media/michael/rootfs -L/media/michael/rootfs/opt/vc/lib \
-L/media/michael/rootfs/usr/lib/arm-linux-gnueabihf -L/media/michael/rootfs/opt/vc/lib \
-L/media/michael/rootfs/usr/lib -L/media/michael/rootfs/lib/arm-linux-gnueabihf -lmmal -lmmal_core -lvcos
-lmmal_vc_client -lmmal_components -lvchiq_arm \
-lvcsm -lmmal_util -lcontainers -lpthread" \
--extra-libs="-lz -lrt -lresolv -lnsl -lm -ldl -lbz2 -lpthread" \
--prefix=/media/michael/rootfs/usr/local

install prefix /media/michael/rootfs/usr/local
source path .
C compiler arm-linux-gnueabihf-gcc
C library glibc
host C compiler gcc
host C library glibc
ARCH arm (armv6)
big-endian no
runtime cpu detection yes
ARMv5TE enabled yes
ARMv6 enabled yes
ARMv6T2 enabled yes
VFP enabled yes
NEON enabled yes
THUMB enabled no
debug symbols yes
strip symbols yes
optimize for size no
optimizations yes
static yes
shared yes
postprocessing support yes
network support yes
threading support pthreads
safe bitstream reader yes
texi2html enabled no
perl enabled yes
pod2man enabled yes
makeinfo enabled yes
makeinfo supports HTML yes

External libraries:
bzlib libmp3lame libvpx libx264 openssl xlib zlib
iconv librtmp

External libraries providing hardware acceleration:
mmal omx v4l2_m2m

Libraries:
avcodec avfilter avformat avutil postproc swresample swscale
avdevice

Programs:
ffmpeg ffprobe ffserver

Enabled decoders:
flv h264_mmal mpeg2video mpeg4_v4l2m2m rawvideo vp8 vp9
h263 mjpeg mpeg4_mmal png vc1_mmal vp8_v4l2m2m vp9_v4l2m2m
h264 mpeg2_mmal

Enabled encoders:
flv h264_omx libx264 mpeg2video mpeg4_v4l2m2m png vp8_v4l2m2m
h263 h264_v4l2m2m mjpeg mpeg4

Enabled hwaccels:
h264_mmal mpeg2_mmal mpeg4_mmal vc1_mmal

Enabled parsers:
h263 h264 mjpeg mpeg4video png vp8 vp9

Enabled demuxers:
asf h264 matroska mov rm rtsp webm_dash_manifest
flv hls mjpeg mpegts rtp sdp

Enabled muxers:
adts ffm hls mov rtp rtsp webm_chunk
avi flv latm mp4 rtp_mpegts webm webm_dash_manifest
dash h264 mjpeg mpegts

Enabled protocols:
async file httpproxy librtmps mmst srtp tls_openssl
cache ftp https librtmpt pipe subfile udp
concat gopher icecast librtmpte prompeg tcp udplite
crypto hls librtmp md5 rtp tee unix
data http librtmpe mmsh

Enabled filters:
[....]

Enabled bsfs:
aac_adtstoasc dump_extradata hevc_mp4toannexb mjpega_dump_header mpeg4_unpack_bframes remove_extradata vp9_superframe
chomp extract_extradata imx_dump_header mov2textsub noise text2movsub vp9_superframe_split
dca_core h264_mp4toannexb mjpeg2jpeg mp3_header_decompress null vp9_raw_reorder

Enabled indevs:
fbdev lavfi oss v4l2

Enabled outdevs:
fbdev oss v4l2

License: nonfree and unredistributable
Creating configuration files ...
config.h is unchanged
libavutil/avconfig.h is unchanged

  • 如果不出问题出问题会在编译目录下出现以下二进制文件:ffserver,ffprobe,ffmpeg ,使用file 测试一下文件类型如下:
    1
    2
    3
    $ file ffmpeg
    ffmpeg: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), dynamically linked,
    interpreter /lib/ld-linux-armhf.so.3, for GNU/Linux 2.6.26, BuildID[sha1]=ec3417b6de5c9d89fe351048f6718a0857e760ff, stripped
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
~ $ ffmpeg -f v4l2 -list_formats all -i /dev/video0
[....]
[video4linux2,v4l2 @ 0x3e38b0] Raw : yuv420p : Planar YUV 4:2:0 : {32-2592, 2}x{32-1944, 2}
[video4linux2,v4l2 @ 0x3e38b0] Raw : yuyv422 : YUYV 4:2:2 : {32-2592, 2}x{32-1944, 2}
[video4linux2,v4l2 @ 0x3e38b0] Raw : rgb24 : 24-bit RGB 8-8-8 : {32-2592, 2}x{32-1944, 2}
[video4linux2,v4l2 @ 0x3e38b0] Compressed: mjpeg : JFIF JPEG : {32-2592, 2}x{32-1944, 2}
[video4linux2,v4l2 @ 0x3e38b0] Compressed: h264 : H.264 : {32-2592, 2}x{32-1944, 2}
[video4linux2,v4l2 @ 0x3e38b0] Compressed: mjpeg : Motion-JPEG : {32-2592, 2}x{32-1944, 2}
[video4linux2,v4l2 @ 0x3e38b0] Raw : Unsupported : YVYU 4:2:2 : {32-2592, 2}x{32-1944, 2}
[video4linux2,v4l2 @ 0x3e38b0] Raw : Unsupported : VYUY 4:2:2 : {32-2592, 2}x{32-1944, 2}
[video4linux2,v4l2 @ 0x3e38b0] Raw : uyvy422 : UYVY 4:2:2 : {32-2592, 2}x{32-1944, 2}
[video4linux2,v4l2 @ 0x3e38b0] Raw : nv12 : Y/CbCr 4:2:0 : {32-2592, 2}x{32-1944, 2}
[video4linux2,v4l2 @ 0x3e38b0] Raw : bgr24 : 24-bit BGR 8-8-8 : {32-2592, 2}x{32-1944, 2}
[video4linux2,v4l2 @ 0x3e38b0] Raw : yuv420p : Planar YVU 4:2:0 : {32-2592, 2}x{32-1944, 2}
[video4linux2,v4l2 @ 0x3e38b0] Raw : Unsupported : Y/CrCb 4:2:0 : {32-2592, 2}x{32-1944, 2}
[video4linux2,v4l2 @ 0x3e38b0] Raw : bgr0 : 32-bit BGRA/X 8-8-8-8 : {32-2592, 2}x{32-1944, 2}

  • 把上述三个文件复制到树莓派的机器下就可以直接运行了.

0x4 安装Web服务

Nginx

  • 可以安装现有的发行版软件也可以自己编译,这里就使系统安装使用Nginx做为Web服务.
1
~$ sudo apt-get install nginx libnginx-mod-rtmp

配置RTMP

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
~$ sudo cat > '/etc/nginx/conf.d/rtmp' << EOF
# RTMP media server
rtmp {
server {
listen 1935;
chunk_size 4096;
allow play all;
# Transcoding (ffmpeg needed)
# 这里纯流文件直播,使用ffmpeg 切片好的文件目录.
application play {
live on;
hls on;
record off;
hls_path /var/www/html/live/play;
}

application hls {
live on;
record off;

hls on;
hls_path /var/www/html/live/hls;
hls_nested on;
hls_type live;
hls_fragment 2s;
hls_variant _low BANDWIDTH=640000;
hls_variant _hi BANDWIDTH=2140000;
hls_cleanup on;
}

application dash {
live on;
record off;
dash on;
dash_path /var/www/html/live/dash;
dash_fragment 2s;
dash_nested on;
dash_playlist_length 20;
dash_cleanup on;
}
exec_static /var/www/html/ffmpeg.sh;
}
}
EOF

~$ sudo sh -c "echo \"include /etc/nginx/conf.d/rtmp;\" >> /etc/nginx/nginx.conf"
~$ id www-data
uid=33(www-data) gid=33(www-data) groups=33(www-data),44(video)
  • 如果没有像上面一样显示,www-datavideo里,可以直接修改/etc/group或用下面命令.
1
~$ sudo useradd -a -G video www-data
  • 使用shm共享内存的方式来暂存hls流片段.
1
2
3
~$ sudo mkdir -p /var/www/html/live/
~$ cd /var/www/html/live/
~$ sudo ln -s /dev/shm hls

开启Basic认证

1
2
3
~$ printf "username:$(openssl passwd -crypt your_passwd)\n" > conf.d/.htpasswd
~$ sudo chown www-data.root conf.d/.htpasswd
~$ sudo chmod 400 conf.d/.htpasswd
  • 修改nginx.conf里面的主机配置文件,包含如下行:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
     location /
    {
    auth_basic "Webcam 登录";
    auth_basic_user_file conf.d/.htpasswd;
    autoindex on;
    /* 如果是整个服务器都使用这一个密码,就把上面三行加到 server 块里 */
    }

    # 这里对应上面的 application play.
    location /play {
    root /var/www/html ;
    types {
    application/vnd.apple.mpegurl m3u8;
    video/mp2t ts;
    }
    add_header Cache-Control no-cache;

    # To avoid issues with cross-domain HTTP requests (e.g. during development)
    add_header Access-Control-Allow-Origin *;
    }
  • 访问测试,curl http://<username>:<password>@<server_ipaddress>/

推流脚本(HLS,Dash)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
~ $ cat ffmpeg.sh
FONT='/usr/share/fonts/truetype/wqy/wqy-zenhei.ttc'
PUB="transpose=1,format=yuv420p,"
VF1="drawtext=fontfile='${FONT}':text='时间\: %{localtime}':x=20:y=620:box=1:boxcolor=black@0.1:fontsize=28:fontcolor=white,"
VF2="drawtext=fontfile='${FONT}':textfile='/var/www/html/cpuinfo':x=2:y=2:boxcolor=white@0.1:box=1,"
VF3="drawtext=fontfile='${FONT}':textfile='/var/www/html/ffmpeg.sh':x=2:y=250:boxcolor=white@0.1:box=1,"
VF4="drawtext=fontfile='${FONT}':text='TCR\:':timecode=' 00\:00\:00\:00':boxcolor=black@0.1:fontsize=24:fontcolor=white:timecode_rate=25:x=20:y=650,"
H="drawtext=fontfile='${FONT}':text='HLS流直播':x=20:y=680:box=1:boxcolor=black@0.1:fontsize=28:fontcolor=white"
D="drawtext=fontfile='${FONT}':text='DASH流直播':x=20:y=680:box=1:boxcolor=black@0.1:fontsize=28:fontcolor=white"
VF=`echo ${PUB}${VF1}${VF2}${VF3}${VF4}`
HLS=`echo ${VF}${H}`
DASH=`echo ${VF}${D}`
/usr/local/bin/ffmpeg -hide_banner -loglevel error -thread_queue_size 2048 -f v4l2 \
-input_format yuv420p -re -i /dev/video0 -framerate 25 \
-c:v h264_omx -keyint_min 0 -map 0:v -b:v 1M -vf "${HLS}" \
-g 60 -an -f flv -rtmp_live live rtmp://127.0.0.2/hls/ \
-c:v h264_omx -keyint_min 0 -map 0:v -b:v 1M -vf "${DASH}" \
-g 60 -an -f flv -rtmp_live live rtmp://127.0.0.2/dash/


  • h264_v4l2m2m很流畅
1
ffmpeg -f v4l2 -video_size 1280x720 -i /dev/video0 -codec:v h264_v4l2m2m -b:v 2048k -f matroska test1.mkv

Systemd服务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
[Unit]
Description=ffmpeg listening and forward stream
After=syslog.target network.target

[Service]
PIDFile=/tmp/ffstreamer.pid
ExecStart= /path/to/ffmpeg.sh

ExecStop=/bin/kill -s QUIT $MAINPID
Restart=always
User=www-data

[Install]
WantedBy=multi-user.target
  • 简单HTML包装
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<head>
<meta charset="utf-8"/>
<script src="https://cdn.jsdelivr.net/npm/hls.js@latest"></script>
<script src="http://cdn.dashjs.org/latest/dash.all.min.js"></script>
</head>
<body>
<h1>Raspberry Pi </h1>
<h2>Fmpeg HLS 直播流服务</h2>
<video id="video" autoplay controls height="1024" width="768"></video>
<h2> Fmpeg Dash 直播流服务</h2>
<video data-dashjs-player src="live/dash/index.mpd" autoplay controls height="1024" width="768"></video>
<script>
if(Hls.isSupported()) {
var video = document.getElementById('video');
var hls = new Hls();
hls.loadSource('live/hls/index.m3u8');
hls.attachMedia(video);
hls.on(Hls.Events.MANIFEST_PARSED,function() {
video.play();
});
}
</script>
<div>
<img src="rpd.jpg" />
</div>
</body>
</html>

编译Libwebsockets,mosquitto支持IPv6

  • 在RPI里可以直接安装发行版的mosquitto,libwebsockets库与服务,但是发现在发行版里的libwebsockets没有开启IPv6支持,导致mosquitto里的websockets协议服务,只有IPv4的服务,编译安装仅仅只为了让它支持IPv6.

libuv编译

1
2
3
4
5
6
7
8
9
~$ git clone https://github.com/libuv/libuv.git
# 初始化交叉编译环境变量,确定安装了automake,libtool.
~$ ./autogen.sh && mkdir build-rpi && cd build-rpi
~$ ../configure --host=arm-linux-gnueabihf --prefix=/media/michael/rootfs/usr/local
# 下面sudo的环境,也要指定交叉工具链的绝对路径.
~$ make && sudo PATH=$PATH:$TOOLCHIAN_PATH make install
~$ file /media/michael/rootfs/usr/local/lib/libuv.so.1.0.0
/media/michael/rootfs/usr/local/lib/libuv.so.1.0.0: ELF 32-bit LSB pie executable, ARM, EABI5 version 1 (SYSV), dynamically linked, BuildID[sha1]=431be81e472cf960d64fdd030254e88e5828d05c, with debug_info, not stripped

libwebsockets编译

1
~$ sudo apt-get install libmbedtls-dev  libmbedtls12 libssl-dev -y
1
2
3
4
5
6
7
8
9
~$ git clone https://libwebsockets.org/repo/libwebsockets
~$ cd libwebsockets && mkdir build-rpi
~$ export ROOTFS=/media/michael/rootfs
~$ cmake -DCMAKE_SYSROOT=$ROOTFS -DCMAKE_INSTALL_PREFIX:PATH=$ROOTFS/usr/local \
-DCMAKE_TOOLCHAIN_FILE=../contrib/cross-arm-linux-gnueabihf.cmake -DLWS_WITH_LWSWS=1 -DCMAKE_BUILD_TYPE=Release \
-DLWS_WITH_ZLIB=1 -DLWS_IPV6=1 -DLWS_WITH_SOCKS5=1 -DLWS_WITH_HTTP2=1 -DLWS_ROLE_WS=1 -DLWS_WITH_SYS_ASYNC_DNS=1 \
-DLWS_WITH_HTTP_BASIC_AUTH=1 -DCMAKE_FIND_ROOT_PATH=$ROOTFS -DLWS_WITHOUT_TESTAPPS=1 -DLWS_WITH_MBEDTLS=1 \
-DCMAKE_C_FLAGS="-I$ROOTFS/usr/include -I$ROOTFS/usr/local/include -O2 -pipe -march=armv6 -mfpu=vfp -mfloat-abi=hard -I/$ROOTFS/usr/include/arm-linux-gnueabihf" ../

  • 错误

  • 如下面错误所示,就是有一个变量没有初始化,可能是这个GCC版本也没有相应处理机制,所以报错了,打开源码找到出错位置,给变量设置一个初值.

1
2
3
4
5
6
7
8
9
/fullpath/libwebsockets/lib/core-net/sorted-usec-list.c: In function ‘__lws_sul_service_ripe’:
/fullpath/libwebsockets/lib/core-net/sorted-usec-list.c:139:4: error: ‘lowest’ may be used uninitialized in this function [-Werror=maybe-uninitialized]
return lowest - usnow;
^
cc1: all warnings being treated as errors
make[2]: *** [lib/CMakeFiles/websockets_shared.dir/build.make:869: lib/CMakeFiles/websockets_shared.dir/core-net/sorted-usec-list.c.o] Error 1
make[1]: *** [CMakeFiles/Makefile2:1076: lib/CMakeFiles/websockets_shared.dir/all] Error 2
make: *** [Makefile:163: all] Error 2

  • 编译Mosquitto
1
2
3
4
5
6
7
8
~$ git clone https://github.com/eclipse/mosquitto
~$ cd mosquitto && mkdir build-rpi
~$ export ROOTFS=/media/michael/rootfs
~$ cmake -DCMAKE_TOOLCHAIN_FILE=../../libwebsockets/contrib/cross-arm-linux-gnueabihf.cmake -DWITH_WEBSOCKETS=yes \
-DWITH_TLS=yes -DCMAKE_INSTALL_PREFIX:PATH=$ROOTFS/usr/local -DWITH_DOCS=no -DDOCUMENTATION=0 \
-DCMAKE_SHARED_LINKER_FLAGS="-L$ROOTFS/usr/lib/arm-linux-gnueabihf -L$ROOTFS/lib/arm-linux-gnueabihf" \
-DCMAKE_C_FLAGS="-I$ROOTFS/usr/include -O2 -pipe -march=armv6 -mfpu=vfp -mfloat-abi=hard -I$ROOTFS/usr/include/arm-linux-gnueabihf -I$ROOTFS/usr/local/include" \
-DCMAKE_SYSROOT=/media/michael/rootfs ../
  • 注意,-DCMAKE_SYSROOT=/media/michael/rootfs在交叉编译中很重要,会无法正确链接.

0x5 内网转发

SSH转发

  • 如果自己有公网的IP或者VPS,可以通SSH远程转发的方式,把本地HLS流服务暴露出去.这里要确保VPS里的sshd_configGatewayPorts=yes这一行,不然SSH服务器只能绑定localhost:8080.下面命令成功后,可以通过http://<vps-domain>:8080访问里内网里的HLS服务了.
1
~$ sudo ssh -NfC -R 8080:localhost:80 user@<vps-domain>

ngrok转发

  • ngrok是一个内网穿透服务,需要注册才能使用,免费版帐号只能运行一个且有功能限制的实例.它在github的源码已经不更新,不过自己可以使用该源码搭建自己的私服.

  • 它的使用也相当的容易,无须配置.先注册子一个帐号,再下载一个对应平台的ngrok客户端程序.在须要转发的内网机内,添加帐号里的Authtoken.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 添加自己帐号里的authtoken
~$ ./ngrok authtoken Nqabz7VHLTEoQEqhXxpK_o8yqiqE9DVyB171LZez9

# 把本地80端口的服务转发去.
~$ ngrok http 80
ngrok by @inconshreveable (Ctrl+C to quit)
Session Status online
Account yjdwbj (Plan: Free)
Version 2.3.35
Region United States (us)
Web Interface http://127.0.0.1:4040
Forwarding http://7ce99246.ngrok.io -> http://localhost:80
Forwarding https://7ce99246.ngrok.io -> http://localhost:80
Connections ttl opn rt1 rt5 p50 p90
0 0 0.00 0.00 0.00 0.00

IPv6-PD(Prefix Delegation)模式,动态域名直连

  • 这里就使用dynv6.com的免费域名.注册帐号->激活帐号->创建域名.会创建一个WAN_6的接口,同时会从ISP获得一个IPv6公网地址与IPv6-PD的前缀.

  • 如果是用NAT6的模式,需要在OpenWRT编译源码时,需选择上iptables-nat6,转发DNAT与IPv4下的NAT是一样的原理.确保安装了dhcpcd5 - DHCPv4, IPv6RA and DHCPv6 client with IPv4LL support,安装完成dhcpcd5后启动systemctl start dhcpcd5.

  • 或者使用下面脚本,如:请求wlan0的IPv6地址.

1
2
3
4
5
6
7
8
~# cat > /etc/network/if-up.d/dhcpcd <<EOF
#!/bin/bash
# filename: wlan0-up
if [ "$IFACE" = wlan0 ]; then
dhcpcd wlan0
fi
EOF
~# chmod +x /etc/network/if-up.d/dhcpcd
  • 或者在/etc/network/interfaces里加入post-up.
1
2
3
4
5
6
7
8
9
10
auto  wlan0
iface wlan0 inet static
address 192.168.1.100
netmask 255.255.255.0
network 192.168.1.0
gateway 192.168.1.1
# here is ovs-vsctl add-port ovsbr0 wlan0
pre-up wpa_supplicant -B -Dnl80211 -iwlan0 -c/etc/wpa_supplicant/wpa_supplicant.conf
post-up dhcpcd wlan0
wait-delay 15
  • 查看IPv6路由.
1
2
3
4
5
6
7
8
9
10
~$ ip -6 route
::1 dev lo proto kernel metric 256 pref medium
# 2409:8a55:2412:6b30::/60 就是路由器通过PPPOE获取到的PD
2409:8a55:2412:6b30::/64 dev wlan0 proto ra metric 303 mtu 1492 pref medium
fe80::/64 dev ovs-system proto kernel metric 256 pref medium
fe80::/64 dev ovsbr0 proto kernel metric 256 pref medium
fe80::/64 dev wlan0 proto kernel metric 256 pref medium
fe80::/64 dev wlan8 proto kernel metric 256 pref medium
default via fe80::2276:xxxx:xxxx:ac08 dev wlan0 proto ra metric 303 mtu 1492 pref medium

更新IPv6的脚本

1
2
3
4
5
6
7
8
9
# 在我的实际电脑中,一块网块除了fd开头的内网地址,还有另外四个,但是从外网能ping通的地址只有一个,就是与路由里 IPv6-PD前缀一致的才可以ping通.
if cat /sys/class/net/eth0/operstate | grep -q "up"; then
IPV6=$(ip -6 addr list scope global eth0 | grep -v " fd" | sed -n 's/.*inet6 \([0-9a-f:]\+\).*/\1/p' | head -n 1)/128
else
IPV6=$(ip -6 addr list scope global wlan0 | grep -v " fd" | sed -n 's/.*inet6 \([0-9a-f:]\+\).*/\1/p' | head -n 1)/128
fi

TOKEN=<dynv6.com Http Token >
curl -fsS -o myddns_ipv6.dat --stderr myddns_ipv6.err "http://dynv6.com/api/update?hostname=<域名全称>&token=${TOKEN}&ipv6=${IPV6}"
  • Luci--> Network--> Firewall--> Traffic Rules里添加一条规则,通过IPv6地址访问它的80端口,在配置文件里显示如下:
1
2
3
4
5
6
7
8
9
10
root@OpenWrt:~# cat /etc/config/firewall
[....]
config rule
option src 'wan'
option name 'camera'
option target 'ACCEPT'
option family 'ipv6'
option dest 'lan'
list proto 'tcp'
option dest_port '80'
  • 如果使用NAT6,且ip6tables -P INPUT ACCEPT话,默认公网就可以通过路由器的IPv6地址,直接访问到路由的80端口,所以这里把nginx服务改成listen [::]:8888 default_server;.

  • 因为是公网可以了访问,可以在系统里安装防火墙脚本apt-get install ufw.

  • 定时刷新DDNS的地址,并且定时刷新OpenWrt里的防火墙规则,否则无法转发端口到内网访问。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    ~$ cat update.sh
    ETH=eth0
    if cat /sys/class/net/${ETH}/operstate | grep -q "up"; then
    IPV6=$(ip -6 addr list scope global ${ETH} | grep -v " fd" | sed -n 's/.*inet6 \([0-9a-f:]\+\).*/\1/p' | head -n 1)
    else
    IPV6=$(ip -6 addr list scope global wlan0 | grep -v " fd" | sed -n 's/.*inet6 \([0-9a-f:]\+\).*/\1/p' | head -n 1)
    fi

    echo "ipv6 addr $IPV6"
    TOKEN=<dynv6.com token>
    DOMAIN=yjdwbj.dynv6.net
    curl -fsS -o myddns_ipv6.dat --stderr myddns_ipv6.err "http://dynv6.com/api/update?hostname=${DOMAIN}&token=${TOKEN}&ipv6=${IPV6}"
    #IPV4=$(ip addr show ${ETH} | sed -rn '/[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}/p' | awk '{print substr($2,1,length($2)-3)}')
    IPV4=$(ifconfig | sed -En 's/127.0.0.1//;s/.*inet (addr:)?(([0-9]*\.){3}[0-9]*).*/\2/p')
    RULE_ID=$(ssh route uci show firewall | grep "2122" | awk -F'.dest_port=' '{print $1}')
    CMD=$(echo ssh route "uci set ${RULE_ID}.dest_ip='${IPV6}'; uci commit firewall")
    $CMD
    V2RAY_ID=$(ssh route uci show firewall | grep "v2ray" | awk -F'.name=' '{print $1}')
    CMD=$(echo ssh route "uci set ${V2RAY_ID}.dest_ip='${IPV6}'; uci commit firewall; /etc/init.d/firewall restart")
    $CMD

golang交叉编译

  • 使用golang交叉编译v2ray-core.可以运行一个v2ray-core的服务提供中继服务。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
 if [ -d v2ray-core ]; then
cd v2ray-core
git pull
else
git clone https://github.com/v2fly/v2ray-core.git
cd v2ray-core
fi
DOWNLOAD="curl -s -L -x socks5://127.0.0.1:3080 -o "
GOMOD_VER=$(grep '^go\ ' go.mod | awk '{print $2}')
LAST_GO=$(ls -l /usr/bin/go | awk '{print $NF}')
if [ -z ${GOMOD_VER} ]; then
sudo apt-get install golang
else
sudo apt-get install golang-${GOMOD_VER} golang-${GOMOD_VER}-go
sudo ln -svf /usr/lib/go-${GOMOD_VER}/bin/go /usr/bin/go
fi

GOOS=linux
#GOARCH=amd64
VERSIONTAG=$(git describe --abbrev=0 --tags)
CODENAME="user"
LDFLAGS="-s -w -buildid= -X v2ray.codename=${CODENAME} -X v2ray.build=$(date '+%Y%m%d-%H%M%S') -X v2ray.version=${VERSIONTAG}"
GO111MODULE=on
TMP=$(mktemp -d)
GOPROXY=https://goproxy.cn
go mod download
env CGO_ENABLED=0 GOARCH=arm GOARM=6 go build -o "$TMP"/v2ray"${EXESUFFIX}" -ldflags "$LDFLAGS" ./main
${DOWNLOAD} "$TMP"/geoip.dat "https://github.com/v2fly/geoip/raw/release/geoip.dat"

echo ">>> Download latest geosite..."
${DOWNLOAD} "$TMP"/geosite.dat "https://github.com/v2fly/domain-list-community/raw/release/dlc.dat"
rm -rf build
mv ${TMP} build
sudo ln -svf ${LAST_GO} /usr/bin/go

基于Docker的多架构交叉编译


谢谢支持