アプリなどを開発するブログ

React Native / Swift / Ruby on Railsなどの学習メモ。


便利そうなXcodeプラグインまとめ

github.com

github.com

github.com

github.com

github.com

Android ネイティブでゲーム作りたい時のメモ

Unityとかcocos 2Dとか使わずに、Androidの機能だけで簡単なゲームが作りたい。
その際に役立ったメモ。

基本的にはCanvasに描画していくのがいいみたい。
Bitmapで描画する方法と、Drawableで描画する方法がある。

Androidでゲームアプリをcanvasで作るときの注意点 | NJF

BitmapかDrawableか 二つの違いは、ゲーム制作に特に関係する部分を一言で言うと ・Bitmap 高速・拡大縮小に弱い ・Drawable 低速・拡大縮小に強い となります。

特に描画領域が大きいとDrawableは格段に遅くなります。pngの透明領域も描画領域に入りますので、できるだけ余白の少ない画像の方が良いようです。OpenGLと違って画像サイズは2の倍数でなくて良いので、削れる限り削りましょう。

iphone.vicent.jp

パラパラアニメでゲームをつくる

iphone.vicent.jp

monoist.atmarkit.co.jp

www.atmarkit.co.jp

#

canvasにanimationDrawableをはりつける stackoverflow.com

Canvasについての詳しい解説

tech.recruit-mp.co.jp

高速化について

www.atmarkit.co.jp

techbooster.org

描画速度的に、ViewよりもSurfaceViewを使うべし

[Android] [Java] SurfaceViewを用いた画面描画

AndroidのSurfaceViewの使い方 - Narrow Escape

もぷろぐ: Activity の動作について

SurfaceViewを用意する - @ANDROID開発

SurfaceViewのライフサイクル

http://blog.global-eng.co.jp/android/2012/01/23/activity%E3%81%A8surfaceview%E3%81%AE%E3%83%A9%E3%82%A4%E3%83%95%E3%82%B5%E3%82%A4%E3%82%AF%E3%83%AB/

canvas内でanimationフレームワークを使う

stackoverflow.com

Canvasでパラパラアニメ

stackoverflow.com

あと、ゲーム関係ないけどmixiが公開してるこちらの資料、とてもいいですね。

github.com

www.slideshare.net

iOSでストリーミング再生中の動画キャプチャを撮りたいが方法がない

やりたいこと

サーバー上にあるm3u8ファイルをiPhoneアプリでストリーミング再生してる。
ボタンを押すと今映ってる映像の写真を撮ってローカルに保存したい。
一見、以下のような処理で簡単に取得できそうである。

let rect = view.bounds

UIGraphicsBeginImageContextWithOptions(rect.size, false, 0.0)
let context: CGContextRef = UIGraphicsGetCurrentContext()
view.layer.renderInContext(context)
let capturedImage : UIImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()

が、真っ黒な画像が出力されるだけ。

色々調べたけど

stackoverflow.com

色々試したけどできないっぽいよという回答。

stackoverflow.com

A) UIGetScreenImage() という非公開メソッドで撮れるけど、リジェクトの可能性もあるよ
B) AVPlayerLayerで再生して、AVAssetImageGenerator の copyCGImageAtTime で撮れるよ
  -> ただしこれは、サーバー上の動画ファイルには使えないみたい

stackoverflow.com ここに載ってる方法でやってみたけど、imageRefが取得できない。
「できた!」って言ってる人は多分ローカルの動画ファイルでやってる気がする。

var url = NSURL(string: Constants.streamUrls[0])
if var asset = AVAsset.assetWithURL(url) as? AVAsset {
    var imageGenerator:AVAssetImageGenerator = AVAssetImageGenerator(asset: asset)
    var time = CMTimeMake(1, 1)
    var imageRef = imageGenerator.copyCGImageAtTime(time, actualTime: nil, error: nil)
    var thumbnail = UIImage(CGImage: imageRef)
    return thumbnail!
}        

以下のようなエラーを吐いてしまう。

Optional(Error Domain=AVFoundationErrorDomain Code=-11800 "The operation could not be completed" UserInfo=0x17046c140 {NSUnderlyingError=0x174243840 "The operation couldn’t be completed. (OSStatus error -12782.)", NSLocalizedFailureReason=An unknown error occurred (-12782), NSLocalizedDescription=The operation could not be completed})

stackoverflow.com こちらもうまくいかない。

AVAssetImageGeneratorを使っての取得も試みたが、ダメだった。
恐らくこちらも有効なのはローカルのビデオのみで、リモートの動画はだめくさい?

func captureFromPlayer(player: AVPlayer, maxSize: CGSize) -> UIImage? {
        var actualTime: CMTime = CMTimeMake(0, 0)
        var error: NSError?
        
        var generator: AVAssetImageGenerator = AVAssetImageGenerator(asset: player.currentItem.asset)
        
        generator.maximumSize = maxSize
        
        println("player.currentTime() :\(player.currentTime())")

        
        var cgIm: CGImageRef = generator.copyCGImageAtTime(player.currentTime(), actualTime: &actualTime, error: &error)
        var image = UIImage(CGImage: cgIm)
        if error != nil {
            println("erorr : \(error?.localizedDescription)")
            println("CMTimeGetSeconds : \(CMTimeGetSeconds(actualTime))")
            if let current = streamView.player?.currentTime() {
                CMTimeGetSeconds(current)
            }
            
            return nil
        }
        return image
    }
    

こっちもやってみたけど、そもそもtracksが空。

