newspaint

Documenting Problems That Were Difficult To Find The Answer To

Monthly Archives: Jun 2018

Copy Metadata From Input to Output in FFmpeg

The documentation for the -map_metadata option for FFmpeg reads:

-map_metadata[:metadata_spec_out] infile[:metadata_spec_in] (output,per-metadata)

Set metadata information of the next output file from infile. Note that those are file indices (zero-based), not filenames. Optional metadata_spec_in/out parameters specify, which metadata to copy. A metadata specifier can have the following forms:

  • g – global metadata, i.e. metadata that applies to the whole file
  • s[:stream_spec] – per-stream metadata. stream_spec is a stream specifier as described in the Stream specifiers chapter. In an input metadata specifier, the first matching stream is copied from. In an output metadata specifier, all matching streams are copied to.
  • c:chapter_index – per-chapter metadata. chapter_index is the zero-based chapter index.
  • p:program_index – per-program metadata. program_index is the zero-based program index.
  • If metadata specifier is omitted, it defaults to global.

    By default, global metadata is copied from the first input file, per-stream and per-chapter metadata is copied along with streams/chapters. These default mappings are disabled by creating any mapping of the relevant type. A negative file index can be used to create a dummy mapping that just disables automatic copying.

    For example to copy metadata from the first stream of the input file to global metadata of the output file:

    ffmpeg -i in.ogg -map_metadata 0:s:0 out.mp3
    

    To do the reverse, i.e. copy global metadata to all audio streams:

    ffmpeg -i in.mkv -map_metadata:s:a 0:g out.mkv
    

    Note that simple 0 would work as well in this example, since global metadata is assumed by default.

So let’s say we had three input streams, 0:0 (video), 0:1 (audio), and 0:2 (subtitle) and we wanted to copy the metadata for all three streams and the global metadata. We could use:

ffmpeg -i input.mov -map 0:0 -map 0:1 -map 0:2
  -map_metadata:g 0:g # take file 0's global metadata and copy to this' global
  -map_metadata:s:0 0:s:0 # take file 0's stream 0 metadata and copy to this' stream 0
  -map_metadata:s:1 0:s:1 # take file 0's stream 1 metadata and copy to this' stream 1
  -map_metadata:s:2 0:s:2 # take file 0's stream 2 metadata and copy to this' stream 2

Subtitle Codec 94213 is Not Supported in FFmpeg

I was attempting to convert a video file from an Ambarella A7L dashcam to the Matroska (mkv) file format but encountered the following error:

...
    Stream #0:2(eng): Subtitle: mov_text (text / 0x74786574), 0 kb/s (default)
    Metadata:
      creation_time   : 2018-06-01 13:05:26
      handler_name    : Ambarella EXT
...
[matroska @ 0x4754d40] Subtitle codec 94213 is not supported.

In order to retain such subtitle codec (using -c:s copy option) better to use the mp4 file format which will allow this subtitle format.

Or, to retain the subtitle information in the Matroska container, it can be converted to the subrip format using the -c:s srt option.

Setting Up OpenVPN Server for Rooted LineageOS Phone

Installation Steps

Install OpenVPN Server

me@server:~$ sudo apt-get install openvpn
The following NEW packages will be installed:
  liblzo2-2 libpkcs11-helper1 openvpn
0 upgraded, 3 newly installed, 0 to remove and 0 not upgraded.
Need to get 513 kB of archives.
After this operation, 1,353 kB of additional disk space will be used.
me@server:~$ sudo apt-get install openssl
The following NEW packages will be installed:
  openssl
0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded.
Need to get 492 kB of archives.
After this operation, 956 kB of additional disk space will be used.

