ffmpeg 多媒体
2024-11-28
# 提取音频
ffmpeg -i 夏洛的网_中文.mp4 -q:a 0 -map a 夏洛的网_中文.mp3
# 合并音频
ffmpeg -i 夏洛的网_英语.mp4 -i 夏洛的网_中文.mp3 -map 0:v -map 1:a -map 0:a -c:v copy -c:a copy 夏洛的网.mp4
# 给不同音轨取个名字
ffmpeg -i 夏洛的网2.mp4 -map 0 -c copy -metadata:s:a:0 title="中文" -metadata:s:a:1 title="English" 夏洛的网3.mp4
# 添加字幕(总是报错,没有成功)
ffmpeg -i 夏洛的网3.mp4 -i 夏洛的网_中文.srt -i 夏洛的网_英文.srt -map 0 -map 1 -map 2 -c:v copy -c:a copy -c:s srt \
-metadata:s:s:0 language=chi -metadata:s:s:0 title="中文" \
-metadata:s:s:1 language=eng -metadata:s:s:1 title="English" \
夏洛的网4.mp4
虽然字幕没有成功,但是播放器会自动加载,也还好。
PS:字幕其实也是播放器自动在线匹配,然后我选择保存在本地的。
Mac 开发者
2024-09-29
Linux
2024-09-17
我看了阮一峰推荐的内容中有篇文章讲什么是“企业 Linux”(后面会附原文和中文翻译)。
RHEL 名字叫红帽企业 Linux,SLE 也是 SUSE Linux Enterprise 的缩写,我也一直好奇,这个“企业”到底是什么意思?
MacOS
2024-09-16
-> % tree -dL2 /
/
├── Applications
│ ├── Another Redis Desktop Manager.app
│ ├── Apifox.app
│ ├── Beyond Compare.app
│ ├── CopyQ.app
│ ├── DBeaver.app
│ ├── DingTalk.app
│ ├── GitButler.app
│ ├── Install macOS Monterey.app
│ ├── Microsoft Edge.app
│ ├── Nutstore.app
│ ├── OpenVPN Connect
│ ├── OpenVPN Connect.app -> /Applications/OpenVPN Connect/OpenVPN Connect.app
│ ├── Safari.app -> ../System/Cryptexes/App/System/Applications/Safari.app
│ ├── Utilities
│ ├── WeChat.app
│ ├── Wireshark.app
│ ├── iTerm.app
│ ├── wpsoffice.app
│ ├── 优酷.app
│ └── 企业微信.app
├── Library
│ ├── Apple
│ ├── Application Support
│ ├── Audio
│ ├── Bluetooth
│ ├── Bundles
│ ├── Caches
│ ├── Catacomb
│ ├── ColorPickers
│ ├── ColorSync
│ ├── Components
│ ├── Compositions
│ ├── Contextual Menu Items
│ ├── CoreAnalytics
│ ├── CoreMediaIO
│ ├── Developer
│ ├── DirectoryServices
│ ├── Documentation
│ ├── DriverExtensions
│ ├── Extensions
│ ├── Filesystems
│ ├── Fonts
│ ├── Frameworks
│ ├── GPUBundles
│ ├── Google
│ ├── Graphics
│ ├── Image Capture
│ ├── Input Methods
│ ├── InstallerSandboxes
│ ├── Internet Plug-Ins
│ ├── Java
│ ├── KernelCollections
│ ├── Keyboard Layouts
│ ├── Keychains
│ ├── LaunchAgents
│ ├── LaunchDaemons
│ ├── Logs
│ ├── Modem Scripts
│ ├── OSAnalytics
│ ├── OpenDirectory
│ ├── Perl
│ ├── PreferencePanes
│ ├── Preferences
│ ├── Printers
│ ├── PrivilegedHelperTools
│ ├── QuickLook
│ ├── Receipts
│ ├── Ruby
│ ├── Sandbox
│ ├── Screen Savers
│ ├── ScriptingAdditions
│ ├── Scripts
│ ├── Security
│ ├── Speech
│ ├── Spotlight
│ ├── StagedDriverExtensions
│ ├── StagedExtensions
│ ├── StartupItems
│ ├── SystemExtensions
│ ├── SystemMigration
│ ├── SystemProfiler
│ ├── Trial
│ ├── Updates
│ ├── User Pictures
│ ├── User Template
│ ├── Video
│ └── WebServer
├── System
│ ├── Applications
│ ├── Cryptexes
│ ├── Developer
│ ├── DriverKit
│ ├── Library
│ ├── Volumes
│ └── iOSSupport
├── Users
│ ├── Guest
│ ├── Shared
│ └── adm
├── Volumes
│ └── 未命名 -> /
├── bin
├── cores
├── dev
│ └── fd
├── etc -> private/etc
├── home -> /System/Volumes/Data/home
├── opt
├── private
│ ├── etc
│ ├── tmp
│ └── var
├── sbin
├── tmp -> private/tmp
├── usr
│ ├── bin
│ ├── lib
│ ├── libexec
│ ├── local
│ ├── sbin
│ ├── share
│ └── standalone
└── var -> private/var
128 directories
Linux 目录结构
/home -> /System/Volumes/Data/home
/usr
/bin
/sbin
/etc -> private/etc
/var -> private/var
/opt
/tmp -> private/tmp
/dev
应用目录
/Applications/
/System/Applications/
/System/Volumes/Data/Applications/
-> % find / -maxdepth 5 -type d -name "*.app" > /tmp/a
-> % awk -F '/' '{path="";for(i=1;i<NF;i++){path=path $i "/"};c[path]++}END{for(i in c){printf "%5d %s\n",c[i],i}}' /tmp/a | sort -nr
107 /System/Library/CoreServices/
39 /System/Applications/
19 /System/Applications/Utilities/
18 /System/Library/Input Methods/
18 /Applications/
5 /Users/adm/Downloads/
4 /Library/Image Capture/Devices/
2 /System/Library/Services/
2 /Library/Input Methods/
2 /Applications/OpenVPN Connect/
1 /usr/libexec/
1 /System/Library/Classroom/
1 /Applications/Nutstore.app/Contents/
-> % type code
code is /usr/local/bin/code
-> % ll /usr/local/bin/code
lrwxr-xr-x@ 1 adm admin 167B 9 20 21:40 /usr/local/bin/code -> /private/var/folders/lh/vyr5k29j1cgbmd4b_lhpxq340000gn/T/AppTranslocation/F14FB3FE-0B4C-4F60-81FA-7AD83514E78D/d/Visual Studio Code.app/Contents/Resources/app/bin/code
-> % echo $TMPDIR
/var/folders/lh/vyr5k29j1cgbmd4b_lhpxq340000gn/T/
武汉
2024-09-15
景点 |
城市 |
区 |
位置 |
电影院 |
武汉 |
- |
光谷里 武昌泛悦奥特莱斯 江夏罗马春天 汉口北 |
黄鹤楼公园 |
武汉 |
武昌区 |
司门口 |
黄鹤楼落梅轩 |
武汉 |
武昌区 |
司门口 |
杜莎夫人蜡像馆 |
武汉 |
武昌区 |
楚河汉街 |
东湖落雁景区 |
武汉 |
东湖 |
- |
东湖飞鸟世界 |
武汉 |
东湖 |
- |
东湖游船 |
武汉 |
东湖 |
- |
龙泉山 |
武汉 |
江夏区 |
- |
武汉植物园 |
武汉 |
武昌区 |
鲁磨路 |
长春观 |
武汉 |
武昌区 |
大东门 |
九峰山森林公园 |
武汉 |
洪山区 |
- |
禧汤生活馆 |
武汉 |
洪山区 |
珞珈山 |
武汉园博园(武汉自然博物馆) |
武汉 |
硚口区 |
- |
张公山寨 |
武汉 |
青山区 |
- |
木兰天池 |
武汉 |
黄陂区 |
- |
木兰草原 |
武汉 |
黄陂区 |
- |
木兰云雾山 |
武汉 |
黄陂区 |
- |
木兰山 |
武汉 |
黄陂区 |
- |
花海乐园 |
武汉 |
黄陂区 |
- |
大余湾 |
武汉 |
黄陂区 |
- |
锦里沟 |
武汉 |
黄陂区 |
- |
清凉寨 |
武汉 |
黄陂区 |
- |
姚家山 |
武汉 |
黄陂区 |
- |
九真山 |
武汉 |
蔡甸区 |
- |
九真桃源 |
武汉 |
蔡甸区 |
- |
金龙水寨 |
武汉 |
蔡甸区 |
- |
紫微都市田园 |
武汉 |
新洲区 |
- |
凤娃古寨 |
武汉 |
新洲区 |
- |
花朝河湾 |
武汉 |
新洲区 |
- |
香草伊甸园 |
武汉 |
新洲区 |
- |
-------------------- |
- |
- |
- |
熙凤水乡 |
孝感 |
- |
- |
楚珍园 |
孝感 |
应城 |
- |
金卉庄园 |
孝感 |
孝南区 |
- |
天紫湖 |
孝感 |
孝南区 |
- |
盛世闻樱景区 |
孝感 |
安陆 |
- |
白兆山风景区 |
孝感 |
安陆 |
- |
-------------------- |
- |
- |
- |
三里畈温泉 |
黄冈 |
罗田县 |
- |
罗田薄刀峰 |
黄冈 |
罗田县 |
- |
黄石河峡谷隧道漂流 |
黄冈 |
罗田县 |
- |
帝王湖 |
黄冈 |
红安县 |
|
-------------------- |
- |
- |
- |
瑶池温泉 |
咸宁 |
咸安区 |
- |
山湖温泉 |
咸宁 |
嘉鱼县 |
- |
Golang
2024-09-09
基础示例
package main
import (
"fmt"
"os"
"strings"
"text/template"
"time"
)
const TEMPLTE = `{{ .Subject }}
Time: {{ .Time.Format "2006-01-02 15:04:05" }}
Source: {{ .Source }}
{{ .Body }}`
func main() {
tmpl01, _ := template.New("tmpl01").Parse("你好,{{ . }}")
tmpl01.Execute(os.Stdout, "世界")
fmt.Println()
fmt.Println(strings.Repeat("=", 80))
fmt.Println()
type Message struct {
Subject string
Time time.Time
Source string
Body string
}
// http://www.xinhuanet.com/politics/2020-02/08/c_1125546135.htm
subject := "国家监察委员会调查组已抵达武汉"
timeobj, _ := time.Parse("2006-01-02 15:04:05", "2020-02-08 13:49:38")
source := "新华社“新华视点”微博"
content := "中央纪委国家监委网站8日消息,国家监察委员会调查组已抵达武汉。经中央批准,国家监察委员会派出调查组赴湖北省武汉市,就群众反映的涉及李文亮医生的有关问题作全面调查。"
tmpl02, _ := template.New("tmpl02").Parse(TEMPLTE)
tmpl02.Execute(os.Stdout, Message{subject, timeobj, source, content})
}
语法说明
- 双花括号
{{ . }} // 输出当前变量
{{ .Name }} // 输出当前变量的 Name 字段
{{/* 注释 */}}
{{- /* 注释(去掉前后空格与换行) */ -}}
{{ if ... }} A {{ end }}
{{ if ... }} A {{ else }} B {{ end }}
{{ if ... }} A {{ else if ... }} B {{ else }} C {{ end }}
{{ range ... }} A {{ end }}
{{ range ... }} A {{ else }} B {{ end }}
{{ range . -}} {{ . }} {{ end -}}
{{ range $key, $val := . -}} ... {{ end -}}
Auth
2024-09-08
日志
2024-08-25
https://en.wikipedia.org/wiki/Extended_Log_Format
相比 Common Log Format (通用日志格式),ELF 是名副其实的可拓展:在头部声明了版本,以及字段。
例如:
#Version: 1.0
#Date: 12-Jan-1996 00:00:00
#Fields: time cs-method cs-uri
00:34:23 GET /foo/bar.html
12:21:16 GET /foo/bar.html
12:45:52 GET /foo/bar.html
12:57:34 GET /foo/bar.html
- Version:
<integer>.<integer>
The version of the extended log file format used. This draft defines version 1.0.
- Fields:
[<specifier>...]
Specifies the fields recorded in the log.
- Software: string
Identifies the software which generated the log.
- Start-Date:
<date> <time>
The date and time at which the log was started.
- End-Date:
<date> <time>
The date and time at which the log was finished.
- Date:
<date> <time>
The date and time at which the entry was added.
- Remark:
<text>
Comment information. Data recorded in this field should be ignored by analysis tools.
然后这个字段的声明又有一套规则,可以参考
开发者
2024-08-23
隐性知识是危险的
隐性知识又称为"部落知识",指的是有些知识没有文档,只掌握在团队成员的头脑里面。
如果你想掌握这些知识,只有去询问团队成员。
隐形知识的优点是,省去了文档成本,而且询问相关成员比自己阅读文档更快,当然前提是那位成员能够快速响应。
隐形知识的缺点是,一旦团队扩大规模,它就会失败。对于掌握知识的团队成员来说,回答问题所占用的时间是一个拖累,影响了生产力,也拖慢了团队的开发速度。
另一方面,随着团队规模的扩大和知识变得更加分散,你自己阅读文档和观看视频讲座,会比向他人寻求帮助更快速和方便。
所以,团队越是大,就越要避免"隐形知识",所有知识尽量文档化,让团队成员能够方便地查阅。
团队知识分享是一个很重要的事情。
- 周会分享
- 专题分享/讨论会
- 文档维护制度
日志
2024-08-12
- NCSA HTTPd (Apache HTTP Server 前身) 定义的一个标准 Web 服务器日志格式。
- 格式:
host ident authuser date request status bytes
例如:127.0.0.1 user-identifier frank [10/Oct/2000:13:55:36 -0700] "GET /apache_pb.gif HTTP/1.0" 200 2326
- 如果哪一个字段没有值,就用
-
代替。
import re
from datetime import datetime
RE_CLF = re.compile(r'(\S+) (\S+) (\S+) \[(.*?)\] "(.*?)" (\d{3}) (\d+|-)')
def parse_clf(log_line):
match = RE_CLF.match(log_line)
if not match:
raise ValueError('Log line does not match CLF format')
ip_address = match.group(1)
identity = match.group(2)
user = match.group(3)
time_str = match.group(4)
request_line = match.group(5)
status_code = int(match.group(6))
size = match.group(7)
time_format = '%d/%b/%Y:%H:%M:%S %z'
timestamp = datetime.strptime(time_str, time_format)
size = int(size) if size != '-' else None
return {
'host': ip_address,
'ident': identity,
'authuser': user,
'date': timestamp,
'request': request_line,
'status': status_code,
'bytes': size,
}
log_example = '127.0.0.1 user-identifier frank [10/Oct/2000:13:55:36 -0700] 'GET /apache_pb.gif HTTP/1.0' 200 2326'
parsed_log = parse_clf(log_example)
print(parsed_log)
# {'host': '127.0.0.1', 'ident': 'user-identifier', 'authuser': 'frank',
# 'date': datetime.datetime(2000, 10, 10, 13, 55, 36, tzinfo=datetime.timezone(datetime.timedelta(days=-1, seconds=61200))),
# 'request': 'GET /apache_pb.gif HTTP/1.0', 'status': 200, 'bytes': 2326}