頭と尻尾はくれてやる!

パソコンおやじのiPhoneアプリ・サイト作成・運営日記


最初のstoryboardを後から追加する

古いコードをメンテしているんだけど、iPhone X対応もあるのでstoryboard / Auto Layoutを導入しようとしたらえらくハマったのでそのあたりをメモ。

当然古いコードはstoryboardを使っていない。アプリ起動時に一番最初に表示されるviewを扱うview controllerをstoryboardで指定したい。

(1) プロジェクトにview controllerクラスファイルとstoryboardのファイルを追加する。ここではMainViewControllerクラス、Main.storyboardとした。

追加したファイル

え?Objective-Cですよ、当然(いや、そんな姿勢だから今苦しんでるんだろう!)。

(2) main.m、AppDelegateを書き換える
適当なとこからコピペするだけでOK。

(3) storyboardファイルの変更
Main.storyboardはデフォルトだとView Controllerがないので画面に追加する。

view controllerを追加

↑画面右下のここからドラッグで。

クラス指定

↑このstoryboardがどのクラスファイルと紐づいてるかを指定するのでここでMainViewControllerを指定。選択すればスペルミスしない。

Is Initial View Controllerにチェック

↑さらにこのview controllerが最初だ、ってことで Is Initial View Controller にチェックを入れる。

矢印が表示されているところ

↑すると viewの左側に矢印が表示される。

(4) info.plist
プロパティリストに最初のstoryboardのファイルを指定するところがあるので記述する。

プロパティリスト

↑Main storyboard file base nameってのを選んで Main と入力。

確かこれでオッケーのはず!!と思ってビルドするも全然動かない。MainViewControllerクラスまで処理が来てない、、、?
ここでハマったんだけど、結局のところ、、、

(5) Deployment Infoで指定する
TargetのとこでGeneral / Deployment Info ってとこにある Main Interface ってところにもMainって指定する必要がある、というかこちらを書けば(4)には書かなくてよかった。チックショー。

Deployment Infoで指定

↑ここね。
とりあえずこれで無事storyboardが動くようになった。



memo
Xcode 9.0



iMovieで縦長動画を作成したい

「赤ちゃんの成長グラフ」というiOSアプリのアップデートで、子供の身長をARKitを使って計測するって機能を追加する予定。



↑そのためアプリ内のヘルプから見られる動画を作ってみた。文字で説明するより動画の方がわかりやすいかなってことで。iPhoneから見ることを想定してるので縦長だ。
埋め込んでもMacのブラウザで見ても上のように左右に黒い部分ができちゃうが、iPhoneで見ると自動的に(スタートボタンのみで)iPhoneのディスプレイにきっちりしたサイズで再生された。


今回初めて縦長動画をiMovieで編集したのでそのあたりの手順をメモ。

(1) iPhone 7 Plus実機で動画を撮影
動画サイズは1080x1920。

オリジナル動画

↑iOS 11の画面録画機能を使っているので録画時にステータスバーが赤くなる。

(2) 動画を回転
編集ソフトのiMovieは縦長動画を出力できない(はず)のでまずはffmpegで90度回転させる。
ffmpeg -i input.mp4 -vf transpose=2 output.mp4
transpose=2は反時計回り。

(3) ステータスバー部分を削除
なんでステータスバーが赤いの?ってユーザーが思うかもしれないのでその部分をffmpegでカットすることに。
ffmpeg -i input.mp4 -vf crop=1868:1080:52:0 output.mp4
↑ざっと測るとステータスバーの高さが52pxくらいだったのでこの値でやってる。

(4) iMovieで編集
上の動画、タイトル画像やキャプションの画像などをiMovieで読み込み編集。

編集中動画

↑90度回転させているのでキャプションなども90度回転させた画像を準備してる。
編集完了後に動画を出力。1280x720の横長動画ができる。

(5) 動画を回転
時計回りに90度回転させて縦長にする。
ffmpeg -i input.mp4 -vf transpose=1 output.mp4
これで720x1280の縦長動画になる。

(6) YouTubeにアップロード
普通にアップロードする。縦長だからといって特にどうこうしなかった。

なお、iOSアプリではUIWebViewを使って動画を表示してる。
{
    UIWebView *webView = [[UIWebView alloc] initWithFrame:CGRectMake(0, 100, w, h)];
    [self.view addSubview:webView];
    
    NSURL* url = [NSURL URLWithString:@"https://www.youtube.com/embed/uyRx7XrNHxQ"];
    NSURLRequest* request = [NSURLRequest requestWithURL:url];
    [webView loadRequest:request];
}
*version
iOS 11 beta 10
iMovie 10.1.6
ffmpeg 3.2.2



AVSpeechSynthesizerの声を録音したい

AVSpeechSynthesizerあたりを使ってiPhoneに喋らせたりできるわけだけど、それを録音して音声ファイルを作成、それを動画で使おうとしたんだわ。