Choose a routed VPN (rather than a bridged). Use username/password authentication (still requires server certificate authority (CA) and server certificate.

Edit /etc/default/openvpn and add:

# Ensure tunnel device is available
if [ ! -d /dev/net ]; then
  mkdir /dev/net
fi

if [ -d /dev/net ]; then
  if [ ! -e /dev/net/tun ]; then
    mknod /dev/net/tun c 10 200
    chmod 666 /dev/net/tun
  fi
fi

Create a tunnel device:

me@server:~# openvpn --mktun --dev tun0

Create Certificate Authority

me@server:~# mkdir /etc/openvpn/ssl
me@server:~# cd /etc/openvpn/ssl
me@server:/etc/openvpn/ssl# openssl genrsa -out ca.key 2048
Generating RSA private key, 2048 bit long modulus
............+++
................................................................................................+++
e is 65537 (0x10001)
me@server:/etc/openvpn/ssl# openssl req -new -x509 -key ca.key -out ca.crt

Now we have ca.crt (the certificate authority certificate) and ca.key (the key for the certificate authority).

You can get the text form of the certificate (used later for the client configuration) by issuing the command:

me@server:/etc/openvpn/ssl# openssl x509 -in ca.crt -text

… and extracting the portion between (and including) the BEGIN CERTIFICATE and END CERTIFICATE lines.

Create Server Certificate and Sign Using Certificate Authority

me@server:/etc/openvpn/ssl# openssl genrsa -out signing.key 2048
Generating RSA private key, 2048 bit long modulus
.....+++
............................................................+++
e is 65537 (0x10001)
me@server:/etc/openvpn/ssl# openssl rsa -in signing.key -pubout -out signing.pub
writing RSA key
me@server:/etc/openvpn/ssl# openssl req -new -key signing.key -out request.csr

me@server:/etc/openvpn/ssl# openssl x509 -req -days 1500 -in request.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt
Signature ok
Getting CA Private Key
me@server:/etc/openvpn/ssl# openssl x509 -in server.crt -noout -text

Now we have server.crt (the server certificate).

Create Difie-Hellman Key

me@server:/etc/openvpn/ssl# openssl dhparam -out dh1024.pem 1024

Create Static Shared Key

me@server:/etc/openvpn/ssl# openvpn --genkey --secret static.key

Create auth.pl

(taken from the example at /usr/share/doc/openvpn/examples/sample-scripts/auth-pam.pl)

#!/usr/bin/perl -w

use strict;

# Allowed username/password combinations
my %users = (
    'jim' => 'letmein',
    'mary' => 'password123',
);

# Get username/password from file

my $ARG;
if ($ARG = shift @ARGV) {
    if (!open (UPFILE, "<$ARG")) {
        print "Could not open username/password file: $ARG\n";
        exit 1;
    }
} else {
    print "No username/password file specified on command line\n";
    exit 1;
}

my $username = <UPFILE>;
my $password = <UPFILE>;

if (!$username || !$password) {
    print "Username/password not found in file: $ARG\n";
    exit 1;
}

chomp $username;
chomp $password;

close (UPFILE);

if ( $users{$username} && ( $password eq $users{$username} ) ) {
    exit 0;
} else {
    print "Auth '$username' failed.\n";
    exit 1;
}

Create server.conf

tls-server
port 1194
proto udp
dev tun
mssfix 576
cipher AES-256-CBC

ca /etc/openvpn/ssl/ca.crt
cert /etc/openvpn/ssl/server.crt
key /etc/openvpn/ssl/signing.key
dh /etc/openvpn/ssl/dh1024.pem

tls-auth /etc/openvpn/ssl/static.key 0

script-security 2 # necessary for auth-user-pass-verify
auth-user-pass-verify /etc/openvpn/auth.pl via-file
client-cert-not-required
username-as-common-name

server 10.44.12.0 255.255.255.0 # subnet for clients
keepalive 10 120
comp-lzo
persist-key
persist-tun
status /var/log/openvpn-status.log
log /var/log/openvpn.log
verb 3

push "redirect-gateway def1"
push "dhcp-option DNS 1.1.1.1" # cloudflare DNS

Enabling/Starting/Stopping OpenVPN

me@server:~# systemctl enable openvpn@server.service
me@server:~# systemctl start openvpn@server.service
me@server:~# systemctl stop openvpn@server.service

Create .ovpn Configuration File for OpenVPN Android Client

tls-client
remote 192.0.2.44 # the IP address of my OpenVPN server
port 1194
proto udp
comp-lzo
auth-user-pass
key-direction 1
mssfix 576
cipher AES-256-CBC

<ca>
-----BEGIN CERTIFICATE-----
...
...
...
-----END CERTIFICATE-----
</ca>

<tls-auth>
-----BEGIN OpenVPN Static key V1-----
...
...
...
-----END OpenVPN Static key V1-----
</tls-auth>

On The Phone

Install “OpenVPN Connect – Fast & Safe SSL VPN Client” by “OpenVPN”.

Then add .ovpn file created above.

Install iptables Scripts

me@server:~# apt-get install iptables-persistent
The following NEW packages will be installed:
  iptables iptables-persistent libnfnetlink0 netfilter-persistent
0 upgraded, 4 newly installed, 0 to remove and 0 not upgraded.
Need to get 292 kB of archives.
After this operation, 1,804 kB of additional disk space will be used.

Edit /etc/iptables/rules.v4:

###############################################################################
# iptables IPv4 rules for reload on start-up
#
# To Reload:
#   service netfilter-persistent restart
#
# To Test:
#   iptables-restore -t </etc/iptables/rules.v4
###############################################################################

*mangle
:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
COMMIT

*nat
:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]

-A POSTROUTING -s 10.44.12.0/24 -o eth0 -j MASQUERADE

COMMIT

*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
COMMIT

Issues

external program fork failed

If you see something like the following:

Wed Jun 20 03:33:31 2018 192.0.2.41:39523 WARNING: External program may not be called unless '--script-security 2' or higher is enabled. See --help text or man page for detailed info.
Wed Jun 20 03:33:31 2018 192.0.2.41:39523 WARNING: Failed running command (--auth-user-pass-verify): external program fork failed

… then you probably have a “script-security 1” parameter somewhere in your configuration (after any other script-security 2 directives). Grep for it and comment it out so that your “script-security 2” directive can take effect.

See Also

Changing Encrypted Partition Password on LineageOS 14.1

This was done on a ZTE Axon 7 running Android 7.1.2 (LineageOS 14.1).

I booted into the LineageOS 14.1 operating system, connected using ADB.

WARNING: the encryption password can only be changed in LineageOS itself, not TWRP, so if you get this wrong you will have an irrecoverable encrypted data partition. To protect yourself ensure you verify the new password before rebooting.

NOTE: this does not change the screen lock code, it only changes the password for decrypting the phone on boot (the first password you’re required to enter after a cold boot).

~$ adb root
~$ adb shell
axon7:/ # vdc cryptfs verifypw 1234 # wrong password
200 8421 -1
axon7:/ # vdc cryptfs verifypw 1111 # wrong password
200 8543 -1
axon7:/ # vdc cryptfs verifypw 4444 # correct password
200 8558 0
axon7:/ # vdc cryptfs changepw help
Usage: cryptfs changepw default|password|pin|pattern [[currentpasswd] newpasswd]

axon7:/ # vdc cryptfs changepw pin 4444 912541324 # change password
200 8703 0

axon7:/ # vdc cryptfs verifypw 4444 # no longer correct password
200 8761 -1
axon7:/ # vdc cryptfs verifypw 912541324 # new correct password
200 8770 0

Thanks to the information in this forum post for assistance in how to do this.