• Xcode Cloud Notes

    Xcode Cloud 是什么?

    Xcode Cloud 是一个搭建在苹果的开发工具链之上的 CI/CD 系统,和苹果的 Xcode、TestFlight 以及 App Store Connect 整个开发工具和生态进行打通。Xcode Cloud 使用 Git 作为项目的代码管理工具,通过 CI/CD,帮助开发者打造更高质量、更稳定的 app。从 Xcode 13 版本开始支持,目前在 beta 阶段,免费限量内测申请,2022 年对所有人开放,具体价格待公布。

    Xcode Cloud 能做什么?

    1. 自动构建和运行测试
    2. 自动在模拟器里运行测试程序
    3. 接收 Xcode Cloud 返回的构建结果通知,提前发现问题
    4. 通过 TestFlight 分发新版本给测试用户
    5. 创建供苹果审核的新版本
    6. 使用 Xcode 和苹果的云基础设施协同开发
  • Karabiner-Elements 之 介绍和使用(part 1)

    什么是 Karabiner-Elements ?

    Karabiner-Elements (下面我们简称为 Karabiner)官网对自己的描述是 “A powerful and stable keyboard customizer for macOS.”,我使用下来的感受是 Karabiner-Elements 是 macOS 平台上一款非常强大的键位映射工具,没有吹嘘的成分,买家秀和卖家秀是一样的。

    这个介绍我会分为两个部分:

    • part1 介绍 Karabiner 的核心功能,以及我自己使用 Karabiner 帮助我高效使用键盘的一个思路,不涉及具体的配置
    • part2 根据实例详细介绍使用 Karabiner 高级映射的配置和高级用法,满足一些高级自定义的需求

    下面我尽量使用通俗易懂的语言来表达,简单来划分 Karabiner 核心功能的话,Karabiner 可以分为 简单修改Simple modifications) 和 复杂修改Complex modifications),我更倾向于称之为 简单映射高级映射

  • FFmpeg avformat_find_stream_info () 函数源码解析

    avformat_find_stream_info() 函数的作用

    先来看一下 avformat_find_stream_info() 的头文件里的注释对该函数的介绍,本文我们基于 FFmpeg n4.2 版本的源码分析。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    /**
    * Read packets of a media file to get stream information. This
    * is useful for file formats with no headers such as MPEG. This
    * function also computes the real framerate in case of MPEG-2 repeat
    * frame mode.
    * The logical file position is not changed by this function;
    * examined packets may be buffered for later processing.
    * ...
    */
    int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options);

    注释里说这个方法通过读取媒体文件中若干个 packet 来获取流信息,对于 MPEG 这种没有 header 的文件格式比较有用,也可以计算像 MPEG-2 这种支持 repeat mode 的真实帧率。(MPEG-2 支持对于大量静止的画面设置 repeat mode,重复的帧不用编码和存储,可以减少体积)

  • Powerline fonts & Nerd fonts 简介

    作为程序员,和命令行打交道很频繁,设置一个赏心悦目的命行行 prompt 或者 Vim 的 status line 主题就很有必要了,不过一般这些漂亮的主题都会用到一些 icon 字符,这些 icon 字符一般的字体里是没有的,今天我们就来聊聊一些带有 icon 字符的字体。

    为了有个直观的认识,我们来看一下设置命令行 prompt 特殊主题前后的对比:
    prompt_theme

  • Linux / Unix 文件的 atime ctime mtime 属性

    一、什么是 atime、ctime、mtime?

    Linux / Unix 系统会为每个文件保存一些时间戳信息,我们可以根据这些时间戳来判断文件什么时候被读取过,什么时候被修改过内容,以及什么时候被修改过文件的权限。以下是 atime,ctime,mtime 三个时间戳的介绍。

    1. atime (last Access time)

      最近一次访问文件的时间,访问指的是 读取或者执行文件 / 文件夹的时间

    2. ctime (last Change time)

      最近一次 metadata 修改的时间,这里修改有两层意思:

      1. 修改文件 / 文件夹的 metadata,比如 user / group 或者访问权限(比如 chmod)
      2. 修改文件内容
    3. mtime (last Modify time)

      最近一次修改的时间,这里的修改 专指文件的内容修改

    注意:

    1. 当创建文件时候,atime、ctime、mtime 都会修改为当前创建的时间
    2. 当修改文件内容的时候,ctime、mtime 都会更新为修改时间
  • iOS CoreAudio AudioStreamBasicDescription 音频格式概念简介

    AudioStreamBasicDescription 简称 ASBDASBD 是 CoreAudio 用来指定线性 PCM 格式,或者使用 CBR 编码的等大小声道的格式。如果使用的是 VBR,或者使用非等大小的 CBR,需要对每个 packet 独立设置 AudioStreamPacketDescription进行描述。

    在分析 ASBD 每个字段之前,我们先来搞懂几个概念:

    • Audio Stream: 一个 audio stream 表示一个声音的连续数据,比如一首歌
    • Channel:声道,一个声道是一个独立的音轨,单声道音频流只有一个 channel,立体声音频流有两个 channel
    • Sample:采样,一个采样对应一个 channel 里的一个具体的数字
    • Frame:一个 frame 包含一组相同时间的samples集合,比如一个线性立体声 PCM 文件每个 frame 包含两个 samples(左声道 sample 和 右声道 sample)
    • Packet: 一个 packet包含一个或者多个连续的frame,在给定的音频数据格式的情况下,一个 packet 定义了一个最小有意义的 frame 集合,也是最小可测量时间的数据单位。 对于线性PCM音频这类非压缩格式,一个packet只包含一个frame
      对于压缩格式,一个 packet 通常会包含多个 frame,比如 AAC 可能会包含 1024 个 frame。
      对于某些格式,比如 Ogg,一个 packet 对应的 frame 数量可能是变化的,该字段填充 0。
  • 结合 AppRTC 源码分析 WebRTC 建立连接的过程

    这两年来,WebRTC 越来越多地出现在人们的视野,在在线教育,在线医疗等领域的应用也越来越多。大家研究 WebRTC 的热情也越来越高涨,不过 WebRTC 的入门门槛个人觉得稍微有些高,特别是各种概念,比如 NAT 穿越,ICE,STUN,TURN,Signaling server 等等,刚开始可能会觉得比较繁杂,不易理解。然后建立连接的整个过程,异步调用比较多,很容易搞混。那么这篇文章里我们会根据 WebRTC 的官方 demo AppRTC 的 iOS 版本来分析一下 WebRTC 从进入房间到建立音视频连接的过程,为了便于了解,我们本次的讨论不涉及到底层的具体实现。

    1. 相关概念

    我们首先来简单地了解几个概念:

    1.1 NAT 穿越(NAT Traversal)

    因为 WebRTC 是 P2P 的,很多时候 peer 是隐藏在 NAT 之后的,没有外网的 IP 地址,如果两个 peer 都在 NAT 后面,都没有外网的 IP (或者说都不知道自己的外网 IP),是无法建立连接的。那么 NAT 穿越就是用来解决这个问题的,NAT 穿越也俗称 “P2P 打洞”。常见的两种穿越方式是 STUN 和 TURN。

  • 安装和配置 WebRTC 的 STUN / TURN 服务 coturn

    TURN server 可以解决点对点通信里的 NAT 穿透,并提供中继(relay) 的服务。coturn 是一个开源的 TURN 和 STUN 服务器,是基于 rfc5766-turn-server 进化过来的,目前比较成熟。之所以安装 coturn 是借助它提供的 TURN 服务,解决 WebRTC P2P 通信中 STUN 服务器解决不了的复杂内网的问题。比如我尝试过移动 4G 和 联通 WIFI 有时候无法通过 STUN 服务穿越内网连接,通过 TURN 服务的中继就可以解决这个问题。下面我们就来介绍一下 coturn 的安装,配置以及测试的过程。

    Install coturn

    coturn 安装可以参考官方的安装文档,按该文档安装即可。如果是 Ubuntu 系列,可以直接通过 apt 安装,安装完成后会放在 /usr/bin/turnserver

    1
    apt install coturn

    网络配置

    以阿里云服务器为例,配置网络安全组/防火墙,开放 3478 的 UDP/TCP 端口,这个我们我们会作为 TURN/STUN 服务器的监听端口,并开放 40000~60000 的 UDP 端口,STUN 和 TURN 可能会使用随机的 UDP 端口。

  • WWDC 2016 - Session 401 - What's New in Xcode App Signing 笔记

    这篇 blog 来自我们内部的分享,内容比较精简,需要更多的细节信息,请参考 WWDC 2016 - 401 的视频

    相信每一个开发者在初学 iOS 的时候,都有过被 Code Signing 坑过的经历,特别是当旁边没有人指导的时候,这也是当时我个人学习 iOS 的时候最困扰的地方,证书,provisioning profile, code signing 等等这些和实际的开发无关的概念,现在还记得苦苦看文档的经历。

    Image1 icon
    iOS 证书申请和签名打包流程图,图来自这里

  • 揭开 Monad 的神秘面纱

    我们知道 Swift 语言支持函数式编程范式,所以函数式编程的一些概念近来比较火。有一些相对于 OOP 来说不太一样的概念,比如 Applicative, Functor 以及今天的主题 Monad. 如果单纯的从字面上来看,很神秘,完全不知道其含义。中文翻译叫做单子,但是翻译过来之后对于这个词的理解并没有起到任何帮助。

    我的理解很简单,Functor是实现了map函数的容器,Monad 就是实现了 flatMap 方法的容器,比如在 Swift 里,Optional, CollectionType 等等都可以称为 Monad。

    既然有了 map, flatMap 又有什么作用呢?两者有什么联系和区别呢?

    map vs flatMap

    map 和 flatMap 的共同点都是接受一个 transform 函数,把一个容器转换为另外一个容器。

    下面主要从维度这一块来解释两者的区别,我们先来简单的定义一下维度

    对于类型 T,如果类型 S 是一个容器,且元素的类型包含 T,那我们就说:
    S (维度) = T (维度) + 1

    举个🌰, [Int] (维度) = Int (维度) +1, Int? (维度) = Int (维度) + 1.