AVSpeechSynthesizerとAVAudioRecorder・AVAudioPlayerを一緒に使おうとしたら躓いた - たくあんおいしいのブログ
↑このあたりを参考に。
出力は音声ファイルとして得るようにして、それをiMovieなどの動画編集ファイルで使うつもりで。
確かに音声ファイルを得ることができたんだけど、、、これ、iPhoneのマイクで拾った音を録音するので当然周りの音も拾うしとても使えたもんじゃないんだわ。え?やる前に気付けよ?おっしゃる通りでございます。

それじゃあ面倒だけど、、、iOS 11だと画面を録画できるからiPhoneで喋らせてるところを動画として録画、それをffmpeg使って音声ファイルを分離、というのをやってみたんだけど、あああ、AVSpeechSynthesizerで出力した音声は録音してくれないっぽい。そういや、何でもかんでも録画できるわけじゃないってリファレンス(?)かどこかで見たなあ(今探したけど見つからない)。ほら、映画とかは確か録画できないようにしてるんだよな。あああ、無念。
なお、従来通りMacのQuickTime PlayerでiPhoneの画面を録画してやればできなくもない。んー、、、どうしたものか。


SceneKitでマスクをしたい

ARKitを使ってごにょごにょしてるんだけど、どこでもドア的な表現をSceneKitでしようとしてふと固まってしまった。SceneKitでマスクってどうやるんだ?

どこでもドアの向こう側には別な世界があって、それらがドアの入り口形状の長方形でマスクされれば表現できるわけだけど、、、

いろいろ調べたつもりなんだがマスクのやり方がわからない。

Metalのステンシルバッファでマスクしてみる
↑Metalでステンシルバッファ使ってやったことはあるけど、、、超絶めんどくさい。天下の(?)SceneKitなんだからもっとサクッとできそうな気がしてならない。

結局、、、ステンシルバッファは使わずに、SceneKitでオフスクリーンレンダリング、つまり最初にマスクしたいオブジェクト(どこでもドアの向こうにあるオブジェクト)をMTLTextureに出力し、次にドアのこちら側のオブジェクトとドア入り口の長方形をディスプレイに表示する。その長方形の色はフラグメントシェーダーでMTLTextureから選んで表示してやる、という流れでやることにした。

オブジェクトの位置関係

↑位置関係はこんなの。黄色い四角形がドア入り口に相当。

↑床面がドアの向こうにも表示されてるのはご愛嬌(手抜き)。

GitHub - lachlanhurst/SceneKitOffscreenRendering: Using SCNRenderer to render a scene offscreen to a texture that's then displayed in another scene
↑すごく参考になったのがこちらのコード。不要な部分を排除してすんごい理解しやすいコード。感謝、感謝。SCNRendererクラスって初めて使ったわ。

上のサンプルコードと異なる部分だと、、、
出力するテクスチャの設定。
{
	MTLTextureDescriptor *textureDescriptor = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:MTLPixelFormatBGRA8Unorm width:width height:height mipmapped:NO];
	offscreenTexture = [device newTextureWithDescriptor:textureDescriptor];
}

ドア入り口の長方形の表示にシェーダーを設定する。ここでシェーダーに渡してやるテクスチャ画像をoffscreen renderingの出力画像に設定してる。
-(void)setupShaderForNode:(SCNNode *)node
{
    SCNGeometry *geometry = node.geometry;
    
    SCNMaterial *material = geometry.firstMaterial;
    
    SCNProgram *program = [SCNProgram program];
    program.vertexFunctionName = @"myVertex";
    program.fragmentFunctionName = @"myFragment";
    material.program = program;
    
    SCNMaterialProperty *imageProperty = [SCNMaterialProperty materialPropertyWithContents:offscreenTexture];
    [material setValue:imageProperty forKey:@"offscreenTexture"];
}

こんな感じでマスクできそうだけど、、、
うーーーーん。やっぱりそのうちSceneKitでしれっと実装される気がする。


XcodeのコンソールにはPythonだと日本語出力できない?

ずっとPython 3を使うのにXcodeを使ってるんだけど、これまで日本語出力はしてなかったのよ。
いや出力しようとするとうまくいかなくて調べるのも面倒だから日本語は使わなかった、ってだけだったんだな。
今まではそれで事足りてたんだけどさ。

最近、Pythonでスクレイピングとかやってんのよ。そしたらどうしても日本語を扱うわけで、その時にエラーが出てしまい困ってるんだわ。

ネットで調べてもPython 2ならともかく3ならそれほど悩まなくても良さそうなもんだけど、、、

print("テスト")
例えば↑このPythonのコードをXcodeから動かすと、、、

print("\u30c6\u30b9\u30c8")
UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-2: ordinal not in range(128)
↑エラーになる。encodeだのunicodeだのいろいろと試してみたがコンソールに日本語が表示されることはなかった。

Python3の実行結果

↑でもターミナルからだと動く。

きっとXcodeになんかあるんかな?ってことであきらめた。



Python 3.5.2 :: Anaconda 4.1.1 (x86_64)
Xcode 8.3 (今はXcode 9 beta 3を使ってるけど正式版からずっとこの調子)





Copyright ©頭と尻尾はくれてやる!. Powered by FC2 Blog. Template by eriraha.

FC2Ad