func setupReader() {
        let url = NSURL(string: urlString)
        let asset:AVURLAsset = AVURLAsset(URL: url, options: nil)
        asset.loadValuesAsynchronouslyForKeys(["tracks"], completionHandler: {
            dispatch_sync(dispatch_get_main_queue(), { () -> () in
                var videoTrack: AVAssetTrack? = nil
                var tracks = asset.tracksWithMediaType(AVMediaTypeVideo)
                if tracks.count == 1 {
                    if let track = tracks[0] as? AVAssetTrack {
                        var error: NSError?
                        self.movieReader = AVAssetReader(asset: asset, error: &error)
                        if error != nil {
                            println("error: \(error)")
                        }
                        
                        var key:String = kCVPixelBufferPixelFormatTypeKey as String
                        var value:Int = kCVPixelFormatType_4444AYpCbCr16 as Int
                        var videoSettings = [key: value]
                        
                        
                        self.movieReader?.addOutput(AVAssetReaderTrackOutput(track: videoTrack, outputSettings: videoSettings))
                        self.movieReader?.startReading()
                    }
                }
            })
        })
    }

iOS7から実装されたスナップショットを撮るメソッドを試す

こんなんあったんですね。

let capture: UIView = view.snapshotViewAfterScreenUpdates(true)

スクリーン自体のスナップショットを撮影するメソッドも、UIScreenに実装されている。

let capture = UIScreen.mainScreen().snapshotViewAfterScreenUpdates(true)

だがこれも、UIViewをUIImageに変換するこちらのお決まりのメソッドに投げると、
AVPlayerLayerの所だけが真っ黒になって返ってくる。

func viewToImage(capturedView:UIView) -> UIImage {
        UIGraphicsBeginImageContextWithOptions(capturedView.bounds.size, capturedView.opaque, 0.0)
        capturedView.layer.renderInContext(UIGraphicsGetCurrentContext())
        var img = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return img
    }

ちなみに、キャプチャのUIView自体は、ビデオの動画もバッチリ表示されている。
UIImageにする段階で、ビデオ動画がすっぽり抜け落ちる。

なんでや!なんでなんや!
うーむ。。

こんなのもあった

stackoverflow.com

これもだめだった

func snapByOpenGL() -> UIImage {
        if let time = streamView.playerItem?.currentTime() {
            if var pixelBuffer: CVPixelBufferRef = streamView.output?.copyPixelBufferForItemTime(time, itemTimeForDisplay: nil) {
                var ciImage = CIImage(CVPixelBuffer: pixelBuffer)
                
                var temporaryContext: CIContext = CIContext(options: nil)
                var rect = CGRectMake(0, 0, CGFloat(CVPixelBufferGetWidth(pixelBuffer)), CGFloat(CVPixelBufferGetHeight(pixelBuffer)))


                var videoImage: CGImageRef = temporaryContext.createCGImage(ciImage, fromRect: rect)
                var image = UIImage(CGImage: videoImage)
                return image!
            }
        }
        
        return UIImage()
    }

Instagramのハッシュタグつけたのに投稿が表示されない問題

f:id:device_me:20150822174427j:plain

今日(2015年8月22日)、Instagram の投稿にハッシュタグが反映されなくてすごく困った。
同じような現象が起こった時に誰かの役に立てばと思い、どんな事が起こったかまとめておく。

正確には以下の状態だった。

#サンプルハッシュタグ • Instagram photos and videos

解決方法をググって以下を試してみた。

【解決方法1】プライベートモードを解除する

よくある話だが、自分のInstagramアカウントがプライベートモードになってて、 ハッシュタグ投稿一覧ページに反映されないパターン。
Instagramアプリの設定から、プライベートモードをOFFにすれば、即時反映されるようになる。

【解決方法2】「禁止ハッシュタグ」を投稿から削除する

インスタグラムには「バンされたハッシュタグ」が存在する。
エッチなものやスパム目的の投稿をはじくためや、
「photography」など抽象的過ぎるハッシュタグを禁止することで、写真を探しやすくするため、
という意図があるらしい。

ちなみにバンされたハッシュタグ一覧は以下

hype.my

バンされたハッシュタグをつけた投稿は、他のハッシュタグ検索にも引っかからなくなる。
なので、バンされたハッシュタグをコメント欄から削除すれば、検索にひっかかるようになる。


【2】は今回初めて知ったが、他にハッシュタグを一切つけない状態でも投稿が正常に表示されない。。。
もしかして、この数日の間にスパム対策のためにInstagramに仕様変更があり、
全てのハッシュタグをデフォルトでバンし、
そのハッシュタグのついた投稿数が一定数になるまでバンされた状態になる、みたいな事になってるのか?
と思ってひたすら投稿したりいいねを押したりしていた。

【結論】Instagramの一時的なバグか

諦めかけた頃、突然ハッシュタグが反映されるようになった。
理由はわからないが、単なるインスタグラムのバグだったようだ。。
今日の朝にバグが発動し、16時頃修正された。

Twittergoogle の24時間以内検索をやってみると、以下のような投稿がひっかかった。
探してもこれくらいしか出てこなかったので、みんなあんまり困ってなかったのかな?

ともあれ、問題が解決して一件落着。よかったよかった。

answers.yahoo.com

新しいChromeで0.0.0.0:* にアクセスできない

いつからか、chromeのアドレスバーで0.0.0.0を入力してエンターを押すと、
0.0.0.0 という単語にアクセスしてしまうようになってしまいました。何で?

とりあえずhttp://localhost:* でアクセスするようにしましたが、
設定で変えることができるのでしょうか?
ご存知のかた、いらっしゃいましたら教えていただけると幸いです。

Node.jsで動画書出し

Video convert to WebM

http://www.sysord.fr/Sysord/ressource_whammy.jsf

Weppyを使ったwebm生成ライブラリ

https://github.com/antimatter15/whammy

Node.js & real-time video encoding

http://blog.romanliutikov.com/post/76000554454/node-js-real-time-video-encoding